Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
arildm committed Nov 28, 2023
2 parents b047cd2 + d7330e1 commit 5638f47
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 19 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ As this project is a user-facing application, the places in the semantic version

## [Unreleased]

## [1.0.5] (2023-11-28)

### Changed

- Improved sync between source files and settings: set format from files, set name to corpus id

### Fixed

- Set `lang` param of Korp/Strix urls

## [1.0.4] (2023-10-24)

### Fixed
Expand Down Expand Up @@ -72,7 +82,8 @@ The frontend is now open to the general public! This version allows users to:

Code changes up until this point are not documented other than in the git commit log.

[unreleased]: https://github.com/spraakbanken/mink-frontend/compare/v1.0.4...HEAD
[unreleased]: https://github.com/spraakbanken/mink-frontend/compare/v1.0.5...HEAD
[1.0.5]: https://github.com/spraakbanken/mink-frontend/compare/v1.0.4...v1.0.5
[1.0.4]: https://github.com/spraakbanken/mink-frontend/compare/v1.0.3...v1.0.4
[1.0.3]: https://github.com/spraakbanken/mink-frontend/compare/v1.0.2...v1.0.3
[1.0.2]: https://github.com/spraakbanken/mink-frontend/compare/v1.0.1...v1.0.2
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mink-frontend",
"version": "1.0.4",
"version": "1.0.5",
"license": "MIT",
"scripts": {
"dev": "vite",
Expand Down
23 changes: 17 additions & 6 deletions src/api/corpusConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ export async function makeConfig(id, options) {
],
};

if (format === "xml") {
if (!textAnnotation) {
throw new TypeError("Text annotation setting is required for XML");
if (format == "xml") {
// The text annotation setting is required if XML, but it may be set later
if (textAnnotation) {
config.import.text_annotation = textAnnotation;
config.export.source_annotations = [`${textAnnotation} as text`, "..."];
}
config.import.text_annotation = textAnnotation;
config.export.source_annotations = [`${textAnnotation} as text`, "..."];
} else if (format === "pdf") {
} else if (format == "pdf") {
config.export.source_annotations = ["text", "page:number"];
}

Expand Down Expand Up @@ -141,3 +141,14 @@ export async function parseConfig(configYaml) {
).params.value,
};
}

/** Check if the config looks ready to run. May throw anything. */
export function validateConfig(config) {
if (!config.format) {
throw new TypeError("Format missing");
}

if (config.format == "xml" && !config.textAnnotation) {
throw new TypeError("Text annotation setting is required for XML");
}
}
5 changes: 3 additions & 2 deletions src/corpus/corpusState.composable.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { computed } from "vue";
import { useI18n } from "vue-i18n";
import { FORMATS_EXT } from "@/api/corpusConfig";
import { validateConfig } from "@/api/corpusConfig";
import useConfig from "./config/config.composable";
import useJob from "./job/job.composable";
import useSources from "./sources/sources.composable";
import { getException } from "@/util";

/** The "corpus state" is related to the job status, but is more about predicting what action the user needs to take. */
export function useCorpusState(corpusId) {
Expand Down Expand Up @@ -38,7 +39,7 @@ export function useCorpusState(corpusId) {
});

const isConfigValid = computed(
() => config.value && FORMATS_EXT.includes(config.value.format)
() => !getException(() => validateConfig(config.value))
);

const hasMetadata = computed(
Expand Down
13 changes: 11 additions & 2 deletions src/corpus/createCorpus.composable.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useRouter } from "vue-router";
import { useAuth } from "@/auth/auth.composable";
import useMinkBackend from "@/api/backend.composable";
import { emptyConfig } from "@/api/corpusConfig";
import { useCorpusStore } from "@/store/corpus.store";
import useMessenger from "@/message/messenger.composable";
import useConfig from "./config/config.composable";
import useSources from "./sources/sources.composable";
import useCorpus from "./corpus.composable";
import { getFilenameExtension } from "@/util";

