-
+
+
diff --git a/components/xlsx-button-detail.vue b/app/components/xlsx-button-detail.vue
similarity index 96%
rename from components/xlsx-button-detail.vue
rename to app/components/xlsx-button-detail.vue
index 6e3e4d2..8664089 100644
--- a/components/xlsx-button-detail.vue
+++ b/app/components/xlsx-button-detail.vue
@@ -177,6 +177,7 @@ switch (props.collection) {
{ label: "Last Names", value: "name" },
{ label: "Married Names", value: "married_name" },
],
+ // eslint-disable-next-line prefer-spread
content: Array.apply(
null,
Array(
@@ -186,11 +187,13 @@ switch (props.collection) {
(props.data.details.data as PersonDetail).married_names.length,
),
),
- ).map((x, i) => ({
- first_name: (props.data.details.data as PersonDetail).alternative_first_names[i],
- name: (props.data.details.data as PersonDetail).alternative_last_names[i],
- married_name: (props.data.details.data as PersonDetail).married_names[i],
- })),
+ ).map((x, i) => {
+ return {
+ first_name: (props.data.details.data as PersonDetail).alternative_first_names[i],
+ name: (props.data.details.data as PersonDetail).alternative_last_names[i],
+ married_name: (props.data.details.data as PersonDetail).married_names[i],
+ };
+ }),
},
{
sheet: "Academic Titles",
diff --git a/components/xlsx-button-table.vue b/app/components/xlsx-button-table.vue
similarity index 82%
rename from components/xlsx-button-table.vue
rename to app/components/xlsx-button-table.vue
index 03ee945..8ab9087 100644
--- a/components/xlsx-button-table.vue
+++ b/app/components/xlsx-button-table.vue
@@ -35,7 +35,12 @@ const sheet = {
columns: [
{ label: "ID", value: "object_id" },
{ label: "Name", value: "name" },
- { label: "Alternative Name", value: (row: Court) => row.alternativenames.join(", ") },
+ {
+ label: "Alternative Name",
+ value: (row: Court) => {
+ return row.alternativenames.join(", ");
+ },
+ },
{ label: "Model", value: "model" },
{ label: "Kind", value: "kind" },
{ label: "Start", value: "start" },
@@ -49,7 +54,12 @@ const sheet = {
columns: [
{ label: "ID", value: "object_id" },
{ label: "Name", value: "name" },
- { label: "Alternative Name", value: (row: Court) => row.alternativenames.join(", ") },
+ {
+ label: "Alternative Name",
+ value: (row: Court) => {
+ return row.alternativenames.join(", ");
+ },
+ },
{ label: "Model", value: "model" },
{ label: "Kind", value: "kind" },
{ label: "Start", value: "start" },
@@ -64,9 +74,24 @@ const sheet = {
{ label: "ID", value: "object_id" },
{ label: "First Name", value: "first_name" },
{ label: "Surname", value: "name" },
- { label: "Functions", value: (row: Person) => row.functions.join(", ") },
- { label: "Institutions", value: (row: Person) => row.institutions.join(", ") },
- { label: "Alternative Name", value: (row: Person) => row.alternativenames.join(", ") },
+ {
+ label: "Functions",
+ value: (row: Person) => {
+ return row.functions.join(", ");
+ },
+ },
+ {
+ label: "Institutions",
+ value: (row: Person) => {
+ return row.institutions.join(", ");
+ },
+ },
+ {
+ label: "Alternative Name",
+ value: (row: Person) => {
+ return row.alternativenames.join(", ");
+ },
+ },
{ label: "Model", value: "model" },
{ label: "Kind", value: "kind" },
{ label: "Birth", value: "start" },
@@ -81,7 +106,12 @@ const sheet = {
columns: [
{ label: "ID", value: "object_id" },
{ label: "Name", value: "name" },
- { label: "Alternative Name", value: (row: Person) => row.alternativenames.join(", ") },
+ {
+ label: "Alternative Name",
+ value: (row: Person) => {
+ return row.alternativenames.join(", ");
+ },
+ },
{ label: "Model", value: "model" },
{ label: "Kind", value: "kind" },
{ label: "Start", value: "start" },
diff --git a/components/xlsx-button.vue b/app/components/xlsx-button.vue
similarity index 95%
rename from components/xlsx-button.vue
rename to app/components/xlsx-button.vue
index c6369e7..4e584cf 100644
--- a/components/xlsx-button.vue
+++ b/app/components/xlsx-button.vue
@@ -154,6 +154,7 @@ switch (props.collection) {
{ label: "Last Names", value: "name" },
{ label: "Married Names", value: "married_name" },
],
+ // eslint-disable-next-line prefer-spread
content: Array.apply(
null,
Array(
@@ -163,11 +164,13 @@ switch (props.collection) {
props.data.details.data.married_names.length,
),
),
- ).map((x, i) => ({
- first_name: props.data.details.data.alternative_first_names[i],
- name: props.data.details.data.alternative_last_names[i],
- married_name: props.data.details.data.married_names[i],
- })),
+ ).map((x, i) => {
+ return {
+ first_name: props.data.details.data.alternative_first_names[i],
+ name: props.data.details.data.alternative_last_names[i],
+ married_name: props.data.details.data.married_names[i],
+ };
+ }),
},
{
sheet: "Academic Titles",
@@ -284,7 +287,7 @@ const downloadXlsx = () => {
diff --git a/composables/use-locale.ts b/app/composables/use-locale.ts
similarity index 100%
rename from composables/use-locale.ts
rename to app/composables/use-locale.ts
diff --git a/app/composables/use-page-metadata.ts b/app/composables/use-page-metadata.ts
new file mode 100644
index 0000000..4fbaa9c
--- /dev/null
+++ b/app/composables/use-page-metadata.ts
@@ -0,0 +1,19 @@
+interface UsePageMetadataParams {
+ title: MaybeRef
;
+ description?: MaybeRef;
+}
+
+export function usePageMetadata(params: UsePageMetadataParams): void {
+ useHead({
+ title: params.title,
+ meta: [
+ { property: "og:title", content: params.title },
+ ...(params.description != null
+ ? [
+ { name: "description", content: params.description },
+ { property: "og:description", content: params.description },
+ ]
+ : []),
+ ],
+ });
+}
diff --git a/composables/use-translations.ts b/app/composables/use-translations.ts
similarity index 100%
rename from composables/use-translations.ts
rename to app/composables/use-translations.ts
diff --git a/composables/use-ts-data.ts b/app/composables/use-ts-data.ts
similarity index 100%
rename from composables/use-ts-data.ts
rename to app/composables/use-ts-data.ts
diff --git a/config/i18n.config.ts b/app/config/i18n.config.ts
similarity index 53%
rename from config/i18n.config.ts
rename to app/config/i18n.config.ts
index c1ef6dd..aa23ff8 100644
--- a/config/i18n.config.ts
+++ b/app/config/i18n.config.ts
@@ -1,15 +1,17 @@
import type { LocaleObject } from "vue-i18n-routing";
-import type de from "@/locales/de.json";
+import type de from "~/i18n/messages/de.json";
-export const locales = {
- de: { code: "de", language: "de-AT", file: "de.json" },
-} satisfies Record;
+export const locales = ["de"] as const;
-export type Locale = keyof typeof locales;
+export type Locale = (typeof locales)[number];
export const defaultLocale: Locale = "de";
+export const localesMap = {
+ de: { code: "de", language: "de", file: "de.json" },
+} satisfies Record;
+
export type Messages = typeof de;
export interface Schema {
@@ -17,7 +19,7 @@ export interface Schema {
}
export function isValidLocale(value: string): value is Locale {
- return value in locales;
+ return value in localesMap;
}
export interface Translations extends Record {
diff --git a/app/config/imprint.config.ts b/app/config/imprint.config.ts
new file mode 100644
index 0000000..878e091
--- /dev/null
+++ b/app/config/imprint.config.ts
@@ -0,0 +1,11 @@
+import { createUrl, createUrlSearchParams } from "@acdh-oeaw/lib";
+
+import type { Locale } from "@/config/i18n.config";
+
+export function createImprintUrl(locale: Locale, redmineId: string): URL {
+ return createUrl({
+ baseUrl: "https://imprint.acdh.oeaw.ac.at",
+ pathname: `/${redmineId}`,
+ searchParams: createUrlSearchParams({ locale }),
+ });
+}
diff --git a/app/error.vue b/app/error.vue
new file mode 100644
index 0000000..b7e2111
--- /dev/null
+++ b/app/error.vue
@@ -0,0 +1,62 @@
+
+
+
+
+
+ {{ t("NotFoundPage.title") }}
+
+
+
+ {{ t("ErrorPage.title") }}
+
+ {{ "statusCode" in props.error ? props.error.statusCode : 500 }}
+ {{ props.error.message }}
+
+
+
+
+
+
+
diff --git a/app/layouts/default.vue b/app/layouts/default.vue
new file mode 100644
index 0000000..8a29bbd
--- /dev/null
+++ b/app/layouts/default.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
+ {{ t("DefaultLayout.skip-to-main-content") }}
+
+
+
+
+
+
+
+
+
diff --git a/lib/facets.ts b/app/lib/facets.ts
similarity index 83%
rename from lib/facets.ts
rename to app/lib/facets.ts
index 52fec0c..ecf1de6 100644
--- a/lib/facets.ts
+++ b/app/lib/facets.ts
@@ -11,9 +11,13 @@ export const facetObjectToTypesenseQuery = (
Object.entries(facetObject).forEach(([key, value]) => {
if (value.length !== 0) {
if (key === "start_date_int") {
- retArray.push(`${key}:[${value[0]}..${value[1]}${includeDateless ? ",0" : ""}]`);
+ retArray.push(
+ `${key}:[${String(value[0])}..${String(value[1])}${includeDateless ? ",0" : ""}]`,
+ );
} else if (key === "end_date_int") {
- retArray.push(`${key}:[${value[0]}..${value[1]}${includeDateless ? ",5000" : ""}]`);
+ retArray.push(
+ `${key}:[${String(value[0])}..${String(value[1])}${includeDateless ? ",5000" : ""}]`,
+ );
} else {
retArray.push(key + ":=[`" + value.join("`,`") + "`]");
}
@@ -40,6 +44,8 @@ export const typesenseQueryToFacetObject = (
} else {
const [key, value] = facetString.split(":");
if (key !== undefined && value !== undefined) {
+ // FIXME:
+ // eslint-disable-next-line regexp/no-super-linear-backtracking
retObject[key] = value.replace(/\[(\d+)\.\.(\d+),?\d*\]/, "$1;$2").split(";"); // converts formats [yyyy..yyyy,y] and [yyyy..yyyy] to classic [yyyy,yyyy]
}
}
@@ -50,5 +56,6 @@ export const typesenseQueryToFacetObject = (
export const getFacetObjectFromURL = (decode = false): Record> => {
const query = useRoute().query;
if (query.facets === undefined) return {};
+ // @ts-expect-error FIXME: Check later.
return typesenseQueryToFacetObject(String(query.facets), decode);
};
diff --git a/lib/get-tree-data.ts b/app/lib/get-tree-data.ts
similarity index 100%
rename from lib/get-tree-data.ts
rename to app/lib/get-tree-data.ts
diff --git a/lib/get-ts-data.ts b/app/lib/get-ts-data.ts
similarity index 51%
rename from lib/get-ts-data.ts
rename to app/lib/get-ts-data.ts
index 523e252..a7d4fab 100644
--- a/lib/get-ts-data.ts
+++ b/app/lib/get-ts-data.ts
@@ -1,15 +1,17 @@
import { Client } from "typesense";
export function useDefaultClient(): Client {
+ const env = useRuntimeConfig();
+
const tsClient = new Client({
nodes: [
{
- host: "typesense.acdh-dev.oeaw.ac.at",
- port: 443,
- protocol: "https",
+ host: env.public.typesenseHost,
+ port: env.public.typesensePort,
+ protocol: env.public.typesenseProtocol,
},
],
- apiKey: "catYoetXCv1rTfAp5LzcQ6TKI48gkB13", // read, get & retrieve only
+ apiKey: env.public.typesenseApiKey,
connectionTimeoutSeconds: 3,
});
diff --git a/lib/helpers.ts b/app/lib/helpers.ts
similarity index 83%
rename from lib/helpers.ts
rename to app/lib/helpers.ts
index 9f4212d..d3db93a 100644
--- a/lib/helpers.ts
+++ b/app/lib/helpers.ts
@@ -10,7 +10,7 @@ export function downloadAsJson(content: object, title: string) {
export function detectURLsAddLinks(content: string) {
const urlRegex =
- /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/;
+ /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.\S{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.\S{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.\S{2,}|www\.[a-zA-Z0-9]+\.\S{2,})/;
return content.replace(
urlRegex,
'$1 ↗',
diff --git a/lib/tree.js b/app/lib/tree.js
similarity index 76%
rename from lib/tree.js
rename to app/lib/tree.js
index 74a70fc..29a7637 100644
--- a/lib/tree.js
+++ b/app/lib/tree.js
@@ -1,3 +1,6 @@
+/* eslint-disable */
+// @ts-nocheck
+
import * as d3 from "d3";
export function Tree(
@@ -5,8 +8,16 @@ export function Tree(
{
// data is either tabular (array of objects) or hierarchy (nested objects)
path, // as an alternative to id and parentId, returns an array identifier, imputing internal nodes
- id = Array.isArray(data) ? (d) => d.id : null, // if tabular data, given a d in data, returns a unique identifier (string)
- parentId = Array.isArray(data) ? (d) => d.parentId : null, // if tabular data, given a node d, returns its parent’s identifier
+ id = Array.isArray(data)
+ ? (d) => {
+ return d.id;
+ }
+ : null, // if tabular data, given a d in data, returns a unique identifier (string)
+ parentId = Array.isArray(data)
+ ? (d) => {
+ return d.parentId;
+ }
+ : null, // if tabular data, given a node d, returns its parent’s identifier
children, // if hierarchical data, given a d in data, returns its children
tree = d3.tree, // layout algorithm (typically d3.tree or d3.cluster)
sort, // how to sort nodes prior to layout (e.g., (a, b) => d3.descending(a.height, b.height))
@@ -47,7 +58,12 @@ export function Tree(
// Compute labels and titles.
const descendants = root.descendants();
- const L = label == null ? null : descendants.map((d) => label(d.data, d));
+ const L =
+ label == null
+ ? null
+ : descendants.map((d) => {
+ return label(d.data, d);
+ });
// Compute the layout.
const dx = 10 + r;
@@ -92,8 +108,12 @@ export function Tree(
"d",
d3
.link(curve)
- .x((d) => d.y)
- .y((d) => d.x),
+ .x((d) => {
+ return d.y;
+ })
+ .y((d) => {
+ return d.x;
+ }),
);
const node = svg
@@ -101,8 +121,17 @@ export function Tree(
.selectAll("a")
.data(root.descendants())
.join("a")
- .attr("href", link == null ? null : (d) => link(d.data, d))
- .attr("transform", (d) => `translate(${d.y},${d.x})`);
+ .attr(
+ "href",
+ link == null
+ ? null
+ : (d) => {
+ return link(d.data, d);
+ },
+ )
+ .attr("transform", (d) => {
+ return `translate(${d.y},${d.x})`;
+ });
node
.append("circle")
@@ -120,19 +149,30 @@ export function Tree(
})
.attr("r", r);
- if (title != null) node.append("title").text((d) => title(d.data, d));
+ if (title != null)
+ node.append("title").text((d) => {
+ return title(d.data, d);
+ });
if (L)
node
.append("text")
.attr("dy", "0.32em")
- .attr("x", (d) => (d.children ? -6 - r : 6 + r))
- .attr("text-anchor", (d) => (d.children ? "end" : "start"))
+ .attr("x", (d) => {
+ return d.children ? -6 - r : 6 + r;
+ })
+ .attr("text-anchor", (d) => {
+ return d.children ? "end" : "start";
+ })
.attr("paint-order", "stroke")
.attr("stroke", halo)
.attr("stroke-width", haloWidth)
- .text((d, i) => L[i])
- .attr("font-size", (d) => (d.data.data.meta.label.length > 20 ? "0.7em" : fontSize));
+ .text((d, i) => {
+ return L[i];
+ })
+ .attr("font-size", (d) => {
+ return d.data.data.meta.label.length > 20 ? "0.7em" : fontSize;
+ });
return svg.node();
}
diff --git a/app/lib/types.ts b/app/lib/types.ts
new file mode 100644
index 0000000..833170d
--- /dev/null
+++ b/app/lib/types.ts
@@ -0,0 +1,6 @@
+export interface HierarchyNode {
+ group: string;
+ label: string;
+ pk: number;
+ value?: Array;
+}
diff --git a/pages/detail/courts/[id].vue b/app/pages/detail/courts/[id]/index.vue
similarity index 93%
rename from pages/detail/courts/[id].vue
rename to app/pages/detail/courts/[id]/index.vue
index fed20f1..6b79149 100644
--- a/pages/detail/courts/[id].vue
+++ b/app/pages/detail/courts/[id]/index.vue
@@ -23,11 +23,15 @@ const collection = "viecpro_courts";
const data = ref({
entity: useQuery({
queryKey: [collection, id],
- queryFn: () => getDocument(collection, `Hofstaat_${id}`),
+ queryFn: () => {
+ return getDocument(collection, `Hofstaat_${id}`);
+ },
}),
details: useQuery({
queryKey: ["detail", collection, id],
- queryFn: () => getDetails("court", id, "institution"),
+ queryFn: () => {
+ return getDetails("court", id, "institution");
+ },
}),
refs: useQuery({
queryKey: [
@@ -53,11 +57,13 @@ const data = ref({
}),
});
-const loading = computed(() => ({
- entity: data.value.entity.isFetching,
- details: data.value.details.isFetching,
- refs: data.value.refs.isFetching,
-}));
+const loading = computed(() => {
+ return {
+ entity: data.value.entity.isFetching,
+ details: data.value.details.isFetching,
+ refs: data.value.refs.isFetching,
+ };
+});
const relCols = ["relation_type", "target.name", "start_date", "end_date"];
@@ -89,7 +95,7 @@ useHead({
{{ data.details.error }}
{{ data.refs.error }}
-