Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
Add feature to import quantum application archives (#34)
Browse files Browse the repository at this point in the history
* Allow importing zip files for BPMN

* Separate QAAs from BPMN files after open dialogue

* Implement CSAR upload to Winery when importing QAA

* Update plugins with client dependency

* Update package-lock

* Return BPMN file contained in QAA

* Open BPMN diagrams from QAAs on import
  • Loading branch information
wederbn authored Jul 22, 2021
1 parent c991f65 commit 121025f
Show file tree
Hide file tree
Showing 9 changed files with 27,922 additions and 12,698 deletions.
40,500 changes: 27,807 additions & 12,693 deletions client/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"events": "^3.0.0",
"formik": "^2.0.4",
"ids": "^1.0.0",
"jquery": "^3.6.0",
"min-dash": "^3.5.2",
"min-dom": "^3.1.3",
"p-defer": "^3.0.0",
Expand Down
26 changes: 24 additions & 2 deletions client/src/app/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ export class App extends PureComponent {

const filters = getOpenFilesDialogFilters(providers);

const filePaths = await dialog.showOpenFilesDialog({
let filePaths = await dialog.showOpenFilesDialog({
activeFile: activeTab.file,
filters
});
Expand All @@ -503,11 +503,33 @@ export class App extends PureComponent {
return;
}

const files = await this.readFileList(filePaths);
// filter QAAs as they have to be uploaded differently due to their size
let qaaPaths = filePaths.filter(path => path.endsWith('zip'));
filePaths = filePaths.filter(path => !path.endsWith('zip'));

let files = await this.readFileList(filePaths);

// unzip QAAs and extract BPMN files
if (qaaPaths && qaaPaths.length > 0) {
files = files.concat(await this.openQAAs(qaaPaths));
}

await this.openFiles(files);
}

openQAAs = async (qaaPaths) => {
this.displayNotification({
type: 'info',
title: 'QAA import pending!',
content: 'QAA import for ' + qaaPaths.length + ' QAAs is running in the background. Uploading CSARs to connected Winery!',
duration: 100000
});

return await this.tabRef.current.triggerAction('import-qaa', {
qaaPaths: qaaPaths
});
}

showCloseFileDialog = (file) => {
const { name } = file;

Expand Down
2 changes: 1 addition & 1 deletion client/src/app/TabsProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export default class TabsProvider {
svg: EXPORT_SVG,
zip: EXPORT_QAA
},
extensions: [ 'bpmn', 'xml' ],
extensions: [ 'bpmn', 'xml', 'zip' ],
getComponent(options) {
return import('./tabs/bpmn');
},
Expand Down
4 changes: 4 additions & 0 deletions client/src/app/tabs/MultiSheetTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ export class MultiSheetTab extends CachedComponent {
const { fileType, tab } = options;

return await editor.exportAs(fileType, tab);
} else if (action === 'import-qaa') {
const { qaaPaths } = options;

return await editor.importQAAs(qaaPaths);
}

return editor.triggerAction(action, options);
Expand Down
81 changes: 80 additions & 1 deletion client/src/app/tabs/bpmn/BpmnEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/

import JSZip from 'jszip';
import $ from 'jquery';
import { saveAs } from 'file-saver';

import React, { Component } from 'react';
Expand Down Expand Up @@ -49,7 +50,6 @@ import Metadata from '../../../util/Metadata';
import { getServiceTasksToDeploy } from '../../quantme/deployment/DeploymentUtils';
import { getRootProcess } from '../../quantme/utilities/Utilities';


const NAMESPACE_URL_ACTIVITI = 'http://activiti.org/bpmn';

const NAMESPACE_CAMUNDA = {
Expand Down Expand Up @@ -568,6 +568,85 @@ export class BpmnEditor extends CachedComponent {
return jszip.generateAsync({ type:'blob' });
}

async importQAAs(qaaPaths) {
console.log('Importing QAAs from paths: ', qaaPaths);

let resultList = [];
for (let id in qaaPaths) {
resultList.push(await this.importQAA(qaaPaths[id]));
}
return resultList;
}

importQAA(qaaPath) {

// retrieve Winery endpoint to upload CSARs to
const wineryEndpoint = this.getModeler().config.wineryEndpoint;

return new Promise(function(resolve, reject) {

// request zip file representing QAA
const xmlhttp = new XMLHttpRequest();
xmlhttp.responseType = 'blob';
xmlhttp.onload = async function(callback) {
if (xmlhttp.status === 200) {
console.log('Request finished with status code 200 for QAA at path %s!', qaaPath);
const blob = new Blob([xmlhttp.response], { type: 'application/zip' });

// load zip file using JSZip
let jszip = new JSZip();
let zip = await jszip.loadAsync(blob);
console.log('Successfully loaded zip!', zip);

// find BPMN file in QAA
let files = zip.filter(function(relativePath, file) {
return !relativePath.startsWith('deployment-models') && relativePath.endsWith('.bpmn');
});

// check if exaclty one workflow is contained in the QAA
if (files.length !== 1) {
console.error('QAA with path %s must contain exactly one BPMN file but contains %i!', qaaPath, files.length);
reject('QAA with path %s must contain exactly one BPMN file but contains %i!', qaaPath, files.length);
}

// get folders representing CSARs
let deploymentModels = zip.folder('deployment-models');
deploymentModels.forEach(function(relativePath, file) {

// CSARs must be direct subfolders
if (file.dir && relativePath.split('/').length === 2) {
let csar = zip.folder(file.name);
csar.generateAsync({ type: 'blob' }).then(function(blob) {

const fd = new FormData();
fd.append('overwrite', 'false');
fd.append('file', blob);
$.ajax({
type: 'POST',
url: wineryEndpoint,
data: fd,
processData: false,
contentType: false,
success: function() {
console.log('Successfully uploaded CSAR: %s', file.name.split('/')[1]);
}
});
});
}
});

// import BPMN file
resolve({
contents: await files[0].async('string'),
name: files[0].name
});
}
};
xmlhttp.open('GET', 'file:///' + qaaPath, true);
xmlhttp.send();
});
}

async exportSVG() {
const modeler = this.getModeler();

Expand Down

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions resources/plugins/QuantME-CamundaPlugin/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 121025f

Please sign in to comment.