Skip to content
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ yarn-error.log*
*.njsproj
*.sln
*.sw*
storybook-static/
14 changes: 13 additions & 1 deletion .storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/** @type { import('@storybook/vue-vite').StorybookConfig } */
const path = require('path');
const { mergeConfig } = require('vite');

const config = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [
Expand All @@ -13,6 +16,15 @@ const config = {
},
docs: {
autodocs: "tag"
}
},
viteFinal: async (config) => {
return mergeConfig(config, {
resolve: {
alias: {
'vue-monaco': path.resolve(__dirname, '../node_modules/vue-monaco/dist/vue-monaco.js'),
},
},
});
},
};
export default config;
9 changes: 9 additions & 0 deletions src/components/inspector/button/handler-event-property.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const handlerEventProperty = {
type: 'CodeEditor',
field: 'handler',
config: {
label: 'Click Handler',
helper: 'The handler is a JavaScript function that will be executed when the button is clicked.',
dataFeature: 'i1177',
},
};
127 changes: 127 additions & 0 deletions src/components/inspector/code-editor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<template>
<div>
<label :for="`${dataFeature}-code-input`">{{ $t(label) }} </label>
<div class="float-right buttons">
<b-button
:title="$t('Expand')"
variant="light"
size="sm"
:data-test="`${dataFeature}-expand-button`"
@click="expand"
><i class="fas fa-expand"></i></b-button>
</div>
<MonacoEditor
:id="`${dataFeature}-code-input`"
v-model="configValue"
:options="smallMonacoOptions"
class="editor"
language="javascript"
:data-test="`${dataFeature}-code-input`"
@change="updateValue"
/>
<small v-if="helper" class="form-text text-muted mt-2">{{ $t(helper) }}</small>
<b-modal
ref="codeEditorModal"
:title="$t(label)"
size="xl"
dialog-class="modal-dialog-fullscreen"
>
<MonacoEditor
v-model="configValue"
:options="largeMonacoOptions"
class="editor large-editor"
language="javascript"
:data-test="`${dataFeature}-code-input`"
@change="updateValue"
/>
<template #modal-footer="{ ok }">
<b-button @click="ok" class="btn btn-secondary text-uppercase">
{{ $t('Close') }}
</b-button>
</template>
</b-modal>
</div>
</template>

<script>
import MonacoEditor from 'vue-monaco';

export default {
name: 'CodeEditor',
props: {
value: {
type: String,
required: false,
},
label: {
type: String,
default: '',
},
helper: {
type: String,
required: false,
},
dataFeature: {
type: String,
required: true,
},
},
components: {
MonacoEditor,
},
data() {
return {
configValue: this.value || '',
smallMonacoOptions: {
lineNumbers: 'off',
lineDecorationsWidth: 0,
lineNumbersMinChars: 0,
minimap: { enabled: false },
fixedOverflowWidgets: true,
automaticLayout: true,
renderLineHighlight: 'none',
overviewRulerLanes: 0,
},
largeMonacoOptions: {
lineNumbers: 'on',
lineDecorationsWidth: 0,
minimap: { enabled: false },
automaticLayout: true,
overviewRulerLanes: 0,
},
};
},
methods: {
updateValue() {
this.$emit('input', this.configValue);
},
expand() {
this.$refs.codeEditorModal.show();
},
},
watch: {
value(newVal) {
this.configValue = newVal;
},
},
};
</script>

<style scoped>
.buttons button {
min-width: 2.2em;
margin-left: 0.5em;
margin-bottom: 0.5em;
}

.editor {
width: 100%;
height: 10em;
border: 1px solid var(--gray);
overflow: hidden;
}

.large-editor {
height: 25em;
}
</style>
1 change: 1 addition & 0 deletions src/components/inspector/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ export { default as LoadingSubmitButton } from "./loading-submit-button.vue";
export { default as LabelSubmitButton } from "./label-submit-button.vue";
export { default as AnalyticsSelector } from "./analytics-selector.vue";
export { default as EncryptedConfig } from "./encrypted-config.vue";
export { default as CodeEditor } from "./code-editor.vue";
21 changes: 20 additions & 1 deletion src/components/renderer/form-button.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { getValidPath } from '@/mixins';

