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/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 2703fff..c817f73 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]
@@ -371,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/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/Concept.jsx b/src/components/Concept.jsx
index 45541cb..e263591 100644
--- a/src/components/Concept.jsx
+++ b/src/components/Concept.jsx
@@ -53,22 +53,55 @@ const Concept = ({
)}
- {concept.scopeNote && (
+ {concept.note && i18n(language)(concept.note) !== "" && (
-
Scope Note
-
- {i18n(language)(concept.scopeNote) ||
- `*No scope note in language "${language}" provided.*`}
-
+
Note
+
+ {i18n(language)(concept.note).map((note, i) => (
+ - {note}
+ ))}
+
)}
- {concept.note && (
+ {concept.changeNote && i18n(language)(concept.changeNote) !== "" && (
-
Note
-
- {i18n(language)(concept.note) ||
- `*No note in language "${language}" provided.*`}
-
+
ChangeNote
+
+ {i18n(language)(concept.changeNote).map((changeNote, i) => (
+ - {changeNote}
+ ))}
+
+
+ )}
+ {concept.editorialNote &&
+ i18n(language)(concept.editorialNote) !== "" && (
+
+
EditorialNote
+
+ {i18n(language)(concept.editorialNote).map((editorialNote, i) => (
+ - {editorialNote}
+ ))}
+
+
+ )}
+ {concept.historyNote && i18n(language)(concept.historyNote) !== "" && (
+
+
HistoryNote
+
+ {i18n(language)(concept.historyNote).map((historyNote, i) => (
+ - {historyNote}
+ ))}
+
+
+ )}
+ {concept.scopeNote && i18n(language)(concept.scopeNote) !== "" && (
+
+
ScopeNote
+
+ {i18n(language)(concept.scopeNote).map((scopeNote, i) => (
+ - {scopeNote}
+ ))}
+
)}
{concept.altLabel && i18n(language)(concept.altLabel) !== "" && (
diff --git a/src/components/Search.jsx b/src/components/Search.jsx
index 0a790e8..22568ba 100644
--- a/src/components/Search.jsx
+++ b/src/components/Search.jsx
@@ -53,7 +53,7 @@ const Search = ({ handleQueryInput, labels, onLabelClick }) => {
closeModal={() => setModal(false)}
id="settingsModal"
>
- Which labels do you want to include in the search?
+ Which fields do you want to include in the search?
diff --git a/src/context.js b/src/context.js
index 0ae32b3..127ced6 100644
--- a/src/context.js
+++ b/src/context.js
@@ -48,11 +48,20 @@ const jsonld = {
definition: {
"@container": "@language",
},
- scopeNote: {
- "@container": "@language",
- },
note: {
- "@container": "@language",
+ "@container": ["@language", "@set"],
+ },
+ changeNote: {
+ "@container": ["@language", "@set"],
+ },
+ editorialNote: {
+ "@container": ["@language", "@set"],
+ },
+ historyNote: {
+ "@container": ["@language", "@set"],
+ },
+ scopeNote: {
+ "@container": ["@language", "@set"],
},
notation: {
"@container": "@set",
diff --git a/src/hooks/configAndConceptSchemes.js b/src/hooks/configAndConceptSchemes.js
index 2becd67..161f618 100644
--- a/src/hooks/configAndConceptSchemes.js
+++ b/src/hooks/configAndConceptSchemes.js
@@ -1,5 +1,45 @@
import { useStaticQuery, graphql } from "gatsby"
+/**
+ * @returns {{
+ * config: {
+ * colors: {
+ * skoHubWhite: string,
+ * skoHubDarkColor: string,
+ * skoHubMiddleColor: string,
+ * skoHubLightColor: string,
+ * skoHubThinColor: string,
+ * skoHubBlackColor: string,
+ * skoHubAction: string,
+ * skoHubNotice: string,
+ * skoHubDarkGrey: string,
+ * skoHubMiddleGrey: string,
+ * skoHubLightGrey: string
+ * },
+ * logo: string,
+ * title: string,
+ * fonts: {
+ * bold: {
+ * font_family: string,
+ * font_style: string,
+ * font_weight: string,
+ * name: string
+ * },
+ * regular: {
+ * font_family: string,
+ * font_style: string,
+ * font_weight: string,
+ * name: string
+ * }
+ * },
+ * searchableAttributes: string[],
+ * customDomain: string,
+ * failOnValidation: boolean
+ * },
+ * conceptSchemes: Object
+ * }} An object containing `config` and `conceptSchemes`
+ *
+ */
export const getConfigAndConceptSchemes = () => {
const { site, allConceptScheme } = useStaticQuery(graphql`
query Colors {
diff --git a/src/queries.js b/src/queries.js
index da97cb4..1211c14 100644
--- a/src/queries.js
+++ b/src/queries.js
@@ -49,10 +49,19 @@ module.exports.allConcept = (inScheme, languages) => `
definition {
${[...languages].join(" ")}
}
- scopeNote {
+ note {
${[...languages].join(" ")}
}
- note {
+ changeNote {
+ ${[...languages].join(" ")}
+ }
+ editorialNote {
+ ${[...languages].join(" ")}
+ }
+ historyNote {
+ ${[...languages].join(" ")}
+ }
+ scopeNote {
${[...languages].join(" ")}
}
notation
@@ -182,6 +191,9 @@ module.exports.allConceptScheme = (languages) => `
example {
${[...languages].join(" ")}
}
+ scopeNote {
+ ${[...languages].join(" ")}
+ }
deprecated
}
`
diff --git a/src/templates/App.jsx b/src/templates/App.jsx
index 57cd894..52d8d9e 100644
--- a/src/templates/App.jsx
+++ b/src/templates/App.jsx
@@ -130,7 +130,7 @@ const App = ({ pageContext, children, location }) => {
labels,
data.selectedLanguage,
setIndex,
- config.customDomain
+ config
)
}, [data, language, labels])
diff --git a/src/templates/helpers.js b/src/templates/helpers.js
index fafe5ec..c28d1b8 100644
--- a/src/templates/helpers.js
+++ b/src/templates/helpers.js
@@ -1,6 +1,6 @@
import { useEffect } from "react"
import Document from "flexsearch/dist/module/document.js"
-import { i18n, getFilePath } from "../common"
+import { getFilePath } from "../common"
import { withPrefix } from "gatsby"
export const handleKeypresses = (labels, setLabels) => {
@@ -43,6 +43,10 @@ export const handleKeypresses = (labels, setLabels) => {
e.preventDefault()
Object.keys(labels).includes("hiddenLabel") &&
setLabels({ ...labels, ["hiddenLabel"]: !labels["hiddenLabel"] })
+ } else if (e.altKey && e.which === 83) {
+ e.preventDefault()
+ Object.keys(labels).includes("scopeNote") &&
+ setLabels({ ...labels, ["scopeNote"]: !labels["scopeNote"] })
}
}
document.addEventListener("keydown", handleKeyDown)
@@ -58,7 +62,7 @@ export const importIndex = async (
labels,
language,
setIndex,
- customDomain
+ config
) => {
if (!conceptSchemeId) return
const idx = new Document({
@@ -68,14 +72,7 @@ export const importIndex = async (
document: {
id: "id",
// store: ["prefLabel", "altLabel"], /* not working flexsearchside */
- index: [
- "notation",
- "prefLabel",
- "altLabel",
- "hiddenLabel",
- "definition",
- "example",
- ],
+ index: [...config.searchableAttributes],
},
})
// filter from labels object the selected entries
@@ -97,7 +94,9 @@ export const importIndex = async (
try {
const path =
getFilePath(conceptSchemeId) + `-cs/search/${language}/${key}`
- data = await fetch(withPrefix(getFilePath(path, `json`, customDomain)))
+ data = await fetch(
+ withPrefix(getFilePath(path, `json`, config.customDomain))
+ )
const jsonData = await data.json()
idx.import(key, jsonData ?? null)
} catch (e) {
diff --git a/src/types.js b/src/types.js
index 911dc60..e189dc4 100644
--- a/src/types.js
+++ b/src/types.js
@@ -20,8 +20,11 @@ module.exports = (languages) => `
altLabel: LanguageMapArray,
hiddenLabel: LanguageMapArray,
definition: LanguageMap,
- scopeNote: LanguageMap,
- note: LanguageMap,
+ note: LanguageMapArray,
+ changeNote: LanguageMapArray,
+ editorialNote: LanguageMapArray,
+ historyNote: LanguageMapArray,
+ scopeNote: LanguageMapArray,
notation: [String],
example: LanguageMap,
topConceptOf: [ConceptScheme] @link(from: "topConceptOf___NODE"),
diff --git a/test/concept.test.jsx b/test/concept.test.jsx
index 4272965..3667f8d 100644
--- a/test/concept.test.jsx
+++ b/test/concept.test.jsx
@@ -125,6 +125,71 @@ describe.concurrent("Concept", () => {
).toBeInTheDocument()
})
+ it("renders notes", () => {
+ render()
+
+ expect(screen.getByText(/Meine Anmerkung/i)).toBeInTheDocument()
+
+ const list = screen.getByRole("list", {
+ name: "Note",
+ })
+ const { getAllByRole } = within(list)
+ const items = getAllByRole("listitem")
+ expect(items.length).toBe(2)
+ })
+
+ it("renders changeNotes", () => {
+ render()
+
+ expect(screen.getByText(/Meine Change Note/i)).toBeInTheDocument()
+
+ const list = screen.getByRole("list", {
+ name: /changenote/i,
+ })
+ const { getAllByRole } = within(list)
+ const items = getAllByRole("listitem")
+ expect(items.length).toBe(2)
+ })
+
+ it("renders editorialNotes", () => {
+ render()
+
+ expect(screen.getByText(/Meine Editorial Note/i)).toBeInTheDocument()
+
+ const list = screen.getByRole("list", {
+ name: /editorialnote/i,
+ })
+ const { getAllByRole } = within(list)
+ const items = getAllByRole("listitem")
+ expect(items.length).toBe(2)
+ })
+
+ it("renders historyNotes", () => {
+ render()
+
+ expect(screen.getByText(/Meine History Note/i)).toBeInTheDocument()
+
+ const list = screen.getByRole("list", {
+ name: /historynote/i,
+ })
+ const { getAllByRole } = within(list)
+ const items = getAllByRole("listitem")
+ expect(items.length).toBe(2)
+ })
+
+ it("renders scopeNotes", () => {
+ render()
+
+ expect(screen.getByText(/Meine Scope Note/i)).toBeInTheDocument()
+
+ const list = screen.getByRole("list", {
+ name: /scopenote/i,
+ })
+ const { getAllByRole } = within(list)
+ const items = getAllByRole("listitem")
+ expect(items.length).toBe(2)
+ })
+
it("renders related Concepts", () => {
render()
expect(
diff --git a/test/data/pageContext.js b/test/data/pageContext.js
index 116a23f..c593355 100644
--- a/test/data/pageContext.js
+++ b/test/data/pageContext.js
@@ -49,11 +49,20 @@ export const topConcept = {
example: {
de: "Ein Beispiel",
},
- scopeNote: {
- de: "Meine Scope Note",
- },
note: {
- de: "Meine Anmerkung",
+ de: ["Meine Anmerkung", "Noch eine Anmerkung"],
+ },
+ changeNote: {
+ de: ["Meine Change Note", "Noch eine Change Note"],
+ },
+ editorialNote: {
+ de: ["Meine Editorial Note", "Noch eine Editorial Note"],
+ },
+ historyNote: {
+ de: ["Meine History Note", "Noch eine History Note"],
+ },
+ scopeNote: {
+ de: ["Meine Scope Note", "Noch eine Scope Note"],
},
notation: ["1"],
narrower: [concept2],