shared-ritm 1.2.55 → 1.2.56

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.
Files changed (74) hide show
  1. package/dist/index.css +1 -1
  2. package/dist/shared-ritm.es.js +4770 -4777
  3. package/dist/shared-ritm.umd.js +7 -7
  4. package/dist/types/api/types/Api_Controls.d.ts +6 -6
  5. package/package.json +1 -1
  6. package/src/App.vue +2461 -2461
  7. package/src/api/services/AuthService.ts +58 -58
  8. package/src/api/services/ControlsService.ts +64 -64
  9. package/src/api/services/FileService.ts +15 -15
  10. package/src/api/services/TasksService.ts +137 -137
  11. package/src/api/settings/ApiService.ts +128 -128
  12. package/src/api/types/Api_Controls.ts +3 -3
  13. package/src/common/app-button/AppButton.vue +173 -173
  14. package/src/common/app-date-picker/AppDatePicker.vue +81 -81
  15. package/src/common/app-icon/AppIcon.vue +108 -108
  16. package/src/common/app-input/AppInput.vue +147 -147
  17. package/src/common/app-input-search/AppInputSearch.vue +174 -174
  18. package/src/common/app-layout/AppLayout.vue +84 -84
  19. package/src/common/app-layout/components/AppLayoutHeader.vue +246 -246
  20. package/src/common/app-layout/components/AppLayoutPage.vue +16 -16
  21. package/src/common/app-loader/index.vue +43 -43
  22. package/src/common/app-page-layout/AppPageLayout.vue +122 -122
  23. package/src/common/app-sidebar/AppSidebar.vue +168 -168
  24. package/src/common/app-sidebar/components/SidebarMenu.vue +37 -37
  25. package/src/common/app-table/AppTable.vue +244 -244
  26. package/src/common/app-table/AppTableLayout.vue +104 -104
  27. package/src/common/app-table/components/ModalSelect.vue +264 -264
  28. package/src/common/app-table/components/TableModal.vue +357 -357
  29. package/src/common/app-table/controllers/useBaseTable.ts +42 -42
  30. package/src/global.d.ts +1 -1
  31. package/src/icons/components/arrow-down-icon.vue +25 -25
  32. package/src/icons/components/arrow-frame-icon.vue +19 -19
  33. package/src/icons/components/arrow-square.vue +22 -22
  34. package/src/icons/header/NotificationIcon.vue +18 -18
  35. package/src/icons/header/PersonIcon.vue +11 -11
  36. package/src/icons/header/SettingIcon.vue +14 -14
  37. package/src/icons/header/flashIcon.vue +24 -24
  38. package/src/icons/header/searchStatusIcon.vue +24 -24
  39. package/src/icons/header/smallCapsIcon.vue +34 -34
  40. package/src/icons/sidebar/assign-module-icon.vue +36 -36
  41. package/src/icons/sidebar/instrument-history-icon.vue +32 -32
  42. package/src/icons/sidebar/instrument-order-icon.vue +38 -38
  43. package/src/icons/sidebar/instrument-work-zone-icon.vue +18 -18
  44. package/src/icons/sidebar/instruments-icon.vue +45 -45
  45. package/src/icons/sidebar/logo-icon.vue +15 -15
  46. package/src/icons/sidebar/logout-icon.vue +13 -13
  47. package/src/icons/sidebar/modules-icon.vue +16 -16
  48. package/src/icons/sidebar/notifications-icon.vue +24 -24
  49. package/src/icons/sidebar/order-icon.vue +44 -44
  50. package/src/icons/sidebar/pass-icon.vue +38 -38
  51. package/src/icons/sidebar/positions-icon.vue +42 -42
  52. package/src/icons/sidebar/preorder-icon.vue +19 -19
  53. package/src/icons/sidebar/projects-icon.vue +31 -31
  54. package/src/icons/sidebar/repair-object-icon.vue +18 -18
  55. package/src/icons/sidebar/repairs-icon.vue +20 -20
  56. package/src/icons/sidebar/roles-icon.vue +26 -26
  57. package/src/icons/sidebar/status-history-icon.vue +24 -24
  58. package/src/icons/sidebar/tasks-icon.vue +28 -28
  59. package/src/icons/sidebar/tasks_tasks-icon.vue +39 -39
  60. package/src/icons/sidebar/tasks_today-icon.vue +27 -27
  61. package/src/icons/sidebar/teams-icon.vue +32 -32
  62. package/src/icons/sidebar/user-icon.vue +18 -18
  63. package/src/icons/sidebar/users-icon.vue +46 -46
  64. package/src/icons/sidebar/videosources-icon.vue +19 -19
  65. package/src/icons/sidebar/videowall-icon.vue +13 -13
  66. package/src/icons/sidebar/videozones-icon.vue +21 -21
  67. package/src/icons/sidebar/warehouses-icon.vue +43 -43
  68. package/src/icons/sidebar/workshop-icon.vue +100 -100
  69. package/src/icons/sidebar/workzones-icon.vue +22 -22
  70. package/src/index.ts +84 -84
  71. package/src/main.ts +28 -28
  72. package/src/quasar-user-options.ts +17 -17
  73. package/src/router/index.ts +10 -10
  74. package/src/shims-vue.d.ts +5 -5
