@westartcom/bread-quasar-fields 0.0.2

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.
@@ -0,0 +1,17 @@
1
+ export enum FieldType {
2
+ BOOL = 'BOOL',
3
+ ENUM = 'ENUM',
4
+ TIMESTAMP = 'TIMESTAMP',
5
+ DATE = 'DATE',
6
+ TEXT = 'TEXT',
7
+ MEDIA = 'MEDIA',
8
+ FLOAT = 'FLOAT',
9
+ INT = 'INT',
10
+ JSON = 'JSON',
11
+ META = 'META',
12
+ RELATION = 'RELATION',
13
+ HASMANY = 'HASMANY',
14
+ HASONE = 'HASONE',
15
+ MANYTOMANY = 'MANYTOMANY',
16
+ SLOTTED = 'SLOTTED'
17
+ }
@@ -0,0 +1,23 @@
1
+ export enum InputType {
2
+ BOOL = 'boolean',
3
+ CHECKBOX = 'checkbox',
4
+ DATE = 'date',
5
+ DATETIME = 'datetime',
6
+ TIME = 'time',
7
+ NUMBER = 'number',
8
+ RELATION_LIST = 'relation-list',
9
+ MODEL_SEARCH = 'model-search',
10
+ IMAGE_UPLOAD = 'image-upload',
11
+ FILE_UPLOAD = 'file-upload',
12
+ NESTED_FIELDS = 'nested-fields',
13
+ REPEATABLE_NESTED_FIELDS = 'repeatable-nested-fields',
14
+ PASSWORD = 'password',
15
+ PASSWORD_CONFIRMATION = 'password-confirmation',
16
+ RADIO = 'radio',
17
+ SELECT = 'select',
18
+ EMAIL = 'email',
19
+ TEL = 'tel',
20
+ TEXT = 'text',
21
+ TEXTAREA = 'textarea',
22
+ WYSIWYG = 'wysiwyg'
23
+ }
@@ -0,0 +1,176 @@
1
+ <template>
2
+ <div class="field-wrap" :id="id">
3
+ <div class="field-wrap-inner">
4
+ <template v-if="stylingFormat === 'toggle'">
5
+ <q-toggle
6
+ size="lg"
7
+ color="positive"
8
+ :label="field.label"
9
+ left-label
10
+ unchecked-icon="fa-solid fa-xmark"
11
+ checked-icon="fa-solid fa-check"
12
+ v-model="internalValue" />
13
+ </template>
14
+
15
+ <template v-else>
16
+ <div class="field-label-wrap">
17
+ <div class="field">
18
+ <label v-if="field.label" :for="id + '-input'">
19
+ <checkbox-marked-icon class="icon-2x" v-if="internalValue"></checkbox-marked-icon>
20
+ <checkbox-blank-outline-icon class="icon-2x" v-else></checkbox-blank-outline-icon>
21
+
22
+ <input
23
+ :name="field.name"
24
+ :id="id + '-input'"
25
+ type="checkbox"
26
+ style="display: none;"
27
+ :class="{'invalid': (invalid && internalErrors && internalErrors.length)}"
28
+ v-model="internalValue">
29
+
30
+ {{ field.label }}<span class="required-asterix" v-if="field.required"> *</span>
31
+ </label>
32
+ </div>
33
+ </div>
34
+ </template>
35
+ </div>
36
+
37
+ <div class="field-description" v-if="field.description">{{ field.description }}</div>
38
+
39
+ <div class="validation-errors" v-if="invalid && internalErrors && internalErrors.length">
40
+ <span class="error danger-txt-color" v-for="(error, index) in internalErrors" :key="index + 'error'">{{ error }}</span>
41
+ </div>
42
+ </div>
43
+ </template>
44
+
45
+ <script lang="ts">
46
+ import { defineAsyncComponent, defineComponent, PropType } from 'vue';
47
+ import { ModelFieldDefinition } from '@westartcom/bread-quasar-fields/interfaces/ModelDefinition';
48
+ import { FieldType } from '@westartcom/bread-quasar-fields/enums/FieldType';
49
+ import { InputType } from '@westartcom/bread-quasar-fields/enums/InputType';
50
+
51
+ interface BoolFieldDefinition extends ModelFieldDefinition<FieldType.BOOL, InputType.BOOL> {
52
+ default: boolean;
53
+ extra_data: {
54
+ styling_format: 'checkbox' | 'toggle'
55
+ }
56
+ }
57
+
58
+ export default defineComponent({
59
+ props: {
60
+ id: {
61
+ type: String,
62
+ required: true
63
+ },
64
+ field: {
65
+ type: Object as PropType<BoolFieldDefinition>,
66
+ required: true
67
+ },
68
+ modelValue: [Boolean, Number, String],
69
+ errors: Array as PropType<string[]>
70
+ },
71
+
72
+ emits: [
73
+ 'update:modelValue',
74
+ 'update:invalid'
75
+ ],
76
+
77
+ components: {
78
+ CheckboxBlankOutlineIcon: defineAsyncComponent(() => import('@westartcom/bread-quasar-fields/icons/CheckboxBlankOutlineIcon.vue')),
79
+ CheckboxMarkedIcon: defineAsyncComponent(() => import('@westartcom/bread-quasar-fields/icons/CheckboxMarkedIcon.vue'))
80
+ },
81
+
82
+ data() {
83
+ return {
84
+ invalid: null as boolean | null,
85
+ internalValue: false,
86
+ internalErrors: [] as string[]
87
+ };
88
+ },
89
+
90
+ mounted() {
91
+ if (this.modelValue !== null && typeof this.modelValue !== 'undefined') {
92
+ this.internalValue = (!(!this.modelValue || this.modelValue === '0'));
93
+ } else if (this.field.default) {
94
+ this.internalValue = this.field.default;
95
+ }
96
+
97
+ this.validate(this.internalValue);
98
+ },
99
+
100
+ computed: {
101
+ stylingFormat: function(): 'checkbox' | 'toggle' {
102
+ return (this.field?.extra_data?.styling_format) ? this.field.extra_data.styling_format : 'checkbox';
103
+ }
104
+ },
105
+
106
+ watch: {
107
+ modelValue: function(val) {
108
+ if (val !== this.internalValue) {
109
+ this.internalValue = !!(val);
110
+ }
111
+ },
112
+
113
+ internalValue: function(val) {
114
+ this.validate(val);
115
+ this.$emit('update:modelValue', val);
116
+ },
117
+
118
+ errors: {
119
+ handler: function(val) {
120
+ this.internalErrors = val;
121
+ },
122
+ deep: true
123
+ },
124
+
125
+ internalErrors: {
126
+ handler: function(val) {
127
+ this.invalid = !!(val && val.length);
128
+ },
129
+ deep: true
130
+ },
131
+
132
+ invalid: function(val) {
133
+ this.$emit('update:invalid', val);
134
+ }
135
+ },
136
+
137
+ methods: {
138
+ validate: function(val) {
139
+ this.invalid = this.field.required && !val;
140
+ }
141
+ }
142
+ });
143
+ </script>
144
+
145
+ <style scoped lang="scss">
146
+ .toggle {
147
+ display: flex;
148
+ max-width: var(--max-input-width);
149
+ width: 100%;
150
+
151
+ .btn {
152
+ border-radius: 0;
153
+
154
+ &:first-of-type {
155
+ border-bottom-left-radius: var(--global-radius);
156
+ border-top-left-radius: var(--global-radius);
157
+ }
158
+ &:last-of-type {
159
+ border-bottom-right-radius: var(--global-radius);
160
+ border-top-right-radius: var(--global-radius);
161
+ }
162
+ }
163
+ }
164
+
165
+ .field > label {
166
+ margin-right: var(--global-spacing);
167
+ user-select: none;
168
+ cursor: pointer;
169
+ display: inline-flex;
170
+ align-items: flex-end;
171
+
172
+ :deep(svg) {
173
+ margin-right: var(--global-spacing-half);
174
+ }
175
+ }
176
+ </style>
@@ -0,0 +1,163 @@
1
+ <template>
2
+ <div class="field-wrap checkbox" :id="id">
3
+ <div class="field-wrap-inner">
4
+ <div class="field-label-wrap">
5
+ <label v-if="field.label">
6
+ {{ field.label }}<span class="required-asterix" v-if="field.required"> *</span>
7
+ </label>
8
+ </div>
9
+
10
+ <div class="field">
11
+ <label
12
+ v-for="(label, optionValue) in allOptions"
13
+ :key="id + '-' + optionValue + '-radio-input'"
14
+ :for="id + '-' + optionValue + '-radio-input'">
15
+ <input
16
+ :id="id + '-' + optionValue + '-radio-input'"
17
+ type="checkbox"
18
+ hidden="true"
19
+ :value="optionValue"
20
+ v-model="internalValue">
21
+
22
+ <checkbox-marked-icon class="icon-2x" v-if="internalValue && internalValue.includes(optionValue)"></checkbox-marked-icon>
23
+ <checkbox-blank-outline-icon class="icon-2x" v-if="!internalValue || !internalValue.includes(optionValue)"></checkbox-blank-outline-icon>
24
+
25
+ {{ label }}
26
+ </label>
27
+ </div>
28
+ </div>
29
+
30
+ <div class="field-description" v-if="field.description">{{ field.description }}</div>
31
+
32
+ <div class="validation-errors" v-if="invalid && internalErrors && internalErrors.length">
33
+ <span class="error danger-txt-color" v-for="(error, index) in internalErrors" :key="index + 'error'">{{ error }}</span>
34
+ </div>
35
+ </div>
36
+ </template>
37
+
38
+ <script lang="ts">
39
+ import { defineAsyncComponent, defineComponent, PropType } from 'vue';
40
+ import { ModelFieldDefinition } from '@westartcom/bread-quasar-fields/interfaces/ModelDefinition';
41
+ import { FieldType } from '@westartcom/bread-quasar-fields/enums/FieldType';
42
+ import { InputType } from '@westartcom/bread-quasar-fields/enums/InputType';
43
+
44
+ interface CheckboxFieldDefinition extends ModelFieldDefinition<FieldType.ENUM, InputType.CHECKBOX> {
45
+ default: string | string[];
46
+ extra_data: {
47
+ styling_format: 'checkbox';
48
+ options: {
49
+ [key: string]: string
50
+ }
51
+ }
52
+ }
53
+
54
+ export default defineComponent({
55
+ props: {
56
+ id: {
57
+ type: String,
58
+ required: true
59
+ },
60
+ field: {
61
+ type: Object as PropType<CheckboxFieldDefinition>,
62
+ required: true
63
+ },
64
+ modelValue: [String, Array],
65
+ errors: Array as PropType<string[]>
66
+ },
67
+
68
+ emits: [
69
+ 'update:modelValue',
70
+ 'update:invalid'
71
+ ],
72
+
73
+ components: {
74
+ CheckboxBlankOutlineIcon: defineAsyncComponent(() => import('@westartcom/bread-quasar-fields/icons/CheckboxBlankOutlineIcon.vue')),
75
+ CheckboxMarkedIcon: defineAsyncComponent(() => import('@westartcom/bread-quasar-fields/icons/CheckboxMarkedIcon.vue'))
76
+ },
77
+
78
+ data() {
79
+ return {
80
+ invalid: null as boolean | null,
81
+ internalValue: [] as string[],
82
+ internalErrors: [] as string[]
83
+ };
84
+ },
85
+
86
+ mounted() {
87
+ if (this.modelValue) {
88
+ this.internalValue = (Array.isArray(this.modelValue)) ? (this.modelValue as string[]) : this.modelValue.split(';');
89
+ } else if (this.field.default) {
90
+ this.internalValue = (Array.isArray(this.field.default)) ? this.field.default : this.field.default.split(';');
91
+ }
92
+
93
+ this.validate(this.internalValue);
94
+ },
95
+
96
+ computed: {
97
+ stylingFormat: function() {
98
+ return (this.field?.extra_data?.styling_format) ? this.field.extra_data.styling_format : 'checkbox';
99
+ },
100
+
101
+ allOptions: function() {
102
+ return (this.field?.extra_data?.options) ? this.field.extra_data.options : {};
103
+ }
104
+ },
105
+
106
+ watch: {
107
+ modelValue: {
108
+ handler: function(val) {
109
+ if (val !== this.internalValue) {
110
+ this.internalValue = val;
111
+ }
112
+ },
113
+ deep: true
114
+ },
115
+
116
+ internalValue: {
117
+ handler: function(val) {
118
+ this.validate(val);
119
+ this.$emit('update:modelValue', val);
120
+ },
121
+ deep: true
122
+ },
123
+
124
+ errors: {
125
+ handler: function(val) {
126
+ this.internalErrors = val;
127
+ },
128
+ deep: true
129
+ },
130
+
131
+ internalErrors: {
132
+ handler: function(val) {
133
+ this.invalid = !!(val && val.length);
134
+ },
135
+ deep: true
136
+ },
137
+
138
+ invalid: function(val) {
139
+ this.$emit('update:invalid', val);
140
+ }
141
+ },
142
+
143
+ methods: {
144
+ validate: function(val) {
145
+ this.invalid = this.field.required && (!val || !val.length);
146
+ }
147
+ }
148
+ });
149
+ </script>
150
+
151
+ <style scoped lang="scss">
152
+ .field > label {
153
+ margin-right: var(--global-spacing);
154
+ user-select: none;
155
+ cursor: pointer;
156
+ display: inline-flex;
157
+ align-items: flex-end;
158
+
159
+ :deep(svg) {
160
+ margin-right: var(--global-spacing-half);
161
+ }
162
+ }
163
+ </style>
@@ -0,0 +1,124 @@
1
+ <template>
2
+ <div class="field-wrap" :id="id">
3
+ <div class="field-wrap-inner">
4
+ <div class="field-label-wrap">
5
+ <label v-if="field.label" :for="id + '-input'">{{ field.label }}<span class="required-asterix" v-if="field.required"> *</span></label>
6
+ </div>
7
+
8
+ <input
9
+ :name="field.name"
10
+ :id="id + '-input'"
11
+ :placeholder="field.placeholder"
12
+ type="date"
13
+ class="field"
14
+ :class="{'invalid': (invalid && internalErrors && internalErrors.length)}"
15
+ :max="formatDate(((field.extra_data?.max) ? field.extra_data.max : null), 'yyyy-MM-dd')"
16
+ :min="formatDate(((field.extra_data?.min) ? field.extra_data.min : null), 'yyyy-MM-dd')"
17
+ v-model="internalValue">
18
+ </div>
19
+ <em class="field-description" v-if="field.description">{{ field.description }}</em>
20
+
21
+ <div class="validation-errors" v-if="invalid && internalErrors && internalErrors.length">
22
+ <span class="error danger-txt-color" v-for="(error, index) in internalErrors" :key="index + 'error'">{{ error }}</span>
23
+ </div>
24
+ </div>
25
+ </template>
26
+
27
+ <script lang="ts">
28
+ import formatDate from '.@westartcom/bread-quasar-fields/.@westartcom/bread-quasar-fields/Helpers/formatDate';
29
+ import { defineComponent, PropType } from 'vue';
30
+ import { ModelFieldDefinition } from '@westartcom/bread-quasar-fields/interfaces/ModelDefinition';
31
+ import { FieldType } from '@westartcom/bread-quasar-fields/enums/FieldType';
32
+ import { InputType } from '@westartcom/bread-quasar-fields/enums/InputType';
33
+
34
+ interface DateFieldDefinition extends ModelFieldDefinition<FieldType.TIMESTAMP, InputType.DATE> {
35
+ default: string | null;
36
+ extra_data: {
37
+ timezone: string;
38
+ max?: string;
39
+ min?: string;
40
+ }
41
+ }
42
+
43
+
44
+ export default defineComponent({
45
+ props: {
46
+ id: {
47
+ type: String,
48
+ required: true
49
+ },
50
+ field: {
51
+ type: Object as PropType<DateFieldDefinition>,
52
+ required: true
53
+ },
54
+ modelValue: String,
55
+ errors: Array as PropType<string[]>
56
+ },
57
+
58
+ emits: [
59
+ 'update:modelValue',
60
+ 'update:invalid'
61
+ ],
62
+
63
+ data() {
64
+ return {
65
+ invalid: null as boolean | null,
66
+ internalValue: '',
67
+ internalErrors: [] as string[]
68
+ };
69
+ },
70
+
71
+ mounted() {
72
+ if (this.modelValue) {
73
+ this.internalValue = formatDate(this.modelValue, 'yyyy-MM-dd');
74
+ } else if (this.field.default) {
75
+ this.internalValue = formatDate(this.field.default, 'yyyy-MM-dd');
76
+ }
77
+
78
+ this.validate(this.internalValue);
79
+ },
80
+
81
+ watch: {
82
+ modelValue: function(val) {
83
+ if (val !== this.internalValue) {
84
+ this.internalValue = formatDate(val, 'yyyy-MM-dd');
85
+ }
86
+ },
87
+
88
+ internalValue: function(val) {
89
+ this.validate(val);
90
+ this.$emit('update:modelValue', val);
91
+ },
92
+
93
+ errors: {
94
+ handler: function(val) {
95
+ this.internalErrors = val;
96
+ },
97
+ deep: true
98
+ },
99
+
100
+ internalErrors: {
101
+ handler: function(val) {
102
+ this.invalid = !!(val && val.length);
103
+ },
104
+ deep: true
105
+ },
106
+
107
+ invalid: function(val) {
108
+ this.$emit('update:invalid', val);
109
+ }
110
+ },
111
+
112
+ methods: {
113
+ formatDate,
114
+
115
+ validate: function(val) {
116
+ this.invalid = (this.field.required && !val);
117
+ }
118
+ }
119
+ });
120
+ </script>
121
+
122
+ <style scoped lang="scss">
123
+
124
+ </style>
@@ -0,0 +1,110 @@
1
+ <template>
2
+ <div class="field-wrap" :id="id">
3
+ <div class="field-wrap-inner">
4
+ <div class="field-label-wrap">
5
+ <label v-if="field.label" :for="id + '-input'">{{ field.label }}<span class="required-asterix" v-if="field.required"> *</span></label>
6
+ </div>
7
+
8
+ <input
9
+ :name="field.name"
10
+ :id="id + '-input'"
11
+ :placeholder="field.placeholder"
12
+ type="datetime-local"
13
+ class="field"
14
+ :class="{'invalid': (invalid && internalErrors && internalErrors.length)}"
15
+ :max="formatDate(((field.extra_data && field.extra_data.max) ? field.extra_data.max : null), 'YYYY-MM-DDTHH:mm')"
16
+ :min="formatDate(((field.extra_data && field.extra_data.min) ? field.extra_data.min : null), 'YYYY-MM-DDTHH:mm')"
17
+ v-model="internalValue">
18
+ </div>
19
+ <em class="field-description" v-if="field.description">{{ field.description }}</em>
20
+
21
+ <div class="validation-errors" v-if="invalid && internalErrors && internalErrors.length">
22
+ <span class="error danger-txt-color" v-for="(error, index) in internalErrors" :key="index + 'error'">{{ error }}</span>
23
+ </div>
24
+ </div>
25
+ </template>
26
+
27
+ <script>
28
+ import formatDate from '@westartcom/bread-quasar-fields/Helpers/formatDate';
29
+ import moment from 'moment';
30
+
31
+ export default {
32
+ props: {
33
+ id: String,
34
+ field: Object,
35
+ modelValue: String,
36
+ errors: Array
37
+ },
38
+
39
+ emits: [
40
+ 'update:modelValue',
41
+ 'update:invalid'
42
+ ],
43
+
44
+ data() {
45
+ return {
46
+ invalid: null,
47
+ internalValue: '',
48
+ internalErrors: []
49
+ };
50
+ },
51
+
52
+ mounted() {
53
+ if (this.modelValue) {
54
+ this.internalValue = moment.utc(this.modelValue).local().format('YYYY-MM-DDTHH:mm');
55
+ } else if (this.field.default) {
56
+ this.internalValue = moment.utc(this.field.default).local().format('YYYY-MM-DDTHH:mm');
57
+ }
58
+
59
+ this.validate(this.internalValue);
60
+ },
61
+
62
+ watch: {
63
+ modelValue: function(val) {
64
+ if (val !== this.internalValue) {
65
+ this.internalValue = moment.utc(val).local().format('YYYY-MM-DDTHH:mm');
66
+ }
67
+ },
68
+
69
+ internalValue: function(val) {
70
+ this.validate(val);
71
+ const date = moment(val);
72
+ if (date.isValid()) {
73
+ this.$emit('update:modelValue', date.utc().format('YYYY-MM-DDTHH:mm'));
74
+ } else {
75
+ this.$emit('update:modelValue', null);
76
+ }
77
+ },
78
+
79
+ errors: {
80
+ handler(val) {
81
+ this.internalErrors = val;
82
+ },
83
+ deep: true
84
+ },
85
+
86
+ internalErrors: {
87
+ handler(val) {
88
+ this.invalid = !!(val && val.length);
89
+ },
90
+ deep: true
91
+ },
92
+
93
+ invalid: function(val) {
94
+ this.$emit('update:invalid', val);
95
+ }
96
+ },
97
+
98
+ methods: {
99
+ formatDate,
100
+
101
+ validate: function(val) {
102
+ this.invalid = !!(this.field.required && !val);
103
+ }
104
+ }
105
+ };
106
+ </script>
107
+
108
+ <style scoped lang="scss">
109
+
110
+ </style>