glib-web 2.4.1 → 3.0.0-beta1
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/LICENSE +0 -0
- package/action.js +6 -1
- package/actions/auth/restart.js +0 -0
- package/actions/commands/enqueue.js +17 -0
- package/actions/components/update.js +13 -14
- package/actions/dialogs/oauth.js +0 -0
- package/actions/dialogs/options.js +0 -0
- package/app.vue +25 -26
- package/components/_button.vue +21 -28
- package/components/_chip.vue +14 -19
- package/components/_dropdownMenu.vue +10 -23
- package/components/_icon.vue +5 -5
- package/components/_message.vue +0 -0
- package/components/_responsive.vue +7 -21
- package/components/avatar.vue +11 -15
- package/components/banners/alert.vue +2 -7
- package/components/banners/select.vue +18 -30
- package/components/button.vue +5 -5
- package/components/component.vue +97 -100
- package/components/datetime.vue +0 -0
- package/components/fab.vue +0 -0
- package/components/fields/_patternText.vue +5 -19
- package/components/fields/_select.vue +7 -28
- package/components/fields/autocomplete.vue +5 -21
- package/components/fields/check.vue +19 -11
- package/components/fields/country/countries.js +0 -0
- package/components/fields/country/field.vue +9 -27
- package/components/fields/country/regions.js +0 -0
- package/components/fields/date.vue +5 -5
- package/components/fields/datetime.vue +5 -5
- package/components/fields/dynamicSelect.vue +8 -29
- package/components/fields/newRichText.vue +66 -53
- package/components/fields/otpField.vue +90 -0
- package/components/fields/phone/field.vue +60 -78
- package/components/fields/radio.vue +16 -23
- package/components/fields/rating.vue +9 -16
- package/components/fields/richText.vue +8 -28
- package/components/fields/select.vue +10 -7
- package/components/fields/stripeExternalAccount.vue +10 -24
- package/components/fields/text.vue +24 -40
- package/components/fields/textarea.vue +13 -27
- package/components/fields/timeZone.vue +9 -6
- package/components/fields/timer.vue +3 -10
- package/components/hr.vue +0 -0
- package/components/html.vue +0 -0
- package/components/image.vue +13 -20
- package/components/map.vue +115 -29
- package/components/markdown.vue +15 -8
- package/components/mixins/events.js +17 -6
- package/components/mixins/longClick.js +0 -0
- package/components/mixins/scrolling.js +0 -0
- package/components/mixins/styles.js +18 -15
- package/components/mixins/table/export.js +0 -0
- package/components/mixins/table/import.js +0 -0
- package/components/p.vue +0 -0
- package/components/panels/column.vue +5 -5
- package/components/panels/custom.vue +15 -15
- package/components/panels/flow.vue +19 -13
- package/components/panels/form.vue +17 -28
- package/components/panels/grid.vue +15 -9
- package/components/panels/horizontal.vue +149 -18
- package/components/panels/list.vue +63 -70
- package/components/panels/responsive.vue +13 -33
- package/components/panels/split.vue +2 -2
- package/components/panels/table.vue +27 -61
- package/components/panels/timeline.vue +20 -30
- package/components/panels/vertical.vue +9 -14
- package/components/tabBar.vue +27 -19
- package/index.js +68 -72
- package/keys.js +0 -0
- package/nav/appbar.vue +4 -4
- package/nav/dialog.vue +24 -34
- package/nav/drawer.vue +39 -51
- package/nav/drawerButton.vue +5 -7
- package/nav/drawerLabel.vue +2 -3
- package/nav/sheet.vue +18 -24
- package/nav/snackbar.vue +16 -26
- package/package.json +10 -11
- package/plugins/driverCustomBehavior.js +1 -1
- package/plugins/updatableComponent.js +1 -7
- package/plugins/vuetify.js +27 -0
- package/settings.json.example +0 -0
- package/styles/test.sass +0 -0
- package/styles/test.scss +0 -0
- package/templates/comment.vue +42 -19
- package/templates/featured.vue +8 -9
- package/templates/thumbnail-old.vue +188 -0
- package/templates/thumbnail.vue +5 -188
- package/templates/unsupported.vue +0 -0
- package/tsconfig.json +1 -1
- package/utils/dom.js +0 -0
- package/utils/eventBus.js +9 -2
- package/utils/history.js +7 -4
- package/utils/http.js +7 -2
- package/utils/launch.js +43 -51
- package/utils/public.js +6 -0
- package/utils/queue.js +110 -0
- package/utils/settings.js +3 -1
- package/utils/storage.js +0 -0
- package/utils/url.js +0 -0
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div style="width: 100%;">
|
|
3
|
-
<v-progress-linear
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
<v-progress-linear
|
|
4
|
+
v-if="showProgress"
|
|
5
|
+
v-model="progress.value"
|
|
6
|
+
/>
|
|
7
|
+
<textarea
|
|
8
|
+
id="editor"
|
|
9
|
+
class="entry"
|
|
10
|
+
></textarea>
|
|
11
|
+
<input
|
|
12
|
+
type="hidden"
|
|
13
|
+
:name="spec.name"
|
|
14
|
+
:value="cleanValue"
|
|
15
|
+
/>
|
|
6
16
|
<input
|
|
7
17
|
v-for="(imageKey, index) in imageKeys"
|
|
8
18
|
:key="index"
|
|
@@ -14,7 +24,10 @@
|
|
|
14
24
|
<p>{{ cleanValue }}</p>
|
|
15
25
|
|
|
16
26
|
<ol>
|
|
17
|
-
<li
|
|
27
|
+
<li
|
|
28
|
+
v-for="(imageKey, index) in imageKeys"
|
|
29
|
+
:key="index"
|
|
30
|
+
>
|
|
18
31
|
{{ images[imageKey] }} -- {{ imageKey }}
|
|
19
32
|
</li>
|
|
20
33
|
</ol>
|
|
@@ -23,7 +36,7 @@
|
|
|
23
36
|
|
|
24
37
|
<script>
|
|
25
38
|
import Uploader from "../../utils/uploader";
|
|
26
|
-
import RedactorX from "../../static/redactorx";
|
|
39
|
+
// import RedactorX from "../../static/redactorx";
|
|
27
40
|
import "../../static/redactorx.css";
|
|
28
41
|
import "../../static/plugins/icons/icons";
|
|
29
42
|
import "../../static/plugins/inlineformat/inlineformat";
|
|
@@ -35,8 +48,8 @@ export default {
|
|
|
35
48
|
props: {
|
|
36
49
|
spec: {
|
|
37
50
|
type: Object,
|
|
38
|
-
default: null
|
|
39
|
-
}
|
|
51
|
+
default: null,
|
|
52
|
+
},
|
|
40
53
|
},
|
|
41
54
|
data() {
|
|
42
55
|
return {
|
|
@@ -44,13 +57,13 @@ export default {
|
|
|
44
57
|
cleanValue: "",
|
|
45
58
|
progress: { value: -1 },
|
|
46
59
|
images: {},
|
|
47
|
-
imageKeys: []
|
|
60
|
+
imageKeys: [],
|
|
48
61
|
};
|
|
49
62
|
},
|
|
50
63
|
computed: {
|
|
51
|
-
showProgress: function() {
|
|
64
|
+
showProgress: function () {
|
|
52
65
|
return this.progress.value >= 0;
|
|
53
|
-
}
|
|
66
|
+
},
|
|
54
67
|
},
|
|
55
68
|
methods: {
|
|
56
69
|
$ready() {
|
|
@@ -60,26 +73,26 @@ export default {
|
|
|
60
73
|
initValue() {
|
|
61
74
|
let rawValue = this.spec.value || "";
|
|
62
75
|
|
|
63
|
-
Utils.type.ifArray(this.spec.images, images => {
|
|
76
|
+
Utils.type.ifArray(this.spec.images, (images) => {
|
|
64
77
|
const vm = this;
|
|
65
|
-
rawValue = rawValue.replace(
|
|
66
|
-
|
|
67
|
-
index
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
rawValue = rawValue.replace(
|
|
79
|
+
/\{\{image([0-9]+)\}\}/g,
|
|
80
|
+
function (_, index) {
|
|
81
|
+
const image = images[index - 1];
|
|
82
|
+
if (
|
|
83
|
+
image &&
|
|
84
|
+
vm.$type.isString(image.value) &&
|
|
85
|
+
vm.$type.isString(image.fileUrl)
|
|
86
|
+
) {
|
|
87
|
+
const url = image.fileUrl;
|
|
88
|
+
const key = url.hashCode().toString();
|
|
89
|
+
vm.images[key] = image.value;
|
|
90
|
+
// return `<img src="${url}">`;
|
|
91
|
+
return url;
|
|
92
|
+
}
|
|
93
|
+
return "{{IMAGE_NOT_FOUND}}";
|
|
80
94
|
}
|
|
81
|
-
|
|
82
|
-
});
|
|
95
|
+
);
|
|
83
96
|
});
|
|
84
97
|
|
|
85
98
|
this.updateValue(rawValue);
|
|
@@ -91,23 +104,23 @@ export default {
|
|
|
91
104
|
source: Utils.settings.isDev,
|
|
92
105
|
plugins: ["inlineformat", "style"],
|
|
93
106
|
image: {
|
|
94
|
-
upload: function(upload, data) {
|
|
107
|
+
upload: function (upload, data) {
|
|
95
108
|
for (var key in data.files) {
|
|
96
109
|
if (typeof data.files[key] === "object") {
|
|
97
110
|
const file = data.files[key];
|
|
98
|
-
vm.uploadImage(file, response => {
|
|
111
|
+
vm.uploadImage(file, (response) => {
|
|
99
112
|
upload.complete(response, data.e);
|
|
100
113
|
});
|
|
101
114
|
}
|
|
102
115
|
}
|
|
103
|
-
}
|
|
116
|
+
},
|
|
104
117
|
},
|
|
105
118
|
subscribe: {
|
|
106
|
-
"editor.change": function(event) {
|
|
119
|
+
"editor.change": function (event) {
|
|
107
120
|
const content = this.app.editor.getContent();
|
|
108
121
|
vm.updateValue(content);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
122
|
+
},
|
|
123
|
+
},
|
|
111
124
|
});
|
|
112
125
|
},
|
|
113
126
|
updateValue(content) {
|
|
@@ -119,20 +132,20 @@ export default {
|
|
|
119
132
|
var index = 0;
|
|
120
133
|
vm.imageKeys.clear();
|
|
121
134
|
// TODO: Fix to avoid replacing <video src="">
|
|
122
|
-
this.cleanValue = this.rawValue.replace(
|
|
123
|
-
|
|
124
|
-
imageValue
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
135
|
+
this.cleanValue = this.rawValue.replace(
|
|
136
|
+
/src="([^"]+)"/g,
|
|
137
|
+
function (_, imageValue) {
|
|
138
|
+
// It seems that quill encodes '&' in the URL to '&' which would screw up key matching.
|
|
139
|
+
var decodedValue = imageValue.replace(/&/g, "&");
|
|
140
|
+
const key = decodedValue.hashCode().toString();
|
|
141
|
+
const existingIndex = vm.imageKeys.indexOf(key);
|
|
142
|
+
if (existingIndex < 0) {
|
|
143
|
+
vm.imageKeys.push(key);
|
|
144
|
+
return `src="{{image${++index}}}"`;
|
|
145
|
+
}
|
|
146
|
+
return `src="{{image${existingIndex + 1}}}"`;
|
|
133
147
|
}
|
|
134
|
-
|
|
135
|
-
});
|
|
148
|
+
);
|
|
136
149
|
},
|
|
137
150
|
uploadImage(file, onComplete) {
|
|
138
151
|
const uploaderSpec = this.spec.imageUploader;
|
|
@@ -157,18 +170,18 @@ export default {
|
|
|
157
170
|
insertImage(file, blob, onComplete) {
|
|
158
171
|
let vm = this;
|
|
159
172
|
var reader = new FileReader();
|
|
160
|
-
reader.onload = function(e) {
|
|
173
|
+
reader.onload = function (e) {
|
|
161
174
|
if (file.type.indexOf("image") !== -1) {
|
|
162
175
|
var image = new Image();
|
|
163
176
|
image.src = e.target.result;
|
|
164
177
|
|
|
165
178
|
const key = image.src.hashCode().toString();
|
|
166
|
-
image.onload = function() {
|
|
179
|
+
image.onload = function () {
|
|
167
180
|
const response = {
|
|
168
181
|
[key]: {
|
|
169
182
|
url: image.src,
|
|
170
|
-
id: key
|
|
171
|
-
}
|
|
183
|
+
id: key,
|
|
184
|
+
},
|
|
172
185
|
};
|
|
173
186
|
|
|
174
187
|
onComplete(response);
|
|
@@ -179,8 +192,8 @@ export default {
|
|
|
179
192
|
};
|
|
180
193
|
reader.readAsDataURL(file);
|
|
181
194
|
vm.progress.value = -1;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
195
|
+
},
|
|
196
|
+
},
|
|
184
197
|
};
|
|
185
198
|
</script>
|
|
186
199
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<input v-for="(digit, index) in digits" ref="input" :key="index" v-model="otp[index]" maxlength="1" class="otp-input"
|
|
4
|
+
@input="handleInput($event, index)" @keydown="handleKeydown($event, index)" @paste="handlePaste($event, index)"
|
|
5
|
+
@focus="handleFocus($event, index)" @blur="handleBlur($event, index)" />
|
|
6
|
+
<input type="hidden" :name="spec.name" :value="otpValue" />
|
|
7
|
+
</div>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script>
|
|
11
|
+
import bus from '../../utils/eventBus'
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
props: {
|
|
15
|
+
spec: { type: Object, required: true }
|
|
16
|
+
},
|
|
17
|
+
data() {
|
|
18
|
+
return {
|
|
19
|
+
digits: 0,
|
|
20
|
+
otp: []
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
computed: {
|
|
25
|
+
otpValue() {
|
|
26
|
+
// concatenate the digits into a single string
|
|
27
|
+
return this.otp.join("");
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
methods: {
|
|
31
|
+
$ready() {
|
|
32
|
+
this.digits = this.spec.lengths;
|
|
33
|
+
this.otp = Array(this.spec.lengths).fill("");
|
|
34
|
+
},
|
|
35
|
+
handleInput(event, index) {
|
|
36
|
+
if (event.target.value.length === 1) {
|
|
37
|
+
this.focusNext(index);
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
handleKeydown(event, index) {
|
|
41
|
+
if (event.key === "Backspace") {
|
|
42
|
+
event.preventDefault();
|
|
43
|
+
this.focusPrevious(index);
|
|
44
|
+
this.$set(this.otp, index, "");
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
handlePaste(event, index) {
|
|
48
|
+
event.preventDefault();
|
|
49
|
+
const pasted = event.clipboardData
|
|
50
|
+
.getData("text")
|
|
51
|
+
.slice(0, this.digits - index);
|
|
52
|
+
for (let i = 0; i < pasted.length; i++) {
|
|
53
|
+
this.$set(this.otp, index + i, pasted[i]);
|
|
54
|
+
}
|
|
55
|
+
this.focusNext(index + pasted.length - 1);
|
|
56
|
+
},
|
|
57
|
+
handleFocus(event, index) {
|
|
58
|
+
if (index > 0 && this.otp[index - 1] === "") {
|
|
59
|
+
this.focusPrevious(index);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
handleBlur(event, index) {
|
|
63
|
+
if (this.otp.filter(digit => digit === "").length === 0) {
|
|
64
|
+
bus.$emit("complete", this.otp.join(""));
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
focusNext(index) {
|
|
68
|
+
if (index < this.digits - 1) {
|
|
69
|
+
this.$refs.input[index + 1].focus();
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
focusPrevious(index) {
|
|
73
|
+
if (index > 0) {
|
|
74
|
+
this.$refs.input[index - 1].focus();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
</script>
|
|
80
|
+
<style scoped>
|
|
81
|
+
.otp-input {
|
|
82
|
+
border: 1px solid #47495f;
|
|
83
|
+
text-align: center;
|
|
84
|
+
width: 50px;
|
|
85
|
+
height: 50px;
|
|
86
|
+
border-radius: 4px;
|
|
87
|
+
font-size: 24px;
|
|
88
|
+
margin: 8px;
|
|
89
|
+
}
|
|
90
|
+
</style>
|
|
@@ -1,56 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :style="$styles()" :class="classes()">
|
|
3
3
|
<div class="country-code">
|
|
4
|
-
<v-select
|
|
5
|
-
|
|
6
|
-
:
|
|
7
|
-
|
|
8
|
-
:
|
|
9
|
-
:
|
|
10
|
-
|
|
11
|
-
item
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
>
|
|
16
|
-
<template v-slot:selection>
|
|
17
|
-
<div :class="activeCountry.iso2.toLowerCase()" class="country_flag" />
|
|
18
|
-
</template>
|
|
19
|
-
<template v-slot:item="data">
|
|
20
|
-
<span :class="data.item.iso2.toLowerCase()" class="country_flag" />
|
|
21
|
-
<span>{{ data.item.name }} {{ `+${data.item.dialCode}` }}</span>
|
|
22
|
-
</template>
|
|
4
|
+
<v-select v-model="countryCode" :items="sortedCountries" :disabled="spec.readOnly"
|
|
5
|
+
:outlined="$classes().includes('outlined') || null" :rounded="$classes().includes('rounded')"
|
|
6
|
+
:dense="$classes().includes('dense') || null" item-text="name" item-value="iso2" return-object
|
|
7
|
+
@change="onChangeCountryCode">
|
|
8
|
+
<!-- <template v-slot:selection> -->
|
|
9
|
+
<div :class="activeCountry.iso2.toLowerCase()" class="country_flag" />
|
|
10
|
+
<!-- </template> -->
|
|
11
|
+
<!-- <template v-slot:item="data"> -->
|
|
12
|
+
<span :class="data.item.iso2.toLowerCase()" class="country_flag" />
|
|
13
|
+
<span>{{ data.item.name }} {{ `+${data.item.dialCode}` }}</span>
|
|
14
|
+
<!-- </template> -->
|
|
23
15
|
</v-select>
|
|
24
16
|
</div>
|
|
25
|
-
<v-text-field
|
|
26
|
-
:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
:label="spec.label"
|
|
31
|
-
:name="fieldName"
|
|
32
|
-
:value="spec.value"
|
|
33
|
-
:hint="spec.hint"
|
|
34
|
-
:placeholder="spec.placeholder"
|
|
35
|
-
:maxlength="spec.maxLength || 25"
|
|
36
|
-
:disabled="spec.readOnly"
|
|
37
|
-
type="tel"
|
|
38
|
-
:rules="hiddenDisplay() ? [] : rules"
|
|
39
|
-
:prefix="spec.leftText"
|
|
40
|
-
:suffix="spec.rightText"
|
|
41
|
-
:outlined="$classes().includes('outlined')"
|
|
42
|
-
:dense="$classes().includes('dense')"
|
|
43
|
-
:rounded="$classes().includes('rounded')"
|
|
44
|
-
:autofocus="spec.autoFocus || false"
|
|
45
|
-
validate-on-blur
|
|
46
|
-
>
|
|
17
|
+
<v-text-field :id="inputId" ref="input" v-model="phone" class="tel" :label="spec.label" :name="fieldName"
|
|
18
|
+
:hint="spec.hint" :placeholder="spec.placeholder" :maxlength="spec.maxLength || 25" :disabled="spec.readOnly"
|
|
19
|
+
type="tel" :rules="hiddenDisplay() ? [] : rules" :prefix="spec.leftText" :suffix="spec.rightText"
|
|
20
|
+
:outlined="$classes().includes('outlined') || null" :dense="$classes().includes('dense') || null"
|
|
21
|
+
:rounded="$classes().includes('rounded')" :autofocus="spec.autoFocus || false" validate-on-blur>
|
|
47
22
|
</v-text-field>
|
|
48
|
-
<input
|
|
49
|
-
v-if="spec.readOnly"
|
|
50
|
-
type="hidden"
|
|
51
|
-
:name="fieldName"
|
|
52
|
-
:value="phone"
|
|
53
|
-
/>
|
|
23
|
+
<input v-if="spec.readOnly" type="hidden" :name="fieldName" v-model="phone" />
|
|
54
24
|
</div>
|
|
55
25
|
</template>
|
|
56
26
|
|
|
@@ -60,8 +30,8 @@ import allCountries from "./countries";
|
|
|
60
30
|
|
|
61
31
|
function getCountryByIp() {
|
|
62
32
|
return fetch("https://ip2c.org/s")
|
|
63
|
-
.then(response => response.text())
|
|
64
|
-
.then(response => {
|
|
33
|
+
.then((response) => response.text())
|
|
34
|
+
.then((response) => {
|
|
65
35
|
const result = (response || "").toString();
|
|
66
36
|
if (!result || result[0] !== "1") {
|
|
67
37
|
throw new Error("unable to fetch the country");
|
|
@@ -74,44 +44,44 @@ export default {
|
|
|
74
44
|
props: {
|
|
75
45
|
spec: {
|
|
76
46
|
type: Object,
|
|
77
|
-
required: true
|
|
47
|
+
required: true,
|
|
78
48
|
},
|
|
79
49
|
rules: {
|
|
80
50
|
type: Array,
|
|
81
51
|
default: () => [
|
|
82
|
-
v =>
|
|
52
|
+
(v) =>
|
|
83
53
|
!v ||
|
|
84
54
|
/^\+[1-9]([0-9\(\)\-\ ]*)$/.test(v) ||
|
|
85
|
-
"Must be a valid international phone number with prefix (e.g. +1 416 555 0134)"
|
|
86
|
-
]
|
|
55
|
+
"Must be a valid international phone number with prefix (e.g. +1 416 555 0134)",
|
|
56
|
+
],
|
|
87
57
|
},
|
|
88
58
|
disableFetchingCountry: {
|
|
89
59
|
type: Boolean,
|
|
90
|
-
default: () => false
|
|
60
|
+
default: () => false,
|
|
91
61
|
},
|
|
92
62
|
mode: {
|
|
93
63
|
type: String,
|
|
94
|
-
default: () => ""
|
|
64
|
+
default: () => "",
|
|
95
65
|
},
|
|
96
66
|
allCountries: {
|
|
97
67
|
type: Array,
|
|
98
|
-
default: () => allCountries
|
|
68
|
+
default: () => allCountries,
|
|
99
69
|
},
|
|
100
70
|
preferredCountries: {
|
|
101
71
|
type: Array,
|
|
102
|
-
default: () => []
|
|
72
|
+
default: () => [],
|
|
103
73
|
},
|
|
104
74
|
inputId: {
|
|
105
75
|
type: String,
|
|
106
|
-
default: () => ""
|
|
107
|
-
}
|
|
76
|
+
default: () => "",
|
|
77
|
+
},
|
|
108
78
|
},
|
|
109
79
|
data() {
|
|
110
80
|
return {
|
|
111
81
|
phone: "",
|
|
112
82
|
activeCountry: { iso2: "" },
|
|
113
83
|
selectedIndex: null,
|
|
114
|
-
countryCode: null
|
|
84
|
+
countryCode: null,
|
|
115
85
|
};
|
|
116
86
|
},
|
|
117
87
|
computed: {
|
|
@@ -130,9 +100,9 @@ export default {
|
|
|
130
100
|
},
|
|
131
101
|
sortedCountries() {
|
|
132
102
|
// Sort by preferred countries
|
|
133
|
-
const preferredCountries = this.getCountries(
|
|
134
|
-
|
|
135
|
-
)
|
|
103
|
+
const preferredCountries = this.getCountries(this.preferredCountries).map(
|
|
104
|
+
(country) => ({ ...country, preferred: true })
|
|
105
|
+
);
|
|
136
106
|
return [...preferredCountries, ...this.allCountries];
|
|
137
107
|
},
|
|
138
108
|
phoneObject() {
|
|
@@ -142,14 +112,14 @@ export default {
|
|
|
142
112
|
).toJSON();
|
|
143
113
|
Object.assign(result, {
|
|
144
114
|
isValid: result.valid,
|
|
145
|
-
country: this.activeCountry
|
|
115
|
+
country: this.activeCountry,
|
|
146
116
|
});
|
|
147
117
|
if (!this.phone) {
|
|
148
118
|
return {
|
|
149
119
|
...result,
|
|
150
120
|
number: {
|
|
151
|
-
input: ""
|
|
152
|
-
}
|
|
121
|
+
input: "",
|
|
122
|
+
},
|
|
153
123
|
};
|
|
154
124
|
}
|
|
155
125
|
return result;
|
|
@@ -160,7 +130,7 @@ export default {
|
|
|
160
130
|
key = this.parsedMode;
|
|
161
131
|
}
|
|
162
132
|
return this.phoneObject.number[key] || "";
|
|
163
|
-
}
|
|
133
|
+
},
|
|
164
134
|
},
|
|
165
135
|
watch: {
|
|
166
136
|
phone(val) {
|
|
@@ -172,7 +142,7 @@ export default {
|
|
|
172
142
|
}
|
|
173
143
|
}
|
|
174
144
|
}
|
|
175
|
-
}
|
|
145
|
+
},
|
|
176
146
|
},
|
|
177
147
|
mounted() {
|
|
178
148
|
this.initializeCountry()
|
|
@@ -190,6 +160,9 @@ export default {
|
|
|
190
160
|
}
|
|
191
161
|
},
|
|
192
162
|
methods: {
|
|
163
|
+
$ready() {
|
|
164
|
+
this.phone = this.spec.value;
|
|
165
|
+
},
|
|
193
166
|
hiddenDisplay() {
|
|
194
167
|
return this.$styles()["display"] == "none";
|
|
195
168
|
},
|
|
@@ -197,7 +170,7 @@ export default {
|
|
|
197
170
|
return this.$classes().concat(["g-text-field--hintless", "fields-phone"]);
|
|
198
171
|
},
|
|
199
172
|
initializeCountry() {
|
|
200
|
-
return new Promise(resolve => {
|
|
173
|
+
return new Promise((resolve) => {
|
|
201
174
|
// 1. If the phone included prefix (+12), try to get the country and set it
|
|
202
175
|
if (this.phone && this.phone[0] === "+") {
|
|
203
176
|
const activeCountry = PhoneNumber(this.phone).getRegionCode();
|
|
@@ -221,13 +194,13 @@ export default {
|
|
|
221
194
|
// 3. Check if fetching country based on user's IP is allowed, set it as the default country
|
|
222
195
|
if (!this.disableFetchingCountry) {
|
|
223
196
|
getCountryByIp()
|
|
224
|
-
.then(res => {
|
|
197
|
+
.then((res) => {
|
|
225
198
|
if (this.phone === "") {
|
|
226
199
|
this.activeCountry =
|
|
227
200
|
this.findCountry(res) || this.activeCountry;
|
|
228
201
|
}
|
|
229
202
|
})
|
|
230
|
-
.catch(error => {
|
|
203
|
+
.catch((error) => {
|
|
231
204
|
console.warn(error);
|
|
232
205
|
// 4. Use the first country from preferred list (if available) or all countries list
|
|
233
206
|
this.choose(fallbackCountry);
|
|
@@ -245,24 +218,24 @@ export default {
|
|
|
245
218
|
// Get ISO2 code from a list of countries
|
|
246
219
|
getCountries(list = []) {
|
|
247
220
|
return list
|
|
248
|
-
.map(countryCode => this.findCountry(countryCode))
|
|
221
|
+
.map((countryCode) => this.findCountry(countryCode))
|
|
249
222
|
.filter(Boolean);
|
|
250
223
|
},
|
|
251
224
|
findCountry(iso = "") {
|
|
252
225
|
return this.allCountries.find(
|
|
253
|
-
country => country.iso2 === iso.toUpperCase()
|
|
226
|
+
(country) => country.iso2 === iso.toUpperCase()
|
|
254
227
|
);
|
|
255
228
|
},
|
|
256
229
|
getItemClass(index, iso2) {
|
|
257
230
|
const highlighted = this.selectedIndex === index;
|
|
258
231
|
const lastPreferred = index === this.preferredCountries.length - 1;
|
|
259
232
|
const preferred = this.preferredCountries.some(
|
|
260
|
-
c => c.toUpperCase() === iso2
|
|
233
|
+
(c) => c.toUpperCase() === iso2
|
|
261
234
|
);
|
|
262
235
|
return {
|
|
263
236
|
highlighted,
|
|
264
237
|
"last-preferred": lastPreferred,
|
|
265
|
-
preferred
|
|
238
|
+
preferred,
|
|
266
239
|
};
|
|
267
240
|
},
|
|
268
241
|
choose(country) {
|
|
@@ -292,13 +265,13 @@ export default {
|
|
|
292
265
|
},
|
|
293
266
|
reset() {
|
|
294
267
|
this.selectedIndex = this.sortedCountries
|
|
295
|
-
.map(c => c.iso2)
|
|
268
|
+
.map((c) => c.iso2)
|
|
296
269
|
.indexOf(this.activeCountry.iso2);
|
|
297
270
|
},
|
|
298
271
|
onChangeCountryCode() {
|
|
299
272
|
this.choose(this.countryCode, true);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
273
|
+
},
|
|
274
|
+
},
|
|
302
275
|
};
|
|
303
276
|
</script>
|
|
304
277
|
|
|
@@ -309,6 +282,7 @@ export default {
|
|
|
309
282
|
.v-text-field__details {
|
|
310
283
|
min-height: 0;
|
|
311
284
|
margin-bottom: 0;
|
|
285
|
+
|
|
312
286
|
.v-messages__message {
|
|
313
287
|
min-height: 0;
|
|
314
288
|
line-height: 14px;
|
|
@@ -316,26 +290,33 @@ export default {
|
|
|
316
290
|
}
|
|
317
291
|
}
|
|
318
292
|
}
|
|
293
|
+
|
|
319
294
|
.country_flag {
|
|
320
295
|
margin-right: 8px;
|
|
321
296
|
}
|
|
297
|
+
|
|
322
298
|
.fields-phone {
|
|
323
299
|
display: flex;
|
|
324
300
|
align-items: center;
|
|
301
|
+
|
|
325
302
|
.country-code {
|
|
326
303
|
width: 75px;
|
|
327
304
|
}
|
|
305
|
+
|
|
328
306
|
li.last-preferred {
|
|
329
307
|
border-bottom: 1px solid #cacaca;
|
|
330
308
|
}
|
|
309
|
+
|
|
331
310
|
.v-text-field {
|
|
332
311
|
.v-select__selections {
|
|
333
312
|
position: relative;
|
|
313
|
+
|
|
334
314
|
.country_flag {
|
|
335
315
|
position: absolute;
|
|
336
316
|
margin-left: 18px;
|
|
337
317
|
}
|
|
338
318
|
}
|
|
319
|
+
|
|
339
320
|
&--outlined {
|
|
340
321
|
.v-select__selections {
|
|
341
322
|
.country_flag {
|
|
@@ -345,6 +326,7 @@ export default {
|
|
|
345
326
|
}
|
|
346
327
|
}
|
|
347
328
|
}
|
|
329
|
+
|
|
348
330
|
.fields-phone.outlined .country-code {
|
|
349
331
|
margin-right: 6px;
|
|
350
332
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<common-tooltip :spec="spec">
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
<!-- <common-tooltip :spec="spec"> -->
|
|
3
|
+
<!-- <template v-slot:activator="{ on }"> -->
|
|
4
|
+
<!-- <common-button :spec="spec" :disabled="$isBusy" :event-handlers="on" /> -->
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
<div :class="$classes()">
|
|
7
|
+
<!-- <v-tooltip
|
|
8
8
|
:disabled="tooltip.disabled"
|
|
9
9
|
:top="tooltipPositionMatches('top')"
|
|
10
10
|
:right="tooltipPositionMatches('right')"
|
|
@@ -12,26 +12,19 @@
|
|
|
12
12
|
:left="tooltipPositionMatches('left')"
|
|
13
13
|
>
|
|
14
14
|
<template v-slot:activator="{ on }"> -->
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
/>
|
|
24
|
-
<div v-if="spec.childViews" class="radio-childviews">
|
|
25
|
-
<div v-for="(item, i) in spec.childViews" :key="i">
|
|
26
|
-
<glib-component :spec="item" />
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
<!-- </template>
|
|
15
|
+
<v-radio :label="spec.label" :value="spec.value.presence() || vuetifyEmptyString" :disabled="spec.readOnly"
|
|
16
|
+
:on-icon="spec.onIcon" :off-icon="spec.offIcon" @click="$onClick()" />
|
|
17
|
+
<div v-if="spec.childViews" class="radio-childviews">
|
|
18
|
+
<div v-for="(item, i) in spec.childViews" :key="i">
|
|
19
|
+
<glib-component :spec="item" />
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
<!-- </template>
|
|
30
23
|
<span>{{ tooltip.text }}</span>
|
|
31
24
|
</v-tooltip> -->
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
</common-tooltip>
|
|
25
|
+
</div>
|
|
26
|
+
<!-- </template>
|
|
27
|
+
</common-tooltip> -->
|
|
35
28
|
</template>
|
|
36
29
|
|
|
37
30
|
<script>
|