Created
November 12, 2022 07:08
-
-
Save ThomasRohde/342b8551428ad56f6c9b2233e7fa4878 to your computer and use it in GitHub Desktop.
Forms in Archi - with examples. #Jarchi, #Archi, #ArchiMate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Author: Thomas Klok Rohde | |
Description: Edit documentation markdown | |
History: | |
November 12, 2022: Created. | |
*/ | |
console.show(); | |
console.clear(); | |
load(__DIR__ + "lib/show_form.js"); | |
let element = $(selection).first(); | |
let formSchema = { | |
type: "object", | |
title: " ", | |
format: "grid-strict", | |
properties: { | |
documentation: { | |
type: "string", | |
format: "markdown", | |
options: { | |
grid_columns: 12, | |
compact: true | |
} | |
}, | |
submit: { | |
format: "button", | |
title: "Insert", | |
options: { | |
grid_columns: 1, | |
inputAttributes: { | |
class: "btn btn-primary btn-sm json-editor-btn-" | |
}, | |
button: { | |
align: "left", | |
action: "submitform", | |
validated: true | |
} | |
} | |
}, | |
cancel: { | |
format: "button", | |
title: "Cancel", | |
options: { | |
grid_columns: 1, | |
grid_break: true, | |
button: { | |
align: "left", | |
action: "cancelform" | |
} | |
} | |
} | |
} | |
} | |
const primary = shell.getDisplay().getPrimaryMonitor(); | |
const bounds = primary.getBounds(); | |
let documentation = { | |
documentation: element.documentation | |
}; | |
let value; | |
if (bounds.width <= 1920) | |
value = showForm(formSchema, documentation, 800, 750); | |
else | |
value = showForm(formSchema, documentation, 1800, 1100); | |
if (value) { | |
console.log(value.documentation); | |
element.documentation = value.documentation; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Author: Thomas Klok Rohde | |
Description: Insert chart to view. | |
Dependencies: https://github.com/json-editor/json-editor | |
History: | |
October 11, 2022 : Created with base set of scripts | |
November 11, 2022 : Updated to new form library (JSON Library) | |
*/ | |
console.show(); | |
console.clear(); | |
load(__DIR__ + "lib/show_form.js"); | |
let note = $(selection).filter("diagram-model-note").first(); | |
if (note == undefined) | |
throw new Error("No note selected"); | |
// Get a list of all defined properties in the model | |
let props = new Set(); | |
$("*").not("folder").each(o => { | |
o.prop().forEach(p => { | |
if (p.length) props.add(p); | |
}) | |
}) | |
let properties = Array.from(props); | |
let elements = []; | |
$("element").each(e => { | |
elements.push(e.name); | |
}) | |
let formSchema = { | |
type: "object", | |
title: " ", | |
format: "grid-strict", | |
required: ["title", "chart"], | |
options: { | |
compact: true | |
}, | |
properties: { | |
chart: { | |
type: "string", | |
title: "Chart type to insert", | |
enum: [ | |
"chartArchiDistribution", | |
"chartPropertyTable", | |
"chartTIME", | |
"chartTreemap", | |
"chartGauges", | |
"chartSpider" | |
], | |
default: "chartArchiDistribution", | |
description: "Select a chart", | |
options: { | |
infoText: "Select among the available charts to render", | |
grid_columns: 6, | |
inputAttributes: { | |
placeholder: "Select an available chart" | |
}, | |
enum_titles: [ | |
"Distribution of ArchiMate elements", | |
"Table of used properties", | |
"TIME chart - Tolerate, Invest, Migrate or Eliminate", | |
"Treemap of Capabilities", | |
"Gauges of select properties", | |
"Spider chart of select properties" | |
] | |
} | |
}, | |
title: { | |
type: "string", | |
title: "Chart title", | |
minLength: 5, | |
options: { | |
infoText: "The chart title will in most charts be placed in the top part.", | |
grid_columns: 6, | |
grid_break: true, | |
inputAttributes: { | |
placeholder: "Enter a chart title" | |
} | |
} | |
}, | |
filter: { | |
type: "string", | |
title: "Javascript filter", | |
options: { | |
infoText: "The expression will be encapsulated in a function with the parameters name, type and obj.", | |
grid_columns: 12, | |
grid_break: true, | |
inputAttributes: { | |
placeholder: "Enter javascript expression" | |
} | |
} | |
}, | |
elements: { | |
type: "array", | |
uniqueItems: true, | |
format: "choices", | |
title: "List of elements to consider in the chart", | |
items: { | |
type: "string", | |
enum: elements | |
}, | |
options: { | |
infoText: "Select one or more elements to include in the chart. You can search by typing the first few characters", | |
grid_columns: 12, | |
grid_break: true, | |
} | |
}, | |
distribution: { | |
type: "object", | |
title: "Element distribution", | |
required: ["type"], | |
format: "grid-strict", | |
properties: { | |
type: { | |
type: "string", | |
title: "Chart variation", | |
enum: [ | |
"bar", | |
"lines" | |
], | |
options: { | |
infoText: "Select visual appearance", | |
grid_columns: 4, | |
inputAttributes: { | |
placeholder: "Select visual appearance" | |
}, | |
enum_titles: [ | |
"Bar", | |
"Lines" | |
] | |
} | |
}, | |
distributionChartIcon: { | |
type: "info", | |
title: "Example", | |
description: "<img src='https://plotly.github.io/static/images/zoom-pan-hover/double-click-autoscale.gif' height='150' />", | |
options: { | |
align: "left", | |
grid_columns: 4, | |
grid_break: true | |
} | |
}, | |
}, | |
options: { | |
infoText: "Select options for the element distribution chart", | |
grid_columns: 12, | |
grid_break: true, | |
dependencies: { | |
"chart": "chartArchiDistribution" | |
}, | |
} | |
}, | |
treemap: { | |
type: "object", | |
title: "Treemap chart", | |
required: ["type"], | |
format: "grid-strict", | |
properties: { | |
property: { | |
type: "string", | |
title: "Property", | |
enum: properties, | |
options: { | |
infoText: "Select the property, or leave empty, the property used to size the elements", | |
grid_columns: 4, | |
} | |
}, | |
type: { | |
type: "string", | |
title: "Chart variation", | |
enum: [ | |
"treemap", | |
"sunburst" | |
], | |
options: { | |
infoText: "Select visual appearance", | |
grid_columns: 3, | |
inputAttributes: { | |
placeholder: "Select visual appearance" | |
}, | |
enum_titles: [ | |
"Treemap", | |
"Sunburst" | |
] | |
} | |
}, | |
level: { | |
type: "integer", | |
format: "range", | |
title: "Level", | |
minimum: 1, | |
maximum: 6, | |
options: { | |
infoText: "Select the maxium level of the treemap", | |
grid_columns: 2 | |
} | |
}, | |
treemapChartIcon: { | |
type: "info", | |
title: "Example", | |
description: "<img src='https://images.plot.ly/plotly-documentation/thumbnail/sunburst.gif' height='150' />", | |
options: { | |
align: "left", | |
grid_columns: 3, | |
grid_break: true | |
} | |
} | |
}, | |
options: { | |
infoText: "Select options for the treemap chart", | |
grid_columns: 12, | |
grid_break: true, | |
dependencies: { | |
"chart": "chartTreemap" | |
}, | |
} | |
}, | |
spider: { | |
type: "object", | |
title: "Spider chart", | |
required: ["type", "properties"], | |
format: "grid-strict", | |
properties: { | |
type: { | |
type: "string", | |
title: "Chart variation", | |
enum: [ | |
"scatterpolar", | |
"bar" | |
], | |
options: { | |
infoText: "Select visual appearance", | |
grid_columns: 3, | |
inputAttributes: { | |
placeholder: "Select visual appearance" | |
}, | |
enum_titles: [ | |
"Spider", | |
"Bar" | |
] | |
} | |
}, | |
properties: { | |
type: "array", | |
title: "List of spoke properties", | |
uniqueItems: true, | |
minItems: 2, | |
maxItems: 7, | |
format: "choices", | |
items: { | |
type: "string", | |
enum: properties | |
}, | |
options: { | |
infoText: "Select three or more properties to include in the chart. You can search by typing the first few characters", | |
grid_columns: 6 | |
} | |
}, | |
spiderChartIcon: { | |
type: "info", | |
title: "Example", | |
description: "<img src='https://images.plot.ly/plotly-documentation/thumbnail/radar.gif' height='150' />", | |
options: { | |
align: "left", | |
grid_columns: 3, | |
grid_break: true | |
} | |
} | |
}, | |
options: { | |
infoText: "Select options for the spider chart", | |
grid_columns: 12, | |
dependencies: { | |
"chart": "chartSpider" | |
}, | |
} | |
}, | |
gauge: { | |
type: "object", | |
title: "Gauge", | |
required: ["type", "property"], | |
format: "grid-strict", | |
properties: { | |
property: { | |
type: "string", | |
title: "Property", | |
enum: properties, | |
options: { | |
infoText: "Select a property", | |
grid_columns: 6, | |
} | |
}, | |
type: { | |
type: "string", | |
title: "Chart variation", | |
enum: [ | |
"bullet", | |
"gauge" | |
], | |
options: { | |
infoText: "Select visual appearance", | |
grid_columns: 6, | |
grid_break: true, | |
inputAttributes: { | |
placeholder: "Select visual appearance" | |
}, | |
enum_titles: [ | |
"Bullet", | |
"Gauge" | |
] | |
} | |
}, | |
min: { | |
type: "number", | |
title: "Minimum", | |
options: { | |
infoText: "Select minimum value", | |
grid_columns: 3 | |
} | |
}, | |
max: { | |
type: "number", | |
title: "Maximum", | |
options: { | |
infoText: "Select maximum value", | |
grid_columns: 3 | |
} | |
}, | |
gaugeChartIcon: { | |
type: "info", | |
title: "Example", | |
description: "<img src='https://images.plot.ly/plotly-documentation/thumbnail/indicator.jpg' height='150' />", | |
options: { | |
align: "left", | |
grid_columns: 3, | |
grid_break: true | |
} | |
} | |
}, | |
options: { | |
infoText: "Select options for the spider chart", | |
grid_columns: 12, | |
dependencies: { | |
"chart": "chartGauges" | |
}, | |
} | |
}, | |
submit: { | |
format: "button", | |
title: "Insert", | |
options: { | |
grid_columns: 1, | |
inputAttributes: { | |
class: "btn btn-primary btn-sm json-editor-btn-" | |
}, | |
button: { | |
align: "left", | |
action: "submitform", | |
validated: true | |
} | |
} | |
}, | |
cancel: { | |
format: "button", | |
title: "Cancel", | |
options: { | |
grid_columns: 1, | |
grid_break: true, | |
button: { | |
align: "left", | |
action: "cancelform" | |
} | |
} | |
} | |
} | |
} | |
if (note.prop("Chart")) formSchema.properties.chart.readOnly = true; | |
const primary = shell.getDisplay().getPrimaryMonitor(); | |
const bounds = primary.getBounds(); | |
let value; | |
if (bounds.width <= 1920) | |
value = showForm(formSchema, JSON.parse(note.prop("Chart")), 800, 750); | |
else | |
value = showForm(formSchema, JSON.parse(note.prop("Chart")), 1800, 1100); | |
if (value) { | |
// Do some house cleaning, which the form validation can't handle | |
console.log(JSON.stringify(value, null, 3)); | |
note.prop("Chart", JSON.stringify(value)); | |
load(__DIR__ + "Refresh chart.ajs"); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Author: Thomas Klok Rohde | |
Description: Display form and return data | |
Dependencies: | |
https://github.com/json-editor/json-editor | |
https://github.com/Choices-js/Choices | |
https://github.com/cure53/DOMPurify | |
+ some CSS | |
History: | |
October 11, 2022 : Created with base set of scripts | |
November 11, 2022 : Updated to new form library | |
*/ | |
function showForm(formSchema, defaultValue = null, width = 1200, height = 900) { | |
const SWT = Java.type('org.eclipse.swt.SWT'); | |
const FillLayout = Java.type('org.eclipse.swt.layout.FillLayout'); | |
const Shell = Java.type('org.eclipse.swt.widgets.Shell'); | |
const Browser = Java.type('org.eclipse.swt.browser.Browser'); | |
const ProgressAdapter = Java.extend(Java.type('org.eclipse.swt.browser.ProgressAdapter')); | |
const LocationAdapter = Java.extend(Java.type('org.eclipse.swt.browser.LocationAdapter')); | |
const CustomFunction = Java.extend(Java.type('org.eclipse.swt.browser.BrowserFunction')); | |
const IArchiImages = Java.type('com.archimatetool.editor.ui.IArchiImages'); | |
const ImageFactory = Java.type('com.archimatetool.editor.ui.ImageFactory'); | |
const Rectangle = Java.type('org.eclipse.swt.graphics.Rectangle'); | |
const Monitor = Java.type('org.eclipse.swt.widgets.Monitor'); | |
let display = shell.getDisplay(); | |
let newShell = new Shell(display, SWT.MODAL | SWT.TITLE | SWT.ON_TOP); | |
newShell.setText("Archi form"); | |
newShell.setLayout(new FillLayout()); | |
let insertValue = (defaultValue) ? `startval: ${JSON.stringify(defaultValue, null, 1)},` : ""; | |
let html = ` | |
<!DOCTYPE HTML> | |
<html> | |
<head> | |
<title>radio button editor examples</title> | |
<meta http-equiv="content-type" content="text/html; charset=utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> | |
<link rel='stylesheet' href='https://use.fontawesome.com/releases/v5.12.1/css/all.css'> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/choices.min.css"> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css"> | |
<script type="text/javascript" src="${__DIR__ + "jsoneditor.js"}"></script> | |
<script type="text/javascript" src="${__DIR__ + "choices.min.js"}"></script> | |
<script type="text/javascript" src="${__DIR__ + "purify.min.js"}"></script> | |
<script type="text/javascript" src="${__DIR__ + "simplemde.min.js"}"></script> | |
<style type="text/css"> | |
html { | |
font-size: 14px; | |
line-height: 1.0; | |
} | |
h3 { | |
font-size: 16px; | |
} | |
body { | |
margin: 8px | |
} | |
[data-schemaid="root"] { | |
margin-top: -2rem; | |
} | |
.required::after { | |
content: " *"; | |
color: red; | |
font: inherit; | |
} | |
</style> | |
</head> | |
<body> | |
<!-- <button id='submit' onclick='submit()' class="btn btn-primary">Submit</button> --> | |
<!-- <button id='cancel' onclick='cancel()' class="btn btn-secondary">Cancel</button> --> | |
<div id='editor_holder'></div> | |
<script type="text/javascript"> | |
let schema = ${JSON.stringify(formSchema, null, 1)}; | |
var editor = new JSONEditor(document.getElementById('editor_holder'),{ | |
theme: "bootstrap4", | |
template: "handlebars", | |
iconlib: "fontawesome5", | |
disable_collapse: true, | |
disable_edit_json: true, | |
disable_properties: true, | |
schema: schema, | |
${insertValue} | |
show_errors: "always" | |
}); | |
function submit() { | |
// Get the value from the editor | |
const errors = editor.validate(); | |
if (errors.length) { | |
console.log(errors); | |
} | |
else { | |
insertPressedEvent(JSON.stringify(editor.getValue())); | |
} | |
} | |
function cancel() { | |
cancelPressedEvent(); | |
} | |
window.JSONEditor.defaults.callbacks.button = { | |
submitform: function(jseditor,e) { | |
var res = jseditor.jsoneditor.getValue(); | |
insertPressedEvent(JSON.stringify(res)); | |
}, | |
cancelform: function(jseditor,e) { | |
cancelPressedEvent(); | |
}, | |
resetform: function(jseditor,e) { | |
jseditor.jsoneditor.setValue({}); | |
} | |
}; | |
let insertElement = document.querySelector("button[name='Insert']"); | |
console.log(insertElement); | |
</script> | |
</body> | |
</html>`; | |
var insertPressed = false; | |
var cancelPressed = false; | |
let browser = new Browser(newShell, SWT.NONE); | |
var value; | |
browser.addProgressListener(new ProgressAdapter({ | |
completed: function (event) { | |
let fncOk = new CustomFunction(browser, "insertPressedEvent", { | |
function: function (args) { | |
value = args[0]; | |
insertPressed = true; | |
} | |
}); | |
let fncCancel = new CustomFunction(browser, "cancelPressedEvent", { | |
function: function (args) { | |
cancelPressed = true; | |
} | |
}); | |
browser.addLocationListener(new LocationAdapter({ | |
changed: function (e) { | |
browser.removeLocationListener(this); | |
fncOk.dispose(); | |
fncCancel.dispose(); | |
} | |
})); | |
} | |
})); | |
// Write the HTML to a temporary file, so we are allowed to execute a local script | |
let System = Java.type('java.lang.System'); | |
let tmpfile = System.getProperty("java.io.tmpdir") + "form.html"; | |
$.fs.writeFile(tmpfile, html); | |
browser.setUrl("file:///" + tmpfile); | |
// Set icon to Archi icon, in case shell has a style which displays icons | |
newShell.setImage(IArchiImages.ImageFactory.getImage(IArchiImages.ICON_APP)); | |
newShell.setSize(width, height); | |
// Center dialog on screen | |
const primary = display.getPrimaryMonitor(); | |
const bounds = primary.getBounds(); | |
const rect = newShell.getBounds(); | |
const x = bounds.x + (bounds.width - rect.width) / 2; | |
const y = bounds.y + (bounds.height - rect.height) / 2; | |
newShell.setLocation(x, y); | |
newShell.open(); | |
while (!newShell.isDisposed() && !insertPressed && !cancelPressed) { | |
if (!display.readAndDispatch()) display.sleep(); | |
} | |
if (insertPressed && value != undefined && value != null) { | |
newShell.dispose(); | |
} | |
else if (cancelPressed) { | |
console.log('Dialog cancelled.'); | |
newShell.dispose(); | |
} | |
if (value) return JSON.parse(value); | |
else return null; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment