Skip to content

Commit

Permalink
Merge pull request #567 from kbss-cvut/development
Browse files Browse the repository at this point in the history
[3.3.0] Release
  • Loading branch information
ledsoft authored Nov 8, 2024
2 parents 0a64eb0 + a33a33b commit 33a7241
Show file tree
Hide file tree
Showing 64 changed files with 2,432 additions and 1,944 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ COPY package.json package-lock.json ./
FROM base AS dependencies
# install node packages
#RUN npm set progress=false && npm config set depth 0
RUN npm install --legacy-peer-deps
RUN npm ci --legacy-peer-deps

# BUILD STAGE
# run NPM build
FROM dependencies as build
FROM dependencies AS build
# If an app is supposed to be deployed in a subdir, this is the place to specify that
# Make sure that React app is built using the right path context
COPY . .
Expand Down
6 changes: 6 additions & 0 deletions NEWS.cs.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#### Verze 3.3.0

- Přidána možnost stáhnout anotovaný soubor bez nepotvrzených výskytů.
- Upraveno fulltextové vyhledávání - nově se zobrazuje informace o atributu, ve kterém byla shoda nalezena.
- Do fasetového vyhledávání přidána možnost filtrovat dle příkladů (`skos:example`).

#### Verze 3.2.0

- Přidána podpora pro import slovníků z MS Excel.
Expand Down
6 changes: 6 additions & 0 deletions NEWS.en.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#### Version 3.3.0

- Added the possibility to download annotated file without unconfirmed occurrences.
- Enhanced fulltext search - now it shows information about the attribute in which a match was found.
- Added support for filtering by example (`skos:example`) in the faceted search.

#### Version 3.2.0

- Added support for importing a vocabulary from MS Excel.
Expand Down
11 changes: 1 addition & 10 deletions doc/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ marking it as production-ready.

## Development Requirements

Unless you are using Docker to build the project, **Node.js 14** or later and **npm 7** or later (due to using lockfile v2) are required. Node.js 16 and npm 8 is recommended.
Unless you are using Docker to build the project, **Node.js 20** or later and **npm 8** or later are required.

## Tests

