@inriver/inri 1.0.0
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/.eslintrc.js +5 -0
- package/componentProperties.d.ts +8 -0
- package/configs/base-eslint-config.js +36 -0
- package/configs/base-tailwind-config.js +149 -0
- package/i18n.ts +11 -0
- package/index.ts +25 -0
- package/package.json +36 -0
- package/src/components/CAutoBreadcrumbs.vue +72 -0
- package/src/components/CBtn.vue +98 -0
- package/src/components/CColorPicker.vue +55 -0
- package/src/components/CContextMenu.vue +29 -0
- package/src/components/CDatePicker.vue +51 -0
- package/src/components/CDeleteTileBtn.vue +52 -0
- package/src/components/CDialog.vue +253 -0
- package/src/components/CDialogCloseBtn.vue +9 -0
- package/src/components/CDirtyCheck.vue +68 -0
- package/src/components/CDrawer.vue +44 -0
- package/src/components/CDrawerButton.vue +91 -0
- package/src/components/CExpansionItem.vue +57 -0
- package/src/components/CExpansionItemWithCheckbox.vue +41 -0
- package/src/components/CFileDropzone.vue +114 -0
- package/src/components/CGrid.vue +101 -0
- package/src/components/CHeader.vue +10 -0
- package/src/components/CHeaderLinks.vue +61 -0
- package/src/components/CHeaderMenuLink.vue +51 -0
- package/src/components/CHeaderSearch.vue +142 -0
- package/src/components/CIconBtn.vue +70 -0
- package/src/components/CMenuItem.vue +66 -0
- package/src/components/CPageContainer.vue +11 -0
- package/src/components/CPageError.vue +24 -0
- package/src/components/CPageSpinner.vue +18 -0
- package/src/components/CSearch.vue +45 -0
- package/src/components/CSection.vue +29 -0
- package/src/components/CSectionTitle.vue +8 -0
- package/src/components/CSelect.vue +208 -0
- package/src/components/CSlideEffect.vue +62 -0
- package/src/components/CSpinner.vue +107 -0
- package/src/components/CTableActions.vue +16 -0
- package/src/components/CTileBtn.vue +178 -0
- package/src/components/CTimePicker.vue +42 -0
- package/src/components/CToggleGridView.vue +26 -0
- package/src/components/CToggleSidebarBtn.vue +19 -0
- package/src/components/CTooltip.vue +44 -0
- package/src/components/CTreeNode.vue +39 -0
- package/src/components/cards/CBannerCard.vue +103 -0
- package/src/components/cards/CSmallCard.vue +149 -0
- package/src/components/internal-components/ConfirmDialog.vue +78 -0
- package/src/composables/useDialog.ts +47 -0
- package/src/composables/useDirtyCheck.ts +25 -0
- package/src/composables/useDoubleClickListener.ts +28 -0
- package/src/composables/useSelectable.ts +62 -0
- package/src/composables/useTruncateChips.ts +46 -0
- package/src/i18n/de/index.ts +17 -0
- package/src/i18n/en/index.ts +84 -0
- package/src/i18n/es/index.ts +7 -0
- package/src/i18n/fr/index.ts +7 -0
- package/src/init/initInriFramework.ts +25 -0
- package/src/init/useInriApp.ts +55 -0
- package/src/layouts/CLayoutBlank.vue +7 -0
- package/src/layouts/CLayoutWithBackButton.vue +50 -0
- package/src/layouts/CLayoutWithSidebars.vue +46 -0
- package/src/layouts/layout-fragments/CPageAutoBreadcrumbs.vue +6 -0
- package/src/layouts/layout-fragments/CPageBackButton.vue +18 -0
- package/src/layouts/layout-fragments/CPageBlank.vue +20 -0
- package/src/layouts/layout-fragments/CPageFlexCol.vue +5 -0
- package/src/layouts/layout-fragments/CPageLeftSidebar.vue +5 -0
- package/src/layouts/layout-fragments/CPageMainContent.vue +5 -0
- package/src/layouts/layout-fragments/CPageOuterWrapper.vue +5 -0
- package/src/layouts/layout-fragments/CPageRightSidebar.vue +5 -0
- package/src/layouts/layout-fragments/CPageTitle.vue +34 -0
- package/src/plugins/dialog.ts +45 -0
- package/src/plugins/errors/ErrorFactories.ts +59 -0
- package/src/plugins/errors/Errors.ts +156 -0
- package/src/plugins/errors/Exception.ts +6 -0
- package/src/plugins/errors/globalErrorHandler.ts +21 -0
- package/src/plugins/errors/handleError.ts +34 -0
- package/src/plugins/errors/logger.ts +16 -0
- package/src/plugins/errors/vueErrorHandler.ts +26 -0
- package/src/plugins/globalAppConfig.ts +25 -0
- package/src/plugins/i18n.ts +46 -0
- package/src/plugins/inriIcons.ts +58 -0
- package/src/plugins/inriverQuasarComponentConfigurations.ts +67 -0
- package/src/plugins/library.ts +119 -0
- package/src/plugins/notify.ts +153 -0
- package/src/plugins/quasar-user-options.ts +19 -0
- package/src/plugins/validationRules.ts +292 -0
- package/src/shims-vue.d.ts +6 -0
- package/src/stores/inriStore.ts +54 -0
- package/src/stores/interfaceLanguageStore.ts +27 -0
- package/src/styles/_css-variables.scss +101 -0
- package/src/styles/_reset.scss +67 -0
- package/src/styles/_transitions.scss +9 -0
- package/src/styles/_utils.scss +15 -0
- package/src/styles/components/_breadcrumbs.scss +3 -0
- package/src/styles/components/_checkboxes.scss +17 -0
- package/src/styles/components/_chips.scss +17 -0
- package/src/styles/components/_forms.scss +203 -0
- package/src/styles/components/_menu.scss +12 -0
- package/src/styles/components/_notifications.scss +24 -0
- package/src/styles/components/_q-editor.scss +14 -0
- package/src/styles/components/_radio-buttons.scss +17 -0
- package/src/styles/components/_tables.scss +92 -0
- package/src/styles/components/_tooltips.scss +5 -0
- package/src/styles/components/_tree.scss +86 -0
- package/src/styles/components/_truncated-chips.scss +39 -0
- package/src/styles/main.scss +45 -0
- package/src/styles/quasar.variables.scss +50 -0
- package/src/typings.d.ts +70 -0
- package/src/utils/colorUtils.ts +73 -0
- package/src/utils/errorUtils.ts +37 -0
- package/src/utils/fileUtils.ts +57 -0
- package/src/utils/helpers.ts +6 -0
- package/src/utils/routeUtils.ts +23 -0
- package/tsconfig.json +37 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { i18n } from './i18n'
|
|
2
|
+
|
|
3
|
+
const $t = i18n.global.t
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The value is required.
|
|
7
|
+
* @param {string} [msg] - Override the default error message
|
|
8
|
+
*/
|
|
9
|
+
export function required (msg?: string) {
|
|
10
|
+
return (value): true | string => {
|
|
11
|
+
return !!value || msg || $t('inri.validation.required')
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The value must have a minimum length.
|
|
17
|
+
* @param {string | number} length - Min length
|
|
18
|
+
* @param {string} [msg] - Override the default error message
|
|
19
|
+
*/
|
|
20
|
+
export function minLength (length: string | number, msg?: string) {
|
|
21
|
+
const parsedLength = typeof length === 'number' ? length : parseInt(length, 10)
|
|
22
|
+
return (value): true | string => {
|
|
23
|
+
if (!value) {
|
|
24
|
+
return true
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return value.length >= parsedLength || msg || $t('inri.validation.minLength', { parsedLength: parsedLength })
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The value can not exceed maximum length.
|
|
33
|
+
* @param {string | number} length - Max length
|
|
34
|
+
* @param {string} [msg] - Override the default error message
|
|
35
|
+
*/
|
|
36
|
+
export function maxLength (length: string | number, msg?: string) {
|
|
37
|
+
const parsedLength = typeof length === 'number' ? length : parseInt(length, 10)
|
|
38
|
+
return (value): true | string => {
|
|
39
|
+
if (!value) {
|
|
40
|
+
return true
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return value.length <= parsedLength || msg || $t('inri.validation.maxLength', { parsedLength: parsedLength })
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The value must be a valid email.
|
|
49
|
+
* @param {string} [msg] - Override the default error message
|
|
50
|
+
*/
|
|
51
|
+
export function email (msg?: string) {
|
|
52
|
+
// eslint-disable-next-line no-useless-escape
|
|
53
|
+
const regExp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
|
54
|
+
return (value): true | string => {
|
|
55
|
+
if (!value) {
|
|
56
|
+
return true
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return regExp.test(String(value).toLowerCase()) || msg || $t('inri.validation.email')
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The value must be a valid url.
|
|
65
|
+
* @param {string} [msg] - Override the default error message
|
|
66
|
+
*/
|
|
67
|
+
export function url (msg?: string) {
|
|
68
|
+
// eslint-disable-next-line no-useless-escape
|
|
69
|
+
const regExp = /^(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*))$/
|
|
70
|
+
return (value): true | string => {
|
|
71
|
+
if (!value) {
|
|
72
|
+
return true
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return regExp.test(String(value).toLowerCase()) || msg || $t('inri.validation.url')
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The value must be a valid url using https.
|
|
81
|
+
* @param {string} [msg] - Override the default error message
|
|
82
|
+
*/
|
|
83
|
+
export function https (msg?: string) {
|
|
84
|
+
// eslint-disable-next-line no-useless-escape
|
|
85
|
+
const regExp = /^(https:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*))$/
|
|
86
|
+
return (value): true | string => {
|
|
87
|
+
if (!value) {
|
|
88
|
+
return true
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return regExp.test(String(value).toLowerCase()) || msg || $t('inri.validation.https')
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Validate file extensions. Supports single and multiple files.
|
|
97
|
+
* @param {string} fileExtensions - A string containing a single file extension, "jpg", or a comma separated string, "jpg,png".
|
|
98
|
+
* @param {string} [msg] - Override the default error message
|
|
99
|
+
*/
|
|
100
|
+
export function extension (fileExtensions: string, msg?: string) {
|
|
101
|
+
// Extension string cleanup and convert to array
|
|
102
|
+
const extensions = fileExtensions
|
|
103
|
+
.toLowerCase()
|
|
104
|
+
.replaceAll(' ', '')
|
|
105
|
+
.replaceAll('.', '')
|
|
106
|
+
.split(',')
|
|
107
|
+
|
|
108
|
+
return (value): true | string => {
|
|
109
|
+
if (!value) {
|
|
110
|
+
return true
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let files: any[] = []
|
|
114
|
+
let isValid = true
|
|
115
|
+
|
|
116
|
+
// If single file then push it into an array for consistency
|
|
117
|
+
if (!value.length) {
|
|
118
|
+
files.push(value)
|
|
119
|
+
} else {
|
|
120
|
+
files = value
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
for (const file of files) {
|
|
124
|
+
const fileExt = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase()
|
|
125
|
+
if (!extensions.includes(fileExt)) {
|
|
126
|
+
isValid = false
|
|
127
|
+
break
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return isValid || msg || $t('inri.validation.extension', { extensions: extensions.join(', .') })
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* The value must contain all the strings in the array.
|
|
137
|
+
* @param {string[]} arr - Array of strings.
|
|
138
|
+
* @param {boolean} caseSensitive
|
|
139
|
+
* @param {string} [msg] - Override the default error message
|
|
140
|
+
*/
|
|
141
|
+
export function contains (arr: string[], caseSensitive = false, msg?: string) {
|
|
142
|
+
return (value): true | string => {
|
|
143
|
+
if (!value) {
|
|
144
|
+
return true
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let foundItems
|
|
148
|
+
|
|
149
|
+
if (!caseSensitive) {
|
|
150
|
+
foundItems = arr.filter(item => !value.toUpperCase().includes(('' + item).toUpperCase()))
|
|
151
|
+
} else {
|
|
152
|
+
foundItems = arr.filter(item => !value.includes('' + item))
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (!foundItems.length) {
|
|
156
|
+
return true
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return msg || $t('inri.validation.contains', { match: foundItems.join(', ') })
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* The value must not contain any of the strings in the array.
|
|
165
|
+
* @param {string[]} arr - Array of strings.
|
|
166
|
+
* @param {boolean} caseSensitive
|
|
167
|
+
* @param {string} [msg] - Override the default error message
|
|
168
|
+
*/
|
|
169
|
+
export function notContains (arr: string[], caseSensitive = false, msg?: string) {
|
|
170
|
+
return (value): true | string => {
|
|
171
|
+
if (!value) {
|
|
172
|
+
return true
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const comparisonValue = value instanceof File ? value.name : value
|
|
176
|
+
|
|
177
|
+
let foundItems
|
|
178
|
+
|
|
179
|
+
if (!caseSensitive) {
|
|
180
|
+
foundItems = arr.filter(item => comparisonValue.toUpperCase().includes(('' + item).toUpperCase()))
|
|
181
|
+
} else {
|
|
182
|
+
foundItems = arr.filter(item => comparisonValue.includes('' + item))
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (!foundItems.length) {
|
|
186
|
+
return true
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return msg || $t('inri.validation.notContains', { match: foundItems.join(', ') })
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* The value must not begin with any of the strings in the array.
|
|
195
|
+
* @param {string[]} arr - Array of strings.
|
|
196
|
+
* @param {boolean} caseSensitive
|
|
197
|
+
* @param {string} [msg] - Override the default error message
|
|
198
|
+
*/
|
|
199
|
+
export function notBeginsWith (arr: string[], caseSensitive = false, msg?: string) {
|
|
200
|
+
return (value): true | string => {
|
|
201
|
+
if (!value) {
|
|
202
|
+
return true
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
let foundItems
|
|
206
|
+
|
|
207
|
+
if (!caseSensitive) {
|
|
208
|
+
foundItems = arr.filter(item => value.toUpperCase().startsWith(('' + item).toUpperCase()))
|
|
209
|
+
} else {
|
|
210
|
+
foundItems = arr.filter(item => value.startsWith('' + item))
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!foundItems.length) {
|
|
214
|
+
return true
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return msg || $t('inri.validation.notBeginsWith', { match: foundItems.join(', ') })
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* The value must not end with any of the strings in the array.
|
|
223
|
+
* @param {string[]} arr - Array of strings.
|
|
224
|
+
* @param {boolean} caseSensitive
|
|
225
|
+
* @param {string} [msg] - Override the default error message
|
|
226
|
+
*/
|
|
227
|
+
export function notEndsWith (arr: string[], caseSensitive = false, msg?: string) {
|
|
228
|
+
return (value): true | string => {
|
|
229
|
+
if (!value) {
|
|
230
|
+
return true
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
let foundItems
|
|
234
|
+
|
|
235
|
+
if (!caseSensitive) {
|
|
236
|
+
foundItems = arr.filter(item => value.toUpperCase().endsWith(('' + item).toUpperCase()))
|
|
237
|
+
} else {
|
|
238
|
+
foundItems = arr.filter(item => value.endsWith('' + item))
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (!foundItems.length) {
|
|
242
|
+
return true
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return msg || $t('inri.validation.notEndsWith', { match: foundItems.join(', ') })
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* The file(s) cannot exceed max size
|
|
251
|
+
* @param {string | number} size - Max size in bytes
|
|
252
|
+
* @param {string} [type] - Only validate against files with this MIME type
|
|
253
|
+
* @param {string} [msg] - Override the default error message
|
|
254
|
+
*/
|
|
255
|
+
export function maxFileSize (size: string | number, type?: string, msg?: string) {
|
|
256
|
+
const parsedFileSize = typeof size === 'number' ? size : parseInt(size, 10)
|
|
257
|
+
|
|
258
|
+
return (value): true | string => {
|
|
259
|
+
if (!value) {
|
|
260
|
+
return true
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
let files: any[] = []
|
|
264
|
+
|
|
265
|
+
if (!value.length) {
|
|
266
|
+
files.push(value)
|
|
267
|
+
} else {
|
|
268
|
+
files = value
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (type) {
|
|
272
|
+
files = files.filter(file => file.type.includes(type))
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return files.every(file => file.size <= size) || msg || $t('inri.validation.maxFileSize', { parsedFileSize })
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export const rules = {
|
|
280
|
+
required,
|
|
281
|
+
maxLength,
|
|
282
|
+
minLength,
|
|
283
|
+
email,
|
|
284
|
+
url,
|
|
285
|
+
https,
|
|
286
|
+
extension,
|
|
287
|
+
contains,
|
|
288
|
+
notContains,
|
|
289
|
+
notBeginsWith,
|
|
290
|
+
notEndsWith,
|
|
291
|
+
maxFileSize,
|
|
292
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { computed, reactive } from 'vue'
|
|
2
|
+
|
|
3
|
+
interface State {
|
|
4
|
+
dirtyComponents: any[],
|
|
5
|
+
leftDrawerIsOpen: boolean,
|
|
6
|
+
rightDrawerIsOpen: boolean,
|
|
7
|
+
showSidebar: boolean,
|
|
8
|
+
showPageSpinner: boolean,
|
|
9
|
+
isGridView: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const state = reactive<State>({
|
|
13
|
+
dirtyComponents: [],
|
|
14
|
+
leftDrawerIsOpen: false,
|
|
15
|
+
rightDrawerIsOpen: false,
|
|
16
|
+
showSidebar: true,
|
|
17
|
+
showPageSpinner: false,
|
|
18
|
+
isGridView: true,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const isAnyDirty = computed(() => {
|
|
22
|
+
return !!state.dirtyComponents.length
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
function toggleLeftDrawer () {
|
|
26
|
+
state.leftDrawerIsOpen = !state.leftDrawerIsOpen
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function toggleRightDrawer () {
|
|
30
|
+
state.rightDrawerIsOpen = !state.rightDrawerIsOpen
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function toggleSidebar () {
|
|
34
|
+
state.showSidebar = !state.showSidebar
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function toggleDirtyComponent (item: any, add: boolean | undefined) {
|
|
38
|
+
if (add && !state.dirtyComponents.find(i => i === item)) {
|
|
39
|
+
state.dirtyComponents.push(item)
|
|
40
|
+
} else {
|
|
41
|
+
state.dirtyComponents = state.dirtyComponents.filter(i => i !== item)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const useInriStore = () => {
|
|
46
|
+
return {
|
|
47
|
+
state,
|
|
48
|
+
isAnyDirty,
|
|
49
|
+
toggleLeftDrawer,
|
|
50
|
+
toggleRightDrawer,
|
|
51
|
+
toggleSidebar,
|
|
52
|
+
toggleDirtyComponent,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { Quasar } from 'quasar'
|
|
3
|
+
import { loadi18nLanguageAsync } from '../plugins/i18n'
|
|
4
|
+
|
|
5
|
+
export const useInterfaceLanguageStore = defineStore({
|
|
6
|
+
id: 'interfaceLanguage',
|
|
7
|
+
state: () => ({}),
|
|
8
|
+
actions: {
|
|
9
|
+
async loadQuasarLanguageAsync (lang: string) {
|
|
10
|
+
// IMPORTANT: Quasar uses "en-US" instead of "en"
|
|
11
|
+
const qLangCode = lang === 'en' ? 'en-US' : lang
|
|
12
|
+
|
|
13
|
+
const qLang = await import(
|
|
14
|
+
/* webpackInclude: /(de|en-US|fr|es)\.js$/ */
|
|
15
|
+
'quasar/lang/' + qLangCode
|
|
16
|
+
)
|
|
17
|
+
Quasar.lang.set(qLang.default)
|
|
18
|
+
},
|
|
19
|
+
async setLanguage (lang : string) {
|
|
20
|
+
await loadi18nLanguageAsync(lang)
|
|
21
|
+
await this.loadQuasarLanguageAsync(lang)
|
|
22
|
+
},
|
|
23
|
+
async init (lang: string) {
|
|
24
|
+
await this.setLanguage(lang)
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
})
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
/* stylelint-disable-next-line */
|
|
3
|
+
--font-family: 'Wallop', 'Roboto', '-apple-system', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
4
|
+
|
|
5
|
+
// Color palette
|
|
6
|
+
--color-grey: #ccc;
|
|
7
|
+
--color-grey-light: #ddd;
|
|
8
|
+
--color-grey-lighter: #eaeaea;
|
|
9
|
+
--color-grey-10: #f3f3f3;
|
|
10
|
+
--color-grey-dark: #888;
|
|
11
|
+
--color-grey-darker: #444;
|
|
12
|
+
--color-grey-darkest: #2d2d2c;
|
|
13
|
+
--color-blue: #4799fc;
|
|
14
|
+
--color-blue-light: #91c2fd;
|
|
15
|
+
--color-purple: #ad66f2;
|
|
16
|
+
--color-purple-light: #cea3f7;
|
|
17
|
+
--color-red: #ff3838;
|
|
18
|
+
--color-red-light: #ff8888;
|
|
19
|
+
--color-orange: #ff7a20;
|
|
20
|
+
--color-orange-light: #ffa874;
|
|
21
|
+
--color-yellow: #ffbf2e;
|
|
22
|
+
--color-yellow-light: #ffd982;
|
|
23
|
+
--color-green: #00b06e;
|
|
24
|
+
--color-green-light: #66d0a8;
|
|
25
|
+
--color-green-light-30: rgba(102,208,168,0.3);
|
|
26
|
+
--color-green-10: #e5f7f0;
|
|
27
|
+
|
|
28
|
+
// Surface is a special color defined in Material Design but not part of Quasar. We still want to use it though.
|
|
29
|
+
// This is any plain surface, like a card or dialog background.
|
|
30
|
+
--surface-color: #fff;
|
|
31
|
+
--on-surface-color: var(--color-grey-darkest);
|
|
32
|
+
--surface-effect-color: var(--color-grey-lighter);
|
|
33
|
+
--surface-border-color: var(--color-grey);
|
|
34
|
+
|
|
35
|
+
// ** Primary, secondary and accent colors **
|
|
36
|
+
// Quasar base colors, like primary, are defined in quasar.variables.scss but can be overwritten like this: "--q-primary: orange !important;"
|
|
37
|
+
|
|
38
|
+
// primary = black
|
|
39
|
+
--on-primary-color: #fff;
|
|
40
|
+
--on-primary-alt-color: #fff; // This alt color is used in some scenarios, like for the context menu on banner cards.
|
|
41
|
+
--primary-effect-color: var(--color-grey-darker);
|
|
42
|
+
|
|
43
|
+
// secondary = grey-lighter
|
|
44
|
+
--on-secondary-color: var(--color-grey-darkest);
|
|
45
|
+
--on-secondary-alt-color: var(--color-grey-darkest);
|
|
46
|
+
--secondary-effect-color: var(--color-grey-light);
|
|
47
|
+
|
|
48
|
+
// accent = green
|
|
49
|
+
--on-accent-color: var(--color-grey-darkest);
|
|
50
|
+
--on-accent-alt-color: #fff;
|
|
51
|
+
--accent-effect-color: var(--color-green-light);
|
|
52
|
+
|
|
53
|
+
// Color aliases
|
|
54
|
+
--color-text: var(--color-grey-darkest);
|
|
55
|
+
--color-border: var(--color-grey-light);
|
|
56
|
+
--color-border-dark: var(--color-grey);
|
|
57
|
+
|
|
58
|
+
// Form elements
|
|
59
|
+
--input-bg-color: var(--surface-color);
|
|
60
|
+
--checkbox-border-color: var(--color-grey);
|
|
61
|
+
--radio-border-color: var(--color-grey);
|
|
62
|
+
|
|
63
|
+
// Table
|
|
64
|
+
--table-header-bg-color: var(--surface-color);
|
|
65
|
+
--table-image-size-width: 45px;
|
|
66
|
+
--table-image-size-height: 35px;
|
|
67
|
+
|
|
68
|
+
// Tree
|
|
69
|
+
--tree-icon-color: var(--color-grey-dark);
|
|
70
|
+
--tree-text-color: var(--color-text);
|
|
71
|
+
|
|
72
|
+
// Small card
|
|
73
|
+
--small-card-image-size: 86px;
|
|
74
|
+
|
|
75
|
+
// Tooltip
|
|
76
|
+
--tooltip-bg-color: #fff;
|
|
77
|
+
--tooltip-text-color: var(--color-grey-darkest);
|
|
78
|
+
--tooltip-border-color: var(--color-grey);
|
|
79
|
+
|
|
80
|
+
// Generic item states (lists/tables/trees etc.)
|
|
81
|
+
--item-selected-bg-color: var(--color-green-10);
|
|
82
|
+
--item-hover-bg-color: var(--color-grey-10);
|
|
83
|
+
|
|
84
|
+
// Dialog
|
|
85
|
+
--dialog-shadow: 0 2px 27px rgba(0, 0, 0, 0.25);
|
|
86
|
+
--dialog-backdrop-color: rgba(0, 0, 0, 0.25);
|
|
87
|
+
|
|
88
|
+
// Chips
|
|
89
|
+
--chip-bg-color: var(--color-grey-lighter);
|
|
90
|
+
--chip-text-color: var(--color-grey-darkest);
|
|
91
|
+
|
|
92
|
+
// Misc
|
|
93
|
+
--breadcrumbs-separator-color: var(--color-grey);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Themes for different sections of the application
|
|
97
|
+
[theme='route-demo-theme'] {
|
|
98
|
+
--q-primary: var(--color-green);
|
|
99
|
+
--q-secondary: var(--color-green-light);
|
|
100
|
+
--q-accent: var(--color-green-light);
|
|
101
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
body {
|
|
2
|
+
color: var(--color-text);
|
|
3
|
+
font-variant-ligatures: none;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// Reset browser heading margin
|
|
7
|
+
h1,
|
|
8
|
+
h2,
|
|
9
|
+
h3,
|
|
10
|
+
h4,
|
|
11
|
+
h5,
|
|
12
|
+
h6 {
|
|
13
|
+
margin: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
code {
|
|
17
|
+
background: var(--color-grey-darkest);
|
|
18
|
+
color: white;
|
|
19
|
+
border-radius: 4px;
|
|
20
|
+
padding: 0 4px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
pre {
|
|
24
|
+
margin: 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Copied from Preflight/Windi reset
|
|
28
|
+
*,
|
|
29
|
+
::before,
|
|
30
|
+
::after {
|
|
31
|
+
border-width: 0;
|
|
32
|
+
border-style: solid;
|
|
33
|
+
border-color: var(--color-border);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
[placeholder]::placeholder {
|
|
37
|
+
color: var(--color-grey);
|
|
38
|
+
opacity: 1; /* Firefox */
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Custom scrollbar in Firefox
|
|
42
|
+
* {
|
|
43
|
+
scrollbar-width: thin;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Custom scrollbar in Chrome/Webkit
|
|
47
|
+
::-webkit-scrollbar-thumb {
|
|
48
|
+
border-radius: 4px;
|
|
49
|
+
background-color: var(--color-grey);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
::-webkit-scrollbar {
|
|
53
|
+
width: 8px;
|
|
54
|
+
height: 8px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
a {
|
|
58
|
+
text-decoration: none;
|
|
59
|
+
color: var(--on-surface-color);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
ol,
|
|
63
|
+
ul {
|
|
64
|
+
list-style: none;
|
|
65
|
+
margin: 0;
|
|
66
|
+
padding: 0;
|
|
67
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// There is a plugin in windi for this, but for some reason it breaks code completion
|
|
2
|
+
.line-clamp-2 {
|
|
3
|
+
overflow: hidden;
|
|
4
|
+
display: -webkit-box;
|
|
5
|
+
-webkit-box-orient: vertical;
|
|
6
|
+
-webkit-line-clamp: 2;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.overflow-y-overlay {
|
|
10
|
+
// Fallback to auto in Firefox
|
|
11
|
+
overflow-y: auto;
|
|
12
|
+
|
|
13
|
+
// Overlay in Chrome
|
|
14
|
+
overflow-y: overlay;
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.c-checkbox {
|
|
2
|
+
&.q-checkbox[aria-label] {
|
|
3
|
+
max-width: max-content;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
&.q-checkbox.disabled {
|
|
7
|
+
opacity: 0.4 !important;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.q-checkbox__inner--falsy .q-checkbox__bg {
|
|
11
|
+
border: 2px solid var(--checkbox-border-color);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.q-checkbox__label {
|
|
15
|
+
padding: 4px 10px;
|
|
16
|
+
}
|
|
17
|
+
}
|