@processmaker/screen-builder 2.83.11 → 2.84.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@processmaker/screen-builder",
3
- "version": "2.83.11",
3
+ "version": "2.84.1",
4
4
  "scripts": {
5
5
  "dev": "VITE_COVERAGE=true vite",
6
6
  "build": "vite build",
@@ -8,7 +8,10 @@
8
8
  "lint": "vue-cli-service lint",
9
9
  "build-bundle": "npm run build",
10
10
  "open-cypress": "nyc cypress open",
11
- "run-cypress": "TZ=UTC nyc cypress run"
11
+ "run-cypress": "TZ=UTC nyc cypress run",
12
+ "storybook": "storybook dev -p 6006",
13
+ "build-storybook": "storybook build",
14
+ "test-storybook": "test-storybook"
12
15
  },
13
16
  "main": "./dist/vue-form-builder.umd.js",
14
17
  "module": "./dist/vue-form-builder.es.js",
@@ -28,6 +31,7 @@
28
31
  ],
29
32
  "dependencies": {
30
33
  "@chantouchsek/validatorjs": "1.2.3",
34
+ "@storybook/addon-docs": "^7.6.13",
31
35
  "axios-extensions": "^3.1.6",
32
36
  "lodash": "^4.17.21",
33
37
  "lru-cache": "^10.0.1",
@@ -53,6 +57,14 @@
53
57
  "@panter/vue-i18next": "^0.15.2",
54
58
  "@processmaker/vue-form-elements": "0.51.0",
55
59
  "@processmaker/vue-multiselect": "2.3.0",
60
+ "@storybook/addon-essentials": "^7.6.13",
61
+ "@storybook/addon-interactions": "^7.6.13",
62
+ "@storybook/addon-links": "^7.6.13",
63
+ "@storybook/blocks": "^7.6.13",
64
+ "@storybook/test": "^7.6.13",
65
+ "@storybook/test-runner": "^0.16.0",
66
+ "@storybook/vue": "^7.6.13",
67
+ "@storybook/vue-vite": "^7.6.13",
56
68
  "@vitejs/plugin-vue2": "^2.3.1",
57
69
  "@vue/test-utils": "^1.1.1",
58
70
  "axios": "^1.6.0",
@@ -71,6 +83,7 @@
71
83
  "eslint-plugin-import": "^2.26.0",
72
84
  "eslint-plugin-jest": "^22.4.1",
73
85
  "eslint-plugin-prettier": "^4.2.1",
86
+ "eslint-plugin-storybook": "^0.6.15",
74
87
  "eslint-plugin-vue": "^9.3.0",
75
88
  "expr-eval": "^2.0.2",
76
89
  "globby": "^11.1.0",
@@ -80,7 +93,10 @@
80
93
  "mustache": "^3.0.1",
81
94
  "nyc": "^15.1.0",
82
95
  "prettier": "2.7.1",
96
+ "react": "^18.2.0",
97
+ "react-dom": "^18.2.0",
83
98
  "sass": "^1.53.0",
99
+ "storybook": "^7.6.13",
84
100
  "v-calendar": "^0.9.7",
85
101
  "validatorjs": "^3.14.2",
86
102
  "vite": "^4.0.4",
package/src/App.vue CHANGED
@@ -1,11 +1,11 @@
1
1
  <template>
2
2
  <b-container id="screen-builder-container" class="h-100">
3
- <b-card id="app" no-body class="h-100 bg-white border-top-0">
3
+ <b-card id="app" no-body class="h-100 bg-white border-top-0 ">
4
4
  <!-- Card Header -->
5
- <b-card-header>
5
+ <b-card-header class="bg-white p-0">
6
6
  <b-row>
7
- <b-col>
8
- <b-button-group size="sm pr-2">
7
+ <b-col class="d-flex align-items-center">
8
+ <b-button-group size="sm px-2">
9
9
  <b-button
10
10
  :variant="displayBuilder ? 'secondary' : 'outline-secondary'"
11
11
  data-cy="mode-editor"
@@ -49,60 +49,33 @@
49
49
  </b-col>
50
50
 
51
51
  <b-col v-if="displayBuilder && !displayPreview" class="text-right">
52
- <div
53
- class="btn-group btn-group-sm mr-2"
54
- role="group"
55
- aria-label="Basic example"
52
+ <screen-toolbar
53
+ @undo="$refs.builder.undo()"
54
+ @redo="$refs.builder.redo()"
55
+ @open-calc="openComputedProperties"
56
+ @open-customCss="openCustomCSS"
57
+ @open-watchers="openWatchersPopup"
56
58
  >
57
- <button
58
- type="button"
59
- class="btn btn-secondary"
60
- :title="$t('Calculated Properties')"
61
- data-cy="topbar-calcs"
62
- @click="openComputedProperties"
59
+ <b-btn
60
+ v-b-modal="'uploadmodal'"
61
+ variant="secondary"
62
+ size="sm"
63
+ class="mr-2"
64
+ :title="$t('Load Screen')"
63
65
  >
64
- <i class="fas fa-flask" />
65
- {{ $t("Calcs") }}
66
- </button>
67
- <button
68
- type="button"
69
- class="btn btn-secondary"
70
- :title="$t('Custom CSS')"
71
- data-cy="topbar-css"
72
- @click="openCustomCSS"
66
+ <i class="fas fa-upload mr-1" />
67
+ </b-btn>
68
+ <b-btn
69
+ v-b-modal.preview-config
70
+ variant="secondary"
71
+ size="sm"
72
+ class="mr-2"
73
+ :title="$t('Save Screen')"
74
+ @click="saveToLocalStorage()"
73
75
  >
74
- <i class="fab fa-css3" />
75
- {{ $t("CSS") }}
76
- </button>
77
- <button
78
- type="button"
79
- class="btn btn-secondary"
80
- :title="$t('Watchers')"
81
- data-cy="topbar-watchers"
82
- @click="openWatchersPopup"
83
- >
84
- <i class="fas fa-mask" />
85
- {{ $t("Watchers") }}
86
- </button>
87
- </div>
88
- <b-btn
89
- v-b-modal="'uploadmodal'"
90
- variant="secondary"
91
- size="sm"
92
- class="mr-2"
93
- :title="$t('Load Screen')"
94
- >
95
- <i class="fas fa-upload mr-1" />
96
- </b-btn>
97
- <button
98
- v-b-modal.preview-config
99
- type="button"
100
- class="btn btn-secondary btn-sm ml-1"
101
- :title="$t('Save Screen')"
102
- @click="saveToLocalStorage()"
103
- >
104
- <i class="fas fa-save" />
105
- </button>
76
+ <i class="fas fa-save mr-1" />
77
+ </b-btn>
78
+ </screen-toolbar>
106
79
  </b-col>
107
80
  <b-modal
108
81
  id="uploadmodal"
@@ -351,6 +324,7 @@ import WatchersPopup from "./components/watchers-popup.vue";
351
324
  import CustomCss from "./components/custom-css.vue";
352
325
  import VueFormBuilder from "./components/vue-form-builder.vue";
353
326
  import VueFormRenderer from "./components/vue-form-renderer.vue";
327
+ import ScreenToolbar from "./components/ScreenToolbar.vue";
354
328
  import canOpenJsonFile from "./mixins/canOpenJsonFile";
355
329
 
356
330
  // Bring in our initial set of controls
@@ -358,6 +332,7 @@ import controlConfig from "./form-builder-controls";
358
332
  import globalProperties from "./global-properties";
359
333
 
360
334
  import "bootstrap";
335
+ import "./assets/css/tabs.css";
361
336
 
362
337
  // To include another language in the Validator with variable processmaker
363
338
  const globalObject = typeof window === "undefined" ? global : window;
@@ -411,7 +386,8 @@ export default {
411
386
  VueFormBuilder,
412
387
  VueFormRenderer,
413
388
  MonacoEditor,
414
- WatchersPopup
389
+ WatchersPopup,
390
+ ScreenToolbar,
415
391
  },
416
392
  mixins: [canOpenJsonFile],
417
393
  data() {
@@ -754,6 +730,7 @@ export default {
754
730
  <style lang="scss">
755
731
  @import "bootstrap/dist/css/bootstrap";
756
732
  @import "bootstrap-vue/dist/bootstrap-vue";
733
+ @import "assets/css/custom";
757
734
 
758
735
  $validation-panel-bottom: 3.5rem;
759
736
  $validation-panel-right: 0;
@@ -786,6 +763,7 @@ body {
786
763
 
787
764
  .card-header {
788
765
  border-radius: 0 !important;
766
+ background-color: none !important;
789
767
  }
790
768
 
791
769
  .border-check {
@@ -0,0 +1,11 @@
1
+ .btn-platform {
2
+ background-color: #ffff;
3
+ color: #6a7888;
4
+ padding: 8px 8px 2px 8px;
5
+ }
6
+ .btn-platform:hover {
7
+ color: #6a7888;
8
+ }
9
+ .page-dropdown-menu {
10
+ min-width: 333px;
11
+ }
@@ -0,0 +1,118 @@
1
+ /* Setup some colors */
2
+ :root {
3
+ --tabs-blue: #1572c2;
4
+ --tabs-light: #c3c9cf;
5
+ --tabs-grey: #6a7888;
6
+ --tabs-border: #cdddee;
7
+ --tabs-scroll-bg: #ebeef2;
8
+ --tabs-white: #ffffff;
9
+ }
10
+ /* Override Bootstrap default tab styles */
11
+ .nav-tabs {
12
+ border-bottom: 1px solid var(--tabs-border) !important;
13
+ flex-wrap: nowrap !important;
14
+ overflow: hidden !important;
15
+ }
16
+
17
+ .nav-tabs .nav-item .nav-link {
18
+ display: flex;
19
+ align-items: center;
20
+ }
21
+
22
+ /* Style for individual tabs */
23
+ .nav-tabs .nav-item.show .nav-link,
24
+ .nav-tabs .nav-link.active {
25
+ border: none;
26
+ box-shadow: inset 0 -3px 0 0 var(--tabs-blue) !important; /* This sets the blue bottom border for the active tab */
27
+ background-color: var(
28
+ --tabs-white
29
+ ); /* This sets the background color for the active tab */
30
+ border-radius: 0 !important; /* This removes the border-radius */
31
+ color: var(--tabs-blue) !important;
32
+ position: relative;
33
+ }
34
+
35
+ /* Style for non-active tabs */
36
+ .nav-tabs .nav-link {
37
+ border: 1px solid var(--tabs-border) !important;
38
+ color: var(--tabs-grey); /* This sets the text color for the inactive tabs */
39
+ border-radius: 0 !important; /* This ensures no border radius for a flat design */
40
+ padding: 0.5rem 1rem;
41
+ margin-right: -1px;
42
+ text-wrap: nowrap !important;
43
+ flex-wrap: nowrap !important;
44
+ }
45
+
46
+ .nav-tabs .nav-item .nav-link:not(.active) {
47
+ .badge {
48
+ background-color: #6A7888 !important;
49
+ }
50
+
51
+ span:not(.badge, .close-tab) {
52
+ color: #556271 !important;
53
+ }
54
+ }
55
+
56
+ /* Style for the hover effect */
57
+ .nav-tabs .nav-link:hover {
58
+ border: none;
59
+ background-color: var(
60
+ --tabs-white
61
+ ); /* This changes the background color when hovering */
62
+ }
63
+
64
+ /* Adding the 'x' button to the tab */
65
+ .nav-tabs .nav-link .close-tab {
66
+ font-size: 0.8rem;
67
+ color: var(--tabs-light);
68
+ margin-left: 0.5rem;
69
+ display: inline !important;
70
+ }
71
+
72
+ /* Style adjustments for the 'x' button */
73
+ .nav-tabs .nav-link .close-tab:hover {
74
+ color: var(--tabs-grey);
75
+ cursor: pointer;
76
+ }
77
+ .nav-tabs .nav-scroll {
78
+ position: absolute;
79
+ top: calc(50% - 0.75rem);
80
+ width: 1.5rem;
81
+ height: 1.5rem;
82
+ font-size: 0.75rem;
83
+ display: flex;
84
+ align-items: center;
85
+ justify-content: center;
86
+ background-color: var(--tabs-scroll-bg);
87
+ color: var(--tabs-grey);
88
+ cursor: pointer;
89
+ border: 1px solid var(--tabs-border);
90
+ border-radius: 100%;
91
+ z-index: 1;
92
+ }
93
+ .nav-tabs .nav-scroll-right {
94
+ right: 5px;
95
+ }
96
+ .nav-tabs .nav-scroll-left {
97
+ margin-left: 5px;
98
+ }
99
+ .nav-tabs .tabs-sticky {
100
+ position: sticky;
101
+ -webkit-position: sticky;
102
+ left: 0;
103
+ right: 0;
104
+ z-index: 2;
105
+ }
106
+ .nav-tabs .tabs-start {
107
+ background-color: var(--tabs-white);
108
+ }
109
+ /* add margin right to the last li element to hide safely the right scroll button */
110
+ .nav-tabs li.nav-item:last-of-type {
111
+ margin-right: 2rem;
112
+ }
113
+ .flat-tabs .h-tab {
114
+ height: calc(100% - 42px) !important;
115
+ }
116
+ .dd-ml {
117
+ margin-left: 2rem;
118
+ }
@@ -0,0 +1,111 @@
1
+ /* eslint-disable vue/multi-word-component-names */
2
+ /* eslint-disable import/extensions */
3
+ /* eslint-disable import/no-unresolved */
4
+ /* eslint-disable import/no-extraneous-dependencies */
5
+ import Vue from "vue";
6
+ import i18next from "i18next";
7
+ import VueI18Next from "@panter/vue-i18next";
8
+ import Vuex from "vuex";
9
+ import axios from "axios";
10
+ import { cacheAdapterEnhancer } from "axios-extensions";
11
+ import { BootstrapVue, IconsPlugin } from "bootstrap-vue";
12
+ import { Multiselect } from "@processmaker/vue-multiselect";
13
+ import { LRUCache } from "lru-cache";
14
+ import VueFormElements from "@processmaker/vue-form-elements";
15
+ import { configure } from "@storybook/test"; // Required for testing
16
+ import undoRedoModule from "@/store/modules/undoRedoModule";
17
+ import globalErrorsModule from "@/store/modules/globalErrorsModule";
18
+ import ScreenBuilder from "@/components";
19
+ import "bootstrap/dist/css/bootstrap.css";
20
+ import "bootstrap-vue/dist/bootstrap-vue.css";
21
+ import "@fortawesome/fontawesome-free/css/all.min.css";
22
+ import "@processmaker/vue-form-elements/dist/vue-form-elements.css";
23
+ import "@processmaker/vue-multiselect/dist/vue-multiselect.min.css";
24
+ import "@/assets/css/custom.css";
25
+ // For QA: Set default testIdAttribute to "data-test"
26
+ configure({ testIdAttribute: "data-test" });
27
+
28
+ Vue.use(BootstrapVue);
29
+ Vue.use(IconsPlugin);
30
+ Vue.config.productionTip = false;
31
+ Vue.use(VueI18Next);
32
+ i18next.init({ lng: "en" });
33
+ Vue.mixin({ i18n: new VueI18Next(i18next) });
34
+ Vue.use(Vuex);
35
+ Vue.use(ScreenBuilder);
36
+ Vue.use(VueFormElements);
37
+ Vue.component("Multiselect", Multiselect);
38
+
39
+ export const store = new Vuex.Store({
40
+ modules: {
41
+ globalErrorsModule,
42
+ undoRedoModule
43
+ }
44
+ });
45
+
46
+ // get cache config from header
47
+ const cacheEnabled = document.head.querySelector(
48
+ "meta[name='screen-cache-enabled']"
49
+ );
50
+ const cacheTimeout = document.head.querySelector(
51
+ "meta[name='screen-cache-timeout']"
52
+ );
53
+
54
+ // Get the current protocol, hostname, and port
55
+ const { protocol, hostname, port } = window.location;
56
+ window.ProcessMaker = {
57
+ isStub: true,
58
+ user: {
59
+ id: 1,
60
+ lang: "en"
61
+ },
62
+ app: {
63
+ url: `${protocol}//${hostname}:${port}` // Create a URL with the current port
64
+ },
65
+ EventBus: new Vue(),
66
+ confirmModal(title, message, variant, callback) {
67
+ // eslint-disable-next-line no-alert
68
+ if (window.confirm(`${title}: ${message}`)) {
69
+ callback();
70
+ }
71
+ },
72
+ // eslint-disable-next-line no-unused-expressions, no-unused-vars
73
+ alert(message, variant) {},
74
+ screen: {
75
+ cacheEnabled: cacheEnabled ? cacheEnabled.content === "true" : false,
76
+ cacheTimeout: cacheTimeout ? Number(cacheTimeout.content) : 0
77
+ }
78
+ };
79
+ window.Echo = {
80
+ listeners: [],
81
+ private() {
82
+ return {
83
+ notification(callback) {
84
+ window.Echo.listeners.push({ callback });
85
+ },
86
+ stopListening() {
87
+ window.Echo.listeners.splice(0);
88
+ },
89
+ listen(event, callback) {
90
+ window.Echo.listeners.push({ event, callback });
91
+ }
92
+ };
93
+ }
94
+ };
95
+
96
+ // axios
97
+ window.axios = axios.create({
98
+ baseURL: "/api/1.0/",
99
+ adapter: cacheAdapterEnhancer(axios.getAdapter(axios.defaults.adapter), {
100
+ enabledByDefault: window.ProcessMaker.screen.cacheEnabled,
101
+ cacheFlag: "useCache",
102
+ defaultCache: new LRUCache({
103
+ ttl: window.ProcessMaker.screen.cacheTimeout,
104
+ max: 100
105
+ })
106
+ })
107
+ });
108
+
109
+ window.ProcessMaker.apiClient = window.axios;
110
+
111
+ export default { ScreenBuilder };
@@ -0,0 +1,100 @@
1
+ <template>
2
+ <div class="flex-grow-1 d-flex flex-row-reverse">
3
+ <b-button-group size="sm" class="bg-white p-2 screen-toolbar">
4
+ <b-button
5
+ class="screen-toolbar-button"
6
+ variant="link"
7
+ :disabled="!canUndo"
8
+ data-cy="toolbar-undo"
9
+ @click="$emit('undo')"
10
+ >
11
+ <i class="fas fa-undo" />
12
+ {{ $t("Undo") }}
13
+ </b-button>
14
+ <b-button
15
+ class="screen-toolbar-button"
16
+ variant="link"
17
+ :disabled="!canRedo"
18
+ data-cy="toolbar-redo"
19
+ @click="$emit('redo')"
20
+ >
21
+ <i class="fas fa-redo" />
22
+ {{ $t("Redo") }}
23
+ </b-button>
24
+ <b-button
25
+ type="button"
26
+ class="screen-toolbar-button"
27
+ variant="link"
28
+ :title="$t('Calculated Properties')"
29
+ data-cy="topbar-calcs"
30
+ @click="$emit('open-calc')"
31
+ >
32
+ <i class="fas fa-flask" />
33
+ {{ $t("Calcs") }}
34
+ </b-button>
35
+ <b-button
36
+ type="button"
37
+ class="screen-toolbar-button"
38
+ variant="link"
39
+ :title="$t('Custom CSS')"
40
+ data-cy="topbar-css"
41
+ @click="$emit('open-customCss')"
42
+ >
43
+ <i class="fab fa-css3" />
44
+ {{ $t("CSS") }}
45
+ </b-button>
46
+ <b-button
47
+ type="button"
48
+ class="screen-toolbar-button"
49
+ variant="link"
50
+ :title="$t('Watchers')"
51
+ data-cy="topbar-watchers"
52
+ @click="$emit('open-watchers')"
53
+ >
54
+ <i class="fas fa-mask" />
55
+ {{ $t("Watchers") }}
56
+ </b-button>
57
+ <b-dropdown
58
+ type="button"
59
+ class="screen-toolbar-button"
60
+ variant="outlined-secondary"
61
+ :popper-opts="{ placement: 'bottom-end' }"
62
+ data-cy="topbar-options"
63
+ >
64
+ <template v-slot:button-content>
65
+ <span class="screen-toolbar-button">
66
+ <i class="fas fa-cog" />
67
+ {{ $t("Options") }}
68
+ </span>
69
+ </template>
70
+ <template v-slot:default>
71
+ <slot />
72
+ </template>
73
+ </b-dropdown>
74
+ </b-button-group>
75
+ </div>
76
+ </template>
77
+
78
+ <script>
79
+ export default {
80
+ data() {
81
+ return {
82
+ showToolbar: true
83
+ };
84
+ },
85
+ computed: {
86
+ canUndo() {
87
+ return this.$store.getters["undoRedoModule/canUndo"];
88
+ },
89
+ canRedo() {
90
+ return this.$store.getters["undoRedoModule/canRedo"];
91
+ },
92
+ }
93
+ };
94
+ </script>
95
+
96
+ <style scoped>
97
+ .screen-toolbar-button {
98
+ color: #556271;
99
+ }
100
+ </style>