Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/fix glossary links #479

Merged
merged 1 commit into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion client/public/locales/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
},
"text": {
"insertTopicDescription": "Themenbeschreibungen einfügen",
"generateNavigation": "Erstelle Navigation"
"generateNavigation": "Erstelle Navigation",
"pleaseSelectSubChapter": "Bitte wählen Sie ein Unterkapitel."
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
decodeXml,
fixLinksInText,
flatten,
getFigureDesignationFromText,
getJsonDataFromXml,
getMenuItemByAttributeValue,
getSearchStringFromHash,
Expand All @@ -26,6 +27,7 @@ import { PageEntryContent } from './PageEntryContent';
import { weitApiUrl } from '../../../app/App';
import { HashLink } from 'react-router-hash-link';
import { DataEntry, PageEntry, TableEntry } from '../Documentation';
import { ProjectType } from '../../projekt/project';

export function Content() {
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -59,6 +61,7 @@ export function Content() {
activityId,
templateDisciplineId,
productDisciplineId,
glossaryEntryId,
entryId,
selectedIndexType,
} = useDocumentation();
Expand Down Expand Up @@ -292,6 +295,18 @@ export function Content() {
//eslint-disable-next-line
}, [templateDisciplineId]);

useEffect(() => {
async function mount() {
if (glossaryEntryId) {
const content = await getGlossaryEntryContent();
setSelectedPageEntry(content);
}
}

void mount().then();
//eslint-disable-next-line
}, [glossaryEntryId]);

useEffect(() => {
async function mount() {
if (entryId) {
Expand Down Expand Up @@ -496,6 +511,8 @@ export function Content() {
const childText = jsonDataFromXml.children.find((child) => child.name === 'Text');
if (childText) {
textPart = decodeXml(childText.value);
} else {
textPart = t('text.pleaseSelectSubChapter');
}
}

Expand Down Expand Up @@ -535,7 +552,7 @@ export function Content() {
id: jsonDataFromXml.attributes.id,
// menuEntryId: jsonDataFromXml.attributes.id,
header: jsonDataFromXml.attributes.name,
descriptionText: '',
descriptionText: t('text.pleaseSelectSubChapter'),
tableEntries: tableEntries,
// subPageEntries: subPageEntries,
};
Expand Down Expand Up @@ -740,7 +757,10 @@ export function Content() {
}
/////////////////////////////

const tools = [...activities, ...products, ...activitiesToTools];
// To hide the links to the activities in the tools section of a product the id has to removed here
const activitiesWithoutId = activities.map(({ id, ...keepAttrs }) => keepAttrs);

const tools = [...activitiesWithoutId, ...products, ...activitiesToTools];

if (tools.length > 0) {
tableEntries.push({
Expand Down Expand Up @@ -1831,6 +1851,30 @@ export function Content() {
return jsonDataFromXml.getElementsByTagName('Aktivität');
}

async function getGlossaryEntryContent(): Promise<XMLElement[]> {
const expressionUrl =
weitApiUrl +
'/V-Modellmetamodell/mm_2021/V-Modellvariante/' +
tailoringParameter.modelVariantId +
'/Begriff/' +
glossaryEntryId;

const jsonDataFromXml = await getJsonDataFromXml(expressionUrl);

const description = decodeXml(jsonDataFromXml.getElementsByTagName('Erläuterung')[0]?.value);

const tableEntries: TableEntry[] = [];

//////////////////////////////////////////////

return {
id: jsonDataFromXml.attributes.id,
header: jsonDataFromXml.attributes.name,
descriptionText: description,
tableEntries: tableEntries,
};
}

async function getTemplatesContent(): Promise<PageEntry> {
const disciplineId = templateDisciplineId?.replace('td_', '');
// get all products with externalTemplate info for templateDisciplineId
Expand Down Expand Up @@ -1875,7 +1919,6 @@ export function Content() {

const jsonDataFromXml = await getJsonDataFromXml(externalTemplateUrl);

const templateId = jsonDataFromXml.attributes.id;
const templateName = jsonDataFromXml.attributes.name;
const templateUri = jsonDataFromXml.getElementsByTagName('URI')[0]?.value;

Expand Down Expand Up @@ -1986,10 +2029,31 @@ export function Content() {
const methodReferences = activity.getElementsByTagName('MethodenreferenzRef');
for (const methodReference of methodReferences) {
if (methodReference.attributes.id === methodReferenceId) {
activitiesToTools.push({
id: activity.attributes.id,
title: activity.attributes.name,
});
/* The method and tool references (reference work aids) contain links to the corresponding activities.
As the activities are no longer part of the documentation (since version 2.4), the links cannot be resolved.
Instead of the activity, a link should therefore be created to the product linked to the activity.

-> So, if the activity id is not in navigation menu change linked site to products page of the activity.
*/

const foundActivity = getMenuItemByAttributeValue(navigationData, 'key', activity.attributes.id);

if (foundActivity) {
activitiesToTools.push({
id: activity.attributes.id,
title: activity.attributes.name,
});
} else {
const products = activity.getElementsByTagName('ProduktRef');

for (const product of products) {
activitiesToTools.push({
id: product.attributes.id,
title: activity.attributes.name,
suffix: '(' + product.attributes.name + ')',
});
}
}
}
}
}
Expand Down Expand Up @@ -2454,7 +2518,30 @@ export function Content() {

let idCounter = 2000;

const title = decodeXml(jsonDataFromXml.attributes.name);
const projectType: ProjectType = jsonDataFromXml.getElementsByTagName('ProjekttypRef')[0]
?.attributes as ProjectType;

const sequence = decodeXml(jsonDataFromXml.getElementsByTagName('Ablauf')[0]?.value);
const figureDesignation = getFigureDesignationFromText(sequence);

const getFigureUrl =
weitApiUrl +
'/Tailoring/V-Modellmetamodell/mm_2021/V-Modellvariante/' +
tailoringParameter.modelVariantId +
'/Projekttyp/' +
projectType.id +
'/Projekttypvariante/' +
projectTypeVariantId +
'/Grafik/Abb:' +
figureDesignation +
'?' +
getProjectFeaturesString();

const imageTag = '<p><img alt="" id="1489155545306" src=' + getFigureUrl + '/></p>';
const imageDescriptionTag =
'<p style="margin-top: 0px;">' + '<i>Abbildung [' + figureDesignation + ']: ' + title + '</i></p>';

const ablaufbausteinRefs: XMLElement[] = jsonDataFromXml.getElementsByTagName('AblaufbausteinRef');

const ablaufbausteine = ablaufbausteinRefs.map((ablaufbausteinRef) => {
Expand Down Expand Up @@ -2482,7 +2569,8 @@ export function Content() {
id: jsonDataFromXml.attributes.id,
// menuEntryId: jsonDataFromXml.attributes.id,
header: jsonDataFromXml.attributes.name,
descriptionText: replaceUrlInText(sequence, tailoringParameter, getProjectFeaturesString()),
descriptionText:
replaceUrlInText(sequence, tailoringParameter, getProjectFeaturesString()) + imageTag + imageDescriptionTag,
tableEntries: tableEntries,
// subPageEntries: subPageEntries,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { DataEntry } from '../Documentation';
export function TableEntriesList(props: { inputData: DataEntry[] }) {
const entries: JSX.Element[] = [];

props.inputData.map((entryItem: DataEntry) => {
props.inputData.map((entryItem: DataEntry, entryItemIndex: number) => {
if (Array.isArray(entryItem)) {
for (const entrySubItem of entryItem) {
entries.push(
Expand All @@ -23,7 +23,7 @@ export function TableEntriesList(props: { inputData: DataEntry[] }) {
</span>
);

entrySubItem.dataEntries.map((innerEntryItem: DataEntry) => {
entrySubItem.dataEntries.map((innerEntryItem: DataEntry, innerEntryItemIndex: number) => {
if (innerEntryItem?.id) {
entries.push(
<span style={{ marginRight: '20px', display: 'inline-flex' }} key={`table-item-${innerEntryItem.id}`}>
Expand All @@ -34,20 +34,30 @@ export function TableEntriesList(props: { inputData: DataEntry[] }) {
</span>
);
} else {
entries.push(<span style={{ marginRight: '20px' }}>{parse(fixLinksInText(innerEntryItem.title))}</span>);
entries.push(
<span style={{ marginRight: '20px' }} key={`table-item-entrySubItem-${innerEntryItemIndex}`}>
{parse(fixLinksInText(innerEntryItem.title))}
{innerEntryItem.suffix && <span style={{ marginLeft: '5px' }}>{innerEntryItem.suffix}</span>}
</span>
);
}
});
}
} else {
if (entryItem?.id) {
entries.push(
<span style={{ marginRight: '20px', display: 'inline-flex' }} key={`table-item-${entryItem.id}`}>
<span style={{ marginRight: '20px', display: 'inline-flex' }} key={`table-item-entryItem-${entryItem.id}`}>
<Link to={`/documentation/${entryItem.id}${getSearchStringFromHash()}`}>{entryItem.title}</Link>
{entryItem.suffix && <span style={{ marginLeft: '5px' }}>{entryItem.suffix}</span>}
</span>
);
} else {
entries.push(<span style={{ marginRight: '20px' }}>{parse(fixLinksInText(entryItem.title))}</span>);
entries.push(
<span style={{ marginRight: '20px' }} key={`table-item-entryItem-${entryItemIndex}`}>
{parse(fixLinksInText(entryItem.title))}
{entryItem.suffix && <span style={{ marginLeft: '5px' }}>{entryItem.suffix}</span>}
</span>
);
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export enum NavTypeEnum {
TEMPLATE_DISCIPLINE = 'templateDiscipline',
PRODUCT_DISCIPLINE = 'productDiscipline',
SAMPLE_TEXT = 'sampleText',
GLOSSARY_ENTRY = 'glossaryEntry',
}

export enum IndexTypeEnum {
Expand Down Expand Up @@ -108,7 +109,7 @@ export interface SectionDetail {
replacedContent?: NavMenuItem[];
mergedChildren?: NavMenuItem[];
addedChildren?: NavMenuItem[];
indexItem?: { key: string; label: string; onClick: () => any };
indexItem?: { key: string; label: string; children: NavMenuItem[]; onClick?: () => any; onTitleClick?: () => any };
}

export type NavMenuItem = {
Expand Down Expand Up @@ -221,11 +222,20 @@ export function Navigation() {
i++;
// }
}

// cleanup menu clicks because inner nodes of the ant tree throw onTitleClick event
// and leaf nodes throw onClick event
if (item.children && item.children.length > 0) {
item.onTitleClick = (item: any) => handleSelectedItem(item.key);
// Überschreibt ansonsten das onTitleClick aus dem Index:Arbeitshilfen
if (!item.hasOwnProperty('onTitleClick')) {
item.onTitleClick = (item: any) => handleSelectedItem(item.key);
}
await addParentRecursive(item.children);
} else {
item.onClick = (item: any) => handleSelectedItem(item.key);
// Überschreibt ansonsten das onClick aus dem Index:Arbeitshilfen
if (!item.hasOwnProperty('onClick')) {
item.onClick = (item: any) => handleSelectedItem(item.key);
}
item.children = undefined;
}
}
Expand Down Expand Up @@ -276,6 +286,11 @@ export function Navigation() {
addedChildren = getDisciplineGroup(childItem.parent, jsonDataFromXml).filter((navMenuItem) =>
disciplineIds.includes(navMenuItem.key)
);
} else if (
generatedContent === 'Elemente:Produktvorlagen_und_Beispielprodukte_nach_Disziplinen' &&
childItem.parent
) {
addedChildren = await getTemplates(childItem);
} else {
switch (generatedContent) {
case 'Index:Produkte': {
Expand Down Expand Up @@ -314,14 +329,21 @@ export function Navigation() {
indexItem = {
key: childItem.key,
label: childItem.label,
onClick: () => setSelectedIndexType(IndexTypeEnum.WORK_AIDS),
children: childItem.children,
onClick:
childItem.children?.length > 0 ? () => false : () => setSelectedIndexType(IndexTypeEnum.WORK_AIDS),
onTitleClick: () => setSelectedIndexType(IndexTypeEnum.WORK_AIDS),
};
break;
}
}
}
}

if (childItem.label === 'Glossar') {
addedChildren = await getGlossaryEntries(childItem);
}

if (
childItem.parent?.label === 'Produktabhängigkeiten' &&
childItem.label === 'Inhaltliche Produktabhängigkeiten'
Expand Down Expand Up @@ -797,6 +819,23 @@ export function Navigation() {
});
}

async function getGlossaryEntries(target: NavMenuItem): Promise<NavMenuItem[]> {
const expressionsUrl =
weitApiUrl + '/V-Modellmetamodell/mm_2021/V-Modellvariante/' + tailoringParameter.modelVariantId + '/Begriff/';

const jsonDataFromXml = await getJsonDataFromXml(expressionsUrl);

return jsonDataFromXml.getElementsByTagName('Begriff').map((expression) => {
return {
key: expression.attributes.id,
parent: target,
label: expression.attributes.name,
dataType: NavTypeEnum.GLOSSARY_ENTRY,
onClick: (item: any) => handleSelectedItem(item.key),
};
});
}

async function getTemplates(target: NavMenuItem): Promise<NavMenuItem[]> {
const templatesUrl =
weitApiUrl +
Expand Down Expand Up @@ -923,6 +962,7 @@ export function Navigation() {
label: projectTypeVariantValue.attributes.name,
dataType: NavTypeEnum.PROJECT_TYPE_VARIANT_SEQUENCE, // TODO: oder auch ProjectExecutionStrategy
onClick: (item: any) => handleSelectedItem(item.key), // TODO: different Types
onTitleClick: (item: any) => handleSelectedItem(item.key), // TODO: different Types
});
});

Expand Down
6 changes: 6 additions & 0 deletions client/src/context/DocumentationContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type DocumentationSession = {
activityId: string | null;
templateDisciplineId: string | null;
productDisciplineId: string | null;
glossaryEntryId: string | null;
entryId: string | null;
getNavigationPath: Function;
onRouteChanged: Function;
Expand Down Expand Up @@ -80,6 +81,7 @@ const DocumentationSessionContextProvider = ({ children }: DocumentationSessionP
const [activityId, setActivityId] = useState<string | null>(null);
const [templateDisciplineId, setTemplateDisciplineId] = useState<string | null>(null);
const [productDisciplineId, setProductDisciplineId] = useState<string | null>(null);
const [glossaryEntryId, setGlossaryEntryId] = useState<string | null>(null);
const [entryId, setEntryId] = useState<string | null>(null);

const value: DocumentationSession = {
Expand Down Expand Up @@ -108,6 +110,7 @@ const DocumentationSessionContextProvider = ({ children }: DocumentationSessionP
activityId,
templateDisciplineId,
productDisciplineId,
glossaryEntryId,
entryId,
getNavigationPath,
onRouteChanged,
Expand Down Expand Up @@ -156,6 +159,7 @@ const DocumentationSessionContextProvider = ({ children }: DocumentationSessionP
setActivityId(null);
setTemplateDisciplineId(null);
setProductDisciplineId(null);
setGlossaryEntryId(null);
setEntryId(null);
}

Expand Down Expand Up @@ -206,6 +210,8 @@ const DocumentationSessionContextProvider = ({ children }: DocumentationSessionP
setActivityId(foundMenuItem.key);
} else if (foundMenuItem.dataType === NavTypeEnum.TEMPLATE_DISCIPLINE) {
setTemplateDisciplineId(foundMenuItem.key);
} else if (foundMenuItem.dataType === NavTypeEnum.GLOSSARY_ENTRY) {
setGlossaryEntryId(foundMenuItem.key);
} else {
setEntryId(foundMenuItem.key);
}
Expand Down
Loading
Loading