shared-ritm 1.2.66 → 1.2.68

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