Expand Down Expand Up @@ -124,15 +124,6 @@ tracking and the corresponding loading mask. See `TermChangeFrequency` for usage
- Tests can be debugged directly in IDEA just like JUnit tests - IDEA is able to run singular tests.
- The application can be debugged in IDEA as well, see the [JetBrains blog](https://blog.jetbrains.com/webstorm/2017/01/debugging-react-apps/).

## Mocking Server REST API

It is possible to mock server REST API, so that the application can be developed and run without having to start the backend application.
To do so, use `npm run start-mock-rest`, which sets environment variables telling the app to mock the REST API. Now, the mock API is set up
in `src/util/Ajax`, function `mockRestApi`, we are using [Axios Mock Adapter](https://github.com/ctimmerm/axios-mock-adapter). The usage should be
fairly intuitive. Data should be kept in JSON files in `src/rest-mock` (has to be in `src`, otherwise webpack refuses to import the data).

However, note that the current mocked API does not cover the actual backend REST API anymore, and it is recommended to run the backend (e.g. in Docker) for real and connect to it instead.

## Adjusting Bootstrap Styles

It is possible to adjust the styling of the application. We are using Bootstrap which provides SCSS definitions which can be overridden. Based on the
Expand Down
1,352 changes: 810 additions & 542 deletions package-lock.json

Large diffs are not rendered by default.

37 changes: 19 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
{
"name": "termit-ui",
"version": "3.2.0",
"version": "3.3.0",
"private": true,
"homepage": ".",
"license": "GPL-3.0-only",
"dependencies": {
"@formatjs/intl-pluralrules": "^5.2.4",
"@formatjs/intl-relativetimeformat": "^11.2.4",
"@fortawesome/fontawesome-free": "^6.4.0",
"@formatjs/intl-pluralrules": "^5.3.1",
"@formatjs/intl-relativetimeformat": "^11.4.1",
"@fortawesome/fontawesome-free": "^6.6.0",
"@opendata-mvcr/assembly-line-shared": "^0.3.2",
"apexcharts": "^3.41.0",
"axios": "^1.6.5",
"apexcharts": "^3.54.0",
"axios": "^1.7.7",
"bootstrap": "4.6.2",
"chart.js": "^3.9.1",
"classnames": "^2.3.2",
"classnames": "^2.5.1",
"dom-serializer": "^1.3.2",
"domhandler": "^4.3.1",
"easymde": "2.18.0",
"html-to-react": "1.5.0",
"htmlparser2": "^4.1.0",
"intelligent-tree-select": "0.11.4",
"intelligent-tree-select": "0.11.8",
"iso-639-1": "^2.1.15",
"javascript-time-ago": "2.5.9",
"javascript-time-ago": "2.5.11",
"js-cookie": "^3.0.5",
"jsonld": "8.3.2",
"last": "^1.1.0",
"ld-query": "^2.6.1",
"lodash": "^4.17.21",
"luxon": "^3.3.0",
"luxon": "^3.5.0",
"marked": "^9.1.6",
"object-assign": "4.1.1",
"oidc-client": "^1.11.5",
Expand Down Expand Up @@ -59,7 +59,8 @@
"redux-thunk": "^2.4.2",
"resolve": "1.22.2",
"simple-xpath-position": "^2.0.2",
"uuid": "^9.0.0",
"use-debounce": "^10.0.4",
"uuid": "^10.0.0",
"whatwg-fetch": "3.6.2",
"whatwg-mimetype": "3.0.0"
},
Expand All @@ -83,21 +84,21 @@
"@types/enzyme": "^3.10.13",
"@types/jest": "^27.4.1",
"@types/js-cookie": "^3.0.3",
"@types/lodash": "^4.14.195",
"@types/luxon": "^3.3.0",
"@types/lodash": "^4.17.10",
"@types/luxon": "^3.4.2",
"@types/node": "^18.11.17",
"@types/react": "^17.0.61",
"@types/react-dom": "^17.0.20",
"@types/react-helmet": "^6.1.6",
"@types/react-highlight-words": "^0.16.4",
"@types/react-router-dom": "^5.3.3",
"@types/react-table": "^7.7.14",
"@types/redux-logger": "^3.0.9",
"@types/redux-logger": "^3.0.13",
"@types/redux-mock-store": "^1.0.3",
"@types/uuid": "^9.0.2",
"@types/uuid": "^10.0.0",
"@types/whatwg-mimetype": "^2.1.1",
"@wojtekmaj/enzyme-adapter-react-17": "^0.8.0",
"axios-mock-adapter": "^1.22.0",
"axios-mock-adapter": "^2.1.0",
"babel-plugin-macros": "2.8.0",
"cross-env": "^7.0.3",
"enzyme": "^3.11.0",
Expand All @@ -106,8 +107,8 @@
"jest-localstorage-mock": "^2.4.26",
"jest-react-hooks-shallow": "^1.5.1",
"jest-watch-typeahead": "^0.6.5",
"prettier": "2.3.0",
"pretty-quick": "^3.1.3",
"prettier": "2.8.8",
"pretty-quick": "^3.3.1",
"raw.macro": "0.6.2",
"redux-mock-store": "^1.5.4",
"sass": "^1.63.3",
Expand Down
30 changes: 0 additions & 30 deletions src/action/AsyncActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1130,36 +1130,6 @@ export function loadLatestTextAnalysisRecord(resourceIri: IRI) {
};
}

/**
* Downloads the content of a file with the specified IRI (assuming it is stored on the server).
* @param fileIri File identifier
* @param at Timestamp of the file version to download
*/
export function exportFileContent(fileIri: IRI, at?: string) {
const action = {
type: ActionType.EXPORT_FILE_CONTENT,
};
return (dispatch: ThunkDispatch) => {
dispatch(asyncActionRequest(action));
const url =
Constants.API_PREFIX + "/resources/" + fileIri.fragment + "/content";
return Ajax.getRaw(
url,
param("namespace", fileIri.namespace)
.param("attachment", "true")
.param("at", at)
.responseType("arraybuffer")
)
.then((resp: AxiosResponse) => {
const fileName = fileIri.fragment;
const mimeType = resp.headers["content-type"];
Utils.fileDownload(resp.data, fileName, mimeType);
return dispatch(asyncActionSuccess(action));
})
.catch((error: ErrorData) => dispatch(asyncActionFailure(action, error)));
};
}

export function loadHistory(asset: Asset) {
const assetIri = VocabularyUtils.create(asset.iri);
const historyConf = resolveHistoryLoadingParams(asset, assetIri);
Expand Down
42 changes: 42 additions & 0 deletions src/action/AsyncResourceActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import JsonLdUtils from "../util/JsonLdUtils";
import File, { FileData } from "../model/File";
import { CONTEXT as DOCUMENT_CONTEXT } from "../model/Document";
import { ErrorData } from "../model/ErrorInfo";
import { AxiosResponse } from "axios";
import Utils from "../util/Utils";

export function loadFileMetadata(fileIri: IRI) {
const action = { type: ActionType.LOAD_FILE_METADATA };
Expand All @@ -37,3 +39,43 @@ export function loadFileMetadata(fileIri: IRI) {
});
};
}

/**
* Downloads the content of a file with the specified IRI (assuming it is stored on the server).
* @param fileIri File identifier
* @param options File export options
*/
export function exportFileContent(
fileIri: IRI,
options: {
at?: string;
withoutUnconfirmedOccurrences?: boolean;
} = {}
) {
const action = {
type: ActionType.EXPORT_FILE_CONTENT,
};
return (dispatch: ThunkDispatch) => {
dispatch(asyncActionRequest(action));
const url =
Constants.API_PREFIX + "/resources/" + fileIri.fragment + "/content";
return Ajax.getRaw(
url,
param("namespace", fileIri.namespace)
.param("attachment", "true")
.param("at", options.at)
.param(
"withoutUnconfirmedOccurrences",
options.withoutUnconfirmedOccurrences?.toString()
)
.responseType("arraybuffer")
)
.then((resp: AxiosResponse) => {
const fileName = fileIri.fragment;
const mimeType = resp.headers["content-type"];
Utils.fileDownload(resp.data, fileName, mimeType);
return dispatch(asyncActionSuccess(action));
})
.catch((error: ErrorData) => dispatch(asyncActionFailure(action, error)));
};
}
12 changes: 9 additions & 3 deletions src/action/AsyncTermActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*
* This file contains asynchronous actions related to term management in the frontend.
*/
import VocabularyUtils, { IRI } from "../util/VocabularyUtils";
import VocabularyUtils, { IRI, IRIImpl } from "../util/VocabularyUtils";
import ActionType from "./ActionType";
import { GetStoreState, ThunkDispatch } from "../util/Types";
import * as SyncActions from "./SyncActions";
Expand Down Expand Up @@ -84,8 +84,14 @@ function resolveTermCreationUrl(term: Term, targetVocabularyIri: IRI) {
let url = `${ENDPOINT}${targetVocabularyIri.fragment}/terms`;
const parents = Utils.sanitizeArray(term.parentTerms);
if (parents.length > 0) {
// Use one of the parents, it does not matter which one
url += `/${VocabularyUtils.create(parents[0].iri!).fragment}/subterms`;
const parentInThisVocabulary = parents.find(
(p) => p.vocabulary!.iri === IRIImpl.toString(targetVocabularyIri)
);
if (parentInThisVocabulary) {
url += `/${
VocabularyUtils.create(parentInThisVocabulary.iri!).fragment
}/subterms`;
}
}
return url;
}
Expand Down
39 changes: 38 additions & 1 deletion src/action/AsyncVocabularyActions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GetStoreState, ThunkDispatch } from "../util/Types";
import { GetStoreState, PageRequest, ThunkDispatch } from "../util/Types";
import * as SyncActions from "./SyncActions";
import {
asyncActionFailure,
Expand Down Expand Up @@ -27,6 +27,10 @@ import SnapshotData, { CONTEXT as SNAPSHOT_CONTEXT } from "../model/Snapshot";
import NotificationType from "../model/NotificationType";
import ExportConfig from "../model/local/ExportConfig";
import RDFStatement, { RDFSTATEMENT_CONTEXT } from "../model/RDFStatement";
import ChangeRecord, {
CONTEXT as CHANGE_RECORD_CONTEXT,
} from "../model/changetracking/ChangeRecord";
import AssetFactory from "../util/AssetFactory";

export function loadTermCount(vocabularyIri: IRI) {
const action = { type: ActionType.LOAD_TERM_COUNT, vocabularyIri };
Expand Down Expand Up @@ -131,6 +135,39 @@ export function loadVocabularyContentChanges(vocabularyIri: IRI) {
};
}

export function loadVocabularyContentDetailedChanges(
vocabularyIri: IRI,
pageReq: PageRequest
) {
const action = {
type: ActionType.LOAD_TERM_HISTORY,
};

return (dispatch: ThunkDispatch) => {
dispatch(asyncActionRequest(action, true));
return Ajax.get(
`${Constants.API_PREFIX}/vocabularies/${vocabularyIri.fragment}/history-of-content/detail`,
param("namespace", vocabularyIri.namespace)
.param("page", pageReq.page?.toString())
.param("size", pageReq.size?.toString())
)
.then((data) =>
JsonLdUtils.compactAndResolveReferencesAsArray<ChangeRecord>(
data,
CHANGE_RECORD_CONTEXT
)
)
.then((data: ChangeRecord[]) => {
dispatch(asyncActionSuccess(action));
return data.map((r) => AssetFactory.createChangeRecord(r));
})
.catch((error: ErrorData) => {
dispatch(asyncActionFailure(action, error));
return [];
});
};
}

export function loadRelatedVocabularies(vocabularyIri: IRI) {
const action = { type: ActionType.LOAD_RELATED_VOCABULARIES, vocabularyIri };
return (dispatch: ThunkDispatch) => {
Expand Down
3 changes: 1 addition & 2 deletions src/action/SearchActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export function removeSearchListener() {
* Timer to delay search requests as user is still typing.
*/
let updateSearchTimer: ReturnType<typeof setTimeout> | null = null;
const updateSearchDelay = 400; // ms

/**
* Change the search criteria and trigger a new search.
Expand Down Expand Up @@ -85,7 +84,7 @@ export function updateSearchFilter(searchString: string) {
updateSearchTimer = setTimeout(() => {
updateSearchTimer = null;
dispatch(searchEverything());
}, updateSearchDelay);
}, Constants.SEARCH_DEBOUNCE_DELAY);
return Promise.resolve();
}
};
Expand Down
Loading

0 comments on commit 33a7241

Please sign in to comment.