Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ Only the third step is specific to enabling external vocabulary support. The oth

If you create your own :CVocConf setting value (i.e. to manage other fields), you can use the /examples/config/CVocConf.schema.json file to validate your syntax.

### Packages

The directory `packages` include complete working sets of metadatablock.tsv / cvoc config and / js files.

- local_contexts
Is pulling and displaying project-data from https://localcontextshub.org/
5 changes: 5 additions & 0 deletions packages/local_contexts/cvocLocalContexts.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#metadataBlock name dataverseAlias displayName blockURI
LocalContextsCVoc Local Contexts
#datasetField name title description watermark fieldType displayOrder displayFormat advancedSearchField allowControlledVocabulary allowmultiples facetable displayoncreate required parent metadatablock_id termURI
LCProjectUrl Local Contexts Project Local Contexts project url Project url url 1 "<a href=""#VALUE"" target=""_blank"" rel=""noopener"">#VALUE</a>" FALSE FALSE FALSE FALSE TRUE FALSE LocalContextsCVoc
#controlledVocabulary DatasetField Value identifier displayOrder
25 changes: 25 additions & 0 deletions packages/local_contexts/lc-cvoc-conf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[
{
"field-name": "LCProjectUrl",
"term-uri-field": "LCProjectUrl",
"js-url": "https://gdcc.github.io/dataverse-external-vocab-support/packages/local_contexts/local_contexts.js",
"protocol": "localcontexts",
"retrieval-uri": "https://localcontextshub.org/api/v1/projects/{0}",
"allow-free-text": false,
"prefix": "https://localcontextshub.org/projects/",
"managed-fields": {},
"languages": "",
"vocabs": {},
"retrieval-filtering": {
"@context": {
"scheme": "http://www.w3.org/2004/02/skos/core#inScheme"
},
"@id": {
"pattern": "{0}",
"params": [
"@id"
]
}
}
}
]
148 changes: 148 additions & 0 deletions packages/local_contexts/local_contexts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
var cvoc_lc_projectSelector = "span[data-cvoc-protocol='localcontexts']"
var cvoc_lc_projectInputSelector = "input[data-cvoc-protocol='localcontexts']"

var cvoc_lc_lcBaseUrl = "https://localcontextshub.org"

var cvoc_lc_seach_minimumInputLength = 4
var cvoc_lc_search_delay = 500

$(document).ready(() => {
// console.log("doc ready")
cvoc_lc_viewProject()
cvoc_lc_editProject()
})

function cvoc_lc_buildLCProjectPopup(project) {

const createItemImage = (notice_label) => {
return `<div style="flex;flex-direction: column;text-align: center; max-width: 175px">
<div style="margin: 12px;">
<img loading="lazy" width="119px" src="${notice_label.img_url}" alt="">
<p style="margin-top:8px; font-size: 14px">${notice_label.name}</p>
</div>
</div>`
}

// console.log(project)
const notices = project.notice || []
const labels = (project.tk_labels || []).concat(project.bc_labels || [])
const lcWrapper = `<div style="max-width: 700px; margin-top: 10px
border: 0.5px solid darkgray;border-radius: 2rem; background: white">
<div style="padding: 12px;padding-bottom: 0; width: 100%; display: flex; flex-wrap: wrap; justify-content: flex-start">
${notices.map(createItemImage).join("")}
${labels.map(createItemImage).join("")}
</div>
<div style="padding: 12px; padding-top: 0; display: flex; flex-wrap: wrap; justify-content: flex-start; width: 100&">
<div style="display: inherit; margin: 0 8px">
<a href="https://localcontexts.org" target="_blank" style="display: inline-flex;">
<img style="width:30px;" src="https://localcontexts.org/wp-content/uploads/2023/04/White-Background.png" alt="Local Contexts Icon">
</a>
</div>
<div style="align-items: center;display: flex;margin-right: 8px;font-size: 14px;">
<a id="project-link" style="font-weight: bold; color: #007585; cursor: pointer; font-size: 14px; text-decoration: underline;" href="${project.project_page}" target="_blank" rel="noopener noreferrer">${project.title}</a>
</div>
</div>
</div>`

const e = document.createElement("div")
e.innerHTML = lcWrapper
return e
}

