shared-ritm 1.2.58 → 1.2.60

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 (55) hide show
  1. package/README.md +103 -103
  2. package/dist/index.css +1 -1
  3. package/dist/shared-ritm.es.js +4323 -4296
  4. package/dist/shared-ritm.umd.js +7 -7
  5. package/dist/types/api/services/InstrumentsService.d.ts +7 -0
  6. package/dist/types/api/services/VideoService.d.ts +6 -0
  7. package/dist/types/api/types/Api_Instruments.d.ts +133 -0
  8. package/dist/types/index.d.ts +3 -1
  9. package/package.json +63 -63
  10. package/src/api/services/ControlsService.ts +64 -64
  11. package/src/api/services/GanttService.ts +17 -17
  12. package/src/api/services/InstrumentsService.ts +22 -0
  13. package/src/api/services/MetricsService.ts +109 -109
  14. package/src/api/services/ProjectsService.ts +67 -67
  15. package/src/api/services/RepairsService.ts +100 -100
  16. package/src/api/services/VideoService.ts +14 -0
  17. package/src/api/types/Api_Files.ts +1 -1
  18. package/src/api/types/Api_Instruments.ts +133 -0
  19. package/src/api/types/Api_Projects.ts +55 -55
  20. package/src/api/types/Api_Repairs.ts +93 -93
  21. package/src/api/types/Api_Tasks.ts +155 -155
  22. package/src/common/app-checkbox/AppCheckbox.vue +26 -26
  23. package/src/common/app-dialogs/AppConfirmDialog.vue +99 -99
  24. package/src/common/app-dropdown/AppDropdown.vue +31 -31
  25. package/src/common/app-select/AppSelect.vue +157 -157
  26. package/src/common/app-sheet/AppSheet.vue +120 -120
  27. package/src/common/app-sidebar/components/SidebarMenuItem.vue +148 -148
  28. package/src/common/app-table/AppTable.vue +241 -241
  29. package/src/common/app-table/AppTableLayout.vue +102 -102
  30. package/src/common/app-table/components/ModalSelect.vue +264 -264
  31. package/src/common/app-table/components/TableModal.vue +329 -329
  32. package/src/common/app-table/components/TablePagination.vue +150 -150
  33. package/src/common/app-table/components/TableSearch.vue +76 -76
  34. package/src/common/app-table/controllers/useBaseTable.ts +42 -42
  35. package/src/common/app-table/controllers/useColumnSelector.ts +38 -38
  36. package/src/common/app-table/controllers/useTableModel.ts +93 -93
  37. package/src/common/app-toggle/AppToggle.vue +23 -23
  38. package/src/common/app-wrapper/AppWrapper.vue +28 -28
  39. package/src/icons/components/table-filter-icon.vue +30 -30
  40. package/src/icons/dialogs/RemoveIcon.vue +12 -12
  41. package/src/icons/dialogs/SafetyIcon.vue +12 -12
  42. package/src/icons/task/attention-icon.vue +13 -13
  43. package/src/icons/task/clock-icon.vue +10 -10
  44. package/src/icons/task/delete-icon.vue +10 -10
  45. package/src/icons/task/fire-icon.vue +16 -16
  46. package/src/index.ts +88 -84
  47. package/src/shared/fonts/Inter_18pt-Black.ttf +0 -0
  48. package/src/shared/fonts/Inter_18pt-Bold.ttf +0 -0
  49. package/src/shared/fonts/Inter_18pt-Regular.ttf +0 -0
  50. package/src/shared/fonts/Inter_18pt-SemiBold.ttf +0 -0
  51. package/src/shared/styles/general.css +125 -96
  52. package/src/styles/variables.sass +12 -12
  53. package/src/utils/confirm.ts +12 -12
  54. package/src/utils/helpers.ts +39 -39
  55. package/src/utils/notification.ts +9 -9
