diff --git a/.github/workflows/github_actions.yaml b/.github/workflows/github_actions.yaml new file mode 100644 index 0000000..4040636 --- /dev/null +++ b/.github/workflows/github_actions.yaml @@ -0,0 +1,51 @@ +name: Build WebUI + +on: + push: + # Sequence of patterns matched against refs/heads + branches: + - '**' + +env: + REGISTRY: ghcr.io + +jobs: + containerize: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: Extract branch name + shell: bash + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" + id: extract_branch + - name: downcase REPO + run: | + echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} + - name: Log in to the Container registry + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build frontend + id: build_frontend + run: | + cd cee && sh run_build.sh + - name: Build container + id: docker_build + uses: docker/build-push-action@v2 + if: steps.extract_branch.outputs.branch != 'main' + with: + context: . + push: true + tags: ghcr.io/${{ env.REPO }}:${{ steps.extract_branch.outputs.branch }} + - name: Build container + id: docker_build_main + uses: docker/build-push-action@v2 + if: steps.extract_branch.outputs.branch == 'main' + with: + context: . + push: true + tags: ghcr.io/${{ env.REPO }}:${{ steps.extract_branch.outputs.branch }}, ghcr.io/${{ env.REPO }}:latest \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9237dba..b6077bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ -data/ env/ -cee/cedar-embeddable-editor* +**/cee/cedar-embeddable-editor* +cee/output +data/ cee/release*.zip -src/static/cee -src/templates/cee.html *.pyc -venv/ \ No newline at end of file +venv/ +**node_modules +package*.json +MaterialIcons* +**/cee/styles.css +.DS_Store \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..45fc749 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM python:3.8-bullseye + +RUN apt update && apt upgrade -y + +ADD src/ /app +EXPOSE 5000 +WORKDIR /app + +COPY requirements.txt requirements.txt +RUN pip install -r requirements.txt + +CMD ["python", "run.py"] \ No newline at end of file diff --git a/README.md b/README.md index 039773f..0dccade 100644 --- a/README.md +++ b/README.md @@ -2,33 +2,33 @@ A Cedar template implementation to fill in (and maintain) forms, based on the [Cedar Embeddable Editor](https://github.com/metadatacenter/cedar-embeddable-editor) ## Prerequisites -* linux / unix OS -* Docker Engine -* NodeJS and NPM +* Docker Engine (linux) / Docker for Windows / Docker for macOS + +Additional prerequisites are needed for development: + +* Python >= 3.8 +* NodeJS v16 and NPM ## How to run -1. Go to the cee folder, and execute the [build_frontend.sh](cee/build_frontend.sh) file (command: `cd cee && sh build_frontend.sh`) -2. Start the GraphDB backend: - - Go to the [development_environment](development_environment) folder - - Run `docker-compose up -d` - - Run `sh run.sh` -3. Run the python backend (which serves the front-end) - - Go to the main folder - - Create and load dependencies: `python -m venv ./venv && source ./venv/bin/activate && pip install -r requirements.txt - - Go to the [src](src) folder and run `python run.py` +1. Clone or download this GitHub repository to your local PC +2. Open the downloaded/cloned contents locally in the terminal +3. Run `docker-compose up -d` +4. when the previous command is finished, open the following url: [http://localhost:5000](http://localhost:5000) ## Configure templates -By default a template is given in [src/template.json](src/template.json). You can change this in the [src/config.yaml](src/config.yaml) file in: +By default a CEDAR template is given in [src/template.json](src/template.json). You can change this in the [src/config.yaml](src/config.yaml) file in: ``` template: - source: file - location: + source: cedar + templateId: ``` -If you want to connect to Cedar itself, it is possible to provide the following information in the [src/config.yaml](src/config.yaml) file: +If you want to connect to the CEDAR service API, it is possible to provide the following information in the [src/config.yaml](src/config.yaml) file: ``` template: source: cedar api_key: templateId: ``` + +Mind that the variable `api_key` is only needed for templates which are not available in Cedar's OpenView. \ No newline at end of file diff --git a/cee/build_frontend.sh b/cee/build_frontend.sh deleted file mode 100644 index caf1d41..0000000 --- a/cee/build_frontend.sh +++ /dev/null @@ -1,23 +0,0 @@ -version='2.6.18' - -rm -Rf cedar-embeddable-editor* -rm -Rf release-*.zip - -# Download and unzip release version of CEE -curl -L -o release-$version.zip https://github.com/metadatacenter/cedar-embeddable-editor/archive/refs/tags/release-$version.zip -unzip release-$version.zip - -# Override files needed to work in our situation -cp app.component.ts cedar-embeddable-editor-release-$version/src/app/app.component.ts -cp app.module.ts cedar-embeddable-editor-release-$version/src/app/app.module.ts - -# Build project -cd cedar-embeddable-editor-release-$version -npm install -node_modules/@angular/cli/bin/ng build --configuration production --baseHref="/static/cee/" - -# Copy to src static -rm -R ../../src/static/cee -mkdir -p ../../src/static/cee -cp -R dist/cedar-embeddable-editor/* ../../src/static/cee/ -cp ../../src/static/cee/index.html ../../src/templates/cee.html \ No newline at end of file diff --git a/cee/app.component.ts b/cee/input/app.component.ts similarity index 100% rename from cee/app.component.ts rename to cee/input/app.component.ts diff --git a/cee/app.module.ts b/cee/input/app.module.ts similarity index 100% rename from cee/app.module.ts rename to cee/input/app.module.ts diff --git a/cee/input/build_frontend.sh b/cee/input/build_frontend.sh new file mode 100644 index 0000000..a018794 --- /dev/null +++ b/cee/input/build_frontend.sh @@ -0,0 +1,29 @@ +version='2.6.41' + +cd /build + +cp /input/*.ts ./ + +rm -Rf cedar-embeddable-editor* +rm -Rf release-*.zip + +# Download and unzip release version of CEE +curl -L -o release-$version.zip https://github.com/metadatacenter/cedar-embeddable-editor/archive/refs/tags/release-$version.zip +unzip release-$version.zip + +# # Override files needed to work in our situation +# cp app.component.ts cedar-embeddable-editor-release-$version/src/app/app.component.ts +# cp app.module.ts cedar-embeddable-editor-release-$version/src/app/app.module.ts + +# Build project +cd cedar-embeddable-editor-release-$version +sed -i "/this.messageHandlerService.traceObject/ a window.location.href = '\\/';" src/app/modules/shared/components/cedar-data-saver/cedar-data-saver.component.ts +npm install --no-audit +# node_modules/@angular/cli/bin/ng build --configuration production --baseHref="./static/cee/" +export NG_CLI_ANALYTICS=ci +npm run ng build -- --configuration production --output-hashing=none --base-href="./static/cee/" + +# copy output +cp -R ./dist/cedar-embeddable-editor/* /output + +cat /output/{runtime,polyfills,main}.js > /output/cedar-embeddable-editor.js diff --git a/cee/run_build.sh b/cee/run_build.sh new file mode 100644 index 0000000..0b69e66 --- /dev/null +++ b/cee/run_build.sh @@ -0,0 +1,17 @@ +NODE_VERSION=16 + +docker volume create node-$NODE_VERSION-cedar-build + +rm -Rf $(pwd)/output + +docker run --rm -v $(pwd)/input:/input -v $(pwd)/output:/output -v node-$NODE_VERSION-cedar-build:/build node:$NODE_VERSION-bullseye /bin/bash /input/build_frontend.sh + +mkdir -p $(pwd)/../src/static/cee/node_modules +# Add static folder prefix to load font type correctly in javascript +sed 's/MaterialIcons/static\/cee\/MaterialIcons/g' output/cedar-embeddable-editor.js > $(pwd)/../src/static/cee/cedar-embeddable-editor.js + +docker run --rm -v $(pwd)/output:/output --workdir /output node:$NODE_VERSION-bullseye npm install @webcomponents/webcomponentsjs + +cp -R $(pwd)/output/node_modules $(pwd)/../src/static/cee +cp $(pwd)/output/styles.css $(pwd)/../src/static/cee/ +cp $(pwd)/output/MaterialIcons-* $(pwd)/../src/static/cee/ \ No newline at end of file diff --git a/development_environment/config.ttl b/development_environment/config.ttl deleted file mode 100644 index 4ff77b6..0000000 --- a/development_environment/config.ttl +++ /dev/null @@ -1,32 +0,0 @@ -@prefix rdfs: . -@prefix rep: . -@prefix sail: . -@prefix xsd: . - -<#public_dump> a rep:Repository; - rep:repositoryID "public_dump"; - rep:repositoryImpl [ - rep:repositoryType "graphdb:FreeSailRepository"; - [ - "http://example.org/owlim#"; - "false"; - ""; - "false"; - "false"; - "true"; - "true"; - "32"; - "10000000"; - ""; - "true"; - "0"; - "0"; - "false"; - "file-repository"; - "owl2-rl-optimized"; - "storage"; - "false"; - sail:sailType "graphdb:FreeSail" - ] - ]; - rdfs:label "public_dump" . diff --git a/development_environment/docker-compose.yaml b/development_environment/docker-compose.yaml deleted file mode 100644 index 372236b..0000000 --- a/development_environment/docker-compose.yaml +++ /dev/null @@ -1,10 +0,0 @@ -version: '3.8' -services: - rdf-store: - image: registry.gitlab.com/um-cds/fair/tools/docker-graphdb:latest - ports: - - "7200:7200" - environment: - - GDB_HEAP_SIZE=2g - - GDB_MIN_MEM=1g - - GDB_MAX_MEM=2g \ No newline at end of file diff --git a/development_environment/run.sh b/development_environment/run.sh deleted file mode 100644 index 6697c48..0000000 --- a/development_environment/run.sh +++ /dev/null @@ -1,14 +0,0 @@ -docker-compose up -d - -echo "Waiting for GraphDB to be up-and-running" -curl -X GET --header 'Accept: application/json' 'http://localhost:7200/rest/locations' -retVal=$? -while [ $retVal -ne 0 ] -do - sleep 5 - curl -X GET --header 'Accept: application/json' 'http://localhost:7200/rest/locations' - retVal=$? -done - -# Create repository from config -curl -X POST -F config=@config.ttl --header 'Content-Type: multipart/form-data' --header 'Accept: */*' 'http://localhost:7200/rest/repositories' \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..ece2de8 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,25 @@ +version: '3.8' +services: + rdf-store: + image: ghcr.io/maastrichtu-cds/fair_tools_docker-graphdb/docker-graphdb:latest + ports: + - "7200:7200" + environment: + - GDB_HEAP_SIZE=2g + - GDB_MIN_MEM=1g + - GDB_MAX_MEM=2g + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:7200/repositories"] + interval: 5s + timeout: 3s + retries: 5 + semforms: + image: ghcr.io/maastrichtu-biss/semanticforms + ports: + - "5000:5000" + volumes: + - ./data:/app/data + - ./src/config.yaml:/app/config.yaml + depends_on: + rdf-store: + condition: service_healthy diff --git a/run_endpoint.sh b/run_endpoint.sh deleted file mode 100644 index f059dc4..0000000 --- a/run_endpoint.sh +++ /dev/null @@ -1,5 +0,0 @@ -docker run -d \ - --name graphdb \ - -p 7200:7200 \ - --restart unless-stopped \ - registry.gitlab.com/um-cds/fair/tools/docker-graphdb:latest diff --git a/src/config.yaml b/src/config.yaml index f88daf6..38e5d68 100644 --- a/src/config.yaml +++ b/src/config.yaml @@ -1,8 +1,10 @@ server: storageFolder: ./data - rdf_endpoint: http://localhost:7200/repositories/public_dump - rdf_endpoint_update: http://localhost:7200/repositories/public_dump/statements + server_url: "http://rdf-store:7200" + repository_name: "semantic_forms" + update_endpoint_suffix: "/statements" template: - source: file - location: template.json - instance_base_url: http://localhost/template-instances \ No newline at end of file + source: cedar + templateId: 102d2c3b-2958-42b1-8baf-8a25ced9aca8 + instance_base_url: http://localhost/template-instances + title_predicate: http://purl.org/dc/terms/title \ No newline at end of file diff --git a/src/endpoint_service.py b/src/endpoint_service.py index 8ea2e19..6738ccf 100644 --- a/src/endpoint_service.py +++ b/src/endpoint_service.py @@ -1,32 +1,105 @@ from SPARQLWrapper import SPARQLWrapper, POST, DIGEST, JSON +import requests import logging +import sys class SPARQLEndpoint: - def __init__(self, sparql_url, sparqlUpdateUrl=None): + def __init__(self, server_url, repository_name, update_endpoint_suffix=None): """ The SPARQLEndpoint class manages communication to the SPARQL endpoint. sparql_url: the SPARQL endpoint URL sparqlUpdateUrl: optional, if the endpoint uses a separate update url, provide this URL here """ - self.__sparql_url = sparql_url - self.__sparql_update_url = sparql_url - if sparqlUpdateUrl is not None: - self.__sparql_update_url = sparqlUpdateUrl + self.__sparql_url = server_url + "/repositories/" + repository_name + self.__sparql_update_url = self.__sparql_url + if update_endpoint_suffix is not None: + self.__sparql_update_url = self.__sparql_update_url + update_endpoint_suffix + + repo_exists = self.__create_repo_if_not_exists(server_url, repository_name) + if not repo_exists: + print(f"Cannot create or find RDF endpoint {self.__sparql_url}") + sys.exit(9) + + def __create_repo_if_not_exists(self, server_url, repository_name): + url = server_url + "/repositories" + response = requests.get(url, headers={"Accept": "application/sparql-results+json"}) + + repositories = response.json()["results"]["bindings"] + for repository in repositories: + print(repository["id"]["value"] + " | " + repository_name) + if repository["id"]["value"] == repository_name: + return True + + print("repository not found, attempting to create") + url = server_url + "/rest/repositories" + repoConfig = f""" + @prefix rdfs: . + @prefix rep: . + @prefix sail: . + @prefix xsd: . + + <#{repository_name}> a rep:Repository; + rep:repositoryID "{repository_name}"; + rep:repositoryImpl [ + rep:repositoryType "graphdb:FreeSailRepository"; + [ + "http://example.org/owlim#"; + "false"; + ""; + "true"; + "false"; + "true"; + "true"; + "32"; + "10000000"; + ""; + "true"; + "0"; + "0"; + "false"; + "file-repository"; + "empty"; + "storage"; + "false"; + sail:sailType "graphdb:FreeSail" + ] + ]; + rdfs:label "{repository_name}" . + """ + data = { "config": repoConfig } + # header = { "Content-Type": "multipart/form-data" } + response = requests.post(url, files=data)#, headers=header) + if response.status_code >= 200 & response.status_code < 300: + return True - def list_instances(self): + return False + + def list_instances(self, titlePredicate=None): """ Retrieve all instances stored in the SPARQL endpoint + Input parameters: + - titlePredicate: Full URL path of the predicate URI to use (DataProperty). """ + if titlePredicate is None: + titlePredicate = "rdfs:label" + + predicateInsert = "OPTIONAL { ?instance <"+titlePredicate+"> ?title. }" + query = """ prefix pav: + prefix rdfs: - select distinct ?instance ?time + select distinct ?instance ?time ?title where { ?instance pav:createdOn ?time. + """ + query += predicateInsert + query += """ } """ + print(query) sparql = SPARQLWrapper(self.__sparql_url) sparql.setQuery(query) sparql.setReturnFormat(JSON) diff --git a/src/run.py b/src/run.py index 593393f..794f1bc 100644 --- a/src/run.py +++ b/src/run.py @@ -41,19 +41,49 @@ def loadConfig(pathString): if not os.path.exists(config['server']['storageFolder']): os.makedirs(config['server']['storageFolder']) -sparqlEndpoint = SPARQLEndpoint(config["server"]["rdf_endpoint"], sparqlUpdateUrl=config["server"]["rdf_endpoint_update"]) +sparqlEndpoint = SPARQLEndpoint(config["server"]["server_url"], config["server"]["repository_name"], update_endpoint_suffix=config["server"]["update_endpoint_suffix"]) @app.route("/") def index(): - instances = sparqlEndpoint.list_instances() + instances = sparqlEndpoint.list_instances(titlePredicate=config["template"]["title_predicate"]) for idx, val in enumerate(instances): - instances[idx]["instance"]["short"] = instances[idx]["instance"]["value"].replace(config["template"]["instance_base_url"] + "/", "") + if "title" not in instances[idx]: + instances[idx]["title"] = { + "value": instances[idx]["instance"]["value"].replace(config["template"]["instance_base_url"] + "/", ""), + "type": "literal" + } return render_template("index.html", instances=instances) @app.route("/add") def cee(): return render_template("cee.html") +@app.route("/edit") +def edit_cee(): + identifier = None + if "uri" in request.args: + identifier = request.args.get("uri").replace(config['template']['instance_base_url'], ".") + jsonData = None + + if identifier: + fileNameJson = os.path.join(config['server']['storageFolder'], f"{identifier}.jsonld") + with open(fileNameJson, "r") as f: + jsonData = json.load(f) + + infoData = {} + + infoData["isBasedOn"] = jsonData["schema:isBasedOn"] + infoData["id"] = jsonData["@id"] + infoData["createdOn"] = jsonData["pav:createdOn"] + infoData["fileName"] = fileNameJson + + del jsonData["@id"] + del jsonData["pav:createdOn"] + del jsonData["schema:isBasedOn"] + return render_template("cee.html", formData=json.dumps(jsonData), formInfo=json.dumps(infoData)) + + return redirect("/", error="Could not load data") + @app.route("/delete") def delete_instance(): identifier = request.args.get("uri") @@ -95,12 +125,16 @@ def get_template(): ``` """ if config['template']['source'] == 'cedar': - headers = { - "Authorization": f"apiKey {config['template']['apiKey']}", - "Content-Type": "application/json" - } + response=None + if "api_key" in config['template']: + headers = { + "Authorization": f"apiKey {config['template']['api_key']}", + "Content-Type": "application/json" + } + response = requests.get(f"https://repo.metadatacenter.org/templates/{config['template']['templateId']}", headers=headers) + else: + response = requests.get(f"https://open.metadatacenter.org/templates/https:%2F%2Frepo.metadatacenter.org%2Ftemplates%2F{config['template']['templateId']}") - response = requests.get(f"https://repo.metadatacenter.org/templates/{config['template']['templateId']}", headers=headers) return json.loads(response.text) if config['template']['source'] == 'file': @@ -124,20 +158,35 @@ def store(): fileNameTurtle = os.path.join(config['server']['storageFolder'], f"{session_id}.ttl") data_to_store = request.get_json() - data_to_store = data_to_store["metadata"] - data_to_store["schema:isBasedOn"] = template['@id'] - data_to_store["pav:createdOn"] = datetime.datetime.now(local_tz).isoformat() - data_to_store["@id"] = f"{config['template']['instance_base_url']}/{session_id}" - with open(fileNameJson, "w") as f: - json.dump(data_to_store, f, indent=4) + print(data_to_store) + data_to_store_meta = data_to_store["metadata"] + data_to_store_info = data_to_store["info"] + + if "id" in data_to_store_info: + print("existing profile") + data_to_store_meta["@id"] = data_to_store_info["id"] + data_to_store_meta["schema:isBasedOn"] = data_to_store_info["isBasedOn"] + data_to_store_meta["pav:createdOn"] = data_to_store_info["createdOn"] + fileNameJson = data_to_store_info["fileName"] + fileNameTurtle = fileNameJson.replace(".jsonld", ".ttl") + else: + print("new profile") + data_to_store_meta["schema:isBasedOn"] = template['@id'] + data_to_store_meta["pav:createdOn"] = datetime.datetime.now(local_tz).isoformat() + data_to_store_meta["@id"] = f"{config['template']['instance_base_url']}/{session_id}" + data_to_store["metadata"] = data_to_store_meta + + with open(fileNameJson, "w") as f: + json.dump(data_to_store_meta, f, indent=4) + g = Graph() - g.parse(data=json.dumps(data_to_store), format='json-ld') + g.parse(data=json.dumps(data_to_store_meta), format='json-ld') g.serialize(destination=fileNameTurtle) turtleData = g.serialize(format='nt') - sparqlEndpoint.store_instance(turtleData, data_to_store["@id"]) + sparqlEndpoint.store_instance(turtleData, data_to_store_meta["@id"]) return {"id": f"{session_id}", "message": "Hi there!"} diff --git a/src/template.json b/src/template.json deleted file mode 100644 index 75fb1c9..0000000 --- a/src/template.json +++ /dev/null @@ -1,622 +0,0 @@ -{ - "@type": "https://schema.metadatacenter.org/core/Template", - "@context": { - "xsd": "http://www.w3.org/2001/XMLSchema#", - "pav": "http://purl.org/pav/", - "bibo": "http://purl.org/ontology/bibo/", - "oslc": "http://open-services.net/ns/core#", - "schema": "http://schema.org/", - "schema:name": { - "@type": "xsd:string" - }, - "schema:description": { - "@type": "xsd:string" - }, - "pav:createdOn": { - "@type": "xsd:dateTime" - }, - "pav:createdBy": { - "@type": "@id" - }, - "pav:lastUpdatedOn": { - "@type": "xsd:dateTime" - }, - "oslc:modifiedBy": { - "@type": "@id" - } - }, - "type": "object", - "title": "Johantest template schema", - "description": "Johantest template schema generated by the CEDAR Template Editor 2.6.17", - "_ui": { - "pages": [], - "order": [ - "has_finding", - "has_age", - "has_date_of_diagnosis" - ], - "propertyLabels": { - "has_age": "has_age", - "has_date_of_diagnosis": "has_date_of_diagnosis", - "has_finding": "has_finding" - }, - "propertyDescriptions": { - "has_age": "Help Text", - "has_date_of_diagnosis": "Help Text", - "has_finding": "Help Text", - "Untitled": "" - } - }, - "properties": { - "@context": { - "type": "object", - "properties": { - "rdfs": { - "type": "string", - "format": "uri", - "enum": [ - "http://www.w3.org/2000/01/rdf-schema#" - ] - }, - "xsd": { - "type": "string", - "format": "uri", - "enum": [ - "http://www.w3.org/2001/XMLSchema#" - ] - }, - "pav": { - "type": "string", - "format": "uri", - "enum": [ - "http://purl.org/pav/" - ] - }, - "schema": { - "type": "string", - "format": "uri", - "enum": [ - "http://schema.org/" - ] - }, - "oslc": { - "type": "string", - "format": "uri", - "enum": [ - "http://open-services.net/ns/core#" - ] - }, - "skos": { - "type": "string", - "format": "uri", - "enum": [ - "http://www.w3.org/2004/02/skos/core#" - ] - }, - "rdfs:label": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "enum": [ - "xsd:string" - ] - } - } - }, - "schema:isBasedOn": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "enum": [ - "@id" - ] - } - } - }, - "schema:name": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "enum": [ - "xsd:string" - ] - } - } - }, - "schema:description": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "enum": [ - "xsd:string" - ] - } - } - }, - "pav:derivedFrom": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "enum": [ - "@id" - ] - } - } - }, - "pav:createdOn": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "enum": [ - "xsd:dateTime" - ] - } - } - }, - "pav:createdBy": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "enum": [ - "@id" - ] - } - } - }, - "pav:lastUpdatedOn": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "enum": [ - "xsd:dateTime" - ] - } - } - }, - "oslc:modifiedBy": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "enum": [ - "@id" - ] - } - } - }, - "skos:notation": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "enum": [ - "xsd:string" - ] - } - } - }, - "has_age": { - "enum": [ - "http://www.cancerdata.org/roo/P100000" - ] - }, - "has_date_of_diagnosis": { - "enum": [ - "http://www.cancerdata.org/roo/P100251" - ] - }, - "has_finding": { - "enum": [ - "http://www.cancerdata.org/roo/P100022" - ] - } - }, - "required": [ - "xsd", - "pav", - "schema", - "oslc", - "schema:isBasedOn", - "schema:name", - "schema:description", - "pav:createdOn", - "pav:createdBy", - "pav:lastUpdatedOn", - "oslc:modifiedBy" - ], - "additionalProperties": { - "type": "string", - "format": "uri" - } - }, - "@id": { - "type": [ - "string", - "null" - ], - "format": "uri" - }, - "@type": { - "oneOf": [ - { - "type": "string", - "format": "uri" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string", - "format": "uri" - }, - "uniqueItems": true - } - ] - }, - "schema:isBasedOn": { - "type": "string", - "format": "uri" - }, - "schema:name": { - "type": "string", - "minLength": 1 - }, - "schema:description": { - "type": "string" - }, - "pav:derivedFrom": { - "type": "string", - "format": "uri" - }, - "pav:createdOn": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "pav:createdBy": { - "type": [ - "string", - "null" - ], - "format": "uri" - }, - "pav:lastUpdatedOn": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "oslc:modifiedBy": { - "type": [ - "string", - "null" - ], - "format": "uri" - }, - "has_age": { - "@type": "https://schema.metadatacenter.org/core/TemplateField", - "@context": { - "xsd": "http://www.w3.org/2001/XMLSchema#", - "pav": "http://purl.org/pav/", - "bibo": "http://purl.org/ontology/bibo/", - "oslc": "http://open-services.net/ns/core#", - "schema": "http://schema.org/", - "skos": "http://www.w3.org/2004/02/skos/core#", - "schema:name": { - "@type": "xsd:string" - }, - "schema:description": { - "@type": "xsd:string" - }, - "skos:prefLabel": { - "@type": "xsd:string" - }, - "skos:altLabel": { - "@type": "xsd:string" - }, - "pav:createdOn": { - "@type": "xsd:dateTime" - }, - "pav:createdBy": { - "@type": "@id" - }, - "pav:lastUpdatedOn": { - "@type": "xsd:dateTime" - }, - "oslc:modifiedBy": { - "@type": "@id" - } - }, - "type": "object", - "title": "has_age field schema", - "description": "has_age field schema generated by the CEDAR Template Editor 2.6.17", - "_ui": { - "inputType": "numeric" - }, - "_valueConstraints": { - "requiredValue": false, - "numberType": "xsd:int", - "unitOfMeasure": "years" - }, - "properties": { - "@value": { - "type": [ - "string", - "null" - ] - }, - "rdfs:label": { - "type": [ - "string", - "null" - ] - }, - "@type": { - "type": "string", - "format": "uri" - } - }, - "required": [ - "@value", - "@type" - ], - "schema:name": "has_age", - "schema:description": "Help Text", - "pav:createdOn": "2022-03-10T07:19:24-08:00", - "pav:createdBy": "https://metadatacenter.org/users/d005592d-1c56-420c-9520-52f43c300f34", - "pav:lastUpdatedOn": "2022-03-10T07:19:24-08:00", - "oslc:modifiedBy": "https://metadatacenter.org/users/d005592d-1c56-420c-9520-52f43c300f34", - "schema:schemaVersion": "1.6.0", - "additionalProperties": false, - "@id": "https://repo.metadatacenter.org/template-fields/86494c9f-ebf3-4555-b82d-6c2bd469b14f", - "skos:prefLabel": "Age", - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "has_date_of_diagnosis": { - "@type": "https://schema.metadatacenter.org/core/TemplateField", - "@context": { - "xsd": "http://www.w3.org/2001/XMLSchema#", - "pav": "http://purl.org/pav/", - "bibo": "http://purl.org/ontology/bibo/", - "oslc": "http://open-services.net/ns/core#", - "schema": "http://schema.org/", - "skos": "http://www.w3.org/2004/02/skos/core#", - "schema:name": { - "@type": "xsd:string" - }, - "schema:description": { - "@type": "xsd:string" - }, - "skos:prefLabel": { - "@type": "xsd:string" - }, - "skos:altLabel": { - "@type": "xsd:string" - }, - "pav:createdOn": { - "@type": "xsd:dateTime" - }, - "pav:createdBy": { - "@type": "@id" - }, - "pav:lastUpdatedOn": { - "@type": "xsd:dateTime" - }, - "oslc:modifiedBy": { - "@type": "@id" - } - }, - "type": "object", - "title": "has_date_of_diagnosis field schema", - "description": "has_date_of_diagnosis field schema generated by the CEDAR Template Editor 2.6.17", - "_ui": { - "inputType": "temporal", - "timezoneEnabled": true, - "inputTimeFormat": "24h", - "temporalGranularity": "minute" - }, - "_valueConstraints": { - "requiredValue": false, - "temporalType": "xsd:dateTime" - }, - "properties": { - "@type": { - "oneOf": [ - { - "type": "string", - "format": "uri" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string", - "format": "uri" - }, - "uniqueItems": true - } - ] - }, - "@value": { - "type": [ - "string", - "null" - ] - }, - "rdfs:label": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "@value" - ], - "schema:name": "has_date_of_diagnosis", - "schema:description": "Help Text", - "pav:createdOn": "2022-03-10T07:19:24-08:00", - "pav:createdBy": "https://metadatacenter.org/users/d005592d-1c56-420c-9520-52f43c300f34", - "pav:lastUpdatedOn": "2022-03-10T07:19:24-08:00", - "oslc:modifiedBy": "https://metadatacenter.org/users/d005592d-1c56-420c-9520-52f43c300f34", - "schema:schemaVersion": "1.6.0", - "additionalProperties": false, - "skos:prefLabel": "Diagnosis date", - "@id": "https://repo.metadatacenter.org/template-fields/23917bcd-58ca-40fa-ac41-e6de36f914e8", - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "has_finding": { - "@type": "https://schema.metadatacenter.org/core/TemplateField", - "@context": { - "xsd": "http://www.w3.org/2001/XMLSchema#", - "pav": "http://purl.org/pav/", - "bibo": "http://purl.org/ontology/bibo/", - "oslc": "http://open-services.net/ns/core#", - "schema": "http://schema.org/", - "skos": "http://www.w3.org/2004/02/skos/core#", - "schema:name": { - "@type": "xsd:string" - }, - "schema:description": { - "@type": "xsd:string" - }, - "skos:prefLabel": { - "@type": "xsd:string" - }, - "skos:altLabel": { - "@type": "xsd:string" - }, - "pav:createdOn": { - "@type": "xsd:dateTime" - }, - "pav:createdBy": { - "@type": "@id" - }, - "pav:lastUpdatedOn": { - "@type": "xsd:dateTime" - }, - "oslc:modifiedBy": { - "@type": "@id" - } - }, - "type": "object", - "title": "has_finding field schema", - "description": "has_finding field schema generated by the CEDAR Template Editor 2.6.17", - "_ui": { - "inputType": "textfield" - }, - "_valueConstraints": { - "requiredValue": false, - "ontologies": [], - "valueSets": [], - "classes": [], - "branches": [ - { - "source": "National Cancer Institute Thesaurus (NCIT)", - "acronym": "NCIT", - "uri": "http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl#C17357", - "name": "Gender", - "maxDepth": 0 - } - ], - "multipleChoice": false - }, - "properties": { - "@type": { - "oneOf": [ - { - "type": "string", - "format": "uri" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string", - "format": "uri" - }, - "uniqueItems": true - } - ] - }, - "rdfs:label": { - "type": [ - "string", - "null" - ] - }, - "@id": { - "type": "string", - "format": "uri" - } - }, - "schema:name": "has_finding", - "schema:description": "Help Text", - "pav:createdOn": "2022-03-10T07:19:24-08:00", - "pav:createdBy": "https://metadatacenter.org/users/d005592d-1c56-420c-9520-52f43c300f34", - "pav:lastUpdatedOn": "2022-03-10T07:19:24-08:00", - "oslc:modifiedBy": "https://metadatacenter.org/users/d005592d-1c56-420c-9520-52f43c300f34", - "schema:schemaVersion": "1.6.0", - "additionalProperties": false, - "@id": "https://repo.metadatacenter.org/template-fields/295ab375-0b49-4c17-850c-a4ec2a0e21e8", - "skos:prefLabel": "Biological Sex", - "$schema": "http://json-schema.org/draft-04/schema#" - } - }, - "required": [ - "@context", - "@id", - "schema:isBasedOn", - "schema:name", - "schema:description", - "pav:createdOn", - "pav:createdBy", - "pav:lastUpdatedOn", - "oslc:modifiedBy", - "has_finding", - "has_age", - "has_date_of_diagnosis" - ], - "schema:name": "JohanTest", - "schema:description": "", - "pav:createdOn": "2022-03-04T01:27:24-08:00", - "pav:createdBy": "https://metadatacenter.org/users/d005592d-1c56-420c-9520-52f43c300f34", - "pav:lastUpdatedOn": "2022-03-10T07:19:24-08:00", - "oslc:modifiedBy": "https://metadatacenter.org/users/d005592d-1c56-420c-9520-52f43c300f34", - "schema:schemaVersion": "1.6.0", - "additionalProperties": { - "type": "object", - "properties": { - "@value": { - "type": [ - "string", - "null" - ] - }, - "@type": { - "type": "string", - "format": "uri" - } - }, - "required": [ - "@value" - ], - "additionalProperties": false - }, - "pav:version": "0.0.2", - "bibo:status": "bibo:draft", - "pav:previousVersion": "https://repo.metadatacenter.org/templates/9b08353a-2d39-424d-9a4d-8113647099e2", - "@id": "https://repo.metadatacenter.org/templates/f39fb608-4ae7-4d13-b500-10c1fbdff9b6", - "$schema": "http://json-schema.org/draft-04/schema#" -} \ No newline at end of file diff --git a/src/templates/cee.html b/src/templates/cee.html new file mode 100644 index 0000000..d9a4556 --- /dev/null +++ b/src/templates/cee.html @@ -0,0 +1,99 @@ + + + + + Cedar form editor + + + + + + +
+ + +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/templates/index.html b/src/templates/index.html index 53436da..fc6ad65 100644 --- a/src/templates/index.html +++ b/src/templates/index.html @@ -2,19 +2,20 @@ {% block content %}

Filled Templates

Please see below for all filled templates, or press the "add" button to fill in the template.

- + - + {%for instance in instances %} - + + {%endfor%} diff --git a/src/templates/instance.html b/src/templates/instance.html index 43e25a8..587be0f 100644 --- a/src/templates/instance.html +++ b/src/templates/instance.html @@ -1,21 +1,42 @@ {% extends "layout.html" %} {% block content %}

Instance details

- + + + +
IDTitle / ID Creation Date
{{instance["instance"]["short"]}}{{instance["title"]["value"]}} {{instance["time"]["value"]}}Edit
- - - - - - - - {%for property in properties %} - - - - - {%endfor%} - + + + + + + + + {%for property in properties %} + + + + + {%endfor%} +
PropertyValue
{{ property["predicate"]["value"] }}{{ property["object"]["value"] }}
PropertyValue
{{ property["predicate"]["value"] }}{{ property["object"]["value"] }}
{% endblock %} \ No newline at end of file