diff --git a/README.md b/README.md index 7532566..5536142 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,7 @@ You can configure the following settings: - Logo - Colors - Fonts +- Searchable Fields The settings are explained in the following sections. @@ -275,6 +276,25 @@ url: [String] This will add the `url` field, being an array of strings. For other types, compare with already existing properties and just copy as you need. +## Adding Searchable Fields + +To add a field to be searchable you have to make the following adjustments: + +- Add the field in the `config.yaml` file to `searchableAttributes`, e.g. `editorialNote` +- In `src/queries.js` add it to `ConceptFields` (around line 176): +```graphql +editorialNote { + ${[...languages].join(" ")} +} +``` +- Add it to the labels to be indexed. Go to `gatsby-node.js` and add it the document object around line 341. For fields being *single* language tagged labels (e.g. `skos:prefLabel`) use `prefLabel` as an example. For fields being arrays of language tagged labels (e.g. `skos:altLabel`) use `altLabel` as an example. For `skos:editorialNote` it would be: +```js +...(concept.editorialNote && +Object.hasOwn(concept.editorialNote, language) && { + editorialNote: i18n(language)(concept.editorialNote), +}), +``` + ## Troubleshooting Depending on special circumstances you may get errors in the log files, e.g. diff --git a/config.default.yaml b/config.default.yaml index 06fab5e..e1f6e95 100644 --- a/config.default.yaml +++ b/config.default.yaml @@ -10,6 +10,7 @@ searchableAttributes: - "hiddenLabel" - "example" - "definition" + - "scopeNote" ui: title: "SkoHub Vocabs" # Title is mandatory logo: "skohub-signet-color.svg" # Path diff --git a/cypress/config.e2e.yaml b/cypress/config.e2e.yaml index 4b2ceb4..8046a3f 100644 --- a/cypress/config.e2e.yaml +++ b/cypress/config.e2e.yaml @@ -10,6 +10,7 @@ searchableAttributes: - "hiddenLabel" - "example" - "definition" + - "scopeNote" ui: title: "SkoHub Vocabs" # Title is mandatory logo: "skohub-signet-color.svg" # Path diff --git a/cypress/e2e/conceptSchemeAndConcept.cy.js b/cypress/e2e/conceptSchemeAndConcept.cy.js index 97ec3fe..7689c06 100644 --- a/cypress/e2e/conceptSchemeAndConcept.cy.js +++ b/cypress/e2e/conceptSchemeAndConcept.cy.js @@ -64,6 +64,16 @@ describe("Concept Scheme and Concept", () => { cy.get("h1").should("have.text", "Hash URI Konzept Schema") }) + it("Visting a hash URI Concept Scheme with hash uri in URL works", () => { + cy.visit("/example.org/hashURIConceptScheme.html#scheme", { + onBeforeLoad(win) { + Object.defineProperty(win.navigator, "language", { value: "de-DE" }) + }, + }) + cy.get(".conceptScheme > a").should("have.text", "Hash URI Konzept Schema") + cy.get("h1").should("have.text", "Hash URI Konzept Schema") + }) + it("Visting a hash URI Concept works", () => { cy.visit("/example.org/hashURIConceptScheme.html#concept1", { onBeforeLoad(win) { diff --git a/cypress/e2e/searchAndFilter.cy.js b/cypress/e2e/searchAndFilter.cy.js index b64e0f0..38503dc 100644 --- a/cypress/e2e/searchAndFilter.cy.js +++ b/cypress/e2e/searchAndFilter.cy.js @@ -151,4 +151,18 @@ describe("search and filter", () => { cy.get("#closeModal").click() cy.get("span").contains("Konzept 1").should("exist") }) + + it("turning on scopeNote checkbox returns scopeNote matches", () => { + cy.visit("/w3id.org/index.html", { + onBeforeLoad(win) { + Object.defineProperty(win.navigator, "language", { value: "de-DE" }) + }, + }) + cy.findByRole("textbox").type("Scope") + cy.get("p").contains("Nothing found").should("exist") + cy.get("#settings").click() + cy.get("#scopeNoteCheckBox").click() + cy.get("#closeModal").click() + cy.get("span").contains("Konzept 1").should("exist") + }) }) diff --git a/gatsby-node.js b/gatsby-node.js index dd869fc..6a2e1d8 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -289,14 +289,7 @@ exports.createPages = async ({ graphql, actions: { createPage } }) => { document: { id: "id", // store: ["prefLabel", "altLabel"], /* not working when importing, bug in flexsearch */ - index: [ - "notation", - "prefLabel", - "altLabel", - "hiddenLabel", - "definition", - "example", - ], + index: [...config.searchableAttributes], }, }) return [l, index] @@ -306,7 +299,14 @@ exports.createPages = async ({ graphql, actions: { createPage } }) => { const conceptsInScheme = await graphql( queries.allConcept(conceptScheme.id, languages) ) - const embeddedConcepts = [] + // embed concept scheme data + const embeddedConcepts = [ + { + json: omitEmpty(Object.assign({}, conceptScheme, context.jsonld)), + jsonld: omitEmpty(Object.assign({}, conceptScheme, context.jsonld)), + }, + ] + conceptsInScheme.data.allConcept.edges.forEach(({ node: concept }) => { const json = omitEmpty(Object.assign({}, concept, context.jsonld)) const jsonld = omitEmpty(Object.assign({}, concept, context.jsonld)) @@ -364,6 +364,10 @@ exports.createPages = async ({ graphql, actions: { createPage } }) => { Object.hasOwn(concept.example, language) && { example: i18n(language)(concept.example), }), + ...(concept.scopeNote && + Object.hasOwn(concept.scopeNote, language) && { + scopeNote: i18n(language)(concept.scopeNote), + }), notation: concept.notation, } indexes[language].add(document) diff --git a/shapes/skohub.shacl.ttl b/shapes/skohub.shacl.ttl index ecb16f9..546780f 100644 --- a/shapes/skohub.shacl.ttl +++ b/shapes/skohub.shacl.ttl @@ -43,7 +43,6 @@ sh:severity sh:Violation ; rdfs:comment "Tested with 01_cs_no_title.ttl" ; ] - ); sh:property [ sh:path skos:hasTopConcept ; @@ -60,15 +59,26 @@ sh:message "The target class for hasTopConcept should be skos:Concept" ; rdfs:comment "Tested with 03_cs_target_class_hasTopConcept.ttl" ; ] ; - sh:property [ - sh:path dct:description ; - sh:datatype rdf:langString ; - sh:severity sh:Warning ; - sh:minCount 1 ; - sh:message: "A description of the Concept Scheme should be provided." ; - rdfs:comment "Tested with 04_cs_no_description.ttl" ; - rdfs:comment "Tested with 05_cs_description_no_langstring.ttl" ; - ] ; + sh:or ( + [ + sh:path dct:description ; + sh:datatype rdf:langString ; + sh:severity sh:Warning ; + sh:minCount 1 ; + sh:message: "A description of the Concept Scheme should be provided." ; + rdfs:comment "Tested with 04_cs_no_description.ttl" ; + rdfs:comment "Tested with 05_cs_description_no_langstring.ttl" ; + ] + [ + sh:path dc:description ; + sh:datatype rdf:langString ; + sh:severity sh:Warning ; + sh:minCount 1 ; + sh:message: "A description of the Concept Scheme should be provided." ; + rdfs:comment "Tested with 04_cs_no_description.ttl" ; + rdfs:comment "Tested with 05_cs_description_no_langstring.ttl" ; + ] + ) ; sh:property [ sh:path dct:license ; sh:minCount 1 ; diff --git a/src/common.js b/src/common.js index 54c0efd..9064e1a 100644 --- a/src/common.js +++ b/src/common.js @@ -98,6 +98,7 @@ const parseLanguages = (graph) => { * @property {string} tokenizer * @property {Object} colors * @property {string} customDomain + * @property {string[]} searchableAttributes */ /** diff --git a/src/components/Collection.jsx b/src/components/Collection.jsx index 4dcd86b..5556116 100644 --- a/src/components/Collection.jsx +++ b/src/components/Collection.jsx @@ -15,7 +15,7 @@ const Collection = ({ pageContext: { node: collection, customDomain } }) => { }, [data?.selectedLanguage]) return ( -
Which labels do you want to include in the search?
+Which fields do you want to include in the search?