@@ -1,241 +1,241 @@
1
- <template>
2
- <q-page class="flex flex-col" style="min-height: 100%">
3
- <q-table
4
- v-model:selected="selected"
5
- :rows="rows.value"
6
- :columns="columns"
7
- row-key="id"
8
- flat
9
- bordered
10
- hide-bottom
11
- class="full-width"
12
- :rows-per-page-options="[0]"
13
- :selection="props.enableMultiSelect ? 'multiple' : 'none'"
14
- @row-click="(_, row) => emit('row-click', row)"
15
- >
16
- <template #header-selection="scope">
17
- <q-toggle v-model="scope.selected" />
18
- </template>
19
-
20
- <template #body-selection="scope">
21
- <q-toggle v-model="scope.selected" />
22
- </template>
23
-
24
- <template #body-cell-index="props">
25
- <q-td :props="props" class="text-center">
26
- {{ props.rowIndex + 1 + (meta.value.currentPage - 1) * meta.value.perPage }}
27
- </q-td>
28
- </template>
29
-
30
- <template v-for="col in columns" :key="col.name" #[`header-cell-${col.name}`]="propsSlot">
31
- <q-th :props="propsSlot" :class="{ 'cursor-pointer': col.filterType }">
32
- <div
33
- v-if="col.filterType"
34
- class="row items-center no-wrap"
35
- @click.stop="emit('open-filter-menu', col.name, !filterMenus.value[col.name])"
36
- >
37
- <filter-icon class="q-mr-xs" />
38
- <span>{{ col.label }}</span>
39
- <div
40
- v-if="['multi', 'single'].includes(col.filterType) && columnFilters.value[col.name]?.length"
41
- class="label-length"
42
- >
43
- - {{ col.filterType === 'multi' ? columnFilters.value[col.name]?.length : 1 }}
44
- </div>
45
- </div>
46
- <div v-else>{{ col.label }}</div>
47
-
48
- <q-menu
49
- v-if="col.filterType"
50
- :model-value="filterMenus.value[col.name]"
51
- fit
52
- max-height="300px"
53
- class="filter-menu"
54
- @update:model-value="isOpen => emit('open-filter-menu', col.name, isOpen)"
55
- >
56
- <div class="filter-content">
57
- <q-input v-model="localSearches[col.name]" dense outlined placeholder="Поиск" class="q-mb-sm" clearable />
58
- <q-scroll-area style="height: 200px">
59
- <q-list style="min-width: 200px">
60
- <q-item v-for="option in filteredOptions[col.name]" :key="`${col.name}-${option.id}`" tag="label">
61
- <q-item-section avatar>
62
- <q-checkbox
63
- v-if="col.filterType === 'multi'"
64
- dense
65
- :model-value="
66
- Array.isArray(columnFilters.value[col.name]) &&
67
- columnFilters.value[col.name]?.includes(option.name)
68
- "
69
- @update:model-value="() => emit('toggle-filter-value', col.name, option.name)"
70
- />
71
- <q-radio
72
- v-else
73
- dense
74
- :model-value="columnFilters.value[col.name]"
75
- :val="option.name"
76
- @update:model-value="emit('toggle-filter-value', col.name, $event)"
77
- />
78
- </q-item-section>
79
- <q-item-section>{{ option.name }}</q-item-section>
80
- </q-item>
81
- </q-list>
82
- </q-scroll-area>
83
-
84
- <div class="filter-footer">
85
- <q-btn color="negative" flat dense label="Сбросить фильтр" @click="emit('clear-filter', col.name)" />
86
- </div>
87
- </div>
88
- </q-menu>
89
- </q-th>
90
- </template>
91
-
92
- <template #body-cell="props">
93
- <q-td :props="props">
94
- <q-badge
95
- v-if="props.col.badge && typeof props.value === 'boolean'"
96
- :color="
97
- props.col.badge.colorTrue && props.value
98
- ? props.col.badge.colorTrue
99
- : props.col.badge.colorFalse && !props.value
100
- ? props.col.badge.colorFalse
101
- : props.value
102
- ? 'green'
103
- : 'red'
104
- "
105
- outline
106
- class="text-bold"
107
- >
108
- {{ props.value ? props.col.badge.true ?? 'Да' : props.col.badge.false ?? 'Нет' }}
109
- </q-badge>
110
- <span v-else-if="props.col.html" v-html="props.value"></span>
111
- <span v-else>{{ props.value }}</span>
112
- </q-td>
113
- </template>
114
- </q-table>
115
- </q-page>
116
- </template>
117
- <script setup lang="ts">
118
- import { defineProps, defineEmits, ref, computed, watch } from 'vue'
119
- import type { Ref } from 'vue'
120
- import FilterIcon from '@/icons/components/table-filter-icon.vue'
121
-
122
- interface FilterOption {
123
- id: string
124
- name: string
125
- }
126
-
127
- interface TableEmits {
128
- 'toggle-filter-value': [colName: string, value: string]
129
- 'clear-filter': [colName: string]
130
- 'open-filter-menu': [colName: string, isOpen: boolean]
131
- 'row-click': [row: Record<string, any>]
132
- 'update:selectedRows': [rows: any[]] // синтаксис defineEmits для эмита с именованными параметрами
133
- }
134
-
135
- const props = defineProps<{
136
- rows: Ref<any[]>
137
- columns: any[]
138
- columnFilters: Ref<Record<string, string | string[] | undefined>>
139
- filterMenus: Ref<Record<string, boolean>>
140
- filtersOptions: Record<string, FilterOption[]>
141
- meta: Ref<{ currentPage: number; perPage: number }>
142
- enableMultiSelect?: boolean
143
- selectedRows: any[]
144
- }>()
145
- const emit = defineEmits<TableEmits>()
146
-
147
- const localSearches = ref<Record<string, string>>({})
148
- const selected = ref<any[]>([])
149
-
150
- const filteredOptions = computed(() => {
151
- const result: Record<string, FilterOption[]> = {}
152
- for (const col of props.columns) {
153
- const search = localSearches.value[col.name]?.toLowerCase() || ''
154
- const options = props.filtersOptions[col.name] || []
155
- result[col.name] = options.filter(opt => opt.name.toLowerCase().includes(search))
156
- }
157
- return result
158
- })
159
-
160
- watch(
161
- () => props.selectedRows,
162
- val => {
163
- selected.value = val
164
- },
165
- { immediate: true },
166
- )
167
-
168
- watch(
169
- selected,
170
- val => {
171
- emit('update:selectedRows', val)
172
- },
173
- { deep: true },
174
- )
175
- </script>
176
- <style scoped lang="scss">
177
- .cursor-pointer {
178
- cursor: pointer;
179
- }
180
-
181
- .filter-menu {
182
- padding: 10px;
183
- }
184
- .label-length {
185
- margin-left: 5px;
186
- }
187
- .filter-content {
188
- display: flex;
189
- flex-direction: column;
190
- color: #1d425d;
191
- .q-item {
192
- padding: 0 5px;
193
- min-height: 40px;
194
- }
195
- .q-item__section {
196
- min-width: 30px;
197
- padding: 0px;
198
- }
199
- ::v-deep(.q-radio__inner),
200
- ::v-deep(.q-checkbox__inner) {
201
- color: #a4b4cf;
202
- }
203
- }
204
-
205
- .filter-footer {
206
- border-top: 1px solid #eee;
207
- display: flex;
208
- justify-content: center;
209
- }
210
-
211
- ::v-deep(.q-table thead) {
212
- background: #f2f7fb;
213
- }
214
-
215
- ::v-deep(.q-table th) {
216
- font-family: NunitoSansFont, sans-serif;
217
- color: #a4b4cf;
218
- font-size: 15px;
219
- font-style: normal;
220
- font-weight: 700;
221
- line-height: 20px;
222
- height: 61px;
223
- }
224
-
225
- ::v-deep(.q-table tbody td) {
226
- height: 61px;
227
- font-size: 14px;
228
- }
229
-
230
- ::v-deep(.q-table tbody) {
231
- font-family: NunitoSansFont, sans-serif;
232
- border-color: #d7e0ef;
233
- color: #1d425d;
234
- line-height: 20px;
235
- font-size: 14px;
236
- }
237
-
238
- ::v-deep(.q-table tbody tr:last-child td) {
239
- border-bottom: 1px solid #d7e0ef;
240
- }
241
- </style>
1
+ <template>
2
+ <q-page class="flex flex-col" style="min-height: 100%">
3
+ <q-table
4
+ v-model:selected="selected"
5
+ :rows="rows.value"
6
+ :columns="columns"
7
+ row-key="id"
8
+ flat
9
+ bordered
10
+ hide-bottom
11
+ class="full-width"
12
+ :rows-per-page-options="[0]"
13
+ :selection="props.enableMultiSelect ? 'multiple' : 'none'"
14
+ @row-click="(_, row) => emit('row-click', row)"
15
+ >
16
+ <template #header-selection="scope">
17
+ <q-toggle v-model="scope.selected" />
18
+ </template>
19
+
20
+ <template #body-selection="scope">
21
+ <q-toggle v-model="scope.selected" />
22
+ </template>
23
+
24
+ <template #body-cell-index="props">
25
+ <q-td :props="props" class="text-center">
26
+ {{ props.rowIndex + 1 + (meta.value.currentPage - 1) * meta.value.perPage }}
27
+ </q-td>
28
+ </template>
29
+
30
+ <template v-for="col in columns" :key="col.name" #[`header-cell-${col.name}`]="propsSlot">
31
+ <q-th :props="propsSlot" :class="{ 'cursor-pointer': col.filterType }">
32
+ <div
33
+ v-if="col.filterType"
34
+ class="row items-center no-wrap"
35
+ @click.stop="emit('open-filter-menu', col.name, !filterMenus.value[col.name])"
36
+ >
37
+ <filter-icon class="q-mr-xs" />
38
+ <span>{{ col.label }}</span>
39
+ <div
40
+ v-if="['multi', 'single'].includes(col.filterType) && columnFilters.value[col.name]?.length"
41
+ class="label-length"
42
+ >
43
+ - {{ col.filterType === 'multi' ? columnFilters.value[col.name]?.length : 1 }}
44
+ </div>
45
+ </div>
46
+ <div v-else>{{ col.label }}</div>
47
+
48
+ <q-menu
49
+ v-if="col.filterType"
50
+ :model-value="filterMenus.value[col.name]"
51
+ fit
52
+ max-height="300px"
53
+ class="filter-menu"
54
+ @update:model-value="isOpen => emit('open-filter-menu', col.name, isOpen)"
55
+ >
56
+ <div class="filter-content">
57
+ <q-input v-model="localSearches[col.name]" dense outlined placeholder="Поиск" class="q-mb-sm" clearable />
58
+ <q-scroll-area style="height: 200px">
59
+ <q-list style="min-width: 200px">
60
+ <q-item v-for="option in filteredOptions[col.name]" :key="`${col.name}-${option.id}`" tag="label">
61
+ <q-item-section avatar>
62
+ <q-checkbox
63
+ v-if="col.filterType === 'multi'"
64
+ dense
65
+ :model-value="
66
+ Array.isArray(columnFilters.value[col.name]) &&
67
+ columnFilters.value[col.name]?.includes(option.name)
68
+ "
69
+ @update:model-value="() => emit('toggle-filter-value', col.name, option.name)"
70
+ />
71
+ <q-radio
72
+ v-else
73
+ dense
74
+ :model-value="columnFilters.value[col.name]"
75
+ :val="option.name"
76
+ @update:model-value="emit('toggle-filter-value', col.name, $event)"
77
+ />
78
+ </q-item-section>
79
+ <q-item-section>{{ option.name }}</q-item-section>
80
+ </q-item>
81
+ </q-list>
82
+ </q-scroll-area>
83
+
84
+ <div class="filter-footer">
85
+ <q-btn color="negative" flat dense label="Сбросить фильтр" @click="emit('clear-filter', col.name)" />
86
+ </div>
87
+ </div>
88
+ </q-menu>
89
+ </q-th>
90
+ </template>
91
+
92
+ <template #body-cell="props">
93
+ <q-td :props="props">
94
+ <q-badge
95
+ v-if="props.col.badge && typeof props.value === 'boolean'"
96
+ :color="
97
+ props.col.badge.colorTrue && props.value
98
+ ? props.col.badge.colorTrue
99
+ : props.col.badge.colorFalse && !props.value
100
+ ? props.col.badge.colorFalse
101
+ : props.value
102
+ ? 'green'
103
+ : 'red'
104
+ "
105
+ outline
106
+ class="text-bold"
107
+ >
108
+ {{ props.value ? props.col.badge.true ?? 'Да' : props.col.badge.false ?? 'Нет' }}
109
+ </q-badge>
110
+ <span v-else-if="props.col.html" v-html="props.value"></span>
111
+ <span v-else>{{ props.value }}</span>
112
+ </q-td>
113
+ </template>
114
+ </q-table>
115
+ </q-page>
116
+ </template>
117
+ <script setup lang="ts">
118
+ import { defineProps, defineEmits, ref, computed, watch } from 'vue'
119
+ import type { Ref } from 'vue'
120
+ import FilterIcon from '@/icons/components/table-filter-icon.vue'
121
+
122
+ interface FilterOption {
123
+ id: string
124
+ name: string
125
+ }
126
+
127
+ interface TableEmits {
128
+ 'toggle-filter-value': [colName: string, value: string]
129
+ 'clear-filter': [colName: string]
130
+ 'open-filter-menu': [colName: string, isOpen: boolean]
131
+ 'row-click': [row: Record<string, any>]
132
+ 'update:selectedRows': [rows: any[]] // синтаксис defineEmits для эмита с именованными параметрами
133
+ }
134
+
135
+ const props = defineProps<{
136
+ rows: Ref<any[]>
137
+ columns: any[]
138
+ columnFilters: Ref<Record<string, string | string[] | undefined>>
139
+ filterMenus: Ref<Record<string, boolean>>
140
+ filtersOptions: Record<string, FilterOption[]>
141
+ meta: Ref<{ currentPage: number; perPage: number }>
142
+ enableMultiSelect?: boolean
143
+ selectedRows: any[]
144
+ }>()
145
+ const emit = defineEmits<TableEmits>()
146
+
147
+ const localSearches = ref<Record<string, string>>({})
148
+ const selected = ref<any[]>([])
149
+
150
+ const filteredOptions = computed(() => {
151
+ const result: Record<string, FilterOption[]> = {}
152
+ for (const col of props.columns) {
153
+ const search = localSearches.value[col.name]?.toLowerCase() || ''
154
+ const options = props.filtersOptions[col.name] || []
155
+ result[col.name] = options.filter(opt => opt.name.toLowerCase().includes(search))
156
+ }
157
+ return result
158
+ })
159
+
160
+ watch(
161
+ () => props.selectedRows,
162
+ val => {
163
+ selected.value = val
164
+ },
165
+ { immediate: true },
166
+ )
167
+
168
+ watch(
169
+ selected,
170
+ val => {
171
+ emit('update:selectedRows', val)
172
+ },
173
+ { deep: true },
174
+ )
175
+ </script>
176
+ <style scoped lang="scss">
177
+ .cursor-pointer {
178
+ cursor: pointer;
179
+ }
180
+
181
+ .filter-menu {
182
+ padding: 10px;
183
+ }
184
+ .label-length {
185
+ margin-left: 5px;
186
+ }
187
+ .filter-content {
188
+ display: flex;
189
+ flex-direction: column;
190
+ color: #1d425d;
191
+ .q-item {
192
+ padding: 0 5px;
193
+ min-height: 40px;
194
+ }
195
+ .q-item__section {
196
+ min-width: 30px;
197
+ padding: 0px;
198
+ }
199
+ ::v-deep(.q-radio__inner),
200
+ ::v-deep(.q-checkbox__inner) {
201
+ color: #a4b4cf;
202
+ }
203
+ }
204
+
205
+ .filter-footer {
206
+ border-top: 1px solid #eee;
207
+ display: flex;
208
+ justify-content: center;
209
+ }
210
+
211
+ ::v-deep(.q-table thead) {
212
+ background: #f2f7fb;
213
+ }
214
+
215
+ ::v-deep(.q-table th) {
216
+ font-family: NunitoSansFont, sans-serif;
217
+ color: #a4b4cf;
218
+ font-size: 15px;
219
+ font-style: normal;
220
+ font-weight: 700;
221
+ line-height: 20px;
222
+ height: 61px;
223
+ }
224
+
225
+ ::v-deep(.q-table tbody td) {
226
+ height: 61px;
227
+ font-size: 14px;
228
+ }
229
+
230
+ ::v-deep(.q-table tbody) {
231
+ font-family: NunitoSansFont, sans-serif;
232
+ border-color: #d7e0ef;
233
+ color: #1d425d;
234
+ line-height: 20px;
235
+ font-size: 14px;
236
+ }
237
+
238
+ ::v-deep(.q-table tbody tr:last-child td) {
239
+ border-bottom: 1px solid #d7e0ef;
240
+ }
241
+ </style>