Skip to content

Commit

Permalink
Diagram Helper APIs (#325)
Browse files Browse the repository at this point in the history
  • Loading branch information
loreanvictor authored Nov 25, 2023
1 parent 064bb5e commit a959e04
Show file tree
Hide file tree
Showing 12 changed files with 769 additions and 34 deletions.
3 changes: 2 additions & 1 deletion src/main/apollon-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { debounce } from './utils/debounce';
import { delay } from './utils/delay';
import { ErrorBoundary } from './components/controls/error-boundary/ErrorBoundary';
import { replaceColorVariables } from './utils/replace-color-variables';
import { UMLModelCompat } from './compat';

export class ApollonEditor {
private ensureInitialized() {
Expand All @@ -46,7 +47,7 @@ export class ApollonEditor {
* Sets a model as the current model of the Apollon Editor
* @param model valid Apollon Editor Model
*/
set model(model: Apollon.UMLModel) {
set model(model: UMLModelCompat) {
this.ensureInitialized();
const state: PartialModelState = {
...ModelState.fromModel(model),
Expand Down
160 changes: 160 additions & 0 deletions src/main/compat/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { Assessment, UMLElement, UMLRelationship } from '../typings';
import { UMLModelCompat } from './typings';
import {
isV2,
findElement as findElementV2,
addOrUpdateElement as addOrUpdateElementV2,
findRelationship as findRelationshipV2,
addOrUpdateRelationship as addOrUpdateRelationshipV2,
findAssessment as findAssessmentV2,
addOrUpdateAssessment as addOrUpdateAssessmentV2,
isInteractiveElement as isInteractiveElementV2,
setInteractiveElement as setInteractiveElementV2,
isInteractiveRelationship as isInteractiveRelationshipV2,
setInteractiveRelationship as setInteractiveRelationshipV2,
} from './v2';

/**
*
* Finds an element in the model by id
*
* @param {UMLModelCompat} model the model to search
* @param {string} id the id of the element to find
* @returns {UMLElement | undefined} the element or undefined if not found
*/
export function findElement(model: UMLModelCompat, id: string): UMLElement | undefined {
if (isV2(model)) {
return findElementV2(model, id);
} else {
return model.elements[id];
}
}

/**
*
* Adds given element to given model. If element with same id already exists, it will be replaced.
*
* @param {UMLModelCompat} model the model to update
* @param {UMLElement} element the element to add or update
*/
export function addOrUpdateElement(model: UMLModelCompat, element: UMLElement): void {
if (isV2(model)) {
return addOrUpdateElementV2(model, element);
} else {
model.elements[element.id] = element;
}
}

/**
*
* Finds a relationship in the model by id
*
* @param {UMLModelCompat} model the model to search
* @param {string} id the id of the relationship to find
* @returns {UMLRelationship | undefined} the relationship or undefined if not found
*/
export function findRelationship(model: UMLModelCompat, id: string): UMLRelationship | undefined {
if (isV2(model)) {
return findRelationshipV2(model, id);
} else {
return model.relationships[id];
}
}

/**
*
* Adds given relationship to given model. If relationship with same id already exists, it will be replaced.
*
* @param {UMLModelCompat} model the model to update
* @param {UMLRelationship} relationship the relationship to add or update
*/
export function addOrUpdateRelationship(model: UMLModelCompat, relationship: UMLRelationship): void {
if (isV2(model)) {
return addOrUpdateRelationshipV2(model, relationship);
} else {
model.relationships[relationship.id] = relationship;
}
}

/**
*
* Finds an assessment in the model by id
*
* @param {UMLModelCompat} model the model to search
* @param {string} id the id of the assessment to find
* @returns {Assessment | undefined} the assessment or undefined if not found
*/
export function findAssessment(model: UMLModelCompat, id: string): Assessment | undefined {
if (isV2(model)) {
return findAssessmentV2(model, id);
} else {
return model.assessments[id];
}
}

/**
*
* Adds given assessment to given model. If assessment with same id already exists, it will be replaced.
*
* @param {UMLModelCompat} model the model to update
* @param {Assessment} assessment the assessment to add or update
*/
export function addOrUpdateAssessment(model: UMLModelCompat, assessment: Assessment): void {
if (isV2(model)) {
return addOrUpdateAssessmentV2(model, assessment);
} else {
model.assessments[assessment.modelElementId] = assessment;
}
}

/**
* @returns true if the element is interactive, false otherwise.
*/
export function isInteractiveElement(model: UMLModelCompat, id: string): boolean {
if (isV2(model)) {
return isInteractiveElementV2(model, id);
} else {
return !!model.interactive.elements[id];
}
}

/**
* Sets the interactive state of the element.
*
* @param {UMLModelCompat} model the model to update
* @param {string} id the id of the element to set interactive state
* @param {boolean} interactive the interactive state to set
*/
export function setInteractiveElement(model: UMLModelCompat, id: string, interactive: boolean): void {
if (isV2(model)) {
return setInteractiveElementV2(model, id, interactive);
} else {
model.interactive.elements[id] = interactive;
}
}

/**
* @returns true if the relationship is interactive, false otherwise.
*/
export function isInteractiveRelationship(model: UMLModelCompat, id: string): boolean {
if (isV2(model)) {
return isInteractiveRelationshipV2(model, id);
} else {
return !!model.interactive.relationships[id];
}
}

/**
* Sets the interactive state of the relationship.
*
* @param {UMLModelCompat} model the model to update
* @param {string} id the id of the relationship to set interactive state
* @param {boolean} interactive the interactive state to set
*/
export function setInteractiveRelationship(model: UMLModelCompat, id: string, interactive: boolean): void {
if (isV2(model)) {
return setInteractiveRelationshipV2(model, id, interactive);
} else {
model.interactive.relationships[id] = interactive;
}
}
25 changes: 5 additions & 20 deletions src/main/compat/index.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,6 @@
import { UMLModel } from '../typings';
import { isV2, UMLModelCompat as UMLModelCompatV2, v2ModeltoV3Model } from './v2';

/**
*
* Represents all model versions that can be converted to the latest version.
*
*/
/*
*
* HINT for future maintainers:
*
* this should always be the union of compatible model versions, i.e.
* if the model version is moved to V4, while support for V2 is still required,
* this should look like the following:
*
* ```ts
* export type UMLModelCompat = UMLModelCompatV2 | UMLModelCompatV3;
* ```
*/
export type UMLModelCompat = UMLModelCompatV2;
import { UMLModelCompat } from './typings';
import { isV2, v2ModeltoV3Model } from './v2';

/**
*
Expand All @@ -35,3 +17,6 @@ export function backwardsCompatibleModel(model: UMLModelCompat): UMLModel {
return model;
}
}

export type { UMLModelCompat } from './typings';
export * from './helpers';
18 changes: 18 additions & 0 deletions src/main/compat/typings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { UMLModelCompat as UMLModelCompatV2 } from './v2';

/*
*
* HINT for future maintainers:
*
* this should always be the union of compatible model versions, i.e.
* if the model version is moved to V4, while support for V2 is still required,
* this should look like the following:
*
* ```ts
* export type UMLModelCompat = UMLModelCompatV2 | UMLModelCompatV3;
* ```
*/
/**
* Represents the union of all compatible model versions.
*/
export type UMLModelCompat = UMLModelCompatV2;
145 changes: 145 additions & 0 deletions src/main/compat/v2/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { Assessment, UMLElement, UMLRelationship } from '../../typings';
import { v2RelationshipToV3Relationship, v3RelaionshipToV2Relationship } from './transform';
import { UMLModelV2 } from './typings';

/**
*
* Finds an element in the model by id
*
* @param {UMLModelV2} model the model to search
* @param {string} id the id of the element to find
* @returns {UMLElement | undefined} the element or undefined if not found
*/
export function findElement(model: UMLModelV2, id: string): UMLElement | undefined {
return model.elements.find((element) => element.id === id);
}

/**
*
* Adds given element to given model. If element with same id already exists, it will be replaced.
*
* @param {UMLModelV2} model the model to update
* @param {UMLElement} element the element to add or update
*/
export function addOrUpdateElement(model: UMLModelV2, element: UMLElement): void {
const priorIndex = model.elements.findIndex((e) => e.id === element.id);
if (priorIndex >= 0) {
model.elements[priorIndex] = element;
} else {
model.elements.push(element);
}
}

/**
*
* Finds a relationship in the model by id
*
* @param {UMLModelV2} model the model to search
* @param {string} id the id of the relationship to find
* @returns {UMLRelationship | undefined} the relationship or undefined if not found
*/
export function findRelationship(model: UMLModelV2, id: string): UMLRelationship | undefined {
const candidate = model.relationships.find((relationship) => relationship.id === id);
return candidate && v2RelationshipToV3Relationship(candidate);
}

/**
*
* Adds given relationship to given model. If relationship with same id already exists, it will be replaced.
*
* @param {UMLModelV2} model the model to update
* @param {UMLRelationship} relationship the relationship to add or update
*/
export function addOrUpdateRelationship(model: UMLModelV2, relationship: UMLRelationship): void {
const v2rel = v3RelaionshipToV2Relationship(relationship);
const priorIndex = model.relationships.findIndex((r) => r.id === relationship.id);
if (priorIndex >= 0) {
model.relationships[priorIndex] = v2rel;
} else {
model.relationships.push(v2rel);
}
}

/**
*
* Finds an assessment in the model by id
*
* @param {UMLModelV2} model the model to search
* @param {string} id the id of the assessment to find
* @returns {Assessment | undefined} the assessment or undefined if not found
*/
export function findAssessment(model: UMLModelV2, id: string): Assessment | undefined {
return model.assessments.find((assessment) => assessment.modelElementId === id);
}

/**
*
* Adds given assessment to given model. If assessment with same id already exists, it will be replaced.
*
* @param {UMLModelV2} model the model to update
* @param {Assessment} assessment the assessment to add or update
*/
export function addOrUpdateAssessment(model: UMLModelV2, assessment: Assessment): void {
const priorIndex = model.assessments.findIndex((a) => a.modelElementId === assessment.modelElementId);
if (priorIndex >= 0) {
model.assessments[priorIndex] = assessment;
} else {
model.assessments.push(assessment);
}
}

/**
* @returns true if given element is interactive, false otherwise
*/
export function isInteractiveElement(model: UMLModelV2, id: string): boolean {
return model.interactive.elements.includes(id);
}

/**
*
* Sets given element interactive state to given value.
*
* @param {UMLModelV2} model the model to update
* @param {string} id the id of the element to update
* @param {boolean} interactive the interactive state to set
*/
export function setInteractiveElement(model: UMLModelV2, id: string, interactive: boolean): void {
if (interactive) {
if (!isInteractiveElement(model, id)) {
model.interactive.elements.push(id);
}
} else {
const index = model.interactive.elements.indexOf(id);
if (index >= 0) {
model.interactive.elements.splice(index, 1);
}
}
}

/**
* @returns true if given relationship is interactive, false otherwise
*/
export function isInteractiveRelationship(model: UMLModelV2, id: string): boolean {
return model.interactive.relationships.includes(id);
}

/**
*
* Sets given relationship interactive state to given value.
*
* @param {UMLModelV2} model the model to update
* @param {string} id the id of the relationship to update
* @param {boolean} interactive the interactive state to set
*/
export function setInteractiveRelationship(model: UMLModelV2, id: string, interactive: boolean): void {
if (interactive) {
if (!isInteractiveRelationship(model, id)) {
model.interactive.relationships.push(id);
}
} else {
const index = model.interactive.relationships.indexOf(id);
if (index >= 0) {
model.interactive.relationships.splice(index, 1);
}
}
}
1 change: 1 addition & 0 deletions src/main/compat/v2/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './typings';
export * from './transform';
export * from './helpers';
Loading

0 comments on commit a959e04

Please sign in to comment.