export default {
mixins: [getValidPath],
props: ['variant', 'label', 'event', 'eventData', 'name', 'fieldValue', 'value', 'tooltip', 'transientData', 'loading', 'loadingLabel'],
props: ['variant', 'label', 'event', 'eventData', 'name', 'fieldValue', 'value', 'tooltip', 'transientData', 'loading', 'loadingLabel', 'handler'],
data() {
return {
showSpinner: false
Expand Down Expand Up @@ -80,6 +80,8 @@ export default {
const trueValue = this.fieldValue || '1';
const value = (this.value == trueValue) ? null : trueValue;
this.$emit('input', value);
// Run handler after setting the value
await this.runHandler();
}
if (this.event !== 'pageNavigate' && this.name) {
this.setValue(this.$parent, this.name, this.fieldValue);
Expand All @@ -89,6 +91,8 @@ export default {
this.showSpinner = true;
}
this.$emit('input', this.fieldValue);
// Run handler after setting the value
await this.runHandler();
this.$nextTick(() => {
this.$emit('submit', this.eventData, this.loading, this.buttonInfo);
});
Expand All @@ -99,6 +103,21 @@ export default {
this.$emit('page-navigate', this.eventData);
}
},
async runHandler() {
if (this.handler) {
try {
const data = this.getScreenDataReference(null, (screen, name, value) => {
// Enable the data reference to be updated by the handler
screen.$set(screen.vdata, name, value);
});
await new Function(['toRaw'], this.handler).apply(data, [(item) => {
return item[Symbol.for('__v_raw')];
}]);
} catch (error) {
console.error('❌ There is an error in the button handler', error);
}
}
}
},
};
</script>
2 changes: 2 additions & 0 deletions src/components/vue-form-builder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,7 @@ import TabsBar from "./TabsBar.vue";
import Sortable from './sortable/Sortable.vue';
import ClipboardButton from './ClipboardButton.vue';
import ScreenTemplates from './ScreenTemplates.vue';
import CodeEditor from "./inspector/code-editor.vue";

// To include another language in the Validator with variable processmaker
const globalObject = typeof window === "undefined" ? global : window;
Expand Down Expand Up @@ -633,6 +634,7 @@ export default {
Sortable,
ClipboardButton,
ScreenTemplates,
CodeEditor,
},
mixins: [HasColorProperty, testing, Clipboard],
props: {
Expand Down
3 changes: 3 additions & 0 deletions src/form-builder-controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import FormListTable from './components/renderer/form-list-table';
import FormAnalyticsChart from "./components/renderer/form-analytics-chart";
import FormCollectionRecordControl from './components/renderer/form-collection-record-control.vue';
import FormCollectionViewControl from './components/renderer/form-collection-view-control.vue';
import { handlerEventProperty } from './components/inspector/button/handler-event-property';
import {DataTypeProperty, DataFormatProperty, DataTypeDateTimeProperty} from './VariableDataTypeProperties';
import {
FormInput,
Expand Down Expand Up @@ -720,6 +721,7 @@ export default [
name: null,
fieldValue: null,
tooltip: {},
handler: '',
},
inspector: [
{
Expand All @@ -742,6 +744,7 @@ export default [
},
},
buttonTypeEvent,
handlerEventProperty,
LoadingSubmitButtonProperty,
LabelSubmitButtonProperty,
tooltipProperty,
Expand Down
4 changes: 4 additions & 0 deletions src/mixins/DataReference.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function findScreenOwner(control, lastScreenContentIfNull = false) {
* @return {object} proxy
*/
function wrapScreenData(screen, customProperties = null, setter = null) {
const RAW = Symbol.for('__v_raw');
const handler = {
get: (target, name) => {
if (customProperties && customProperties[name]) {
Expand All @@ -44,6 +45,9 @@ function wrapScreenData(screen, customProperties = null, setter = null) {
}
return undefined;
}
if (name === RAW) {
return screen.vdata;
}
// Check if vdata exists
if (screen.vdata !== undefined && screen.vdata !== null) {
return screen.vdata[name];
Expand Down
4 changes: 4 additions & 0 deletions src/mixins/extensions/LoadFieldComponents.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ export default {
properties[":disabled"] = isCalcProp || element.config.disabled;
// Events
properties['@submit'] = 'submitForm';
// Add handler event if Button
if(componentName === 'FormButton') {
properties[':handler'] = this.byRef(element.config.handler);
}
},
},
mounted() {
Expand Down
Loading
Loading