diff --git a/Gruntfile.js b/Gruntfile.js index 31d3d308..0f7cf5e6 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -66,6 +66,16 @@ module.exports = function(grunt) { } ] }, + dot: { + files: [ + { + expand: true, + cwd: 'node_modules/dot', + src: ['**/*.min.js'], + dest: 'dist/dependencies' + } + ] + }, app: { files: [ { diff --git a/app/app.js b/app/app.js index a911bb01..0e97aa49 100644 --- a/app/app.js +++ b/app/app.js @@ -39,6 +39,10 @@ import { downloadSVG, setEncoded } from './domain-story-modeler/features/export/svgDownload'; +import { + initStoryDownload, + downloadStory +} from './domain-story-modeler/features/export/storyDownload'; import { downloadPNG } from './domain-story-modeler/features/export/pngDownload'; import { loadPersistedDST, @@ -166,6 +170,7 @@ let modal = document.getElementById('modal'), ), pngSaveButton = document.getElementById('buttonPNG'), svgSaveButton = document.getElementById('buttonSVG'), + storySaveButton = document.getElementById('buttonDownloadStory'), wpsLogoButton = document.getElementById('closeWPSLogoInfo'), dstLogoButton = document.getElementById('closeDSTLogoInfo'), exportConfigurationButton = document.getElementById( @@ -221,6 +226,7 @@ function initialize( modeler.on('commandStack.changed', exportArtifacts); initReplay(canvas, selection); + initStoryDownload(canvas, selection, modeler); initElementRegistry(elementRegistry); initImports(elementRegistry, version, modeler, eventBus, saveSVG); @@ -538,6 +544,13 @@ pngSaveButton.addEventListener('click', function() { closeImageDownloadDialog(); }); +storySaveButton.addEventListener('click', function() { + const filename = + title.innerText + '_' + new Date().toISOString().slice(0, 10); + downloadStory(filename); + closeImageDownloadDialog(); +}); + incompleteStoryDialogButtonCancel.addEventListener('click', function() { modal.style.display = 'none'; incompleteStoryDialog.style.display = 'none'; diff --git a/app/domain-story-modeler/features/export/storyDownload.js b/app/domain-story-modeler/features/export/storyDownload.js new file mode 100644 index 00000000..7aea596d --- /dev/null +++ b/app/domain-story-modeler/features/export/storyDownload.js @@ -0,0 +1,261 @@ +'use strict'; + +import { sanitizeForDesktop } from '../../util/Sanitizer'; +import { GROUP } from '../../language/elementTypes'; +import { + getActivitesFromActors, + wasInitialized, +} from '../../language/canvasElementRegistry'; +import { traceActivities } from '../replay/initializeReplay'; +import doT from 'dot'; +import { editMode, presentationMode, showCurrentStep } from '../replay/replayFunctions'; + +let canvas; +let selection; + +let multiplexSecret; +let multiplexId; + +let replayOn = false; +let currentStep = 0; +let replaySteps = []; +let initialViewbox; + +let errorStep = 0; + +let dsModeler; + +let modal = document.getElementById('modal'); +let incompleteStoryDialog = document.getElementById('incompleteStoryInfo'); + +export function initStoryDownload(inCanvas, inSelection, modeler) { + canvas = inCanvas; + selection = inSelection; + dsModeler = modeler; + + // cors.bridged.cc is a CORS ANYWHERE server. For details: https://blog.bridged.xyz/cors-anywhere-for-everyone-free-reliable-cors-proxy-service-73507192714e + fetch('https://cors.bridged.cc/https://reveal-multiplex.glitch.me/token', { headers: { 'x-requested-with':'XMLHttpRequest' } }).then(res => res.json()).then((out) => { + multiplexSecret=out.secret; + multiplexId=out.socketId; + }).catch(err => console.error(err)); +} + +export async function downloadStory(filename) { + var svgData = []; + currentStep = 0; + + // export all sentences of domain story + startReplay(); + try { + const result = await dsModeler.saveSVG({ }); + svgData.push({ content: createSVGData(result.svg), transition: 'slide' }); + } catch (err) { + alert('There was an error exporting the SVG.\n' + err); + } + while (currentStep < replaySteps.length - 1) { + nextStep(); + try { + const result = await dsModeler.saveSVG({ }); + svgData.push({ content: createSVGData(result.svg), transition: 'slide' }); + } catch (err) { + alert('There was an error exporting the SVG.\n' + err); + } + } + stopReplay(); + + // create download for presentation + let revealjsTemplate = document.getElementById('revealjs-template'); + var dots = doT.template(revealjsTemplate.innerHTML); + var revealjsData = { }; + revealjsData.script = 'script'; // don't change this!! + revealjsData.title = document.getElementById('title').innerHTML; + revealjsData.description = document.getElementById('infoText').innerHTML; + revealjsData.sentences = svgData; + revealjsData.multiplexSecret = multiplexSecret; + revealjsData.multiplexId = multiplexId; + let element; + element = document.createElement('a'); + element.setAttribute( + 'href', + 'data:text/html;charset=UTF-8,' + dots(revealjsData) + ); + element.setAttribute('download', sanitizeForDesktop(filename) + '.html'); + element.style.display = 'none'; + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); +} + +function startReplay() { + if (wasInitialized()) { + initialViewbox = canvas.viewbox(); + let activities = getActivitesFromActors(); + + if (!replayOn && activities.length > 0) { + replaySteps = traceActivities(activities); + + if (isStoryConsecutivelyNumbered(replaySteps)) { + replayOn = true; + presentationMode(selection); + currentStep = 0; + showCurrentStep(currentStep, replaySteps, canvas); + } else { + let errorText = '\nThe numbers: '; + for (let i = 0; i < replaySteps.length; i++) { + if (errorStep[i]) { + errorText += i + 1 + ','; + } + } + errorText = errorText.substring(0, errorText.length - 1); + errorText += ' are missing!'; + + let oldText = incompleteStoryDialog.getElementsByTagName('text'); + if (oldText) { + for (let i = 0; i < oldText.length; i++) { + incompleteStoryDialog.removeChild(oldText[i]); + } + } + + let text = document.createElement('text'); + text.innerHTML = + ' The activities in this Domain Story are not numbered consecutively.
' + + 'Please fix the numbering in order to replay the story.
' + + errorText; + incompleteStoryDialog.appendChild(text); + incompleteStoryDialog.style.display = 'block'; + modal.style.display = 'block'; + } + } + } +} + +function stopReplay() { + if (replayOn) { + editMode(); + + // show all canvas elements + let allObjects = []; + let groupObjects = []; + let canvasObjects = canvas._rootElement.children; + let i = 0; + + for (i = 0; i < canvasObjects.length; i++) { + if (canvasObjects[i].type.includes(GROUP)) { + groupObjects.push(canvasObjects[i]); + } else { + allObjects.push(canvasObjects[i]); + } + } + + i = groupObjects.length - 1; + while (groupObjects.length >= 1) { + let currentgroup = groupObjects.pop(); + currentgroup.children.forEach(child => { + if (child.type.includes(GROUP)) { + groupObjects.push(child); + } else { + allObjects.push(child); + } + allObjects.push(currentgroup); + }); + i = groupObjects.length - 1; + } + allObjects.forEach(element => { + let domObject = document.querySelector( + '[data-element-id=' + element.id + ']' + ); + domObject.style.display = 'block'; + }); + + replayOn = false; + currentStep = 0; + canvas.viewbox(initialViewbox); + } +} + +function nextStep() { + if (replayOn) { + if (currentStep < replaySteps.length - 1) { + currentStep += 1; + showCurrentStep(currentStep, replaySteps, canvas); + } + } +} + +function isStoryConsecutivelyNumbered(replaySteps) { + errorStep = []; + let complete = true; + for (let i = 0; i < replaySteps.length; i++) { + if (!replaySteps[i].activities[0]) { + complete = false; + errorStep[i] = true; + } else { + errorStep[i] = false; + } + } + return complete; +} + +/* +--------------------------- +SVG handling starts here +---------------------------- +*/ + +function createSVGData(svg) { + + let data = JSON.parse(JSON.stringify(svg)); + + // to ensure that the title and description are inside the SVG container and do not overlapp with any elements, + // we change the confines of the SVG viewbox + let viewBoxIndex = data.indexOf('width="'); + + let viewBox = viewBoxCoordinates(data); + + let xLeft, xRight, yUp, yDown; + let bounds = ''; + let splitViewBox = viewBox.split(/\s/); + + xLeft = +splitViewBox[0]; + yUp = +splitViewBox[1]; + xRight = +splitViewBox[2]; + yDown = +splitViewBox[3]; + + if (xRight < 300) { + xRight += 300; + } + + bounds = + 'width="100%"' + + ' height="auto" ' + + ' preserveAspectRatio="xMidYMid meet"' + + ' viewBox="' + + xLeft + + ' ' + + yUp + + ' ' + + xRight + + ' ' + + (yDown + 30); + let dataStart = data.substring(0, viewBoxIndex); + viewBoxIndex = data.indexOf('" version'); + let dataEnd = data.substring(viewBoxIndex); + dataEnd.substring(viewBoxIndex); + + data = dataStart + bounds + dataEnd; + + let insertIndex = data.indexOf(''); + if (insertIndex < 0) { + insertIndex = data.indexOf('version="1.2">') + 14; + } else { + insertIndex += 7; + } + + return encodeURIComponent(data); +} + +function viewBoxCoordinates(svg) { + const ViewBoxCoordinate = /width="([^"]+)"\s+height="([^"]+)"\s+viewBox="([^"]+)"/; + const match = svg.match(ViewBoxCoordinate); + return match[3]; +} diff --git a/app/domain-story-modeler/features/replay/replay.js b/app/domain-story-modeler/features/replay/replay.js index 49134445..f46af859 100644 --- a/app/domain-story-modeler/features/replay/replay.js +++ b/app/domain-story-modeler/features/replay/replay.js @@ -1,15 +1,12 @@ 'use strict'; -import { CONNECTION, GROUP } from '../../language/elementTypes'; +import { GROUP } from '../../language/elementTypes'; import { getActivitesFromActors, - getAllCanvasObjects, wasInitialized, - getAllGroups, - getAllActivities, - getAllConnections } from '../../language/canvasElementRegistry'; import { traceActivities } from './initializeReplay'; +import { editMode, presentationMode, showCurrentStep } from './replayFunctions'; let canvas; let selection; @@ -26,7 +23,6 @@ let startReplayButton = document.getElementById('buttonStartReplay'); let nextStepButton = document.getElementById('buttonNextStep'); let previousStepButton = document.getElementById('buttonPreviousStep'); let stopReplayButton = document.getElementById('buttonStopReplay'); -let currentReplayStepLabel = document.getElementById('replayStep'); let incompleteStoryDialog = document.getElementById('incompleteStoryInfo'); export function getReplayOn() { @@ -61,9 +57,9 @@ export function initReplay(inCanvas, inSelection) { if (isStoryConsecutivelyNumbered(replaySteps)) { replayOn = true; - presentationMode(); + presentationMode(selection); currentStep = 0; - showCurrentStep(); + showCurrentStep(currentStep, replaySteps, canvas); } else { let errorText = '\nThe numbers: '; for (let i = 0; i < replaySteps.length; i++) { @@ -151,7 +147,7 @@ function nextStep() { if (replayOn) { if (currentStep < replaySteps.length - 1) { currentStep += 1; - showCurrentStep(); + showCurrentStep(currentStep, replaySteps, canvas); } } } @@ -160,7 +156,7 @@ function previousStep() { if (replayOn) { if (currentStep > 0) { currentStep -= 1; - showCurrentStep(); + showCurrentStep(currentStep, replaySteps, canvas); } } } @@ -182,266 +178,3 @@ export function isStoryConsecutivelyNumbered(replaySteps) { } return complete; } - -export function getAllShown(stepsUntilNow) { - let shownElements = []; - - // for each step until the current one, add all referenced elements to the list of shown elements - stepsUntilNow.forEach(step => { - if (step.groups && step.groups.length > 0) { - step.groups.forEach(group => { - shownElements.push(group); - }); - } else { - - // add the source of the step and their annotations to the shown elements - step.sources.forEach(source => { - - shownElements.push(source); - if (source.outgoing) { - source.outgoing.forEach(out => { - if (out.type.includes(CONNECTION)) { - shownElements.push(out, out.target); - } - }); - } - }); - - // add the target of the step and their annotations to the shown elements - step.targets.forEach(target => { - shownElements.push(target); - if (target.outgoing) { - target.outgoing.forEach(out => { - if (out.type.includes(CONNECTION)) { - shownElements.push(out, out.target); - } - }); - } - - // add each activity to the step - step.activities.forEach(activity => { - shownElements.push(activity); - }); - }); - } - }); - - return shownElements; -} - -function removeHighlights() { - const numberBackgroundColour = '#42aebb'; - const numberColour = 'white'; - - const allActivities = getAllActivities(); - const allConnections = getAllConnections(); - - allActivities.forEach(activity => { - const activityDomObject = document.querySelector( - '[data-element-id=' + activity.id + ']' - ).getElementsByTagName('polyline')[0]; - - activityDomObject.style.stroke = activity.businessObject.pickedColor || 'black'; - activityDomObject.style.strokeWidth = 1.5; - - const { numberBackgroundDom, numberTextDom } = getNumberDomForActivity(activityDomObject); - if (numberBackgroundDom && numberTextDom) { - numberBackgroundDom.style.fill = numberBackgroundColour; - numberTextDom.style.fill = numberColour; - } - - }); - - allConnections.forEach(connnection => { - const connectionDomObject = document.querySelector( - '[data-element-id=' + connnection.id + ']' - ).getElementsByTagName('polyline')[0]; - - connectionDomObject.style.stroke = connnection.businessObject.pickedColor || 'black'; - connectionDomObject.style.strokeWidth = 1.5; - - }); -} - -function hightlightStep(step) { - const highlightColour = 'black'; - const numberBackgroundHighlightColour = 'orange'; - const numberHighlightColour = 'black'; - - if (!step.groups) { - - step.activities.forEach(activity => { - const activityDomObject = document.querySelector( - '[data-element-id=' + activity.id + ']' - ).getElementsByTagName('polyline')[0]; - - activityDomObject.style.stroke = highlightColour; - activityDomObject.style.strokeWidth = 4; - - const { numberBackgroundDom, numberTextDom } = getNumberDomForActivity(activityDomObject); - if (numberTextDom && numberBackgroundDom) { - numberBackgroundDom.style.fill = numberBackgroundHighlightColour; - numberTextDom.style.fill = numberHighlightColour; - } - - }); - } -} - -function getNumberDomForActivity(activity) { - const numberDOMS = activity.parentElement.getElementsByClassName('djs-labelNumber'); - return { - numberBackgroundDom: numberDOMS[0], - numberTextDom: numberDOMS[1] - }; -} - -// get all elements, that are supposed to be hidden in the current step -export function getAllNotShown(allObjects, shownElements) { - let notShownElements = []; - - // every element that is not referenced in shownElements - // and is neither a group (since they are not refeenced in allObjects), - // nor an annotation conntected to a group should be hidden - allObjects.forEach(element => { - if (!shownElements.includes(element)) { - if (element.type.includes(CONNECTION)) { - if (!element.source.type.includes(GROUP)) { - notShownElements.push(element); - } else { - shownElements.push(element.target); - } - } else { - notShownElements.push(element); - } - } - }); - return notShownElements; -} - -// replay functions -function presentationMode() { - - removeSelectionAndEditing(); - - const contextPadElements = document.getElementsByClassName('djs-context-pad'); - const paletteElements = document.getElementsByClassName('djs-palette'); - - const infoContainer = document.getElementById('infoContainer'); - infoContainer.style.display = 'none'; - - const editModeButtons = document.getElementById('editModeButtons'); - editModeButtons.style.display = 'none'; - editModeButtons.style.pointerEvents = 'none'; - - const presentationModeButtons = document.getElementById( - 'presentationModeButtons' - ); - presentationModeButtons.style.display = 'block'; - presentationModeButtons.style.pointerEvents = 'all'; - - const headerAndCanvas = document.getElementsByClassName('headerAndCanvas')[0]; - headerAndCanvas.style.gridTemplateRows = '0px 50px 1px auto'; - - const headlineAndButtons = document.getElementById('headlineAndButtons'); - headlineAndButtons.style.gridTemplateColumns = 'auto 230px 3px'; - - let i = 0; - for (i = 0; i < contextPadElements.length; i++) { - contextPadElements[i].style.display = 'none'; - } - - for (i = 0; i < paletteElements.length; i++) { - paletteElements[i].style.display = 'none'; - } - - currentReplayStepLabel.style.opacity = 1; -} - -function removeSelectionAndEditing() { - selection.select([]); - const directEditingBoxes = document.getElementsByClassName('djs-direct-editing-parent'); - - if (directEditingBoxes.length > 0) { - const directEditing = directEditingBoxes[0]; - directEditing.parentElement.removeChild(directEditing); - } -} - -function editMode() { - removeHighlights(); - - const contextPadElements = document.getElementsByClassName('djs-context-pad'); - const paletteElements = document.getElementsByClassName('djs-palette'); - - const infoContainer = document.getElementById('infoContainer'); - infoContainer.style.display = 'block'; - infoContainer.style.height = '75px'; - - let editModeButtons = document.getElementById('editModeButtons'); - editModeButtons.style.display = 'inherit'; - editModeButtons.style.pointerEvents = 'all'; - - let presentationModeButtons = document.getElementById( - 'presentationModeButtons' - ); - presentationModeButtons.style.display = 'none'; - presentationModeButtons.style.pointerEvents = 'none'; - - let headerAndCanvas = document.getElementsByClassName('headerAndCanvas')[0]; - headerAndCanvas.style.gridTemplateRows = '0px 125px 1px auto'; - - let headlineAndButtons = document.getElementById('headlineAndButtons'); - headlineAndButtons.style.gridTemplateColumns = 'auto 390px 3px'; - - let i = 0; - for (i = 0; i < contextPadElements.length; i++) { - contextPadElements[i].style.display = 'block'; - } - - for (i = 0; i < paletteElements.length; i++) { - paletteElements[i].style.display = 'block'; - } - currentReplayStepLabel.style.opacity = 0; -} - -function showCurrentStep() { - let stepsUntilNow = []; - let allObjects = []; - let i = 0; - - currentReplayStepLabel.innerText = - currentStep + 1 + ' / ' + replaySteps.length; - - for (i = 0; i <= currentStep; i++) { - stepsUntilNow.push(replaySteps[i]); - } - - allObjects = getAllCanvasObjects(canvas); - getAllGroups().forEach(group => { - allObjects.push(group); - }); - - let shownElements = getAllShown(stepsUntilNow); - - const notShownElements = getAllNotShown(allObjects, shownElements); - - removeHighlights(); - hightlightStep(replaySteps[currentStep]); - - // hide all elements, that are not to be shown - notShownElements.forEach(element => { - const domObject = document.querySelector( - '[data-element-id=' + element.id + ']' - ); - domObject.style.display = 'none'; - }); - - shownElements.forEach(element => { - const domObject = document.querySelector( - '[data-element-id=' + element.id + ']' - ); - domObject.style.display = 'block'; - }); - -} diff --git a/app/domain-story-modeler/features/replay/replayFunctions.js b/app/domain-story-modeler/features/replay/replayFunctions.js new file mode 100644 index 00000000..6eb61454 --- /dev/null +++ b/app/domain-story-modeler/features/replay/replayFunctions.js @@ -0,0 +1,267 @@ +import { getAllActivities, getAllCanvasObjects, getAllConnections, getAllGroups } from '../../language/canvasElementRegistry'; +import { CONNECTION, GROUP } from '../../language/elementTypes'; + +let currentReplayStepLabel = document.getElementById('replayStep'); + +export function showCurrentStep(currentStep, replaySteps, canvas) { + let stepsUntilNow = []; + let allObjects = []; + let i = 0; + + currentReplayStepLabel.innerText = + currentStep + 1 + ' / ' + replaySteps.length; + + for (i = 0; i <= currentStep; i++) { + stepsUntilNow.push(replaySteps[i]); + } + + allObjects = getAllCanvasObjects(canvas); + getAllGroups().forEach(group => { + allObjects.push(group); + }); + + let shownElements = getAllShown(stepsUntilNow); + + const notShownElements = getAllNotShown(allObjects, shownElements); + + removeHighlights(); + hightlightStep(replaySteps[currentStep]); + + // hide all elements, that are not to be shown + notShownElements.forEach(element => { + const domObject = document.querySelector( + '[data-element-id=' + element.id + ']' + ); + domObject.style.display = 'none'; + }); + + shownElements.forEach(element => { + const domObject = document.querySelector( + '[data-element-id=' + element.id + ']' + ); + domObject.style.display = 'block'; + }); +} + +function getAllShown(stepsUntilNow) { + let shownElements = []; + + // for each step until the current one, add all referenced elements to the list of shown elements + stepsUntilNow.forEach(step => { + if (step.groups && step.groups.length > 0) { + step.groups.forEach(group => { + shownElements.push(group); + }); + } else { + + // add the source of the step and their annotations to the shown elements + step.sources.forEach(source => { + + shownElements.push(source); + if (source.outgoing) { + source.outgoing.forEach(out => { + if (out.type.includes(CONNECTION)) { + shownElements.push(out, out.target); + } + }); + } + }); + + // add the target of the step and their annotations to the shown elements + step.targets.forEach(target => { + shownElements.push(target); + if (target.outgoing) { + target.outgoing.forEach(out => { + if (out.type.includes(CONNECTION)) { + shownElements.push(out, out.target); + } + }); + } + + // add each activity to the step + step.activities.forEach(activity => { + shownElements.push(activity); + }); + }); + } + }); + + return shownElements; +} + +function hightlightStep(step) { + const highlightColour = 'black'; + const numberBackgroundHighlightColour = 'orange'; + const numberHighlightColour = 'black'; + + if (!step.groups) { + + step.activities.forEach(activity => { + const activityDomObject = document.querySelector( + '[data-element-id=' + activity.id + ']' + ).getElementsByTagName('polyline')[0]; + + activityDomObject.style.stroke = highlightColour; + activityDomObject.style.strokeWidth = 4; + + const { numberBackgroundDom, numberTextDom } = getNumberDomForActivity(activityDomObject); + if (numberTextDom && numberBackgroundDom) { + numberBackgroundDom.style.fill = numberBackgroundHighlightColour; + numberTextDom.style.fill = numberHighlightColour; + } + + }); + } +} + +// get all elements, that are supposed to be hidden in the current step +function getAllNotShown(allObjects, shownElements) { + let notShownElements = []; + + // every element that is not referenced in shownElements + // and is neither a group (since they are not refeenced in allObjects), + // nor an annotation conntected to a group should be hidden + allObjects.forEach(element => { + if (!shownElements.includes(element)) { + if (element.type.includes(CONNECTION)) { + if (!element.source.type.includes(GROUP)) { + notShownElements.push(element); + } else { + shownElements.push(element.target); + } + } else { + notShownElements.push(element); + } + } + }); + return notShownElements; +} + + +// replay functions +export function presentationMode(selected) { + + removeSelectionAndEditing(selected); + + const contextPadElements = document.getElementsByClassName('djs-context-pad'); + const paletteElements = document.getElementsByClassName('djs-palette'); + + const infoContainer = document.getElementById('infoContainer'); + infoContainer.style.display = 'none'; + + const editModeButtons = document.getElementById('editModeButtons'); + editModeButtons.style.display = 'none'; + editModeButtons.style.pointerEvents = 'none'; + + const presentationModeButtons = document.getElementById( + 'presentationModeButtons' + ); + presentationModeButtons.style.display = 'block'; + presentationModeButtons.style.pointerEvents = 'all'; + + const headerAndCanvas = document.getElementsByClassName('headerAndCanvas')[0]; + headerAndCanvas.style.gridTemplateRows = '0px 50px 1px auto'; + + const headlineAndButtons = document.getElementById('headlineAndButtons'); + headlineAndButtons.style.gridTemplateColumns = 'auto 230px 3px'; + + let i = 0; + for (i = 0; i < contextPadElements.length; i++) { + contextPadElements[i].style.display = 'none'; + } + + for (i = 0; i < paletteElements.length; i++) { + paletteElements[i].style.display = 'none'; + } + + currentReplayStepLabel.style.opacity = 1; +} + +export function editMode() { + removeHighlights(); + + const contextPadElements = document.getElementsByClassName('djs-context-pad'); + const paletteElements = document.getElementsByClassName('djs-palette'); + + const infoContainer = document.getElementById('infoContainer'); + infoContainer.style.display = 'block'; + infoContainer.style.height = '75px'; + + let editModeButtons = document.getElementById('editModeButtons'); + editModeButtons.style.display = 'inherit'; + editModeButtons.style.pointerEvents = 'all'; + + let presentationModeButtons = document.getElementById( + 'presentationModeButtons' + ); + presentationModeButtons.style.display = 'none'; + presentationModeButtons.style.pointerEvents = 'none'; + + let headerAndCanvas = document.getElementsByClassName('headerAndCanvas')[0]; + headerAndCanvas.style.gridTemplateRows = '0px 125px 1px auto'; + + let headlineAndButtons = document.getElementById('headlineAndButtons'); + headlineAndButtons.style.gridTemplateColumns = 'auto 390px 3px'; + + let i = 0; + for (i = 0; i < contextPadElements.length; i++) { + contextPadElements[i].style.display = 'block'; + } + + for (i = 0; i < paletteElements.length; i++) { + paletteElements[i].style.display = 'block'; + } + currentReplayStepLabel.style.opacity = 0; +} + +function removeSelectionAndEditing(selected) { + selected.select([]); + const directEditingBoxes = document.getElementsByClassName('djs-direct-editing-parent'); + + if (directEditingBoxes.length > 0) { + const directEditing = directEditingBoxes[0]; + directEditing.parentElement.removeChild(directEditing); + } +} + +function removeHighlights() { + const numberBackgroundColour = '#42aebb'; + const numberColour = 'white'; + + const allActivities = getAllActivities(); + const allConnections = getAllConnections(); + + allActivities.forEach(activity => { + const activityDomObject = document.querySelector( + '[data-element-id=' + activity.id + ']' + ).getElementsByTagName('polyline')[0]; + + activityDomObject.style.stroke = activity.businessObject.pickedColor || 'black'; + activityDomObject.style.strokeWidth = 1.5; + + const { numberBackgroundDom, numberTextDom } = getNumberDomForActivity(activityDomObject); + if (numberBackgroundDom && numberTextDom) { + numberBackgroundDom.style.fill = numberBackgroundColour; + numberTextDom.style.fill = numberColour; + } + + }); + + allConnections.forEach(connnection => { + const connectionDomObject = document.querySelector( + '[data-element-id=' + connnection.id + ']' + ).getElementsByTagName('polyline')[0]; + + connectionDomObject.style.stroke = connnection.businessObject.pickedColor || 'black'; + connectionDomObject.style.strokeWidth = 1.5; + + }); +} + +function getNumberDomForActivity(activity) { + const numberDOMS = activity.parentElement.getElementsByClassName('djs-labelNumber'); + return { + numberBackgroundDom: numberDOMS[0], + numberTextDom: numberDOMS[1] + }; +} diff --git a/app/index.html b/app/index.html index ff113890..796853eb 100644 --- a/app/index.html +++ b/app/index.html @@ -44,7 +44,7 @@


- +
@@ -328,10 +331,10 @@

- + - + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d3e8f805..9c23ea73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "domain-story-modeler", - "version": "1.2.1-dev", + "version": "1.2.2-dev", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -4340,6 +4340,11 @@ "resolved": "https://registry.npmjs.org/domify/-/domify-1.4.0.tgz", "integrity": "sha1-EUg2F/dk+GlZdbS9x5sU8IA7Yps=" }, + "dot": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dot/-/dot-1.1.3.tgz", + "integrity": "sha512-/nt74Rm+PcfnirXGEdhZleTwGC2LMnuKTeeTIlI82xb5loBBoXNYzr2ezCroPSMtilK8EZIfcNZwOcHN+ib1Lg==" + }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", diff --git a/package.json b/package.json index 13a93cb8..728369a3 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,8 @@ "devDependencies": { "@babel/core": "7.7.2", "@babel/plugin-transform-runtime": "^7.13.9", - "@babel/preset-env": "7.7.1", "@babel/polyfill": "7.12.1", + "@babel/preset-env": "7.7.1", "babelify": "^10.0.0", "browserify": "^16.5.1", "chai": "^4.3.1", @@ -69,6 +69,7 @@ "bpmn-js": "^8.2.1", "diagram-js": "^7.2.1", "diagram-js-direct-editing": "^1.6.2", + "dot": "^1.1.3", "inherits": "2.0.4", "jquery": "^3.6.0", "min-dash": "^3.5.2",