async function cvoc_lc_LoadOrFetch(fullUrl) {
const lc_project_url_base = `${cvoc_lc_lcBaseUrl}/projects/`
let lc_uuid = fullUrl
if (lc_uuid.startsWith(lc_project_url_base)) {
lc_uuid = lc_uuid.substring(lc_project_url_base.length)
}
const inStorage = sessionStorage.getItem(lc_uuid)
if (inStorage) {
return Promise.resolve(JSON.parse(inStorage))
}
const response = await fetch(`${cvoc_lc_lcBaseUrl}/api/v1/projects/${lc_uuid}`)
const project = await response.json()
sessionStorage.setItem(lc_uuid, JSON.stringify(project))
return Promise.resolve(project)
}

async function cvoc_lc_viewProject() {
// console.log("cvoc_lc_viewProject")
const jqSelect = $(cvoc_lc_projectSelector)
if (jqSelect.length === 0)
return
const projectField = jqSelect[0]
if (projectField.getAttribute("expanded") === "true") {
return
}
projectField.setAttribute("expanded", "true")
const fullUrl = projectField.textContent
const project = await cvoc_lc_LoadOrFetch(fullUrl)
let lcContainerElement = cvoc_lc_buildLCProjectPopup(project)
projectField.after(lcContainerElement)
projectField.innerHTML = `<a href='${fullUrl}' target='_blank' rel='noopener' >${fullUrl}</a>`
}

async function cvoc_lc_editProject() {
var projectInput = $(cvoc_lc_projectInputSelector)
if (projectInput.length === 0)
return
projectInput.hide()
let select_ = document.createElement("select")
select_.id = "localcontextsProjectInputSelector"
select_.classList = "form-control add-resource select2"
select_.setAttribute("aria-hidden", true)
select_.setAttribute("tabindex", -1)
projectInput.after(select_)
let placeholder = ""
if (projectInput[0].value !== "") {
const project = await cvoc_lc_LoadOrFetch(projectInput[0].value)
// console.log(project)
placeholder = project.title
} else {
placeholder = "Search for a project by name or paste the exact project ID"
}
// todo we have: projectInput.value
$(select_).select2({
placeholder: placeholder,
minimumInputLength: cvoc_lc_seach_minimumInputLength,
ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
url: (params) => {
// check if the user posted a uuid (lc project id) and
const uuid_regex = new RegExp("([a-f 0-9]{8})-([a-f 0-9]{4})-([a-f 0-9]{4})-([a-f 0-9]{4})-([a-f 0-9]{12})")
if (uuid_regex.test(params.term)) {
//await get_or_fetch(params.term)
return `${cvoc_lc_lcBaseUrl}/api/v1/projects/${params.term}`
} else {
return `${cvoc_lc_lcBaseUrl}/api/v1/projects/?search=${params.term}`
}
},
data: {},
dataType: 'json',
delay: cvoc_lc_search_delay,
processResults: function (data, page) { // parse the results into the format expected by Select2.
// console.log("processResults", data)
// check if we did the search by uuid
if (data.results === undefined && data.unique_id !== undefined) {
return {
results: [{id: data.unique_id, text: data.title}]
}
}
// normal search results
return {
results: data.results.map(e => ({
id: e.unique_id, text: e.title
}))
}
},
cache: true
}
})

$(select_).on('select2:select', function (e) {
let data = e.params.data
// console.log(data)
projectInput.val(`${cvoc_lc_lcBaseUrl}/projects/${data.id}`)
cvoc_lc_LoadOrFetch(data.id)
})
}