export default function useCreateCorpus() {
const corpusStore = useCorpusStore();
Expand All @@ -31,9 +31,18 @@ export default function useCreateCorpus() {
const corpusId = await createCorpus().catch(alertError);
if (!corpusId) return;

// Get file extension of first file, assuming all are using the same extension.
const format = getFilenameExtension(files[0]?.name);

// Create a minimal config.
const config = {
name: { swe: corpusId, eng: corpusId },
format,
};

const results = await Promise.allSettled([
uploadSources(files, corpusId),
uploadConfig(emptyConfig(), corpusId),
uploadConfig(config, corpusId),
]);

const rejectedResults = results.filter(
Expand Down
6 changes: 4 additions & 2 deletions src/corpus/exports/Exports.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
:link-text="$t('exports.tools.help.korp.manual.text')"
:can-install="canInstall"
:is-installed="korpStatus.isDone"
:show-url="`${korpUrl}?mode=mink#?corpus=${corpusId}`"
:show-url="`${korpUrl}?mode=mink#?corpus=${corpusId}&lang=${locale3}`"
@install="korpInstall()"
/>

Expand All @@ -25,7 +25,7 @@
:info="$t('exports.tools.help.strix')"
:can-install="canInstall"
:is-installed="strixStatus.isDone"
:show-url="`${strixUrl}?filters=corpus_id:${corpusId}&modeSelected=mink`"
:show-url="`${strixUrl}?modeSelected=mink&filters=corpus_id:${corpusId}&lang=${locale3}`"
@install="strixInstall()"
/>
</div>
Expand Down Expand Up @@ -67,13 +67,15 @@ import { useCorpusState } from "@/corpus/corpusState.composable";
import useJob from "@/corpus/job/job.composable";
import PendingContent from "@/spin/PendingContent.vue";
import ToolPanel from "./ToolPanel.vue";
import useLocale from "@/i18n/locale.composable";
const corpusId = useCorpusIdParam();
const { exports, loadExports, downloadResult, getDownloadFilename } =
useExports(corpusId);
const { isDone } = useCorpusState(corpusId);
const { installKorp, installStrix, sparvStatus, korpStatus, strixStatus } =
useJob(corpusId);
const { locale3 } = useLocale();
const korpUrl = ensureTrailingSlash(import.meta.env.VITE_KORP_URL);
const strixUrl = ensureTrailingSlash(import.meta.env.VITE_STRIX_URL);
Expand Down
15 changes: 13 additions & 2 deletions src/corpus/sources/SourceUpload.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@

<script setup>
import { computed } from "vue";
import { getFilenameExtension } from "@/util";
import useMessenger from "@/message/messenger.composable";
import useSources from "./sources.composable";
import Filedrop from "./Filedrop.vue";
import useCorpusIdParam from "@/corpus/corpusIdParam.composable";
import UploadSizeLimits from "./UploadSizeLimits.vue";
import useConfig from "../config/config.composable";
const props = defineProps({
fileHandler: {
Expand All @@ -68,13 +70,22 @@ const props = defineProps({
const corpusId = useCorpusIdParam();
const { uploadSources, extensions } = useSources(corpusId);
const { clear, alertError } = useMessenger();
const { config, uploadConfig } = useConfig(corpusId);
const { alertError, clear } = useMessenger();
const extensionsAccept = computed(() =>
extensions.value?.map((ext) => `.${ext}`).join()
);
async function defaultFileHandler(files) {
return uploadSources(files).catch(alertError);
const requests = [uploadSources(files).catch(alertError)];
// Also update format setting in config if needed
const format = getFilenameExtension(files[0]?.name);
if (format != config.value.format) {
requests.push(uploadConfig({ ...config.value, format }));
}
await Promise.all(requests);
}
const fileHandler = props.fileHandler || defaultFileHandler;
Expand Down
3 changes: 2 additions & 1 deletion src/corpus/sources/sources.composable.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import uniq from "lodash/uniq";
import useMinkBackend from "@/api/backend.composable";
import { useCorpusStore } from "@/store/corpus.store";
import useMessenger from "@/message/messenger.composable";
import { getFilenameExtension } from "@/util";

export default function useSources(corpusId) {
const corpusStore = useCorpusStore();
Expand Down Expand Up @@ -38,7 +39,7 @@ export default function useSources(corpusId) {
const extensions = computed(() =>
uniq(
corpusStore.corpora[corpusId]?.sources?.map((source) =>
source.name.split(".").pop()
getFilenameExtension(source.name)
)
)
);
Expand Down
6 changes: 5 additions & 1 deletion src/i18n/locale.composable.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { inject, watch } from "vue";
import { computed, inject, watch } from "vue";
import { useI18n } from "vue-i18n";
import { useStorage } from "@vueuse/core";
import { filesize } from "filesize";
Expand All @@ -14,6 +14,9 @@ export default function useLocale() {
document.querySelector("html")?.setAttribute("lang", locale.value);
};

// The ISO 639-3 code is used in many parts of the Språkbanken infrastructure.
const locale3 = computed(() => (locale.value == "en" ? "eng" : "swe"));

// Sync from storage once, if present
if (storedLocale.value) {
locale.value = storedLocale.value;
Expand Down Expand Up @@ -50,6 +53,7 @@ export default function useLocale() {

return {
locale,
locale3,
th,
filesize: myFilesize,
};
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/locales/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ api.code.failed_uploading_sources: Failed to upload source files
api.code.failed_uploading_sources_file_size: Some files could not be uploaded, because they exceed the maximum file size of {max_file_size} MB
api.code.failed_uploading_sources_invalid_file_extension: 'File "{file}" could not be uploaded, because it has an invalid filename extension. Please use any of the supported file formats: xml, txt, odt, docx, pdf.'
api.code.failed_uploading_sources_invalid_xml: File "{file}" could not be uploaded, because it contains invalid XML
api.code.failed_uploading_sources_incompatible_file_extension: File "{file}" could not be uploaded, because it has an different filename extension. Please check that the file format of this corpus is configured to agree with your source files.
api.code.failed_uploading_sources_incompatible_file_extension: File "{file}" could not be uploaded, because it has a different filename extension. Please check that the file format of this corpus is configured to agree with your source files.
api.code.uploaded_sources: The source files were successfully added
api.code.data_too_large: Request data too large (max {max_content_length} MB per upload)
api.code.listing_sources: Listing current source files for the corpus "{corpus_id}"
Expand Down
13 changes: 13 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,16 @@ export function setKeys(obj, keys, defaultValue = null) {

/** Create a random string of around 11 chars in the [0-9a-z] range. */
export const randomString = () => Math.random().toString(36).slice(2);

/** Execute callback, catch and return any exception, otherwise return undefined. */
export const getException = (f) => {
try {
f();
} catch (e) {
return e;
}
return undefined;
};

export const getFilenameExtension = (filename) =>
filename.split(".").slice(1).pop() || "";
36 changes: 36 additions & 0 deletions src/util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
ensureExtension,
formatDate,
formatSeconds,
getException,
getFilenameExtension,
pathJoin,
randomString,
setKeys,
Expand Down Expand Up @@ -64,3 +66,37 @@ describe("randomString", () => {
expect(fails).toEqual([]);
});
});

describe("getException", () => {
test("translate success to undefined", () => {
const f = () => "foobar";
const exception = getException(f);
expect(exception).toBeUndefined();
});
test("reflect exception", () => {
const f = () => {
throw new EvalError("Leverpastej");
};
const exception = getException(f);
expect(exception.name).toBe("EvalError");
expect(exception.message).toBe("Leverpastej");
});
});

describe("getFilenameExtension", () => {
test("one extension", () => {
const filename = "palakpaneer.txt";
const extension = getFilenameExtension(filename);
expect(extension).toBe("txt");
});
test("no extension", () => {
const filename = "marinara";
const extension = getFilenameExtension(filename);
expect(extension).toBe("");
});
test("two extensions", () => {
const filename = "svt.xml.bz2";
const extension = getFilenameExtension(filename);
expect(extension).toBe("bz2");
});
});
Empty file added walrus
Empty file.

0 comments on commit 5638f47

Please sign in to comment.