rb-document-form-constructor 0.0.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 ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "rb-document-form-constructor",
3
+ "version": "0.0.1",
4
+ "description": "",
5
+ "main": "dist/rb-document-form-constructor.ssr.js",
6
+ "browser": "dist/rb-document-form-constructor.esm.js",
7
+ "module": "dist/rb-document-form-constructor.esm.js",
8
+ "unpkg": "dist/rb-document-form-constructor.min.js",
9
+ "files": [
10
+ "dist/*",
11
+ "src/**/*.vue"
12
+ ],
13
+ "sideEffects": false,
14
+ "scripts": {
15
+ "serve": "vue-cli-service serve dev/serve.js",
16
+ "prebuild": "rimraf ./dist",
17
+ "build": "cross-env NODE_ENV=production rollup --config build/rollup.config.js",
18
+ "build:ssr": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format cjs",
19
+ "build:es": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format es",
20
+ "build:unpkg": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format iife"
21
+ },
22
+ "dependencies": {
23
+ "bootstrap": "^4.5.0",
24
+ "bootstrap-vue": "^2.15.0",
25
+ "debounce": "^1.2.1",
26
+ "jquery": "^3.6.0",
27
+ "sass": "^1.32.0",
28
+ "sass-loader": "^10.1.0",
29
+ "vuedraggable": "^2.24.3"
30
+ },
31
+ "devDependencies": {
32
+ "@babel/core": "^7.14.6",
33
+ "@babel/preset-env": "^7.14.7",
34
+ "@rollup/plugin-alias": "^3.1.2",
35
+ "@rollup/plugin-babel": "^5.3.0",
36
+ "@rollup/plugin-commonjs": "^14.0.0",
37
+ "@rollup/plugin-node-resolve": "^9.0.0",
38
+ "@rollup/plugin-replace": "^2.4.2",
39
+ "@vue/cli-plugin-babel": "^4.5.13",
40
+ "@vue/cli-service": "^4.5.13",
41
+ "cross-env": "^7.0.3",
42
+ "minimist": "^1.2.5",
43
+ "rimraf": "^3.0.2",
44
+ "rollup": "^2.52.8",
45
+ "rollup-plugin-terser": "^7.0.2",
46
+ "rollup-plugin-vue": "^5.1.9",
47
+ "vue": "^2.6.14",
48
+ "vue-template-compiler": "^2.6.14",
49
+ "rb-bv-components": "^1.4.1"
50
+ },
51
+ "peerDependencies": {
52
+ "vue": "^2.6.14"
53
+ },
54
+ "engines": {
55
+ "node": ">=12"
56
+ }
57
+ }
@@ -0,0 +1,236 @@
1
+ <template>
2
+ <div class="rb-doc-template-constructor d-flex">
3
+ <doc-template-facet-list @fieldMoveEnd="onFieldMoveEnd" :facets="facets"></doc-template-facet-list>
4
+
5
+ <div class="rb-form-constructor flex-fill">
6
+ <div class="rb-constructor-toolbar d-flex flex-row">
7
+ <h4>Верстка документа</h4>
8
+ <div class="rb-layout-buttons">
9
+ <b-button pill variant="outline-gray" @click="addSection(1)">
10
+ <rb-text>1 колонка</rb-text>
11
+ <rb-icon icon="icon-add"></rb-icon>
12
+ </b-button>
13
+ <b-button pill variant="outline-gray" @click="addSection(2)">
14
+ <rb-text>2 колонки</rb-text>
15
+ <rb-icon icon="icon-add"></rb-icon>
16
+ </b-button>
17
+ <b-button pill variant="outline-gray" @click="addSection(3)">
18
+ <rb-text>3 колонки</rb-text>
19
+ <rb-icon icon="icon-add"></rb-icon>
20
+ </b-button>
21
+ </div>
22
+ </div>
23
+
24
+ <div class="rb-constructor-body">
25
+ <draggable v-model="formConfig.section"
26
+ :animation="200"
27
+ group="section"
28
+ ghost-class="rb-form-card-moving"
29
+ handle=".rb-row-drag-handle">
30
+ <b-card v-for="(section, index) in formConfig.sections" :key="section.labelRu"
31
+ class="rb-form-card" :data-hash="hash">
32
+ <template #header>
33
+ <rb-icon icon="icon-reorder"
34
+ class="cursor-pointer rb-row-drag-handle"></rb-icon>
35
+ <rb-text class="flex-fill" @click="editSection(section)">
36
+ {{section.labelRu}}
37
+ </rb-text>
38
+ <span class="rb-actions">
39
+ <rb-icon icon="icon-edit" class="cursor-pointer"
40
+ @click="editSection(section)"></rb-icon>
41
+ <rb-icon icon="icon-delete" class="cursor-pointer"
42
+ @click="removeSection(section, index)"></rb-icon>
43
+ </span>
44
+ </template>
45
+
46
+ <div class="d-flex flex-row">
47
+ <draggable tag="b-form"
48
+ class="rb-form-column"
49
+ v-for="column in section.columns"
50
+ :key="column.index"
51
+ :class="{'rb-single-column': section.columnCount === 1}"
52
+ v-model="column.fields"
53
+ @add="onFieldAddedToColumn($event, column, section)"
54
+ :animation="200"
55
+ group="fields"
56
+ ghost-class="rb-moving-item"
57
+ handle=".icon-reorder">
58
+ <b-form-row v-for="field in column.fields" :key="field.name"
59
+ class="cursor-pointer" @click="showProperties(field)">
60
+ <b-col lg="12">
61
+ <b-form-group :label="field.labelRu">
62
+ <template #label>
63
+ <rb-icon icon="icon-reorder"></rb-icon>
64
+ <rb-text>{{field.labelRu}}</rb-text>
65
+ <rb-icon icon="icon-delete"
66
+ @click.prevent="onRemoveField($event, field, column)">
67
+ </rb-icon>
68
+ </template>
69
+ <component v-bind:is="field.input.type"
70
+ v-if="field.input"
71
+ v-bind="getFieldExtendedPropsData(field)"
72
+ disabled
73
+ class="cursor-pointer">
74
+ </component>
75
+ </b-form-group>
76
+ </b-col>
77
+ </b-form-row>
78
+ </draggable>
79
+ </div>
80
+ </b-card>
81
+ </draggable>
82
+ </div>
83
+
84
+ <doc-template-field-sidebar v-model="sidebarField" :visible="sidebarVisible"
85
+ @hide="sidebarVisible=false">
86
+ </doc-template-field-sidebar>
87
+
88
+ <doc-template-section-modal :mode="sectionModalCfg.mode"
89
+ :section="sectionModalCfg.section"
90
+ :on-after-ok="sectionModalCfg.onAfterOk"></doc-template-section-modal>
91
+ </div>
92
+ </div>
93
+ </template>
94
+
95
+ <script>
96
+ import DocTemplateFacetList from "@/components/DocTemplateFacetList";
97
+ import DocTemplateFieldSidebar from "@/components/DocTemplateFieldSidebar";
98
+ import DocTemplateSectionModal from "@/components/DocTemplateSectionModal";
99
+ import draggable from 'vuedraggable';
100
+
101
+ export default {
102
+ name: 'DocTemplateConstructor',
103
+ components: {DocTemplateFacetList, DocTemplateFieldSidebar, DocTemplateSectionModal, draggable},
104
+ props: {
105
+ formConfig: {
106
+ type: Object, default: () => {
107
+ return {sections: []}
108
+ }
109
+ },
110
+ facets: {type: Array, default: () => []}
111
+ },
112
+ data() {
113
+ return {
114
+ sidebarVisible: false,
115
+ sidebarField: null,
116
+ columnTo: false,
117
+ hash: '',
118
+ sectionModalCfg: {
119
+ id: 'rb-doc-template-section-modal',
120
+ mode: 'ins',
121
+ section: null,
122
+ onAfterOk() {
123
+ }
124
+ }
125
+ }
126
+ },
127
+ methods: {
128
+ showProperties(field) {
129
+ this.sidebarVisible = true;
130
+ this.sidebarField = field;
131
+ },
132
+ addSection(columnCount) {
133
+ let section = {labelRu: null, columnCount: columnCount};
134
+ this.sectionModalCfg.mode = 'ins';
135
+ this.sectionModalCfg.section = section;
136
+ this.sectionModalCfg.onAfterOk = () => {
137
+ section.columns = [];
138
+ for (let i = 0; i < columnCount; i++) {
139
+ section.columns.push({
140
+ index: i,
141
+ fields: []
142
+ });
143
+ }
144
+
145
+ this.formConfig.sections.push(section)
146
+ }
147
+ this.$bvModal.show(this.sectionModalCfg.id);
148
+ },
149
+ editSection(section) {
150
+ this.sectionModalCfg.mode = 'update';
151
+ this.sectionModalCfg.section = section;
152
+ this.sectionModalCfg.onAfterOk = () => {}
153
+ this.$bvModal.show(this.sectionModalCfg.id);
154
+ },
155
+ removeSection(section, index) {
156
+ this.formConfig.sections.splice(index, 1);
157
+ /*UtModal.showYesNoDialog('Вы действительно хотите удалить секцию?', {
158
+ onOk: (event, modal) => {
159
+ this.formConfig.sections.splice(index, 1);
160
+ UtModal.closeModal(modal);
161
+ }
162
+ });*/
163
+ },
164
+ multipleFieldAreOnFormConfig(field) {
165
+ let count = 0;
166
+ this.formConfig.sections.every(r => {
167
+ r.columns.every(c => {
168
+ c.fields.forEach(f => {
169
+ if (f.name === field.name) {
170
+ count++;
171
+ }
172
+ })
173
+
174
+ if (count > 1) {
175
+ return false;
176
+ }
177
+ })
178
+ if (count > 1) {
179
+ return false;
180
+ }
181
+ });
182
+ return count > 1;
183
+ },
184
+ removeFieldFromColumn(field, column, newIndex) {
185
+ let index = newIndex != null ? newIndex : -1;
186
+
187
+ if (index < 0) {
188
+ column.fields.every((f, i) => {
189
+ if (field.name === f.name) {
190
+ index = i;
191
+ return false;
192
+ }
193
+ });
194
+ }
195
+
196
+ if (index >= 0) {
197
+ column.fields.splice(index, 1);
198
+ }
199
+ },
200
+ onRemoveField(event, field, column) {
201
+ event.preventDefault();
202
+ this.removeFieldFromColumn(field, column)
203
+ },
204
+ onFieldAddedToColumn(event, column, section) {
205
+ this.columnTo = column;
206
+ },
207
+ onFieldMoveEnd(event) {
208
+ const {newIndex} = event;
209
+ let field = event.item._underlying_vm_;
210
+
211
+ let found = this.multipleFieldAreOnFormConfig(field);
212
+ if (found) {
213
+ this.removeFieldFromColumn(field, this.columnTo, newIndex);
214
+ this.resetDragVariables();
215
+ this.$bvModal.msgBoxOk('На форме уже есть это поле', {
216
+ title: 'Ошибка',
217
+ headerClass: 'rb-error-msg-box__header',
218
+ bodyClass: 'rb-error-msg-box__body',
219
+ footerClass: 'rb-error-msg-box__footer',
220
+ centered: true,
221
+ noCloseOnBackdrop: true,
222
+ noCloseOnEsc: true
223
+ });
224
+ }
225
+ this.resetDragVariables();
226
+ this.hash = (Math.random() + 1).toString(36).substring(7);
227
+ },
228
+ getFieldExtendedPropsData(field) {
229
+ return {...field.input.propsData, placeholder: field.tag, disabled: true};
230
+ },
231
+ resetDragVariables() {
232
+ this.columnTo = null;
233
+ },
234
+ },
235
+ }
236
+ </script>
@@ -0,0 +1,103 @@
1
+ <template>
2
+ <div class="rb-facets-sidebar">
3
+ <h4>Компоненты</h4>
4
+ <b-form>
5
+ <b-form-row>
6
+ <b-col lg="12">
7
+ <b-form-group>
8
+ <b-form-input placeholder="Название поля" v-model="facetSearchStr">
9
+ </b-form-input>
10
+ </b-form-group>
11
+ </b-col>
12
+ </b-form-row>
13
+ </b-form>
14
+ <div class="rb-facet-list">
15
+ <div class="rb-facet" v-for="facet in innerFacets" :key="facet.name">
16
+ <h6 class="rb-facet-label d-flex">
17
+ <rb-text class="flex-fill">{{facet.labelRu}}</rb-text>
18
+ <rb-icon :icon="`icon-chevron-${facet.expanded? 'up': 'down'}`" class="cursor-pointer"
19
+ @click="facet.expanded = !facet.expanded"></rb-icon>
20
+ </h6>
21
+
22
+ <b-list-group v-if="facet.expanded">
23
+ <draggable v-model="facet.fields"
24
+ :clone="onFieldCloned"
25
+ :animation="200"
26
+ :group="{name: 'fields', pull: 'clone', put: false}"
27
+ @end="onFieldMoveEnd($event)"
28
+ ghost-class="rb-facet-field-moving">
29
+ <b-list-group-item v-for="field in facet.fields" :key="field.name"
30
+ class="cursor-pointer">
31
+ <rb-text>{{field.labelRu}}</rb-text>
32
+ </b-list-group-item>
33
+ </draggable>
34
+ </b-list-group>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </template>
39
+
40
+ <script>
41
+ import draggable from "vuedraggable";
42
+ import {UtFormConfig} from "@/utils/UtFormConfig";
43
+
44
+ export default {
45
+ name: 'DocTemplateFacetList',
46
+ components: {draggable},
47
+ props: {
48
+ facets: {type: Array, default: () => []}
49
+ },
50
+ data() {
51
+ return {
52
+ allFacets: [],
53
+ innerFacets: [],
54
+ facetSearchStr: null,
55
+ }
56
+ },
57
+ watch: {
58
+ facetSearchStr() {
59
+ this.findInFacets(this.facetSearchStr);
60
+ },
61
+ facets() {
62
+ this.handleFacetsProp();
63
+ }
64
+ },
65
+ methods: {
66
+ onFieldCloned(cloneField) {
67
+ let field = JSON.parse(JSON.stringify(cloneField));
68
+ field.input = UtFormConfig.getDefaultInput(field);
69
+ return field;
70
+ },
71
+ onFieldMoveEnd(event) {
72
+ this.$emit('fieldMoveEnd', event);
73
+ },
74
+ findInFacets(str) {
75
+ str = str.toLowerCase();
76
+ if(!str || str.length === 0) {
77
+ this.innerFacets = this.allFacets;
78
+ }
79
+ let facets = JSON.parse(JSON.stringify(this.allFacets));
80
+ facets = facets.filter(facet => {
81
+ let facetFound = false;
82
+ facet.fields = facet.fields.filter(field => {
83
+ let fieldFound = field.labelRu.toLowerCase().indexOf(str) >= 0;
84
+ if(fieldFound) {
85
+ facetFound = true;
86
+ }
87
+ return fieldFound;
88
+ });
89
+ return facetFound;
90
+ });
91
+ this.innerFacets = facets;
92
+ },
93
+ handleFacetsProp() {
94
+ let innerFacets = this.facets.map(f => ({...f, expanded: false}));
95
+ this.innerFacets = JSON.parse(JSON.stringify(innerFacets));
96
+ this.allFacets = JSON.parse(JSON.stringify(innerFacets));
97
+ }
98
+ },
99
+ created() {
100
+ this.handleFacetsProp();
101
+ }
102
+ }
103
+ </script>
@@ -0,0 +1,184 @@
1
+ <template>
2
+ <b-sidebar right class="rb-doc-template-field-sidebar" bg-variant="white" shadow
3
+ v-model="innerVisible">
4
+ <template #header>
5
+ <b-button class="rb-sidebar-close-btn" variant="secondary" @click="hide">
6
+ <rb-icon :icon="innerVisible? 'icon-chevron-right': 'icon-chevron-left'"></rb-icon>
7
+ </b-button>
8
+ <h4>Редактор свойств</h4>
9
+ </template>
10
+
11
+ <b-form v-if="field">
12
+ <div class="rb-form-section">
13
+ <b-form-row>
14
+ <b-col lg="12">
15
+ <b-form-group label="Название" class="rb-immutable">
16
+ <rb-text>{{field.name}}</rb-text>
17
+ </b-form-group>
18
+ </b-col>
19
+ </b-form-row>
20
+ <b-form-row>
21
+ <b-col lg="12">
22
+ <b-form-group label="Тип" class="rb-immutable">
23
+ <rb-text>{{field.type}}</rb-text>
24
+ </b-form-group>
25
+ </b-col>
26
+ </b-form-row>
27
+ <b-form-row>
28
+ <b-col lg="12">
29
+ <b-form-group label="Тэг для файла шаблона" class="rb-immutable">
30
+ <rb-text>{{field.tag}}</rb-text>
31
+ </b-form-group>
32
+ </b-col>
33
+ </b-form-row>
34
+ <b-form-row>
35
+ <b-col lg="12">
36
+ <b-form-group label="Заголовок">
37
+ <b-form-input v-model="field.labelRu"></b-form-input>
38
+ </b-form-group>
39
+ </b-col>
40
+ </b-form-row>
41
+ <b-form-row>
42
+ <b-col lg="12">
43
+ <b-checkbox size="lg" v-model="field.multiple">Множественное</b-checkbox>
44
+ </b-col>
45
+ </b-form-row>
46
+ <b-form-row>
47
+ <b-col lg="12">
48
+ <b-checkbox size="lg" v-model="field.visible">Отображаемое</b-checkbox>
49
+ </b-col>
50
+ </b-form-row>
51
+ <b-form-row>
52
+ <b-col lg="12">
53
+ <b-checkbox size="lg" v-model="field.editable">Редактируемое</b-checkbox>
54
+ </b-col>
55
+ </b-form-row>
56
+ <b-form-row>
57
+ <b-col lg="12">
58
+ <b-checkbox size="lg" v-model="field.required">Обязательное</b-checkbox>
59
+ </b-col>
60
+ </b-form-row>
61
+ </div>
62
+ <div class="rb-form-section">
63
+ <div class="rb-title">
64
+ Настройки ввода
65
+ </div>
66
+
67
+ <b-form-row>
68
+ <b-col lg="12">
69
+ <b-form-group label="Тип инпута">
70
+ <rb-dropdown-input v-model="currentInputName"
71
+ :items="inputOptions"
72
+ display-field="text"
73
+ value-field="name"
74
+ block>
75
+ </rb-dropdown-input>
76
+ </b-form-group>
77
+
78
+ <template v-for="(prop, propName) in field.input.props">
79
+ <b-form-group :label="prop.label" :key="propName" v-if="prop.visible">
80
+ <component v-bind:is="getPropInputType(prop, propName)"
81
+ v-model="field.input.propsData[propName]"
82
+ v-bind="getPropInputPropData(prop, propName)"></component>
83
+ </b-form-group>
84
+ </template>
85
+
86
+ </b-col>
87
+ </b-form-row>
88
+ </div>
89
+
90
+ <div class="rb-form-section" v-if="field.input">
91
+ <div class="rb-title">
92
+ Значение по-умолчанию
93
+ </div>
94
+
95
+ <b-form-row>
96
+ <b-col lg="12">
97
+ <b-form-group :label="field.labelRu" ref="inputContainer">
98
+ <component v-bind:is="field.input.type"
99
+ v-model="field.defaultValue"
100
+ v-bind="field.input.propsData"></component>
101
+ </b-form-group>
102
+ </b-col>
103
+ </b-form-row>
104
+ </div>
105
+ </b-form>
106
+ </b-sidebar>
107
+ </template>
108
+
109
+ <script>
110
+ import {UtFormConfig} from "@/utils/UtFormConfig";
111
+
112
+ export default {
113
+ name: 'DocTemplateFieldSidebar',
114
+ props: {
115
+ value: {
116
+ type: Object,
117
+ default: null
118
+ },
119
+ visible: {
120
+ type: Boolean,
121
+ default: null,
122
+ }
123
+ },
124
+ data() {
125
+ return {
126
+ innerVisible: null,
127
+ field: null,
128
+ currentInputName: null,
129
+ }
130
+ },
131
+ computed: {
132
+ inputOptions() {
133
+ return this.field ? UtFormConfig.getInputTypes(this.field) : [];
134
+ }
135
+ },
136
+ watch: {
137
+ visible() {
138
+ this.innerVisible = this.visible;
139
+ },
140
+ value() {
141
+ this.field = this.value;
142
+ if (this.field && this.field.input) {
143
+ this.currentInputName = this.field.input.name;
144
+ }
145
+ },
146
+ field() {
147
+ this.$emit('input', this.field);
148
+ this.$emit('change', this.field);
149
+ },
150
+ currentInputName() {
151
+ this.field.input = UtFormConfig.getInputTypeByName(this.currentInputName, this.field);
152
+ },
153
+ },
154
+ methods: {
155
+ hide() {
156
+ this.innerVisible = false;
157
+ this.$emit('hide');
158
+ },
159
+ getPropInputType(prop, propName) {
160
+ if (prop.type === 'string') {
161
+ return 'b-form-input'
162
+ } else {
163
+ return 'rb-boolean-single-option-input';
164
+ }
165
+ },
166
+ getPropInputPropData(prop, propName) {
167
+ if (prop.type === 'string') {
168
+ return {
169
+ type: 'text',
170
+ }
171
+ } else {
172
+ return {}
173
+ }
174
+ }
175
+ },
176
+ created() {
177
+ this.innerVisible = this.visible;
178
+ this.field = this.value;
179
+ if (this.field && this.field.input) {
180
+ this.currentInputName = this.field.input.name;
181
+ }
182
+ }
183
+ }
184
+ </script>
@@ -0,0 +1,63 @@
1
+ <template>
2
+ <b-modal id="rb-doc-template-section-modal" modal-class="rb-doc-template-section-modal"
3
+ ok-title="Сохранить изменения"
4
+ cancel-variant="outline-gray"
5
+ cancel-title="Отмена"
6
+ @ok.prevent="onOk"
7
+ :title="title">
8
+ <b-form @submit.prevent="onOk">
9
+ <b-form-row>
10
+ <b-col lg="12">
11
+ <b-form-group label="Наименование секции">
12
+ <b-form-input v-model="label"></b-form-input>
13
+ </b-form-group>
14
+ </b-col>
15
+ </b-form-row>
16
+ </b-form>
17
+ </b-modal>
18
+ </template>
19
+
20
+ <script>
21
+ export default {
22
+ name: 'DocTemplateSectionModal',
23
+ props: {
24
+ section: Object,
25
+ mode: {type: String, default: 'ins'},
26
+ onAfterOk: {type: Function, default: () => {}}
27
+ },
28
+ data() {
29
+ return {
30
+ id: 'rb-doc-template-section-modal',
31
+ label: null
32
+ }
33
+ },
34
+ computed: {
35
+ title() {
36
+ return this.mode === 'ins' ? 'Добавление секции' : 'Редактирование секции';
37
+ }
38
+ },
39
+ watch: {
40
+ section() {
41
+ if(this.section) {
42
+ this.label = this.section.labelRu;
43
+ }
44
+ }
45
+ },
46
+ methods: {
47
+ onOk() {
48
+ this.section.labelRu = this.label;
49
+ if(this.onAfterOk) {
50
+ this.onAfterOk();
51
+ }
52
+ this.$nextTick(() => {
53
+ this.$bvModal.hide(this.id);
54
+ });
55
+ }
56
+ },
57
+ created() {
58
+ if(this.section) {
59
+ this.label = this.section.labelRu;
60
+ }
61
+ }
62
+ }
63
+ </script>