@@ -1,244 +1,244 @@
1
- <script setup lang="ts">
2
- import { defineProps, defineEmits, ref, computed, watch } from 'vue'
3
- import type { Ref } from 'vue'
4
- import FilterIcon from '@/icons/components/table-filter-icon.vue'
5
-
6
- interface FilterOption {
7
- id: string
8
- name: string
9
- }
10
-
11
- interface TableEmits {
12
- 'toggle-filter-value': [colName: string, value: string]
13
- 'clear-filter': [colName: string]
14
- 'open-filter-menu': [colName: string, isOpen: boolean]
15
- 'row-click': [row: Record<string, any>]
16
- 'update:selectedRows': [rows: any[]]
17
- }
18
-
19
- const emit = defineEmits<TableEmits>()
20
-
21
- const props = defineProps<{
22
- rows: Ref<any[]>
23
- columns: any[]
24
- columnFilters: Ref<Record<string, string | string[] | undefined>>
25
- filterMenus: Ref<Record<string, boolean>>
26
- filtersOptions: Record<string, FilterOption[]>
27
- meta: Ref<{ currentPage: number; perPage: number }>
28
- enableMultiSelect?: boolean
29
- selectedRows: any[]
30
- }>()
31
-
32
- const localSearches = ref<Record<string, string>>({})
33
-
34
- const filteredOptions = computed(() => {
35
- const result: Record<string, FilterOption[]> = {}
36
- for (const col of props.columns) {
37
- const search = localSearches.value[col.name]?.toLowerCase() || ''
38
- const options = props.filtersOptions[col.name] || []
39
- result[col.name] = options.filter(opt => opt.name.toLowerCase().includes(search))
40
- }
41
- return result
42
- })
43
- const selected = ref<any[]>([])
44
-
45
- watch(
46
- () => props.selectedRows,
47
- val => {
48
- selected.value = val
49
- },
50
- { immediate: true },
51
- )
52
-
53
- watch(
54
- selected,
55
- val => {
56
- emit('update:selectedRows', val)
57
- },
58
- { deep: true },
59
- )
60
- </script>
61
-
62
- <template>
63
- <q-page class="flex flex-col" style="min-height: 100%">
64
- <q-table
65
- v-model:selected="selected"
66
- :rows="rows.value"
67
- :columns="columns"
68
- row-key="id"
69
- flat
70
- bordered
71
- hide-bottom
72
- class="full-width"
73
- :rows-per-page-options="[0]"
74
- :selection="props.enableMultiSelect ? 'multiple' : 'none'"
75
- @row-click="(_, row) => emit('row-click', row)"
76
- >
77
- <template #header-selection="scope">
78
- <q-toggle v-model="scope.selected" />
79
- </template>
80
-
81
- <template #body-selection="scope">
82
- <q-toggle v-model="scope.selected" />
83
- </template>
84
-
85
- <template #body-cell-index="props">
86
- <q-td :props="props" class="text-center">
87
- {{ props.rowIndex + 1 + (meta.value.currentPage - 1) * meta.value.perPage }}
88
- </q-td>
89
- </template>
90
-
91
- <template v-for="col in columns" :key="col.name" #[`header-cell-${col.name}`]="propsSlot">
92
- <q-th :props="propsSlot" :class="{ 'cursor-pointer': col.filterType }">
93
- <div
94
- v-if="col.filterType"
95
- class="row items-center no-wrap"
96
- @click.stop="emit('open-filter-menu', col.name, !filterMenus.value[col.name])"
97
- >
98
- <filter-icon class="q-mr-xs" />
99
- <span>{{ col.label }}</span>
100
- <div
101
- v-if="['multi', 'single'].includes(col.filterType) && columnFilters.value[col.name]?.length"
102
- class="label-length"
103
- >
104
- - {{ col.filterType === 'multi' ? columnFilters.value[col.name]?.length : 1 }}
105
- </div>
106
- </div>
107
- <div v-else>{{ col.label }}</div>
108
-
109
- <q-menu
110
- v-if="col.filterType"
111
- :model-value="filterMenus.value[col.name]"
112
- fit
113
- max-height="300px"
114
- class="filter-menu"
115
- @update:model-value="isOpen => emit('open-filter-menu', col.name, isOpen)"
116
- >
117
- <div class="filter-content">
118
- <q-input v-model="localSearches[col.name]" dense outlined placeholder="Поиск" class="q-mb-sm" clearable />
119
- <q-scroll-area style="height: 200px">
120
- <q-list style="min-width: 200px">
121
- <q-item v-for="option in filteredOptions[col.name]" :key="`${col.name}-${option.id}`" tag="label">
122
- <q-item-section avatar>
123
- <q-checkbox
124
- v-if="col.filterType === 'multi'"
125
- dense
126
- :model-value="
127
- Array.isArray(columnFilters.value[col.name]) &&
128
- columnFilters.value[col.name]?.includes(option.name)
129
- "
130
- @update:model-value="() => emit('toggle-filter-value', col.name, option.name)"
131
- />
132
- <q-radio
133
- v-else
134
- dense
135
- :model-value="columnFilters.value[col.name]"
136
- :val="option.name"
137
- @update:model-value="emit('toggle-filter-value', col.name, $event)"
138
- />
139
- </q-item-section>
140
- <q-item-section>{{ option.name }}</q-item-section>
141
- </q-item>
142
- </q-list>
143
- </q-scroll-area>
144
-
145
- <div class="filter-footer">
146
- <q-btn color="negative" flat dense label="Сбросить фильтр" @click="emit('clear-filter', col.name)" />
147
- </div>
148
- </div>
149
- </q-menu>
150
- </q-th>
151
- </template>
152
-
153
- <template #body-cell="props">
154
- <q-td :props="props">
155
- <q-badge
156
- v-if="props.col.badge && typeof props.value === 'boolean'"
157
- :color="
158
- props.col.badge.colorTrue && props.value
159
- ? props.col.badge.colorTrue
160
- : props.col.badge.colorFalse && !props.value
161
- ? props.col.badge.colorFalse
162
- : props.value
163
- ? 'green'
164
- : 'red'
165
- "
166
- outline
167
- class="text-bold"
168
- >
169
- {{ props.value ? props.col.badge.true ?? 'Да' : props.col.badge.false ?? 'Нет' }}
170
- </q-badge>
171
- <span v-else-if="props.col.html" v-html="props.value"></span>
172
- <span v-else>{{ props.value }}</span>
173
- </q-td>
174
- </template>
175
- </q-table>
176
- </q-page>
177
- </template>
178
-
179
- <style scoped lang="scss">
180
- .cursor-pointer {
181
- cursor: pointer;
182
- }
183
-
184
- .filter-menu {
185
- padding: 10px;
186
- }
187
- .label-length {
188
- margin-left: 5px;
189
- }
190
- .filter-content {
191
- display: flex;
192
- flex-direction: column;
193
- color: #1d425d;
194
- .q-item {
195
- padding: 0 5px;
196
- min-height: 40px;
197
- }
198
- .q-item__section {
199
- min-width: 30px;
200
- padding: 0px;
201
- }
202
- ::v-deep(.q-radio__inner),
203
- ::v-deep(.q-checkbox__inner) {
204
- color: #a4b4cf;
205
- }
206
- }
207
-
208
- .filter-footer {
209
- border-top: 1px solid #eee;
210
- display: flex;
211
- justify-content: center;
212
- }
213
-
214
- ::v-deep(.q-table thead) {
215
- background: #f2f7fb;
216
- }
217
-
218
- ::v-deep(.q-table th) {
219
- font-family: NunitoSansFont, sans-serif;
220
- color: #a4b4cf;
221
- font-size: 15px;
222
- font-style: normal;
223
- font-weight: 700;
224
- line-height: 20px;
225
- height: 61px;
226
- }
227
-
228
- ::v-deep(.q-table tbody td) {
229
- height: 61px;
230
- font-size: 14px;
231
- }
232
-
233
- ::v-deep(.q-table tbody) {
234
- font-family: NunitoSansFont, sans-serif;
235
- border-color: #d7e0ef;
236
- color: #1d425d;
237
- line-height: 20px;
238
- font-size: 14px;
239
- }
240
-
241
- ::v-deep(.q-table tbody tr:last-child td) {
242
- border-bottom: 1px solid #d7e0ef;
243
- }
244
- </style>
1
+ <script setup lang="ts">
2
+ import { defineProps, defineEmits, ref, computed, watch } from 'vue'
3
+ import type { Ref } from 'vue'
4
+ import FilterIcon from '@/icons/components/table-filter-icon.vue'
5
+
6
+ interface FilterOption {
7
+ id: string
8
+ name: string
9
+ }
10
+
11
+ interface TableEmits {
12
+ 'toggle-filter-value': [colName: string, value: string]
13
+ 'clear-filter': [colName: string]
14
+ 'open-filter-menu': [colName: string, isOpen: boolean]
15
+ 'row-click': [row: Record<string, any>]
16
+ 'update:selectedRows': [rows: any[]]
17
+ }
18
+
19
+ const emit = defineEmits<TableEmits>()
20
+
21
+ const props = defineProps<{
22
+ rows: Ref<any[]>
23
+ columns: any[]
24
+ columnFilters: Ref<Record<string, string | string[] | undefined>>
25
+ filterMenus: Ref<Record<string, boolean>>
26
+ filtersOptions: Record<string, FilterOption[]>
27
+ meta: Ref<{ currentPage: number; perPage: number }>
28
+ enableMultiSelect?: boolean
29
+ selectedRows: any[]
30
+ }>()
31
+
32
+ const localSearches = ref<Record<string, string>>({})
33
+
34
+ const filteredOptions = computed(() => {
35
+ const result: Record<string, FilterOption[]> = {}
36
+ for (const col of props.columns) {
37
+ const search = localSearches.value[col.name]?.toLowerCase() || ''
38
+ const options = props.filtersOptions[col.name] || []
39
+ result[col.name] = options.filter(opt => opt.name.toLowerCase().includes(search))
40
+ }
41
+ return result
42
+ })
43
+ const selected = ref<any[]>([])
44
+
45
+ watch(
46
+ () => props.selectedRows,
47
+ val => {
48
+ selected.value = val
49
+ },
50
+ { immediate: true },
51
+ )
52
+
53
+ watch(
54
+ selected,
55
+ val => {
56
+ emit('update:selectedRows', val)
57
+ },
58
+ { deep: true },
59
+ )
60
+ </script>
61
+
62
+ <template>
63
+ <q-page class="flex flex-col" style="min-height: 100%">
64
+ <q-table
65
+ v-model:selected="selected"
66
+ :rows="rows.value"
67
+ :columns="columns"
68
+ row-key="id"
69
+ flat
70
+ bordered
71
+ hide-bottom
72
+ class="full-width"
73
+ :rows-per-page-options="[0]"
74
+ :selection="props.enableMultiSelect ? 'multiple' : 'none'"
75
+ @row-click="(_, row) => emit('row-click', row)"
76
+ >
77
+ <template #header-selection="scope">
78
+ <q-toggle v-model="scope.selected" />
79
+ </template>
80
+
81
+ <template #body-selection="scope">
82
+ <q-toggle v-model="scope.selected" />
83
+ </template>
84
+
85
+ <template #body-cell-index="props">
86
+ <q-td :props="props" class="text-center">
87
+ {{ props.rowIndex + 1 + (meta.value.currentPage - 1) * meta.value.perPage }}
88
+ </q-td>
89
+ </template>
90
+
91
+ <template v-for="col in columns" :key="col.name" #[`header-cell-${col.name}`]="propsSlot">
92
+ <q-th :props="propsSlot" :class="{ 'cursor-pointer': col.filterType }">
93
+ <div
94
+ v-if="col.filterType"
95
+ class="row items-center no-wrap"
96
+ @click.stop="emit('open-filter-menu', col.name, !filterMenus.value[col.name])"
97
+ >
98
+ <filter-icon class="q-mr-xs" />
99
+ <span>{{ col.label }}</span>
100
+ <div
101
+ v-if="['multi', 'single'].includes(col.filterType) && columnFilters.value[col.name]?.length"
102
+ class="label-length"
103
+ >
104
+ - {{ col.filterType === 'multi' ? columnFilters.value[col.name]?.length : 1 }}
105
+ </div>
106
+ </div>
107
+ <div v-else>{{ col.label }}</div>
108
+
109
+ <q-menu
110
+ v-if="col.filterType"
111
+ :model-value="filterMenus.value[col.name]"
112
+ fit
113
+ max-height="300px"
114
+ class="filter-menu"
115
+ @update:model-value="isOpen => emit('open-filter-menu', col.name, isOpen)"
116
+ >
117
+ <div class="filter-content">
118
+ <q-input v-model="localSearches[col.name]" dense outlined placeholder="Поиск" class="q-mb-sm" clearable />
119
+ <q-scroll-area style="height: 200px">
120
+ <q-list style="min-width: 200px">
121
+ <q-item v-for="option in filteredOptions[col.name]" :key="`${col.name}-${option.id}`" tag="label">
122
+ <q-item-section avatar>
123
+ <q-checkbox
124
+ v-if="col.filterType === 'multi'"
125
+ dense
126
+ :model-value="
127
+ Array.isArray(columnFilters.value[col.name]) &&
128
+ columnFilters.value[col.name]?.includes(option.name)
129
+ "
130
+ @update:model-value="() => emit('toggle-filter-value', col.name, option.name)"
131
+ />
132
+ <q-radio
133
+ v-else
134
+ dense
135
+ :model-value="columnFilters.value[col.name]"
136
+ :val="option.name"
137
+ @update:model-value="emit('toggle-filter-value', col.name, $event)"
138
+ />
139
+ </q-item-section>
140
+ <q-item-section>{{ option.name }}</q-item-section>
141
+ </q-item>
142
+ </q-list>
143
+ </q-scroll-area>
144
+
145
+ <div class="filter-footer">
146
+ <q-btn color="negative" flat dense label="Сбросить фильтр" @click="emit('clear-filter', col.name)" />
147
+ </div>
148
+ </div>
149
+ </q-menu>
150
+ </q-th>
151
+ </template>
152
+
153
+ <template #body-cell="props">
154
+ <q-td :props="props">
155
+ <q-badge
156
+ v-if="props.col.badge && typeof props.value === 'boolean'"
157
+ :color="
158
+ props.col.badge.colorTrue && props.value
159
+ ? props.col.badge.colorTrue
160
+ : props.col.badge.colorFalse && !props.value
161
+ ? props.col.badge.colorFalse
162
+ : props.value
163
+ ? 'green'
164
+ : 'red'
165
+ "
166
+ outline
167
+ class="text-bold"
168
+ >
169
+ {{ props.value ? props.col.badge.true ?? 'Да' : props.col.badge.false ?? 'Нет' }}
170
+ </q-badge>
171
+ <span v-else-if="props.col.html" v-html="props.value"></span>
172
+ <span v-else>{{ props.value }}</span>
173
+ </q-td>
174
+ </template>
175
+ </q-table>
176
+ </q-page>
177
+ </template>
178
+
179
+ <style scoped lang="scss">
180
+ .cursor-pointer {
181
+ cursor: pointer;
182
+ }
183
+
184
+ .filter-menu {
185
+ padding: 10px;
186
+ }
187
+ .label-length {
188
+ margin-left: 5px;
189
+ }
190
+ .filter-content {
191
+ display: flex;
192
+ flex-direction: column;
193
+ color: #1d425d;
194
+ .q-item {
195
+ padding: 0 5px;
196
+ min-height: 40px;
197
+ }
198
+ .q-item__section {
199
+ min-width: 30px;
200
+ padding: 0px;
201
+ }
202
+ ::v-deep(.q-radio__inner),
203
+ ::v-deep(.q-checkbox__inner) {
204
+ color: #a4b4cf;
205
+ }
206
+ }
207
+
208
+ .filter-footer {
209
+ border-top: 1px solid #eee;
210
+ display: flex;
211
+ justify-content: center;
212
+ }
213
+
214
+ ::v-deep(.q-table thead) {
215
+ background: #f2f7fb;
216
+ }
217
+
218
+ ::v-deep(.q-table th) {
219
+ font-family: NunitoSansFont, sans-serif;
220
+ color: #a4b4cf;
221
+ font-size: 15px;
222
+ font-style: normal;
223
+ font-weight: 700;
224
+ line-height: 20px;
225
+ height: 61px;
226
+ }
227
+
228
+ ::v-deep(.q-table tbody td) {
229
+ height: 61px;
230
+ font-size: 14px;
231
+ }
232
+
233
+ ::v-deep(.q-table tbody) {
234
+ font-family: NunitoSansFont, sans-serif;
235
+ border-color: #d7e0ef;
236
+ color: #1d425d;
237
+ line-height: 20px;
238
+ font-size: 14px;
239
+ }
240
+
241
+ ::v-deep(.q-table tbody tr:last-child td) {
242
+ border-bottom: 1px solid #d7e0ef;
243
+ }
244
+ </style>