Skip to content

Commit

Permalink
Merge pull request #554 from kbss-cvut/enhancement#528-ontographer-in…
Browse files Browse the repository at this point in the history
…tegration

Enhancement#528 ontographer integration
  • Loading branch information
ledsoft authored Oct 23, 2024
2 parents bd1b22c + f7c67b1 commit 3749047
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 2 deletions.
4 changes: 3 additions & 1 deletion src/component/misc/ConfirmCancelDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ interface ConfirmCancelDialogProps {
confirmDisabled?: boolean;
cancelKey?: string;
cancelColor?: string;
size?: string;
size?: "lg" | "sm";
className?: string;
}

/**
Expand All @@ -37,6 +38,7 @@ const ConfirmCancelDialog: React.FC<ConfirmCancelDialogProps> = (props) => {
isOpen={props.show}
toggle={props.onClose}
size={props.size}
className={props.className}
>
<ModalHeader toggle={props.onClose}>{props.title}</ModalHeader>
<ModalBody>{props.children}</ModalBody>
Expand Down
36 changes: 35 additions & 1 deletion src/component/vocabulary/VocabularyActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,23 @@ import {
DropdownToggle,
UncontrolledButtonDropdown,
} from "reactstrap";
import { GoClippy, GoCloudDownload, GoCloudUpload } from "react-icons/go";
import {
GoClippy,
GoCloudDownload,
GoCloudUpload,
GoRepoForked,
} from "react-icons/go";
import ImportBackupOfVocabulary from "./importing/ImportBackupOfVocabulary";
import { FaCamera } from "react-icons/fa";
import Vocabulary from "../../model/Vocabulary";
import IfVocabularyActionAuthorized from "./authorization/IfVocabularyActionAuthorized";
import AccessLevel from "../../model/acl/AccessLevel";
import IfUserIsAdmin from "../authorization/IfUserIsAdmin";
import If from "../misc/If";
import { useSelector } from "react-redux";
import TermItState from "../../model/TermItState";
import Utils from "../../util/Utils";
import OpenModelingToolDialog from "./modeling/OpenModelingToolDialog";

interface VocabularyActionsProps {
vocabulary: Vocabulary;
Expand All @@ -31,6 +41,8 @@ const VocabularyActions: React.FC<VocabularyActionsProps> = ({
}) => {
const { i18n } = useI18n();
const [showImportDialog, setShowImportDialog] = React.useState(false);
const [showModelingDialog, setShowModelingDialog] = React.useState(false);
const config = useSelector((state: TermItState) => state.configuration);

return (
<>
Expand All @@ -39,6 +51,11 @@ const VocabularyActions: React.FC<VocabularyActionsProps> = ({
showDialog={showImportDialog}
closeDialog={() => setShowImportDialog(false)}
/>
<OpenModelingToolDialog
open={showModelingDialog}
onClose={() => setShowModelingDialog(false)}
vocabulary={vocabulary}
/>
<UncontrolledButtonDropdown className="ml-1">
<DropdownToggle
size="sm"
Expand Down Expand Up @@ -99,6 +116,23 @@ const VocabularyActions: React.FC<VocabularyActionsProps> = ({
{i18n("vocabulary.snapshot.create.label")}
</DropdownItem>
</IfUserIsAdmin>
<If expression={Utils.notBlank(config.modelingToolUrl)}>
<IfVocabularyActionAuthorized
vocabulary={vocabulary}
requiredAccessLevel={AccessLevel.WRITE}
key="vocabulary-model"
>
<DropdownItem
name="vocabulary-model"
className="btn-sm"
title={i18n("vocabulary.summary.model.title")}
onClick={() => setShowModelingDialog(true)}
>
<GoRepoForked className="mr-1 align-text-top" />
{i18n("vocabulary.summary.model.label")}
</DropdownItem>
</IfVocabularyActionAuthorized>
</If>
</DropdownMenu>
</UncontrolledButtonDropdown>
</>
Expand Down
9 changes: 9 additions & 0 deletions src/component/vocabulary/modeling/OpenModelingToolDialog.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.modeling-vocabulary-select-dialog {
max-width: 80%;
}

input.vocabulary-checkbox {
position: relative;
margin-left: 0;
margin-right: 0.5rem;
}
120 changes: 120 additions & 0 deletions src/component/vocabulary/modeling/OpenModelingToolDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import React from "react";
import Vocabulary from "../../../model/Vocabulary";
import { useI18n } from "../../hook/useI18n";
import ConfirmCancelDialog from "../../misc/ConfirmCancelDialog";
import { getLocalized } from "../../../model/MultilingualString";
import { ThunkDispatch } from "../../../util/Types";
import { useDispatch, useSelector } from "react-redux";
import { loadRelatedVocabularies } from "../../../action/AsyncVocabularyActions";
import VocabularyUtils from "../../../util/VocabularyUtils";
import TermItState from "../../../model/TermItState";
import { loadVocabularies } from "../../../action/AsyncActions";
import { Col, Input, Row } from "reactstrap";
import { getShortLocale } from "../../../util/IntlUtil";
import "./OpenModelingToolDialog.scss";

const COLUMN_COUNT = 3;

interface OpenModelingToolDialogProps {
open: boolean;
onClose: () => void;
vocabulary: Vocabulary;
}

const OpenModelingToolDialog: React.FC<OpenModelingToolDialogProps> = ({
open,
onClose,
vocabulary,
}) => {
const { formatMessage, i18n, locale } = useI18n();
const dispatch: ThunkDispatch = useDispatch();
const [relatedVocabularies, setRelatedVocabularies] = React.useState<
string[]
>([]);
const [selectedVocabularies, setSelectedVocabularies] = React.useState<
string[]
>([]);
const modelingToolUrl = useSelector(
(state: TermItState) => state.configuration
).modelingToolUrl;
const vocabularies = useSelector((state: TermItState) => state.vocabularies);
const vocabularyIris = Object.keys(vocabularies);
React.useEffect(() => {
dispatch(
loadRelatedVocabularies(VocabularyUtils.create(vocabulary.iri))
).then((data) => {
setRelatedVocabularies(data);
// The vocabulary is also among the related vocabularies loaded from the server
setSelectedVocabularies(data);
});
if (Object.keys(vocabularies).length === 0) {
dispatch(loadVocabularies());
}
}, [vocabulary.iri, vocabularies, dispatch]);

const onSelect = (vIri: string) => {
if (selectedVocabularies.includes(vIri)) {
setSelectedVocabularies(selectedVocabularies.filter((v) => v !== vIri));
} else {
setSelectedVocabularies([...selectedVocabularies, vIri]);
}
};
const onOpen = () => {
let params = selectedVocabularies
.map((v) => encodeURIComponent(v))
.join("&vocabulary=");
window.location.href = modelingToolUrl + "?vocabulary=" + params;
};

const rowCount = Math.ceil(vocabularyIris.length / COLUMN_COUNT);
const rows = [];
for (let i = 0; i < rowCount; i++) {
const cols = [];
for (let j = 0; j < COLUMN_COUNT; j++) {
const index = i * COLUMN_COUNT + j;
if (index >= vocabularyIris.length) {
break;
}
cols.push(
<Col key={index} md={12 / COLUMN_COUNT}>
<Input
type="checkbox"
checked={selectedVocabularies.includes(vocabularyIris[index])}
disabled={relatedVocabularies.includes(vocabularyIris[index])}
onChange={() => onSelect(vocabularyIris[index])}
className="vocabulary-checkbox"
/>
{getLocalized(
vocabularies[vocabularyIris[index]].label,
getShortLocale(locale)
)}
</Col>
);
}
rows.push(
<Row key={i} className="mb-2">
{cols}
</Row>
);
}

return (
<ConfirmCancelDialog
id="vocabulary-model-dialog"
show={open}
onClose={onClose}
confirmKey="vocabulary.summary.model.open"
onConfirm={onOpen}
title={formatMessage("vocabulary.summary.model.dialog.title", {
vocabulary: getLocalized(vocabulary.label),
})}
size="lg"
className="modeling-vocabulary-select-dialog"
>
<p className="mb-4">{i18n("vocabulary.summary.model.dialog.text")}</p>
{rows}
</ConfirmCancelDialog>
);
};

export default OpenModelingToolDialog;
8 changes: 8 additions & 0 deletions src/i18n/cs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,14 @@ const cs = {
"Při zaškrtnutí tohoto políčka budou při importu identifikátory nahrazeny novými, pokud by kolidovaly s existujícími identifikátory.",
"vocabulary.summary.startTextAnalysis.title":
"Spustit textovou analýzu definic všech pojmů v tomto slovníku",
"vocabulary.summary.model.label": "Modelovat vztahy",
"vocabulary.summary.model.title":
"Modelovat vztahy mezi pojmy ve slovníku pomocí externího nástroje",
"vocabulary.summary.model.open": "Otevřít",
"vocabulary.summary.model.dialog.title":
"Modelovat vztahy pojmů slovníku {vocabulary}",
"vocabulary.summary.model.dialog.text":
"Vyberte slovníky, které chcete pro modelování otevřít. Předvybrány jsou slovníky, které s otevíraným slovníkem souvisí a musí být v seznamy zahrnuty.",
"vocabulary.updated.message": "Slovník úspěšně uložen.",
"vocabulary.created.message": "Slovník úspěšně vytvořen.",
"vocabulary.detail.subtitle": "Vytvořen autorem {author} ",
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,14 @@ const en = {
"When ticked, identifiers colliding with existing ones will be replaced by new ones.",
"vocabulary.summary.startTextAnalysis.title":
"Start text analysis on definitions of all terms in this vocabulary",
"vocabulary.summary.model.label": "Model relationships",
"vocabulary.summary.model.title":
"Model relationships between terms in this vocabulary using an external tool",
"vocabulary.summary.model.open": "Open",
"vocabulary.summary.model.dialog.title":
"Model relationships of terms in {vocabulary}",
"vocabulary.summary.model.dialog.text":
"Select vocabularies you want to open for modeling. Vocabularies related to the one being open are pre-selected as they are required by the modeling tool.",
"vocabulary.updated.message": "Vocabulary successfully updated.",
"vocabulary.created.message": "Vocabulary successfully created.",
"vocabulary.detail.subtitle": "Created by {author} on ",
Expand Down
2 changes: 2 additions & 0 deletions src/model/Configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const ctx = {
roles: `${VocabularyUtils.NS_TERMIT}má-uživatelskou-roli`,
maxFileUploadSize: `${VocabularyUtils.NS_TERMIT}má-maximální-velikost-souboru`,
versionSeparator: `${VocabularyUtils.NS_TERMIT}má-oddělovač-verze`,
modelingToolUrl: `${VocabularyUtils.NS_TERMIT}má-adresu-modelovacího-nástroje`,
};

export const CONTEXT = Object.assign({}, USERROLE_CONTEXT, ctx);
Expand All @@ -21,6 +22,7 @@ export interface Configuration {
roles: UserRole[];
maxFileUploadSize: string;
versionSeparator: string;
modelingToolUrl?: string;
}

export const DEFAULT_CONFIGURATION: Configuration = {
Expand Down
4 changes: 4 additions & 0 deletions src/util/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ const Utils = {
}
return true;
},

notBlank(str?: string | null) {
return !!(str && str.trim().length > 0);
},
};

export default Utils;

0 comments on commit 3749047

Please sign in to comment.