diff --git a/demonstrator/triple-combined-service.rq b/demonstrator/triple-combined-service.rq index fdba8a2a..a5407f51 100644 --- a/demonstrator/triple-combined-service.rq +++ b/demonstrator/triple-combined-service.rq @@ -1,4 +1,4 @@ -# Datasources: https://triple.ilabt.imec.be/test/chist-era-annex-1-chemicals.ttl +# Datasources: http://localhost:3000/test/Uploads/nbn-chist-era-annex-1-chemicals-alt.ttl PREFIX rdfs: PREFIX rh: PREFIX xsd: diff --git a/demonstrator/triple-idsm-3.rq b/demonstrator/triple-idsm-3.rq new file mode 100644 index 00000000..8db5b8a7 --- /dev/null +++ b/demonstrator/triple-idsm-3.rq @@ -0,0 +1,96 @@ +# Datasources: https://idsm.elixir-czech.cz/sparql/endpoint/idsm +PREFIX xsd: +PREFIX sio: +PREFIX vocab: +PREFIX sachem: + +SELECT ?CAS ?COMPOUND ?SIMILAR_COMPOUND ?SCORE WHERE { + { + # values from Solid pod + VALUES ?CAS { + "75-35-4" + "71-55-6" + "79-00-5" + "630-20-6" + "79-34-5" + "106-93-4" + "107-06-2" + "542-75-6" + "10061-01-5" + "13952-84-6" + "91-59-8" + "553-00-4" + "612-52-2" + "120-23-0" + "121-14-2" + "93-76-5" + "10519-33-2" + "92-67-1" + "2113-61-3" + "92-93-3" + "101-77-9" + "81-15-2" + "30560-19-1" + "34256-82-1" + "50594-66-6" + "15972-60-8" + "116-06-3" + "834-12-8" + "33089-61-1" + "61-82-5" + "84-65-1" + "1332-21-4" + "77536-66-4" + "77536-67-5" + "12172-73-5" + "12001-28-4" + "77536-68-6" + "3337-71-1" + "2302-17-2" + "1912-24-9" + "2642-71-9" + "86-50-0" + "41083-11-8" + "71626-11-4" + "82560-54-1" + "17606-31-4" + "71-43-2" + "92-87-5" + "36341-27-2" + "85-68-7" + "1820573-27-0" + "65731-84-2" + "82657-04-3" + "485-31-4" + } + + ?SYNONYM a sio:CHEMINF_000446 . # CAS registry number + ?SYNONYM sio:SIO_000300 ?CAS . + ?SYNONYM sio:SIO_000011 ?COMPOUND . + + ?COMPOUND a vocab:Compound . + + ?ATTRIBUTE a sio:SIO_011120 . # molecular structure file + ?ATTRIBUTE sio:SIO_000011 ?COMPOUND . + ?ATTRIBUTE sio:SIO_000300 ?MOLFILE . + + SERVICE { + [ + sachem:compound ?SIMILAR_COMPOUND ; + sachem:score ?SCORE + ] sachem:similaritySearch [ + sachem:query ?MOLFILE ; + sachem:cutoff "0.7"^^xsd:double ; + sachem:similarityRadius "3"^^xsd:integer ; + sachem:aromaticityMode sachem:aromaticityDetectIfMissing ; + sachem:tautomerMode sachem:inchiTautomers + ] . + } + } UNION { + SERVICE { + ?SIMILAR_COMPOUND sachem:substructureSearch [ + sachem:query "[As]" + ] . + } + } +} ORDER BY DESC(?SCORE) diff --git a/demonstrator/triple-oma-6.rq b/demonstrator/triple-oma-6.rq new file mode 100644 index 00000000..7a4b79df --- /dev/null +++ b/demonstrator/triple-oma-6.rq @@ -0,0 +1,41 @@ +# Datasources: https://sparql.omabrowser.org/sparql +PREFIX rdf: +PREFIX rdfs: +PREFIX owl: +PREFIX xsd: +PREFIX dc: +PREFIX dct: +PREFIX skos: +PREFIX obo: +PREFIX ensembl: +PREFIX oma: +PREFIX orth: +PREFIX sio: +PREFIX taxon: +PREFIX up: +PREFIX void: +PREFIX lscr: + +select ?protein2 ?OMA_LINK ?taxon_sci_name where { + + VALUES (?Uniprot_link) { ( ) } # here + #The three that contains Orthologs. The leafs are proteins. + #This graph pattern defines the relationship protein1 is Orthologs to protein2 + ?cluster a orth:OrthologsCluster. + ?cluster orth:hasHomologousMember ?node1. + ?cluster orth:hasHomologousMember ?node2. + ?node2 orth:hasHomologousMember* ?protein2. + ?node1 orth:hasHomologousMember* ?protein1. + ######## + + #Specify the protein to look for its orthologs + ?protein1 lscr:xrefUniprot ?Uniprot_link. + ######## + + #The OMA link to the second protein + ?protein2 rdfs:seeAlso ?OMA_LINK. + ?protein2 orth:organism/obo:RO_0002162/up:scientificName ?taxon_sci_name. + ######## + + filter(?node1 != ?node2) +} diff --git a/demonstrator/triple-rhea.rq b/demonstrator/triple-rhea-4.rq similarity index 100% rename from demonstrator/triple-rhea.rq rename to demonstrator/triple-rhea-4.rq diff --git a/demonstrator/triple-solid-2.rq b/demonstrator/triple-solid-2.rq new file mode 100644 index 00000000..286f294b --- /dev/null +++ b/demonstrator/triple-solid-2.rq @@ -0,0 +1,8 @@ +# Datasources: http://localhost:3000/test/Uploads/nbn-chist-era-annex-1-chemicals-alt.ttl +PREFIX thd: +SELECT DISTINCT ?CAS WHERE { + + # Solid pod data + ?SOLIDPOD thd:predicate ?CAS . + +} \ No newline at end of file diff --git a/demonstrator/triple-uniprot.rq b/demonstrator/triple-uniprot-5.rq similarity index 100% rename from demonstrator/triple-uniprot.rq rename to demonstrator/triple-uniprot-5.rq diff --git a/demonstrator/triple-wikidata.rq b/demonstrator/triple-wikidata-1.rq similarity index 100% rename from demonstrator/triple-wikidata.rq rename to demonstrator/triple-wikidata-1.rq diff --git a/package.json b/package.json index ca9fefd9..b0d34ff1 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,8 @@ "actor-query-process-remote-cache": "^0.1.0", "core-js": "^3.8.3", "fs": "^0.0.1-security", - "pinia": "^2.2.6", - "query-sparql-remote-cache": "^0.0.8", + "pinia": "^2.3.1", + "query-sparql-remote-cache": "^0.0.9", "sparqljs": "^3.7.3", "vite": "^6.2.3", "vue": "^3.2.13", diff --git a/src/assets/main.css b/src/assets/main.css index 4a0b1028..647824dc 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -1,5 +1,7 @@ +@import url('https://fonts.googleapis.com/css2?family=Oxanium:wght@200..800&display=swap'); + body { - background-color: #a9a7ad; + background-color: var(--bg); margin: 0; } @@ -8,7 +10,7 @@ body { flex-direction: column; min-height: 80vh; min-height: 80dvh; - color: #EDE7F6; /* This sets the text color inside the #app div to a dark grey */ + color: var(--text); } #footer { @@ -16,3 +18,7 @@ body { flex-direction: column; margin-top: auto; } + +.v-application, .v-overlay-container { + font-family: 'Oxanium', monospace; +} diff --git a/src/assets/theme.css b/src/assets/theme.css new file mode 100644 index 00000000..69e9bf9d --- /dev/null +++ b/src/assets/theme.css @@ -0,0 +1,144 @@ +:root { + --main: #445560; + --main-darker: #37474f; + --main-darker2: #28353e; + --main-gray: #bfbdc4; + --main-dark-gray: #1e1e1e; + --main-purple: #754ff6; + --main-purple-dark: #5728d9; + --main-purple-darker: #201054; + --main-white: #ede7f6; + --main-black: #000000; + + --purple: hsl(262 92% 65%); /* #8a42f4 */ + --teal: hsl(200 26% 26%); /* #344952 */ + --ink: hsl(210 15% 12%); /* #1a1f21 */ + --gray-50: hsl(260 20% 98%); /* #fafafc */ + --gray-100: hsl(255 18% 96%); /* #f3f2f8 */ + --gray-200: hsl(250 14% 90%); /* #e3e1e8 */ + --gray-300: hsl(240 10% 84%); /* #d2d1d8 */ + --gray-400: hsl(230 9% 70%); /* #adacb3 */ + --gray-500: hsl(220 8% 56%); /* #888990 */ + --gray-600: hsl(215 11% 40%); /* #5b6269 */ + --gray-700: hsl(210 15% 30%); /* #414b52 */ + --gray-800: hsl(205 18% 22%); /* #2d3a42 */ + --gray-900: hsl(200 20% 12%); /* #181e21 */ + + /* radii & shadow */ + --radius: 14px; + --shadow-1: 0 1px 2px hsl(0 0% 0% / 0.06), 0 1px 1px hsl(0 0% 0% / 0.04); /* #000000 */ + --shadow-2: 0 8px 24px hsl(220 40% 2% / 0.22), + 0 2px 8px hsl(220 40% 2% / 0.18); /* #040508 */ +} + +/* --------------------------- + Light theme (default) + --------------------------- */ +:root { + --bg: var(--gray-300); /* #d2d1d8 */ + --bg-secondary: var(--gray-400); /* #adacb3 */ + --panel: var(--main-gray); /* #ffffff */ + --panel-elev: var(--gray-200); + --muted: hsl(250 14% 90%); /* #e3e1e8 */ + --border: var(--main-white); + --text-primary: var(--gray-900); + --text-secondary: var(--ink); + --text-muted: hsl(215 11% 40%); /* #5b6269 */ + --primary: var(--main-purple); + --primary-600: hsl(262 92% 58%); /* #6f23ec */ + --primary-700: hsl(262 92% 52%); /* #5b09e5 */ + --primary-100: hsl(262 92% 95%); /* #f2ebfd */ + --accent: hsl(195 85% 48%); /* #1ba9e0 */ + --accent-100: hsl(195 85% 94%); /* #e4f6fc */ + --accent-700: hsl(195 85% 36%); /* #107eab */ + + --success: hsl(160 72% 42%); /* #1fba74 */ + --warning: #ffd904; /* #f7a611 */ + --danger: #ff7f7fbb; + --error: #ff1e00c2; + --info: hsl(195 85% 48%); /* #1ba9e0 */ + + --focus-ring: 2px solid hsl(262 92% 65% / 0.7); /* #8a42f4 */ + --hover: #764ff633; + --active: hsl(210 15% 12% / 0.08); /* #1a1f21 */ + + --yasqe-bg: var(--main-white); + --yasqe-bg-2: var(--gray-200); + --yasqe-keyword: #5f3df1; + --yasqe-atom: #865700; + --yasqe-variable-2: #1f6feb; + --yasqe-string: #2e7d32; + --yasqe-string-2: #d32f45; + --yasqe-variable-3: #0e8a6a; + --yasqe-number: #6e56cf; + --yasqe-comment: #6b7280; + --yasqe-operator: #0b7fd3; + --yasqe-meta: #8a6d1a; + --yasqe-matchhighlight-bg: #fff2a8; + --yasqe-cursor: #7b61ff; + --yasqe-selected: #a0a0d8; +} + +/* --------------------------- + Dark theme (stealth) + --------------------------- */ +:root[data-theme="dark"] { + --bg: hsl(200 26% 14%); /* #19262b */ + --bg-secondary: var(--main-darker); + --panel: hsl(200 20% 18%); /* #242e33 */ + --panel-elev: hsl(200 20% 22%); /* #2b3840 */ + --muted: hsl(200 14% 28%); /* #3c474c */ + --border: hsl(200 10% 34%); /* #4f585c */ + --text-primary: var(--gray-300); + --text-secondary: var(--main-white); + --text-muted: hsl(260 14% 72%); /* #b3b0be */ + --primary: var(--main-purple); + --primary-600: hsl(262 92% 58%); /* #6f23ec */ + --primary-700: hsl(262 92% 50%); /* #5605e0 */ + --primary-100: hsl(262 92% 20%); /* #1b023b */ + --accent: hsl(195 85% 48%); /* #1ba9e0 */ + --accent-100: hsl(195 85% 22%); /* #083a4d */ + --accent-700: hsl(195 85% 60%); /* #4dc0ec */ + + --success: hsl(160 72% 46%); /* #26c980 */ + --warning: #ffd700; + --danger: #ff7f7fbb; + --error: #ff1e00; + --info: hsl(195 85% 54%); /* #34b8e6 */ + + --focus-ring: 2px solid hsl(262 92% 65% / 0.8); /* #8a42f4 */ + --hover: hsl(0 0% 100% / 0.03); /* #ffffff */ + --active: hsl(0 0% 100% / 0.06); /* #ffffff */ + + --yasqe-bg: var(--ink); + --yasqe-bg-2: var(--main-darker2); + --yasqe-keyword: #c792ea; + --yasqe-atom: #f78c6c; + --yasqe-variable-2: #82aaff; + --yasqe-string: #c3e88d; + --yasqe-string-2: #ff5370; + --yasqe-variable-3: #a0fa87; + --yasqe-number: #ede7f6; + --yasqe-comment: #a9a7ad; + --yasqe-operator: #89ddff; + --yasqe-meta: #ffcb6b; + --yasqe-matchhighlight: #5f5f5f; + --yasqe-cursor: #ffcc00; + --yasqe-selected: #292929; +} + +/* sensible global defaults */ +:where(html, body) { + background: var(--bg); + color: var(--text); +} + +/* optional: smoothen transitions between themes */ +* { + transition: background-color 0.18s ease, color 0.18s ease, + border-color 0.18s ease; +} + +:root { + --v-font-family: "Oxanium", monospace; +} diff --git a/src/components/ContainerNav.vue b/src/components/ContainerNav.vue index 1a2609e2..f40eddc3 100644 --- a/src/components/ContainerNav.vue +++ b/src/components/ContainerNav.vue @@ -160,11 +160,16 @@ export default defineComponent({ list-style-type: none; padding-left: 1rem; margin-left: 0; + color: var(--text-secondary); } .dir-nav { padding: 1rem; } - +.dir-nav li { + display: flex; + justify-content: center; + align-items: center; +} .directory-nav span { font-size: 16pt; font-family: "Oxanium", monospace; @@ -181,17 +186,22 @@ export default defineComponent({ margin-left: 15px; gap: 20px; } - -.select-dir .v-btn { - margin-bottom: 15px; -} .select-dir .v-select { min-width: 150px; - margin-top: 15px; font-family: "Oxanium", monospace; } .navigate-btn { font-family: "Oxanium", monospace; - margin-top: 10px; + background-color: var(--primary); + color: var(--main-white); +} +.navigate-btn:hover { + background-color: var(--primary-700); +} +:deep(.v-input__details) { + display:none; +} +:deep(.v-field__loader) { + display:none; } diff --git a/src/components/DataQuery.vue b/src/components/DataQuery.vue index d2ae4512..e8b40a8e 100644 --- a/src/components/DataQuery.vue +++ b/src/components/DataQuery.vue @@ -10,14 +10,52 @@
- @@ -562,7 +537,6 @@ import Yasqe from "@triply/yasqe"; import "@triply/yasqe/build/yasqe.min.css"; import Yasr from "@triply/yasr"; import "@triply/yasr/build/yasr.min.css"; -import { isLoggedin } from "./login"; import { ensureCacheContainer, createQueriesTTL, @@ -578,25 +552,21 @@ import { CacheOutput, cleanSourcesUrls, QueryResultJson, + ComunicaSources, + executeQueryInMainThread, } from "./queryPod"; import { fetchPermissionsData, fetchAclAgents, fetchPublicAccess, } from "./getData"; -import { - changeAclAgent, - changeAclPublic, - checkUrl, - generateAcl, - createInboxWithACL, - updateSharedWithMe, - updateSharedWithOthers, -} from "./privacyEdit"; +import { deleteFromPod, deleteThing } from "./fileUpload"; +import { generateAcl } from "./privacyEdit"; import PodLogin from "./PodLogin.vue"; import PodRegistration from "./PodRegistration.vue"; import DataQueryGuide from "./Guides/DataQueryGuide.vue"; import { toRaw, shallowRef } from "vue"; +import { useAuthStore } from "../stores/auth"; export default { components: { @@ -610,8 +580,8 @@ export default { yasqe: shallowRef(null), yasr: shallowRef(null), resultsForYasr: null as QueryResultJson | null, + queryError: null as Error | null, successfulLogin: false as boolean, - currentPod: "" as string, currentView: "newQuery" as "newQuery" | "previousQueries", selectedExample: null as any, loadExampleQuery: false as boolean, @@ -668,8 +638,31 @@ export default { showResultQuery: false as boolean, cachedQueryIndex: null as number | null, worker: null as Worker | null, + containsSolidSources: false as boolean, + customCachePath: "" as string, + useCustomCachePath: false as boolean, + cacheError: null as string | null, + invalidUrl: false as boolean, + authenticationFailed: false as boolean, + deletedQuery: null as string | null, + deletionSuccess: null as boolean | null, + renderKey: 0 as number, }; }, + computed: { + authStore() { + return useAuthStore(); // Access the store + }, + loggedIn() { + return this.authStore.loggedIn; // Access loggedIn state + }, + webId() { + return this.authStore.webId; // Access webId state + }, + selectedPodUrl() { + return this.authStore.selectedPodUrl; // Access selected Pod URL + }, + }, methods: { handleDelay() { this.delay = false; @@ -726,7 +719,7 @@ export default { for (const path in demonstratorFiles) { const content = await demonstratorFiles[path](); - const lines = content.split("\n"); + const lines = (content as string).split("\n"); const name = path.split("/").pop()?.replace(".rq", "") || ""; let sources: string[] = []; @@ -765,20 +758,12 @@ export default { y.focus(); }, - /* Takes in the emitted value from PodLogin.vue */ - handleLoginStatus(loginSuccess) { - this.successfulLogin = loginSuccess; - }, - /* Checks if user is already logged in */ - loginCheck() { - this.successfulLogin = isLoggedin(); - }, - /* Takes in the emitted value from PodRegistration.vue */ - handlePodSelected(selectedPod) { - this.currentPod = selectedPod; - this.possibleSources.unshift(`<${this.currentPod}>`); + /* Determines whether sources contain a Solid source and reflects this in boolean */ + checkSolidSources(querySources: ComunicaSources[]) { + this.containsSolidSources = querySources.some( + (source) => source.context != null + ); }, - // Executes user provided query and saves it to querycache if specified async runExecuteQuery() { this.loading = true; @@ -789,25 +774,65 @@ export default { return; } + // make sources into a ComunicaSources[] + const cleanedSources = cleanSourcesUrls(this.currentQuery.sources); + this.checkSolidSources(cleanedSources); + try { + // reset query error + this.queryError = null; + // if Save Query box is selected (pod must be connected) if (this.saveQuery) { - this.cachePath = await ensureCacheContainer(this.currentPod); + // if the user provided a custom cache path, use that + if (this.useCustomCachePath && this.customCachePath) { + this.cachePath = await ensureCacheContainer( + this.selectedPodUrl, + this.webId, + this.customCachePath + ); + } else { + // otherwise use default (connected pod) + this.cachePath = await ensureCacheContainer( + this.selectedPodUrl, + this.webId, + this.selectedPodUrl + ); + } + + // Catch error with accessing custom query cache location + if (this.cachePath.includes("Error")) { + this.cacheError = + "Could not access or create query cache container. Please check the cache path and your pod permissions."; + this.loading = false; + return; + } + this.currentQuery.output = await executeQueryWithPodConnected( this.currentQuery.query, - this.currentQuery.sources, + cleanedSources, this.cachePath ); // If the output is a string, it means there was no matching entry in the cache - if (typeof this.currentQuery.output === "string") { - this.currentQuery.output = await this.executeQuery( - this.currentQuery.query, - this.currentQuery.sources - ); + if (this.currentQuery.output === "no-cache") { + // if there are NOT solid sources use the Worker + if (!this.containsSolidSources) { + this.currentQuery.output = await this.executeQuery( + this.currentQuery.query, + cleanedSources + ); + } else { + // if there are Solid sources, use custom execution in main thread + this.currentQuery.output = await executeQueryInMainThread( + this.currentQuery.query, + cleanedSources + ); + } } // obtaining query cache hash if the cache contains a similar query + // TODO: Fix getCacheEntryHash if ( this.currentQuery.output && this.currentQuery.output.provenanceOutput != null @@ -819,22 +844,13 @@ export default { ); } - // if the result of the query was null - if ( - !this.currentQuery.output.resultsOutput || - !this.currentQuery.output.resultsOutput.results - ) { - this.currentQuery.output.resultsOutput = { - head: { vars: [] }, - results: { bindings: [] }, - }; - } - // pass found results to YASR (with save query selected) this.resultsForYasr = this.currentQuery.output.resultsOutput; + this.currentQuery.output = toRaw(this.currentQuery.output); // If there is NOT an equivalent query in cache, then add it to cache if ( + this.currentQuery.output.provenanceOutput === null || this.currentQuery.output.provenanceOutput.algorithm != "equivalence" ) { this.currHash = await createQueriesTTL( @@ -854,32 +870,76 @@ export default { ); } } else { - // If the Save Query button was not selected - if (this.currentPod !== "") { - // if there is a pod connected, try to use cache - this.cachePath = await ensureCacheContainer(this.currentPod); + // If the Save Query button was not selected (pod is connected) + if (this.selectedPodUrl !== "" || this.customCachePath !== "") { + // if the user provided a custom cache path, use that + if (this.useCustomCachePath && this.customCachePath) { + this.cachePath = await ensureCacheContainer( + this.selectedPodUrl, + this.webId, + this.customCachePath + ); + } else { + // otherwise use default (connected pod) + this.cachePath = await ensureCacheContainer( + this.selectedPodUrl, + this.webId, + this.selectedPodUrl + ); + } + + // Catch error with accessing custom query cache location + if (this.cachePath.includes("Error")) { + this.cacheError = + "Could not access or create query cache container. Please check the cache path and your pod permissions."; + this.loading = false; + return; + } + + // Execute Query this.currentQuery.output = await executeQueryWithPodConnected( this.currentQuery.query, - this.currentQuery.sources, + cleanedSources, this.cachePath ); // If the output is a string, it means there was no matching entry in the cache - if (typeof this.currentQuery.output === "string") { + if (this.currentQuery.output === "no-cache") { + // if there are NOT solid sources use the Worker + if (!this.containsSolidSources) { + this.currentQuery.output = await this.executeQuery( + this.currentQuery.query, + cleanedSources + ); + } else { + // if there are Solid sources, use custom execution in main thread + this.currentQuery.output = await executeQueryInMainThread( + this.currentQuery.query, + cleanedSources + ); + } + } + } else { + // if there is NO pod connected, use the default query execution + this.cacheError = this.currentQuery.output; + + // if there are NOT solid sources --> use the Worker + if (!this.containsSolidSources) { this.currentQuery.output = await this.executeQuery( this.currentQuery.query, - this.currentQuery.sources + cleanedSources + ); + } else { + // if there are Solid sources, use custom execution in main thread + this.currentQuery.output = await executeQueryInMainThread( + this.currentQuery.query, + cleanedSources ); } - } else { - // if there is no pod connected, use the default query execution - this.currentQuery.output = await this.executeQuery( - this.currentQuery.query, - this.currentQuery.sources - ); } // try to obtain cache hash if the cache contains a similar query + // TODO: Fix getCacheEntryHash if ( this.currentQuery.output && this.currentQuery.output.provenanceOutput != null @@ -890,7 +950,12 @@ export default { this.currentQuery.output.provenanceOutput.id.value ); } - + } + // if there was an error report it here + if (this.currentQuery.output instanceof Error) { + this.queryError = this.currentQuery.output.message; + } else { + // if the query was empty assign it empty bindings if ( !this.currentQuery.output.resultsOutput || !this.currentQuery.output.resultsOutput.results @@ -900,9 +965,9 @@ export default { results: { bindings: [] }, }; } - // pass found results to YASR (if save query was not selected) - this.resultsForYasr = this.currentQuery.output.resultsOutput; } + // pass found results to YASR (if save query was not selected) + this.resultsForYasr = this.currentQuery.output.resultsOutput; } catch (err) { if (this.cancelRequested) { console.log("Query canceled by user."); @@ -922,16 +987,15 @@ export default { */ async executeQuery( query: string, - providedSources: string[] - ): Promise { + providedSources: ComunicaSources[] + ): Promise { this.cancelRequested = false; - const cleanedSources = cleanSourcesUrls(providedSources); this.worker = new Worker(new URL("./queryWorker.js", import.meta.url), { type: "module", }); - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { this.worker!.onmessage = (e: MessageEvent) => { const { data } = e as { data: any }; switch (data?.type) { @@ -943,9 +1007,8 @@ export default { }); break; case "error": - console.log("Worker error:", data.error); this.cleanupWorker(); - resolve(null); // or reject(data.error) if you prefer + resolve(new Error(data.error.message)); // or reject(data.error) if you prefer break; case "cancelled": this.cleanupWorker(); @@ -958,15 +1021,14 @@ export default { }; // for an error or cancellation this.worker!.onerror = (err) => { - console.log("Worker error:", err); this.cancelQuery(); - reject(err); + resolve(err as any); }; // starts a run this.worker.postMessage({ type: "run", query, - sources: cleanedSources, + sources: providedSources, }); }); }, @@ -1064,6 +1126,56 @@ export default { ); }, + // Methods for the deletion of a query cache entry + async confirmAndDelete(queryHash: string) { + const queryFile = `${this.selectedPodUrl}querycache/${queryHash}.rq`; + const resultsFile = `${this.selectedPodUrl}querycache/${queryHash}.json`; + + const message = + "Are you sure you want to delete this cache entry? This action cannot be undone."; + const userConfirmed = window.confirm(message); + + if (userConfirmed) { + const removedCacheRecord = await this.removeCachedRecord(queryHash); + const removedQuery = await this.deleteResource(queryFile); + const removedResults = await this.deleteResource(resultsFile); + + if (removedCacheRecord && removedQuery && removedResults) { + this.deletionSuccess = true; + await this.loadCache(); // Refresh the cache view + this.deletedQuery = queryHash; + this.renderKey += 1; // Force re-render + } else { + this.deletionSuccess = false; + console.log("Failed to delete one or more components of the cache entry."); + } + } else { + console.log("Deletion canceled by the user."); + } + }, + + /* + Deleted the resource at the given URL. + */ + async deleteResource(fileUrl: string): Promise { + try { + return await deleteFromPod(fileUrl); + } catch (err) { + console.error(`Error deleting resource: ${fileUrl}`, err); + alert(`An error occurred while deleting resource: ${fileUrl}`); + return false; + } + }, + + async removeCachedRecord(queryHash: string) { + // remove the record from queries.ttl + const queriesttlUpdate = await deleteThing( + this.selectedPodUrl + "querycache/queries.ttl", + queryHash + ); + return queriesttlUpdate; + }, + // TODO: Sharing of query results (maybe just the whole container?) async previousQueriesView() { @@ -1072,12 +1184,12 @@ export default { }, async loadCache() { this.queriesCacheExists = await getStoredTtl( - this.currentPod + "querycache/queries.ttl" + this.selectedPodUrl + "querycache/queries.ttl" ); if (this.queriesCacheExists) { try { this.cachedQueries = await getCachedQueries( - this.currentPod + "querycache/queries.ttl" + this.selectedPodUrl + "querycache/queries.ttl" ); } catch (err) { console.log("Error fetching queries:", err); @@ -1094,18 +1206,16 @@ export default { this.showRetrievedQuery = !this.showRetrievedQuery; }, // retrieves cached results for display - async fetchResults(hash: string) { + async fetchResults(hash: string, cacheLoc: string) { const retrievedQueryResults = await fetchSparqlJsonFileData( - `${this.currentPod}querycache/${hash}.json` + `${cacheLoc}/${hash}.json` ); this.retrievedResults = toRaw(retrievedQueryResults); this.togglRetrievedResults(); }, // retrieves cached query for display - async fetchQuery(hash: string) { - this.retrievedQuery = await fetchQueryFileData( - `${this.currentPod}querycache/${hash}.rq` - ); + async fetchQuery(hash: string, cacheLoc: string) { + this.retrievedQuery = await fetchQueryFileData(`${cacheLoc}/${hash}.rq`); this.togglRetrievedQuery(); }, @@ -1115,7 +1225,7 @@ export default { * @param path the URL of the resource or container for which access rights are to be displayed */ async getSpecificCacheAclData() { - const cacheUrl = this.currentPod + "querycache/"; + const cacheUrl = this.selectedPodUrl + "querycache/"; this.hasAcl = await fetchPermissionsData(cacheUrl); // value is either .acl obj OR null (if .acl does not exist) if (this.hasAcl !== null) { this.hasAccess = await fetchAclAgents(cacheUrl); @@ -1133,7 +1243,7 @@ export default { * @param path the URL of the resource or container for which access rights are to be displayed */ async getSpecificQueryAclData(queryHash: string) { - const queryUrl = this.currentPod + "querycache/" + queryHash; + const queryUrl = this.selectedPodUrl + "querycache/" + queryHash; this.hasAcl = await fetchPermissionsData(queryUrl); // value is either .acl obj OR null (if .acl does not exist) if (this.hasAcl !== null) { this.hasAccess = await fetchAclAgents(queryUrl); @@ -1151,7 +1261,7 @@ export default { * @param path the URL of the resource or container for which an .acl is to be made */ async makeNewAcl() { - const cacheUrl = this.currentPod + "querycache/"; + const cacheUrl = this.selectedPodUrl + "querycache/"; try { await generateAcl(cacheUrl, this.webId); await this.getSpecificCacheAclData(); @@ -1171,6 +1281,18 @@ export default { } return prefixes; }, + validateCustomCachePath() { + if (this.useCustomCachePath && this.customCachePath) { + try { + new URL(this.customCachePath); + this.cacheError = null; // Clear error if valid + } catch { + this.cacheError = "Invalid URL. Please enter a valid URL."; + } + } else { + this.cacheError = null; // Clear error if not using custom path + } + }, }, watch: { currentQuery: { @@ -1205,14 +1327,10 @@ export default { showQueryButton: false, }); this.yasqe.setValue(this.currentQuery.query); - this.yasqe.on("change", (instance) => { this.currentQuery.query = instance.getValue(); }); - setTimeout(() => { - this.loginCheck(); - }, 500); setTimeout(() => { this.handleDelay(); }, 520); @@ -1232,7 +1350,7 @@ body { padding: 20px; background: #445560; border-radius: 10px; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow-1); } .tool-tip { font-family: "Oxanium", monospace; @@ -1240,7 +1358,7 @@ body { /* Title bar */ .title-container { - background-color: #445560; + background-color: var(--bg-secondary); border-radius: 8px; margin: 0.5rem 0.5rem 0 0.5rem; } @@ -1250,6 +1368,7 @@ body { font-weight: 500; padding-left: 20px; padding-right: 20px; + color: var(--text-primary); } .login-container { margin: 0.5rem 0.25rem 0 0.25rem; @@ -1258,7 +1377,7 @@ body { /* loading spinner for login-check */ .loading-spinner-container { display: flex; - background-color: #445560; + background-color: var(--panel); border-radius: 6px; align-items: center; justify-content: flex-start; @@ -1272,28 +1391,72 @@ body { font-size: 1.25rem; font-weight: 600; letter-spacing: 0.5px; + color: var(--text-primary); } /* Container pod-chooser bar */ .pod-chooseContainer { - background: #445560; - border-radius: 8px; + background: var(--bg-secondary); + border-radius: 6px; padding: 0 0 0 1rem; margin: 0.5rem 0.5rem 0 0.5rem; } - +.custom-cache-container { + background-color: var(--bg-secondary); + margin: 0 0.5rem 0 0.5rem; + border-radius: 6px; +} +.custom-cache-path { + display: flex; + font-family: "Oxanium", monospace; + align-items: center; + justify-content: flex-start; + gap: 8px; +} +.custom-cache-guide { + margin-left: 1rem; + color: var(--text-muted); +} +.custom-cache-checkbox { + min-width: fit-content; + margin-left: 1rem; + padding: 0 0.5rem; + color: var(--text-secondary); +} +.custom-cache-input { + width: 100%; + margin-right: 1rem; + padding: 0.5rem; + color: var(--text-secondary); +} +.custom-cache-error { + display: flex; + font-family: "Oxanium", monospace; + padding: 0.5rem 0; + justify-content: center; +} +.custom-cache-error span { + padding: 0.5rem; + border-radius: 6px; + background-color: var(--danger); + color: var(--main-white); +} /* Whole nav and query container */ .general-container { - background-color: #445560; + background-color: var(--bg-secondary); border-radius: 8px; margin: 0.5rem; display: flex; } /* Left nav bar */ +.general-container :deep(.v-input__details) { + display: none !important; +} .nav-container { display: flex; - background-color: #28353e; + background-color: var(--panel); + border: 2px solid var(--border); border-radius: 8px; font-family: "Oxanium", monospace; font-size: 14pt; @@ -1304,37 +1467,38 @@ body { padding: 10px; height: 100%; overflow: auto; + color: var(--text-secondary); } .nav-container li span { font-size: 18pt; font-weight: bold; padding: 10px 8px 4px 8px; text-decoration: none; - border-bottom: 1px solid #ccc; + border-bottom: 1px solid var(--border); } #top-button { margin-top: 10px; } .nav-container li button { display: block; - color: #ede7f6; + color: var(--text-secondary); width: 100%; border-radius: 4px; padding: 0.8rem 1.2rem; text-decoration: none; } .nav-container li button.active { - background-color: #04aa6d; - color: white; + background-color: var(--success); + color: var(--main-white); } .nav-container li button:hover:not(.active) { - background-color: #555; - color: white; + background-color: var(--hover); + color: var(--text-muted); width: 100%; } .nav-container .highlight { - background-color: #754ff6; - color: #ede7f6; + background-color: var(--primary); + color: var(--main-white); } /* Query elements */ @@ -1370,6 +1534,7 @@ body { display: flex; align-items: center; justify-content: space-between; + color: var(--text-secondary); } .top-container .top-label span { display: flex; @@ -1384,76 +1549,83 @@ body { } /* Query Container Customizations */ #yasqe-container { - border: 3px solid #1e1e1e; + border: 3px solid var(--yasqe-bg); border-radius: 8px; margin-bottom: 1rem; } #yasqe-container :deep(.CodeMirror-gutters) { - background-color: #1e1e1e; + background-color: var(--yasqe-bg); } #yasqe-container :deep(.resizeWrapper) { - background-color: #1e1e1e; + background-color: var(--yasqe-bg); } #yasqe-container :deep(.CodeMirror) { - background-color: #28353e; - border: 1px solid #1e1e1e; + background-color: var(--yasqe-bg-2); + border: 1px solid var(--yasqe-bg); color: #ede7f6; } #yasqe-container :deep(.CodeMirror-linenumber) { padding: 0; } #yasqe-container :deep(.notification.notif_property) { - background-color: #28353e; + background-color: var(--yasqe-bg); padding: 0; color: #a9a7ad; } #yasqe-container :deep(.notification.active) { - background-color: #28353e; + background-color: var(--yasqe-bg); padding: 0; - color: #a9a7ad; + color: var(--text-muted); } #yasqe-container :deep(.yasqe_buttons) { display: none; } /* TODO: Change colors to look nicer */ #yasqe-container :deep(.cm-keyword) { - color: #c792ea; /* Example: purple for keywords like SELECT, WHERE */ + color: var( + --yasqe-keyword + ); /* Example: purple for keywords like SELECT, WHERE */ } #yasqe-container :deep(.cm-atom) { - color: #f78c6c; /* Example: orange for atoms like 'a' */ + color: var(--yasqe-atom); /* Example: orange for atoms like 'a' */ } #yasqe-container :deep(.cm-variable-2) { - color: #82aaff; /* Example: blue for variables like ?s */ + color: var(--yasqe-variable-2); /* Example: blue for variables like ?s */ } #yasqe-container :deep(.cm-string) { - color: #c3e88d; /* Example: green for string literals */ + color: var(--yasqe-string); /* Example: green for string literals */ } #yasqe-container :deep(.cm-string-2) { - color: #ff5370; /* Example: red for IRI's like */ + color: var(--yasqe-string-2); /* Example: red for IRI's like */ } #yasqe-container :deep(.cm-variable-3) { - color: #a0fa87; /* Example: red for IRI's like */ + color: var(--yasqe-variable-3); /* Example: red for IRI's like */ } #yasqe-container :deep(.cm-number) { - color: #ede7f6; /* Example: red for IRI's like */ + color: var(--yasqe-number); /* Example: red for IRI's like */ } #yasqe-container :deep(.cm-comment) { - color: #a9a7ad; /* Example: grey for comments */ + color: var(--yasqe-comment); /* Example: grey for comments */ } #yasqe-container :deep(.cm-operator) { - color: #89ddff; /* Example: light blue for operators */ + color: var(--yasqe-operator); /* Example: light blue for operators */ } #yasqe-container :deep(.cm-meta) { - color: #ffcb6b; /* Example: yellow for PREFIX */ + color: var(--yasqe-meta); /* Example: yellow for PREFIX */ +} +#yasqe-container :deep(.cm-punc) { + color: var(--text-primary); /* Example: yellow for PREFIX */ } #yasqe-container :deep(.cm-matchhighlight) { - background-color: #5f5f5f; /* Example: yellow for PREFIX */ + background-color: var( + --yasqe-matchhighlight + ); /* Example: yellow for PREFIX */ } #yasqe-container :deep(.CodeMirror-cursor) { - border-left: 1px solid #ffcc00; /* Example: yellow cursor */ + border-left: 1px solid var(--yasqe-cursor); /* Example: yellow cursor */ } #yasqe-container :deep(.CodeMirror-selected) { - background: #545454; /* Example: dark grey for selection */ + background: var(--yasqe-selected); /* Example: dark grey for selection */ } /* source designation */ @@ -1462,12 +1634,14 @@ body { align-items: center; border-radius: 4px; margin: 0.2rem 0.2rem 0.4rem 0.2rem; - outline: #28353e 3px solid; + outline: 3px solid var(--yasqe-bg); + color: var(--text-secondary); } .source-selection span { font-size: 16pt; font-weight: 600; padding: 4px 8px 4px 8px; + color: var(--text-secondary); } .source-selection .autocomplete { padding: 0; @@ -1495,36 +1669,41 @@ body { /* execute */ .execute-button { padding: 8px 14px; - border: 2px solid #28353e; + border: 2px solid var(--yasqe-bg); border-radius: 8px; + color: var(--text-secondary); } .cancel-query { padding: 8px 14px; - border: 2px solid #28353e; + border: 2px solid var(--yasqe-bg); border-radius: 8px; + color: var(--text-secondary); } .query-container .execute-button:hover { - background-color: #754ff6; + background-color: var(--primary); + color: var(--main-white); } .query-container .execute-button:disabled { - background-color: #888; + background-color: var(--text-muted); cursor: not-allowed; } .sparql-guide { padding-left: 0.5rem; margin-left: auto; + color: var(--text-muted); } .clear-button { padding: 8px 14px; margin-right: 1rem; - border: 2px solid #28353e; + border: 2px solid var(--yasqe-bg); border-radius: 8px; + color: var(--text-secondary); } .query-container .clear-button:hover { - background-color: #ff7f7fbb; + background-color: var(--danger); } .query-container .clear-button:disabled { - background-color: #888; + background-color: var(--text-muted); cursor: not-allowed; } .save-query { @@ -1532,16 +1711,18 @@ body { align-items: center; margin-left: 1rem; gap: 1rem; + color: var(--text-secondary); } .save-checkbox { padding: 0px 0px 0px 20px; } .save-info { padding: 0px 0px 0px 10px; - color: #a9aeb1; + color: var(--text-muted); } /* message in past queries when no pod is connected */ .no-pod { + color: var(--text-secondary); display: block; text-align: center; font-size: 1.2rem; @@ -1550,7 +1731,7 @@ body { /* Past Queries Display */ .query-catalog { - background-color: #445560; + background-color: var(--panel); border-radius: 8px; margin-top: 10px; display: flex; @@ -1574,9 +1755,14 @@ body { .cached-title { font-size: 24px; font-weight: bold; - color: #ede7f6; + color: var(--text-secondary); margin-bottom: 20px; } +.no-cached-queries { + color: var(--text-secondary); + font-size: 1.2rem; + padding: 2rem; +} /* Query List Items */ ul { list-style: none; @@ -1587,14 +1773,14 @@ ul { display: flex; flex-direction: column; width: 100%; - background-color: #28353e; + background-color: var(--bg); border-radius: 8px; padding: 16px; margin: 10px 0; transition: all 0.3s ease-in-out; } .folder:hover { - background-color: #37474f; + background-color: var(--panel); cursor: pointer; } /* Folder Header */ @@ -1620,7 +1806,7 @@ ul { font-family: "Oxanium", monospace; font-size: large; font-weight: 600; - color: white; + color: var(--text-secondary); transition: background 0.3s ease-in-out; } /* Ensure full-width coverage */ @@ -1648,26 +1834,26 @@ ul { flex-grow: 1; text-align: left; padding-left: 10px; - color: #ede7f6; + color: var(--text-secondary); } .card-panel .not-colored { - color: #ede7f6; + color: var(--text-secondary); } /* Query Details (Hidden by Default) */ .specific-query { display: flex; flex-direction: column; justify-content: space-between; - background: #1e1e1e; + background: var(--panel); padding: 10px; margin-top: 10px; border-radius: 5px; - color: white; + color: var(--text-secondary); } /* Query Details Spacing */ .specific-query div { padding: 8px; - border-bottom: 1px solid #444; + border-bottom: 1px solid var(--border); } .specific-query div:last-child { border-bottom: none; @@ -1675,11 +1861,11 @@ ul { /* Query Labels */ .user-tag { font-weight: bold; - color: #ede7f6; + color: var(--text-secondary); } /* Query Data */ .the-user { - color: #90caf9; + color: var(--yasqe-variable-2); font-style: italic; } /* Query Sources */ @@ -1690,12 +1876,24 @@ ul { list-style-type: disc; } .query-sources a { - color: #ffab40; + color: var(--yasqe-keyword); text-decoration: none; } .query-sources a:hover { text-decoration: underline; } +.edit-delete { + margin: 0.5rem 0 0 0; +} +.delete-button { + background-color: var(--danger); + border-radius: 6px; + padding: 0.5rem 0.75rem !important; +} +.delete-button:hover { + background-color: var(--hover); +} + /* Displayed SPARQL query from .rq file */ .query-file-info { @@ -1710,15 +1908,15 @@ ul { } /* SPARQL Code Box */ .sparql-box { - background-color: #1e1e1e; - color: #dcdcdc; + background-color: var(--bg); + color: var(--text-secondary); padding: 15px; border-radius: 6px; font-family: "Courier New", monospace; font-size: 14px; overflow-x: auto; max-height: 250px; - border-left: 4px solid #754ff6; + border-left: 4px solid var(--primary); } /* Syntax Formatting */ .sparql-box pre { @@ -1729,7 +1927,7 @@ ul { .sparql-box code { display: block; padding: 5px; - color: #ede7f6; + color: var(--text-secondary); } /* Displayed query results from .json file */ .query-results { @@ -1737,6 +1935,29 @@ ul { justify-content: space-between; width: 100%; } +/* Deletion success pop-up */ +.success-popup { + font-family: "Oxanium", monospace; + position: fixed; + top: 20px; + right: 20px; + background-color: var(--success); + color: var(--main-white); + padding: 1rem; + border-radius: 8px; + z-index: 1000; + display: flex; + align-items: center; + justify-content: space-between; + box-shadow: var(--shadow-1); +} +.close-popup-button { + background: none; + border: none; + color: var(--main-white); + cursor: pointer; + margin-left: 1rem; +} /* Container for the Table */ .results-container { @@ -1746,9 +1967,9 @@ ul { border-radius: 6px; margin: 0 0.5rem 0.5rem 0.5rem; padding: 1rem; - background-color: #28353e; - color: #ede7f6; - scrollbar-color: #a9a7ad #1e1e1e; + background-color: var(--bg-secondary); + color: var(--text-secondary); + scrollbar-color: dark; scrollbar-width: thin; } /* Loading Spinner */ @@ -1778,6 +1999,18 @@ ul { } } +/* No results */ +.null-results { + font-family: "Oxanium", monospace; + color: var(--text-secondary); + font-size: 14pt; + padding: 0.25rem; + text-align: center; +} +.null-results b { + color: var(--error); +} + /* Results */ .results-container .results-text { font-size: 18pt; @@ -1789,12 +2022,12 @@ ul { /* YASR Results Display Customizations */ #yasr-container :deep(.yasr) { font-family: "Oxanium", monospace; - background-color: #1e1e1e; - color: #ede7f6 !important; + background-color: var(--yasqe-bg); + color: var(--text-secondary) !important; border-radius: 8px; padding: 0; margin-top: 0.5rem; - border: 2px solid #1e1e1e; + border: 2px solid var(--border); } #yasr-container :deep(.grip-container) { padding-top: 0.4rem; @@ -1816,25 +2049,25 @@ ul { border-bottom: none; } #yasr-container :deep(.yasr_btn) { - color: #a9a7ad; + color: var(--text-secondary); } #yasr-container :deep(.yasr_btn.select_table.selected) { - color: #ede7f6 !important; - border-bottom: 3px solid #5728d9; + color: var(--text-secondary) !important; + border-bottom: 3px solid var(--primary); } #yasr-container :deep(.yasr_btn.select_response.selected) { - color: #ede7f6 !important; - border-bottom: 3px solid #5728d9; + color: var(--text-secondary) !important; + border-bottom: 3px solid var(--primary); } #yasr-container :deep(.yasr_btnGroup) { - color: #ede7f6 !important; + color: var(--text-secondary) !important; } #yasr-container :deep(.yasr_download_control) { margin-left: auto; } #yasr-container :deep(.tableControls div) { padding: 0 1rem 0 1.5rem; - border-left: 1px solid #f8f8f8; + border-left: 1px solid var(--bg-secondary); } #yasr-container :deep(.yasr_plugin_control label span) { margin: 0 0.5rem 0 0; @@ -1842,29 +2075,29 @@ ul { #yasr-container :deep(.tableFilter) { padding: 0 0.5rem 0 0.5rem; margin-right: 0; - color: #ede7f6; - border-left: 1px solid #f8f8f8; + color: var(--text-secondary); + border-left: 1px solid var(--bg-secondary); text-align: center !important; } #yasr-container :deep(.pageSizeWrapper) { padding: 0 1rem 0 1.5rem !important; text-align: center !important; - border-right: 1px solid #f8f8f8; + border-right: 1px solid var(--bg-secondary); } #yasr-container :deep(.pageSizeWrapper select) { padding: 0; text-align: center !important; - color: #ede7f6; - background-color: #1e1e1e; + color: var(--text-secondary); + background-color: var(--yasqe-bg); } #yasr-container :deep(.yasr_external_ref_btn) { display: none; } #yasr-container :deep(.yasr_btn) { - color: #a9a7ad; + color: var(--text-secondary); } #yasr-container :deep(.yasr_btnGroup) { - color: #ede7f6 !important; + color: var(--text-secondary) !important; } #yasr-container :deep(.yasr_response_chip) { display: none; @@ -1880,22 +2113,22 @@ ul { margin-bottom: 1rem; } #yasr-container :deep(ul.yasr_tabs li) { - background-color: #445560; - border: 1px solid #1e1e1e !important; + background-color: var(--bg); + border: 1px solid var(--border) !important; border-radius: 4px !important; margin-right: 0.5rem; } #yasr-container :deep(ul.yasr_tabs li.active) { - background-color: #754ff6; + background-color: var(--muted); } #yasr-container :deep(ul.yasr_tabs li span) { - color: #ede7f6 !important; + color: var(--text-secondary) !important; } /* Table results */ #yasr-container :deep(.yasr_results) { border-radius: 6px; overflow-x: auto; - scrollbar-color: #a9a7ad #1e1e1e; + scrollbar-color: dark; scrollbar-width: thin; } #yasr-container :deep(.dataTable) { @@ -1903,8 +2136,8 @@ ul { min-width: 100%; } #yasr-container :deep(thead tr th) { - background-color: #5728d9; - color: #ede7f6; + background-color: var(--primary); + color: var(--main-white); font-weight: bold; font-size: 13pt; padding: 12px 15px; @@ -1913,19 +2146,19 @@ ul { white-space: normal; } #yasr-container :deep(tbody tr:nth-child(even)) { - background-color: #445560; + background-color: var(--bg); } #yasr-container :deep(tbody tr:nth-child(odd)) { - background-color: #2c363d; + background-color: var(--panel); } #yasr-container :deep(tbody tr:hover) { - background-color: #201054; + background-color: var(--border); cursor: pointer; } #yasr-container :deep(tbody tr td) { padding: 12px 15px; border: none; - border-top: 1px solid #4a4a4a; + border-top: 1px solid var(--border); white-space: normal; /* Allow cell content to wrap */ overflow-wrap: break-word; /* Break long words to prevent overflow */ } @@ -1933,34 +2166,34 @@ ul { border-top: none; } #yasr-container :deep(tbody tr td .nonIri) { - color: #ede7f6; + color: var(--text-secondary); } #yasr-container :deep(tbody tr td .iri) { - color: #ffab40; + color: var(--yasqe-keyword); } #yasr-container :deep(.CodeMirror-lines) { - background-color: #28353e; + background-color: var(--panel); text-decoration: none; } #yasr-container :deep(.CodeMirror-gutters) { - background-color: #1e1e1e; + background-color: var(--yasqe-bg); } #yasr-container :deep(.resizeWrapper) { - background-color: #1e1e1e; + background-color: var(--yasqe-bg); } #yasr-container :deep(.CodeMirror) { - background-color: #28353e; - border: 1px solid #1e1e1e; - color: #ede7f6; + background-color: var(--panel); + border: 1px solid var(--yasqe-bg); + color: var(--text-secondary); } #yasr-container :deep(.CodeMirror-linenumber) { padding: 0; } #yasr-container :deep(.cm-string) { - color: #baa6fc; /* Example: green for string literals */ + color: var(--yasqe-string); /* Example: green for string literals */ } #yasr-container :deep(.cm-property) { - color: #ff5370; /* Example: red for IRI's like */ + color: var(--yasqe-keyword); /* Example: red for IRI's like */ } #yasr-container :deep(.overlay_content) { border-radius: 6px; @@ -1969,30 +2202,30 @@ ul { border-radius: 6px; } #yasr-container ::selection { - background: #5f5f5f; /* highlight background */ - color: #ede7f6; /* highlighted text color */ + background: var(--yasqe-selected); /* highlight background */ + color: var(--yasqe-number); /* highlighted text color */ } #yasr-container :deep(.dataTables_info) { padding-left: 0.5rem; - color: #a9a7ad; + color: var(--text-muted); } #yasr-container :deep(.paginate_button) { - color: #a9a7ad !important; + color: var(--text-muted) !important; } .cache-header { font-family: "Oxanium", monospace; display: flex; align-items: center; - background-color: #444; + background-color: var(--panel); border-radius: 6px; } .query-hash { display: flex; margin-right: auto; margin-left: 2rem; - color: #90caf9; + color: var(--yasqe-keyword); font-style: italic; font-size: 16pt; } @@ -2035,35 +2268,35 @@ ul { } /* Header Styling */ .result-table th { - background-color: #754ff6; - color: EDE7F6; + background-color: var(--primary); font-weight: bold; + color: var(--main-white); } /* Alternate Header colors */ .result-table th:nth-child(even) { - background-color: #5423f6; + background-color: var(--primary-600); } /* Alternating Row Colors */ .result-table tr:nth-child(even) { - background-color: #445560; /* Slightly lighter shade */ + background-color: var(--bg); } .result-table tr:nth-child(odd) { - background-color: #2c363d; /* Slightly lighter shade */ + background-color: var(--panel-elev); } /* Hover Effect */ .result-table tr:hover { - background-color: #201054; /* Light blue highlight */ + background-color: var(--hover); /* Light blue highlight */ cursor: pointer; } /* Sharing of a cached query */ .sharing-prompt { - background-color: #0d1115; + background-color: var(--bg-secondary); border-radius: 8px; - margin-top: 0.25rem; + margin-top: 0.5rem; } .sharing-prompt:hover { - background-color: #764ff633; + background-color: var(--hover); transition: background-color 0.2s ease; } .sharing-button { @@ -2075,7 +2308,7 @@ ul { .new-acl { padding: 0.25rem; margin-top: 5px; - background-color: #ede7f6; + background-color: var(--bg-secondary); color: #445560; border: none; cursor: pointer; diff --git a/src/components/EditPrivacy.vue b/src/components/EditPrivacy.vue index 0012fca9..a354144f 100644 --- a/src/components/EditPrivacy.vue +++ b/src/components/EditPrivacy.vue @@ -6,7 +6,7 @@ /> -
+
@@ -29,11 +146,11 @@
- +
-
+
  • @@ -86,7 +203,7 @@
  • @@ -96,9 +213,16 @@
    • -
      +
      +
      + Loading access rights... +
      +
      content_copy - Copy WebID to clipboard @@ -174,6 +304,7 @@ 'true-color': permission, 'false-color': !permission, }" + :key="renderKey" > {{ ind }} @@ -228,7 +359,10 @@ @@ -238,7 +372,10 @@ v-model="permissions.append" /> Append - Add to to existing content @@ -248,7 +385,10 @@ v-model="permissions.write" /> Write - Change existing content + create new content @@ -258,7 +398,10 @@ v-model="permissions.control" /> Control - Change .acl permissions for the resource @@ -274,7 +417,10 @@ :class="{ highlight: accessType === 'Agent' }" > Agent - Change access for a specific WebId @@ -286,7 +432,10 @@ :class="{ highlight: accessType === 'Public' }" > Public - Change access for anyone @@ -429,11 +578,10 @@
      -
      @@ -442,7 +590,7 @@
      @@ -451,37 +599,12 @@
      - -
      -

      Privacy Editing Guide

      - -
      -
        -
      1. Select the Pod you want to Browse.
      2. - -
      3. - Use the nav bar above the container/resource list to navigate between - containers -
      4. - -
      5. - Click the lock next to a container or - resource to see current access rights -
      6. -
      7. - Select the "Add access rights +" section to adjust access for a - provided WebID -
      8. -
      9. - Future work: The left nav bar pages, add filter functionality, and - functionality to the info/notifications icons -
      10. -
      -
      +
      diff --git a/src/components/Guides/DataPrivacyGuide.vue b/src/components/Guides/DataPrivacyGuide.vue deleted file mode 100644 index e69de29b..00000000 diff --git a/src/components/Guides/DataQueryGuide.vue b/src/components/Guides/DataQueryGuide.vue index 7713f9d4..f0bc8a17 100644 --- a/src/components/Guides/DataQueryGuide.vue +++ b/src/components/Guides/DataQueryGuide.vue @@ -37,7 +37,7 @@ + + diff --git a/src/components/Guides/LandingGuide.vue b/src/components/Guides/LandingGuide.vue index 05a7a726..1c35fb42 100644 --- a/src/components/Guides/LandingGuide.vue +++ b/src/components/Guides/LandingGuide.vue @@ -443,11 +443,11 @@ export default { diff --git a/src/components/Guides/PrivacyEditingGuide.vue b/src/components/Guides/PrivacyEditingGuide.vue new file mode 100644 index 00000000..4f92dcab --- /dev/null +++ b/src/components/Guides/PrivacyEditingGuide.vue @@ -0,0 +1,119 @@ + + + + + diff --git a/src/components/LandingPage.vue b/src/components/LandingPage.vue index 133c062a..e6dbf054 100644 --- a/src/components/LandingPage.vue +++ b/src/components/LandingPage.vue @@ -2,12 +2,8 @@
      - Full Solid Cockpit logo + Full Solid Cockpit logo
      -
      @@ -15,16 +11,21 @@
      +
      + +
      +
      @@ -70,27 +79,12 @@ img { text-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } .login-container { - margin: 0 0.5rem 0.5rem 0.5rem; - -} -.pod-reg { - background-color: #445560; - border-radius: 8px; - max-width: 100%; - margin: 0.5rem 1rem; - padding: 0.2rem 0 0 1rem; + margin: 0 0.5rem 0.25rem 0.5rem; } -.entry { - font-family: "Oxanium", monospace; - color: #28353e; - text-align: center; - margin-top: 10px; +.pod-chooseContainer { + margin: 0 1rem 0.5rem 1rem; + background-color: var(--panel); + border-radius: 6px; } -.entry a { - text-decoration: none; - color: #28353e; -} -.entry span { - font-family: "Orbitron"; -} - \ No newline at end of file + + diff --git a/src/components/PodBrowser.vue b/src/components/PodBrowser.vue index 931e69d1..edba64cf 100644 --- a/src/components/PodBrowser.vue +++ b/src/components/PodBrowser.vue @@ -8,12 +8,19 @@ Pod Data Browser
+
+ {{ deletedItemType }} deleted successfully! + +
+
- +
-
+