From 7dc497261b394dcf34e62a8b91d2520bafbfb271 Mon Sep 17 00:00:00 2001 From: Arild Matsson Date: Mon, 11 Mar 2024 14:41:00 +0100 Subject: [PATCH 01/43] Add missing metadata-related sv strings --- src/i18n/locales/sv.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/i18n/locales/sv.yaml b/src/i18n/locales/sv.yaml index 0756a17..0480454 100644 --- a/src/i18n/locales/sv.yaml +++ b/src/i18n/locales/sv.yaml @@ -20,6 +20,7 @@ library: Bibliotek library.help.corpora: Här listas de korpusar du har skapat. De är bara synliga för dig. Klicka på dem för att visa mer. library.help.corpora.none: >- Mink erbjuder automatisk språkvetenskaplig analys av din data. Börja med att skapa en korpus: använd knappen "@:{'new_corpus'}" eller dra textfiler till uppladdningsrutan nedan. +library.help.metadata: Ett metadataobjekt har information som beskriver en godtycklig resurs. Mink bearbetar ingen data för dessa objekt, men de kan exporteras till en datakatalog. corpus.create.help: Korpusen kommer bara att vara synlig för dig. Du kan alltid uppdatera de här uppgifterna senare. corpus.creating: Skapar korpus corpus.configuring: Konfigurerar korpus @@ -48,6 +49,10 @@ corpus.state.help.running_install: Installationen körs i bakgrunden. Det går b corpus.state.help.done_install: Nu är datan installerad! corpus.state.help.failed: Ett fel uppstod under annotering. Om du behöver hjälp kan du kontakta sb-info{'@'}svenska.gu.se corpus.state.help.failed_install: Ett fel uppstod under installation. Om du behöver hjälp kan du kontakta sb-info{'@'}svenska.gu.se +metadata.new: Ny metadata +metadata.public_id.help: Varje resurs i Mink har en förutbestämd identifierare. Den publika identifieraren är vad denna resurs kommer at få när den exporteras till en datakatalog. Välj gärna något unikt och beskrivande, men inte för långt. Den får endast innehålla små bokstäver, siffror och bindestreck, och måste börja med ditt tilldelade organisationsprefix. +metadata.public_id.error.format: Den publika identifieraren får endast innehålla små bokstäver (a-z), siffror (0-9) och bindestreck (-). Den får inte börja eller sluta med bindestreck. +metadata.delete: Radera metadata resource.loading: Laddar resurs resource.delete.ask: Är du säker på att du vill ta bort den här resursen? config.metadata.help: Metadata är information om datan, och fungerar som underlag för potentiellt intresserade användare (om du publicerar datan) samt underlättar katalogiseringen i datarepositorier. @@ -129,6 +134,7 @@ lastModify: Senast ändrad fileSize: Storlek delete: Radera original: Original +public_id: Publik identifierare source_text_help: Under annoteringen extraheras ren text från filen, och kan sedan visas här. contact: Kontakt save: Spara From 44db39b802d9b1da422c4ee85c01297d01c6110c Mon Sep 17 00:00:00 2001 From: Arild Matsson Date: Thu, 14 Mar 2024 15:25:49 +0100 Subject: [PATCH 02/43] Special resource listing for admin, fix #146 --- CHANGELOG.md | 4 + src/corpus/corpus.composable.ts | 4 +- src/i18n/locales/en.yaml | 3 + src/i18n/locales/sv.yaml | 3 + src/library/AdminResourcesView.vue | 49 +++++++++++ src/library/LibraryView.vue | 113 ++++++++++++++------------ src/library/resources.composable.ts | 10 ++- src/metadata/metadata.composable.ts | 4 +- src/resource/ResourceRedirectView.vue | 22 +++++ src/router/main.routes.ts | 13 +++ src/store/resource.store.ts | 34 ++++---- src/user/AdminModeBanner.vue | 16 ++-- src/user/AdminModeSwitcher.vue | 9 +- src/user/UserView.vue | 7 +- src/user/admin.composable.ts | 5 +- 15 files changed, 211 insertions(+), 85 deletions(-) create mode 100644 src/library/AdminResourcesView.vue create mode 100644 src/resource/ResourceRedirectView.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a36bbb..5d17de4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ As this project is a user-facing application, the places in the semantic version ## [Unreleased] +### Added + +- A quick, brief resource listing view for admin [#146](https://github.com/spraakbanken/mink-frontend/issues/146) + ## [1.4.0] (2024-03-11) ### Added diff --git a/src/corpus/corpus.composable.ts b/src/corpus/corpus.composable.ts index 7daddab..09a23cc 100644 --- a/src/corpus/corpus.composable.ts +++ b/src/corpus/corpus.composable.ts @@ -7,13 +7,13 @@ const isCorpusFresh: Record = {}; export default function useCorpus(corpusId: string) { const resourceStore = useResourceStore(); - const { loadResources } = useResources(); + const { loadResource } = useResources(); const { loadConfig } = useConfig(corpusId); /** Load data about a corpus and store it. */ async function loadCorpus(): Promise { // Make sure the corpus has an entry in the store. - await loadResources(); + await loadResource(corpusId); // Skip if already loaded. if (isCorpusFresh[corpusId]) return; diff --git a/src/i18n/locales/en.yaml b/src/i18n/locales/en.yaml index 4891f56..20e8fc6 100644 --- a/src/i18n/locales/en.yaml +++ b/src/i18n/locales/en.yaml @@ -121,6 +121,7 @@ metadata: Metadata texts: Source texts configuration: Settings result: Result +resources: Resources corpus: Corpus corpuses: Corpora files: No files | 1 file | {count} files @@ -220,6 +221,8 @@ annotations.info: |

You can find some more information about the annotations in the Sparv documentation.

+admin.page.subtitle: Administration +admin.goto: Shortcuts accessdenied: Access denied accessdenied.contact: If you have questions, or you want to report a bug, please contact sb-info{'@'}svenska.gu.se. Thank you! notfound: Page not found diff --git a/src/i18n/locales/sv.yaml b/src/i18n/locales/sv.yaml index 0480454..66341a0 100644 --- a/src/i18n/locales/sv.yaml +++ b/src/i18n/locales/sv.yaml @@ -122,6 +122,7 @@ metadata: Metadata texts: Källtexter configuration: Inställningar result: Resultat +resources: Resurser corpus: Korpus corpuses: Korpusar files: Inga filer | 1 fil | {count} filer @@ -222,6 +223,8 @@ annotations.info: |

Du kan hitta lite mer info om annotationerna i Sparvs dokumentation.

+admin.page.subtitle: Administration +admin.goto: Genvägar accessdenied: Åtkomst nekad accessdenied.contact: Om du har frågor eller vill rapportera en bugg, kontakta gärna sb-info{'@'}svenska.gu.se. Tack! notfound: Sidan kan inte hittas diff --git a/src/library/AdminResourcesView.vue b/src/library/AdminResourcesView.vue new file mode 100644 index 0000000..08a4630 --- /dev/null +++ b/src/library/AdminResourcesView.vue @@ -0,0 +1,49 @@ + + + diff --git a/src/library/LibraryView.vue b/src/library/LibraryView.vue index 24632bc..3e20ce8 100644 --- a/src/library/LibraryView.vue +++ b/src/library/LibraryView.vue @@ -1,4 +1,5 @@ diff --git a/src/library/resources.composable.ts b/src/library/resources.composable.ts index ee1788e..b1619b2 100644 --- a/src/library/resources.composable.ts +++ b/src/library/resources.composable.ts @@ -13,6 +13,14 @@ export default function useResources() { const { alertError } = useMessenger(); const mink = useMinkBackend(); + /** Load and store data about a given resource. */ + async function loadResource(resourceId: string) { + const data = await mink.resourceInfoOne(resourceId).catch(alertError); + if (!data) return; + return resourceStore.setResource(data); + } + + /** Load and store data about all the user's resources, with caching. */ async function loadResources() { // Skip if already loaded. if (isFresh) return; @@ -50,9 +58,9 @@ export default function useResources() { } return { + loadResource, loadResources, loadResourceIds, - loadResourceInfo, refreshResources, }; } diff --git a/src/metadata/metadata.composable.ts b/src/metadata/metadata.composable.ts index a3c235a..07984bf 100644 --- a/src/metadata/metadata.composable.ts +++ b/src/metadata/metadata.composable.ts @@ -9,13 +9,13 @@ const isFresh: Record = {}; export default function useMetadata(resourceId: string) { const mink = useMinkBackend(); const resourceStore = useResourceStore(); - const { loadResources } = useResources(); + const { loadResource } = useResources(); const { alertError } = useMessenger(); /** Load data about a metadata and store it. */ async function loadMetadata(): Promise { // Make sure the resource has an entry in the store. - await loadResources(); + await loadResource(resourceId); // Skip if already loaded. if (isFresh[resourceId]) return; diff --git a/src/resource/ResourceRedirectView.vue b/src/resource/ResourceRedirectView.vue new file mode 100644 index 0000000..b7a99fe --- /dev/null +++ b/src/resource/ResourceRedirectView.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/router/main.routes.ts b/src/router/main.routes.ts index 875b290..9617b1c 100644 --- a/src/router/main.routes.ts +++ b/src/router/main.routes.ts @@ -1,9 +1,12 @@ import { type RouteRecordRaw } from "vue-router"; import HomeView from "@/home/HomeView.vue"; const LibraryView = () => import("@/library/LibraryView.vue"); +const ResourceRedirectView = () => + import("@/resource/ResourceRedirectView.vue"); import LoginView from "@/auth/LoginView.vue"; import SignupView from "@/auth/SignupView.vue"; const UserView = () => import("@/user/UserView.vue"); +const AdminResourcesView = () => import("@/library/AdminResourcesView.vue"); import AccessDenied from "@/auth/AccessDenied.vue"; import NotFound from "@/page/NotFound.vue"; import corpusRoutes from "./corpus.routes"; @@ -22,6 +25,11 @@ const routes: RouteRecordRaw[] = [ component: LibraryView, meta: { title: "library" }, }, + { + // Redirects to the resource page for an unknown resource type. + path: "/library/resource/:resourceId", + component: ResourceRedirectView, + }, { path: "/login", component: LoginView, @@ -42,6 +50,11 @@ const routes: RouteRecordRaw[] = [ component: AccessDenied, meta: { title: "accessdenied" }, }, + { + path: "/admin/resources", + component: AdminResourcesView, + meta: { title: "resources" }, + }, ...corpusRoutes, ...metadataRoutes, { diff --git a/src/store/resource.store.ts b/src/store/resource.store.ts index 7a5ee53..7f5e0a6 100644 --- a/src/store/resource.store.ts +++ b/src/store/resource.store.ts @@ -68,29 +68,34 @@ export const useResourceStore = defineStore("resource", () => { setKeys(resources, resourceIds, {}); } + /** Update state to match fresh data. */ function setResources(infos: ResourceInfo[]) { // Drop old keys, assign empty records for each new id const ids = infos.map((info) => info.resource.id); setKeys(resources, ids, {}); - for (const infoNew of infos) { - // Patch any existing record, otherwise create a new one. - const info = - infoNew.resource.id in resources ? resources[infoNew.resource.id] : {}; - info.type = infoNew.resource.type; - info.name = infoNew.resource.name; + infos.forEach(setResource); + } - if (isCorpus(info)) { - info.sources = infoNew.resource.source_files; - info.status = infoNew.job; - } + /** Store new state for a given resource. */ + function setResource(info: ResourceInfo): Resource { + // Patch any existing record, otherwise create a new one. + const resource = + info.resource.id in resources ? resources[info.resource.id] : {}; + resource.type = info.resource.type; + resource.name = info.resource.name; - if (isMetadata(info)) { - info.publicId = infoNew.resource.public_id; - } + if (isCorpus(resource)) { + resource.sources = info.resource.source_files; + resource.status = info.job; + } - resources[infoNew.resource.id] = info; + if (isMetadata(resource)) { + resource.publicId = info.resource.public_id; } + + resources[info.resource.id] = resource; + return resource; } const hasCorpora = computed(() => !!Object.keys(corpora).length); @@ -101,6 +106,7 @@ export const useResourceStore = defineStore("resource", () => { metadatas, setResourceIds, setResources, + setResource, hasCorpora, }; }); diff --git a/src/user/AdminModeBanner.vue b/src/user/AdminModeBanner.vue index ba67a28..c33132a 100644 --- a/src/user/AdminModeBanner.vue +++ b/src/user/AdminModeBanner.vue @@ -3,12 +3,12 @@ import { useAuth } from "@/auth/auth.composable"; import ActionButton from "@/components/ActionButton.vue"; import useAdmin from "./admin.composable"; -const { refreshJwt } = useAuth(); -const { adminMode, isAdmin, checkAdminMode, disableAdminMode } = useAdmin(); +const { refreshJwt, canUserAdmin } = useAuth(); +const { adminMode, checkAdminMode, disableAdminMode } = useAdmin(); (async () => { await refreshJwt(); - if (isAdmin.value) checkAdminMode(); + if (canUserAdmin.value) checkAdminMode(); })(); function disable() { @@ -21,12 +21,16 @@ function disable() { v-if="adminMode" class="bg-amber-300 shadow shadow-amber-600 text-amber-900 p-2 px-4 mb-4" > -
- +
+ {{ $t("user.admin_mode.warning") }} - + {{ $t("disable") }} + {{ $t("admin.goto") }}: + + {{ $t("resources") }} +
diff --git a/src/user/AdminModeSwitcher.vue b/src/user/AdminModeSwitcher.vue index 895f66c..3f7b7ac 100644 --- a/src/user/AdminModeSwitcher.vue +++ b/src/user/AdminModeSwitcher.vue @@ -5,7 +5,7 @@ import PendingContent from "@/spin/PendingContent.vue"; const { enableAdminMode, disableAdminMode, adminMode } = useAdmin(); -const localValue = ref(false); +const localValue = ref(); watchEffect(() => (localValue.value = adminMode.value)); @@ -14,7 +14,12 @@ watch(localValue, (value) => (value ? enableAdminMode() : disableAdminMode())); diff --git a/src/i18n/locale.composable.ts b/src/i18n/locale.composable.ts index 7aaeb07..b430bad 100644 --- a/src/i18n/locale.composable.ts +++ b/src/i18n/locale.composable.ts @@ -3,8 +3,9 @@ import { useI18n } from "vue-i18n"; import { filesize } from "filesize"; import { useStorage } from "@vueuse/core"; import { configSymbol } from "@formkit/vue"; +import type { ByLang, SvEn, SweEng } from "@/util.types"; -const storedLocale = useStorage("locale", ""); +const storedLocale = useStorage("locale", ""); export default function useLocale() { const { locale } = useI18n(); @@ -18,7 +19,9 @@ export default function useLocale() { }; // The ISO 639-3 code is used in many parts of the Språkbanken infrastructure. - const locale3 = computed(() => (locale.value == "en" ? "eng" : "swe")); + const locale3 = computed(() => + locale.value == "en" ? "eng" : "swe", + ); // Sync from storage once, if present if (storedLocale.value) { @@ -28,22 +31,20 @@ export default function useLocale() { // Then sync from switcher continually watch(locale, () => { - storedLocale.value = locale.value; + storedLocale.value = (locale.value as SvEn) || ""; exportLocale(); }); /** Translate here - picks the current language out of a strings-by-language object. */ - function th(stringsByLang?: Record) { - if (!stringsByLang) return undefined; - if (typeof stringsByLang == "string") return stringsByLang; - const lang3 = { sv: "swe", en: "eng" }[locale.value]; - return ( - stringsByLang[locale.value] || - (lang3 && stringsByLang[lang3]) || - stringsByLang.eng || - stringsByLang.swe || - Object.values(stringsByLang)[0] - ); + function th(map?: ByLang): string | undefined { + if (!map) return undefined; + return th2({ sv: map.swe, en: map.eng }); + } + + /** Translate here - picks the current language out of a strings-by-language object. */ + function th2(map?: Record): string | undefined { + if (!map) return undefined; + return map[locale.value as SvEn]; } /** Wrap the filesize lib with some sane defaults and avoiding exponential notation. */ @@ -58,6 +59,7 @@ export default function useLocale() { locale, locale3, th, + th2, filesize: myFilesize, }; } diff --git a/src/util.types.ts b/src/util.types.ts index 646449c..155b7d4 100644 --- a/src/util.types.ts +++ b/src/util.types.ts @@ -1 +1,4 @@ -export type ByLang = { swe: T; eng: T }; +export type SweEng = "swe" | "eng"; +export type SvEn = "sv" | "en"; + +export type ByLang = Record; From 422f4729d854658dc6a702082340755b09668894 Mon Sep 17 00:00:00 2001 From: Arild Matsson Date: Mon, 18 Mar 2024 10:35:00 +0100 Subject: [PATCH 10/43] Store resource owner, fix #156 --- src/api/api.types.ts | 11 ++++++++++- src/library/AdminResourcesView.vue | 2 +- src/store/resource.store.ts | 12 +++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/api/api.types.ts b/src/api/api.types.ts index d7f2cd6..429ab1e 100644 --- a/src/api/api.types.ts +++ b/src/api/api.types.ts @@ -1,4 +1,4 @@ -import type { ByLang } from "@/util.types"; +import type { ByLang, SweEng } from "@/util.types"; import type { AxiosProgressEvent } from "axios"; /** Properties common to most backend responses */ @@ -61,10 +61,19 @@ export type ResourceInfoOneData = ResourceInfo; /** Data about a resource and its job status */ export type ResourceInfo = { + owner?: UserData; resource: ResourceData; job: CorpusStatus; }; +/** Data about a Mink user */ +export type UserData = { + id: string; + name: string; + email: string; + ui_language: SweEng; +}; + /** Basic data about a resource */ export type ResourceData = { type: ResourceType; diff --git a/src/library/AdminResourcesView.vue b/src/library/AdminResourcesView.vue index 3acead5..9c6f69c 100644 --- a/src/library/AdminResourcesView.vue +++ b/src/library/AdminResourcesView.vue @@ -81,7 +81,7 @@ async function load(resourceId: string) {
- {{ $t(resource.type) }} + {{ resource.owner.name }} { // current date (YYMMDD) if the state shape is changed, to make the browser // forget the old state. The actual number doesn't really matter, as long as // it's a new one. - const resourcesRef = useStorage("mink@230208.resources", {}); + const resourcesRef = useStorage("mink@240318.resources", {}); const resources: Record = reactive(resourcesRef.value); const corpora = computed>>(() => @@ -83,6 +89,9 @@ export const useResourceStore = defineStore("resource", () => { const resource = { type: info.resource.type, name: info.resource.name, + owner: info.owner + ? { name: info.owner.name, id: info.owner.id } + : undefined, }; if (isCorpus(resource)) { @@ -91,6 +100,7 @@ export const useResourceStore = defineStore("resource", () => { } if (isMetadata(resource)) { + resource.owner = info.owner; resource.publicId = info.resource.public_id; } From 1419c9f3d93fa21204418d0ec71cc944302ea534 Mon Sep 17 00:00:00 2001 From: Arild Matsson Date: Mon, 18 Mar 2024 11:02:06 +0100 Subject: [PATCH 11/43] Merge resource info with existing record in store Dropped the merging recently in 72b8805, but it's needed for instance when a resourceInfoAll response comes after downloadConfig responses. --- src/store/resource.store.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/store/resource.store.ts b/src/store/resource.store.ts index 0dde39a..a82f6c2 100644 --- a/src/store/resource.store.ts +++ b/src/store/resource.store.ts @@ -104,7 +104,11 @@ export const useResourceStore = defineStore("resource", () => { resource.publicId = info.resource.public_id; } - resources[info.resource.id] = resource; + // Merge with any existing record. + resources[info.resource.id] = { + ...(resources[info.resource.id] || {}), + resource, + }; return resource; } From a8808b1ed08aff53261c25ce72a84c3cf191863b Mon Sep 17 00:00:00 2001 From: Arild Matsson Date: Mon, 18 Mar 2024 11:56:08 +0100 Subject: [PATCH 12/43] Order imports --- .eslintrc.cjs | 6 +- package.json | 1 + src/App.vue | 2 +- src/api/api.ts | 2 +- src/api/backend.composable.ts | 4 +- src/api/backendInfo.composable.ts | 4 +- src/api/corpusConfig.test.ts | 2 +- src/api/corpusConfig.ts | 5 +- src/auth/LoginButton.vue | 2 +- src/auth/LoginView.vue | 2 +- src/auth/SignupView.vue | 2 +- src/auth/auth.composable.ts | 4 +- src/components/FileUpload.vue | 4 +- src/components/RouteButton.vue | 2 +- src/components/TextData.vue | 2 +- src/corpus/CorpusDelete.vue | 4 +- src/corpus/CorpusOverview.vue | 20 +- src/corpus/CorpusStateHelp.vue | 4 +- src/corpus/CorpusStateMessage.vue | 2 +- src/corpus/CorpusView.vue | 8 +- src/corpus/config/ConfigPanel.vue | 2 +- src/corpus/config/CorpusConfiguration.vue | 32 +- src/corpus/config/CorpusMetadata.vue | 2 +- src/corpus/config/MetadataPanel.vue | 2 +- src/corpus/corpus.composable.ts | 2 +- src/corpus/corpusState.composable.ts | 6 +- src/corpus/createCorpus.composable.ts | 2 +- src/corpus/exports/CorpusResult.vue | 2 +- src/corpus/exports/ExportsPanel.vue | 4 +- src/corpus/job/JobStatus.vue | 4 +- src/corpus/job/JobStatusMessage.vue | 2 +- src/corpus/sources/SourceUpload.vue | 6 +- src/corpus/sources/SourceView.vue | 4 +- src/corpus/sources/SourcesPanel.vue | 4 +- src/home/Home.test.ts | 2 +- src/home/HomeNews.vue | 2 +- src/home/HomeView.vue | 2 +- src/i18n/i18n.ts | 4 +- src/library/AdminResourcePreview.vue | 2 +- src/library/AdminResourcesView.vue | 4 +- src/library/LibraryView.vue | 4 +- src/main.ts | 14 +- src/message/MessageAlert.vue | 4 +- src/message/MessageToasts.vue | 2 +- src/metadata/MetadataDelete.vue | 2 +- src/metadata/MetadataOverview.vue | 2 +- src/metadata/MetadataView.vue | 2 +- src/page/AppHeader.vue | 2 +- src/page/BreadcrumbBar.vue | 2 +- src/page/title.composable.ts | 4 +- src/resource/ResourceRedirectView.vue | 2 +- src/router/main.routes.ts | 4 +- src/router/router.ts | 2 +- src/spin/PendingContent.vue | 4 +- src/user/AdminModeBanner.vue | 2 +- src/user/AdminModeSwitcher.vue | 2 +- src/user/UserView.vue | 2 +- src/util.test.ts | 2 +- yarn.lock | 541 +++++++++++++++++++++- 59 files changed, 644 insertions(+), 127 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 9a2392f..789ec88 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -7,6 +7,10 @@ module.exports = { "eslint:recommended", "plugin:vue/vue3-recommended", "@vue/eslint-config-typescript", - "prettier", + "prettier", // Keep Prettier last ], + plugins: ["import"], + rules: { + "import/order": ["warn"], + }, }; diff --git a/package.json b/package.json index e1c44b7..184cf90 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "@types/node": "^20.10.6", "@vue/eslint-config-typescript": "^12.0.0", "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-vue": "^9.0", "happy-dom": "^12.10.3", "prettier": "^3.2.4", diff --git a/src/App.vue b/src/App.vue index e3fd257..a10495c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -2,6 +2,7 @@ import { computed } from "vue"; import { useRoute } from "vue-router"; import { useTitle } from "@vueuse/core"; +import AppHeader from "@/page/AppHeader.vue"; import api from "@/api/api"; import * as util from "@/util"; import { useAuth } from "@/auth/auth.composable"; @@ -10,7 +11,6 @@ import { useResourceStore } from "@/store/resource.store"; import MessageToasts from "@/message/MessageToasts.vue"; import usePageTitle from "@/page/title.composable"; import BreadcrumbBar from "@/page/BreadcrumbBar.vue"; -import AppHeader from "./page/AppHeader.vue"; const { refreshJwt } = useAuth(); useLocale(); diff --git a/src/api/api.ts b/src/api/api.ts index a2060cc..2be6c9e 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -13,7 +13,7 @@ import type { AdminModeStatusData, CreateMetadataData, ProgressHandler, -} from "./api.types"; +} from "@/api/api.types"; /** Mink backend API client */ class MinkApi { diff --git a/src/api/backend.composable.ts b/src/api/backend.composable.ts index 8ac9de5..9559046 100644 --- a/src/api/backend.composable.ts +++ b/src/api/backend.composable.ts @@ -1,7 +1,7 @@ import { useI18n } from "vue-i18n"; -import api from "./api"; +import api from "@/api/api"; import useSpin from "@/spin/spin.composable"; -import type { ProgressHandler } from "./api.types"; +import type { ProgressHandler } from "@/api/api.types"; /** Wraps API endpoints with Spin. */ export default function useMinkBackend() { diff --git a/src/api/backendInfo.composable.ts b/src/api/backendInfo.composable.ts index e15d348..1783155 100644 --- a/src/api/backendInfo.composable.ts +++ b/src/api/backendInfo.composable.ts @@ -1,6 +1,6 @@ import { computed, readonly, ref } from "vue"; -import api from "./api"; -import type { InfoData } from "./api.types"; +import api from "@/api/api"; +import type { InfoData } from "@/api/api.types"; import { keyBy, objsToDict } from "@/util"; export type Info = { diff --git a/src/api/corpusConfig.test.ts b/src/api/corpusConfig.test.ts index 1ab101c..98c4019 100644 --- a/src/api/corpusConfig.test.ts +++ b/src/api/corpusConfig.test.ts @@ -5,7 +5,7 @@ import { parseConfig, type ConfigOptions, validateConfig, -} from "./corpusConfig"; +} from "@/api/corpusConfig"; describe("makeConfig", () => { test("sets minimal info", async () => { diff --git a/src/api/corpusConfig.ts b/src/api/corpusConfig.ts index d077804..057e672 100644 --- a/src/api/corpusConfig.ts +++ b/src/api/corpusConfig.ts @@ -1,7 +1,10 @@ const yaml = import("js-yaml").then((m) => m.default); import type { ByLang } from "@/util.types"; -import type { ConfigSentenceSegmenter, SparvConfig } from "./sparvConfig.types"; +import type { + ConfigSentenceSegmenter, + SparvConfig, +} from "@/api/sparvConfig.types"; export type FileFormat = "txt" | "xml" | "odt" | "docx" | "pdf"; diff --git a/src/auth/LoginButton.vue b/src/auth/LoginButton.vue index ca7758b..15643e3 100644 --- a/src/auth/LoginButton.vue +++ b/src/auth/LoginButton.vue @@ -1,7 +1,7 @@