shared-ritm 1.3.38 → 1.3.40
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/dist/index.css +1 -1
- package/dist/shared-ritm.es.js +16 -10
- package/dist/shared-ritm.umd.js +150 -150
- package/dist/types/api/services/AuthService.d.ts +1 -0
- package/package.json +70 -64
- package/src/App.vue +2461 -2461
- package/src/api/services/AuthService.ts +10 -3
- package/src/api/services/ControlsService.ts +96 -96
- package/src/api/services/EquipmentService.ts +29 -29
- package/src/api/services/GanttService.ts +23 -23
- package/src/api/services/MetricsService.ts +123 -123
- package/src/api/services/RepairsService.ts +111 -111
- package/src/api/services/TasksService.ts +157 -157
- package/src/api/services/UserService.ts +123 -123
- package/src/api/services/VideoService.ts +118 -118
- package/src/api/types/Api_Metrics.ts +5 -5
- package/src/api/types/Api_Repairs.ts +186 -186
- package/src/api/types/Api_Tasks.ts +376 -376
- package/src/api/types/Api_Video.ts +244 -244
- package/src/common/app-button/Button.stories.ts +369 -0
- package/src/common/app-checkbox/Checkbox.stories.ts +60 -0
- package/src/common/app-date-picker/DatePicker.stories.ts +66 -0
- package/src/common/app-datepicker/Datepicker.stories.ts +145 -0
- package/src/common/app-dialogs/AppConfirmDialog.vue +109 -109
- package/src/common/app-dialogs/Confirm.stories.ts +93 -0
- package/src/common/app-dropdown/Dropdown.stories.ts +94 -0
- package/src/common/app-file/File.stories.ts +104 -0
- package/src/common/app-icon/AppIcon.vue +108 -108
- package/src/common/app-icon/Icon.stories.ts +91 -0
- package/src/common/app-input/Input.stories.ts +160 -0
- package/src/common/app-input-new/InputNew.stories.ts +240 -0
- package/src/common/app-input-search/InputSearch.stories.ts +149 -0
- package/src/common/app-layout/components/AppLayoutHeader.vue +289 -273
- package/src/common/app-loader/Loader.stories.ts +114 -0
- package/src/common/app-select/AppSelect.vue +159 -159
- package/src/common/app-select/Select.stories.ts +155 -0
- package/src/common/app-sidebar/AppSidebar.vue +174 -174
- package/src/common/app-table/AppTable.vue +313 -313
- package/src/common/app-table/components/ModalSelect.stories.ts +323 -0
- package/src/common/app-table/components/ModalSelect.vue +302 -302
- package/src/common/app-table/components/TableModal.vue +367 -367
- package/src/common/app-table/controllers/useColumnSelector.ts +45 -45
- package/src/common/app-table/controllers/useTableModel.ts +97 -102
- package/src/common/app-toggle/Toggle.stories.ts +69 -0
- package/src/common/app-wrapper/AppWrapper.vue +31 -28
- package/src/configs/storybook.ts +14 -0
- package/src/index.ts +131 -131
- package/src/shared/styles/general.css +140 -124
- package/src/styles/variables.sass +12 -12
- package/src/utils/helpers.ts +59 -59
- package/dist/types/api/services/PhotoService.d.ts +0 -40
- package/dist/types/stories/Button.stories.d.ts +0 -13
- package/dist/types/stories/Checkbox.stories.d.ts +0 -7
- package/dist/types/stories/Confirm.stories.d.ts +0 -8
- package/dist/types/stories/DatePicker.stories.d.ts +0 -8
- package/dist/types/stories/Dropdown.stories.d.ts +0 -8
- package/dist/types/stories/File.stories.d.ts +0 -8
- package/dist/types/stories/Icon.stories.d.ts +0 -7
- package/dist/types/stories/Input.stories.d.ts +0 -11
- package/dist/types/stories/InputNew.stories.d.ts +0 -12
- package/dist/types/stories/InputSearch.stories.d.ts +0 -10
- package/dist/types/stories/Loader.stories.d.ts +0 -8
- package/dist/types/stories/Select.stories.d.ts +0 -7
- package/dist/types/stories/Toggle.stories.d.ts +0 -8
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
import { computed, ref } from 'vue'
|
|
2
|
-
|
|
3
|
-
export interface ColumnConfig {
|
|
4
|
-
name: string
|
|
5
|
-
label: string
|
|
6
|
-
[key: string]: any
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function useColumnSelector(allColumns: ColumnConfig[], fixedColumnNames: string[] = []) {
|
|
10
|
-
const selectedColumnNames = ref<string[]>([...new Set([...fixedColumnNames, ...allColumns.map(col => col.name)])])
|
|
11
|
-
|
|
12
|
-
const visibleColumns = computed(() => allColumns.filter(col => selectedColumnNames.value.includes(col.name)))
|
|
13
|
-
|
|
14
|
-
function openColumnSelectorDialog($q: any) {
|
|
15
|
-
$q.dialog({
|
|
16
|
-
title: 'Выберите колонки',
|
|
17
|
-
options: {
|
|
18
|
-
type: 'checkbox',
|
|
19
|
-
model: [...selectedColumnNames.value],
|
|
20
|
-
items: allColumns.map(col => ({
|
|
21
|
-
label: col.label,
|
|
22
|
-
value: col.name,
|
|
23
|
-
disable: fixedColumnNames.includes(col.name),
|
|
24
|
-
})),
|
|
25
|
-
},
|
|
26
|
-
cancel: {
|
|
27
|
-
label: 'Отмена',
|
|
28
|
-
'data-test': 'cancel-button',
|
|
29
|
-
},
|
|
30
|
-
ok: {
|
|
31
|
-
label: 'Ок',
|
|
32
|
-
'data-test': 'ok-button',
|
|
33
|
-
},
|
|
34
|
-
persistent: true,
|
|
35
|
-
}).onOk((val: string[]) => {
|
|
36
|
-
selectedColumnNames.value = Array.from(new Set([...val, ...fixedColumnNames]))
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
selectedColumnNames,
|
|
42
|
-
visibleColumns,
|
|
43
|
-
openColumnSelectorDialog,
|
|
44
|
-
}
|
|
45
|
-
}
|
|
1
|
+
import { computed, ref } from 'vue'
|
|
2
|
+
|
|
3
|
+
export interface ColumnConfig {
|
|
4
|
+
name: string
|
|
5
|
+
label: string
|
|
6
|
+
[key: string]: any
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function useColumnSelector(allColumns: ColumnConfig[], fixedColumnNames: string[] = []) {
|
|
10
|
+
const selectedColumnNames = ref<string[]>([...new Set([...fixedColumnNames, ...allColumns.map(col => col.name)])])
|
|
11
|
+
|
|
12
|
+
const visibleColumns = computed(() => allColumns.filter(col => selectedColumnNames.value.includes(col.name)))
|
|
13
|
+
|
|
14
|
+
function openColumnSelectorDialog($q: any) {
|
|
15
|
+
$q.dialog({
|
|
16
|
+
title: 'Выберите колонки',
|
|
17
|
+
options: {
|
|
18
|
+
type: 'checkbox',
|
|
19
|
+
model: [...selectedColumnNames.value],
|
|
20
|
+
items: allColumns.map(col => ({
|
|
21
|
+
label: col.label,
|
|
22
|
+
value: col.name,
|
|
23
|
+
disable: fixedColumnNames.includes(col.name),
|
|
24
|
+
})),
|
|
25
|
+
},
|
|
26
|
+
cancel: {
|
|
27
|
+
label: 'Отмена',
|
|
28
|
+
'data-test': 'cancel-button',
|
|
29
|
+
},
|
|
30
|
+
ok: {
|
|
31
|
+
label: 'Ок',
|
|
32
|
+
'data-test': 'ok-button',
|
|
33
|
+
},
|
|
34
|
+
persistent: true,
|
|
35
|
+
}).onOk((val: string[]) => {
|
|
36
|
+
selectedColumnNames.value = Array.from(new Set([...val, ...fixedColumnNames]))
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
selectedColumnNames,
|
|
42
|
+
visibleColumns,
|
|
43
|
+
openColumnSelectorDialog,
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1,102 +1,97 @@
|
|
|
1
|
-
import { Ref, computed, ref } from 'vue'
|
|
2
|
-
|
|
3
|
-
export interface TableColumn {
|
|
4
|
-
name: string
|
|
5
|
-
label: string
|
|
6
|
-
style?: string
|
|
7
|
-
headerStyle?: string
|
|
8
|
-
field?: string | ((row: any) => any)
|
|
9
|
-
sortable?: boolean
|
|
10
|
-
filterType?: 'single' | 'multi' | null
|
|
11
|
-
align?: 'left' | 'center' | 'right'
|
|
12
|
-
badge?: {
|
|
13
|
-
true?: string
|
|
14
|
-
false?: string
|
|
15
|
-
colorTrue?: string
|
|
16
|
-
colorFalse?: string
|
|
17
|
-
}
|
|
18
|
-
format?: (val: any) => any
|
|
19
|
-
html?: boolean
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface FilterOption {
|
|
23
|
-
id: string
|
|
24
|
-
name: string
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface TableModel<T = any> {
|
|
28
|
-
columns: TableColumn[]
|
|
29
|
-
rows: T[] | Ref<T[]>
|
|
30
|
-
filtersOptions?: Ref<Record<string, FilterOption[]>>
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const useTableModel = <T = any>(model: TableModel<T>) => {
|
|
34
|
-
const columnFilters = ref<Record<string, string | string[] | undefined>>({})
|
|
35
|
-
const filterMenus = ref<Record<string, boolean>>({})
|
|
36
|
-
|
|
37
|
-
model.columns.forEach(({ name, filterType }) => {
|
|
38
|
-
if (filterType) {
|
|
39
|
-
columnFilters.value[name] = filterType === 'multi' ? [] : undefined
|
|
40
|
-
filterMenus.value[name] = false
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
const resolvedRows = computed(() => (Array.isArray(model.rows) ? model.rows : model.rows.value))
|
|
45
|
-
|
|
46
|
-
const toggleFilterValue = (colName: string, value: string) => {
|
|
47
|
-
const col = model.columns.find(c => c.name === colName)
|
|
48
|
-
if (col?.filterType === 'multi') {
|
|
49
|
-
const current = columnFilters.value[colName] as string[]
|
|
50
|
-
const index = current.indexOf(value)
|
|
51
|
-
index > -1 ? current.splice(index, 1) : current.push(value)
|
|
52
|
-
columnFilters.value[colName] = [...current]
|
|
53
|
-
} else {
|
|
54
|
-
columnFilters.value[colName] = value
|
|
55
|
-
filterMenus.value[colName] = false
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const selectedFilters = computed(() => {
|
|
60
|
-
const result: Record<string, string[]> = {}
|
|
61
|
-
for (const col of model.columns) {
|
|
62
|
-
const filter = columnFilters.value[col.name]
|
|
63
|
-
const options = model.filtersOptions?.value[col.name] || []
|
|
64
|
-
|
|
65
|
-
if (filter) {
|
|
66
|
-
let selectedIds: string[] = []
|
|
67
|
-
if (Array.isArray(filter)) {
|
|
68
|
-
selectedIds = options
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
clearFilter,
|
|
99
|
-
openFilterMenu,
|
|
100
|
-
selectedFilters,
|
|
101
|
-
}
|
|
102
|
-
}
|
|
1
|
+
import { Ref, computed, ref } from 'vue'
|
|
2
|
+
|
|
3
|
+
export interface TableColumn {
|
|
4
|
+
name: string
|
|
5
|
+
label: string
|
|
6
|
+
style?: string
|
|
7
|
+
headerStyle?: string
|
|
8
|
+
field?: string | ((row: any) => any)
|
|
9
|
+
sortable?: boolean
|
|
10
|
+
filterType?: 'single' | 'multi' | null
|
|
11
|
+
align?: 'left' | 'center' | 'right'
|
|
12
|
+
badge?: {
|
|
13
|
+
true?: string
|
|
14
|
+
false?: string
|
|
15
|
+
colorTrue?: string
|
|
16
|
+
colorFalse?: string
|
|
17
|
+
}
|
|
18
|
+
format?: (val: any) => any
|
|
19
|
+
html?: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface FilterOption {
|
|
23
|
+
id: string
|
|
24
|
+
name: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface TableModel<T = any> {
|
|
28
|
+
columns: TableColumn[]
|
|
29
|
+
rows: T[] | Ref<T[]>
|
|
30
|
+
filtersOptions?: Ref<Record<string, FilterOption[]>>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const useTableModel = <T = any>(model: TableModel<T>) => {
|
|
34
|
+
const columnFilters = ref<Record<string, string | string[] | undefined>>({})
|
|
35
|
+
const filterMenus = ref<Record<string, boolean>>({})
|
|
36
|
+
|
|
37
|
+
model.columns.forEach(({ name, filterType }) => {
|
|
38
|
+
if (filterType) {
|
|
39
|
+
columnFilters.value[name] = filterType === 'multi' ? [] : undefined
|
|
40
|
+
filterMenus.value[name] = false
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const resolvedRows = computed(() => (Array.isArray(model.rows) ? model.rows : model.rows.value))
|
|
45
|
+
|
|
46
|
+
const toggleFilterValue = (colName: string, value: string) => {
|
|
47
|
+
const col = model.columns.find(c => c.name === colName)
|
|
48
|
+
if (col?.filterType === 'multi') {
|
|
49
|
+
const current = columnFilters.value[colName] as string[]
|
|
50
|
+
const index = current.indexOf(value)
|
|
51
|
+
index > -1 ? current.splice(index, 1) : current.push(value)
|
|
52
|
+
columnFilters.value[colName] = [...current]
|
|
53
|
+
} else {
|
|
54
|
+
columnFilters.value[colName] = value
|
|
55
|
+
filterMenus.value[colName] = false
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const selectedFilters = computed(() => {
|
|
60
|
+
const result: Record<string, string[]> = {}
|
|
61
|
+
for (const col of model.columns) {
|
|
62
|
+
const filter = columnFilters.value[col.name]
|
|
63
|
+
const options = model.filtersOptions?.value[col.name] || []
|
|
64
|
+
|
|
65
|
+
if (filter) {
|
|
66
|
+
let selectedIds: string[] = []
|
|
67
|
+
if (Array.isArray(filter)) {
|
|
68
|
+
selectedIds = options.filter(opt => filter.includes(opt.name)).map(opt => opt.id)
|
|
69
|
+
} else {
|
|
70
|
+
selectedIds = options.filter(opt => opt.name === filter).map(opt => opt.id)
|
|
71
|
+
}
|
|
72
|
+
result[col.name] = Array.from(new Set(selectedIds))
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return result
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const clearFilter = (colName: string) => {
|
|
79
|
+
const col = model.columns.find(c => c.name === colName)
|
|
80
|
+
columnFilters.value[colName] = col?.filterType === 'multi' ? [] : undefined
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const openFilterMenu = (colName: string, isOpen: boolean) => {
|
|
84
|
+
filterMenus.value[colName] = isOpen
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
rows: resolvedRows,
|
|
89
|
+
columns: computed(() => model.columns),
|
|
90
|
+
columnFilters,
|
|
91
|
+
filterMenus,
|
|
92
|
+
toggleFilterValue,
|
|
93
|
+
clearFilter,
|
|
94
|
+
openFilterMenu,
|
|
95
|
+
selectedFilters,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import AppToggle from '@/common/app-toggle/AppToggle.vue'
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof AppToggle> = {
|
|
5
|
+
title: 'Components/AppToggle',
|
|
6
|
+
component: AppToggle,
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
argTypes: {
|
|
9
|
+
modelValue: {
|
|
10
|
+
control: 'boolean',
|
|
11
|
+
},
|
|
12
|
+
disable: {
|
|
13
|
+
control: 'boolean',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
args: {
|
|
17
|
+
modelValue: false,
|
|
18
|
+
disable: false,
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default meta
|
|
23
|
+
|
|
24
|
+
type Story = StoryObj<typeof AppToggle>
|
|
25
|
+
|
|
26
|
+
export const Default: Story = {}
|
|
27
|
+
|
|
28
|
+
export const States: Story = {
|
|
29
|
+
render: () => ({
|
|
30
|
+
components: { AppToggle },
|
|
31
|
+
template: `
|
|
32
|
+
<div style="display: flex; flex-direction: column; gap: 12px;">
|
|
33
|
+
<label style="display: flex; align-items: center; gap: 12px;">
|
|
34
|
+
<AppToggle :model-value="true" />
|
|
35
|
+
Включён
|
|
36
|
+
</label>
|
|
37
|
+
<label style="display: flex; align-items: center; gap: 12px;">
|
|
38
|
+
<AppToggle :model-value="false" />
|
|
39
|
+
Выключен
|
|
40
|
+
</label>
|
|
41
|
+
<label style="display: flex; align-items: center; gap: 12px; opacity: 0.6;">
|
|
42
|
+
<AppToggle :model-value="true" :disable="true" />
|
|
43
|
+
Включён + отключён
|
|
44
|
+
</label>
|
|
45
|
+
<label style="display: flex; align-items: center; gap: 12px; opacity: 0.6;">
|
|
46
|
+
<AppToggle :model-value="false" :disable="true" />
|
|
47
|
+
Выключен + отключён
|
|
48
|
+
</label>
|
|
49
|
+
</div>
|
|
50
|
+
`,
|
|
51
|
+
}),
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const WithBinding: Story = {
|
|
55
|
+
render: () => ({
|
|
56
|
+
components: { AppToggle },
|
|
57
|
+
template: `
|
|
58
|
+
<div style="display: flex; align-items: center; gap: 16px;">
|
|
59
|
+
<AppToggle v-model="toggleState" />
|
|
60
|
+
<span>Значение: {{ toggleState ? 'включено' : 'выключено' }}</span>
|
|
61
|
+
</div>
|
|
62
|
+
`,
|
|
63
|
+
data() {
|
|
64
|
+
return {
|
|
65
|
+
toggleState: true,
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
}),
|
|
69
|
+
}
|
|
@@ -1,28 +1,31 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="app-wrapper">
|
|
3
|
-
<slot />
|
|
4
|
-
</div>
|
|
5
|
-
</template>
|
|
6
|
-
<script setup lang="ts"></script>
|
|
7
|
-
<style scoped lang="scss">
|
|
8
|
-
.app-wrapper {
|
|
9
|
-
width: 100%;
|
|
10
|
-
height: 100%;
|
|
11
|
-
margin: 20px 0 12px 0;
|
|
12
|
-
padding: 30px;
|
|
13
|
-
border-radius: 8px;
|
|
14
|
-
background: #fff;
|
|
15
|
-
outline: 4px solid #598dd5;
|
|
16
|
-
outline-offset: -3px;
|
|
17
|
-
box-shadow:
|
|
18
|
-
0px
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
<template>
|
|
2
|
+
<div class="app-wrapper">
|
|
3
|
+
<slot />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
<script setup lang="ts"></script>
|
|
7
|
+
<style scoped lang="scss">
|
|
8
|
+
.app-wrapper {
|
|
9
|
+
width: 100%;
|
|
10
|
+
height: 100%;
|
|
11
|
+
margin: 20px 0 12px 0;
|
|
12
|
+
padding: 30px;
|
|
13
|
+
border-radius: 8px;
|
|
14
|
+
background: #fff;
|
|
15
|
+
outline: 4px solid #598dd5;
|
|
16
|
+
outline-offset: -3px;
|
|
17
|
+
box-shadow:
|
|
18
|
+
0px 4px 4px 0px rgba(0, 0, 0, 0.25),
|
|
19
|
+
0px 4px 4px 0px #c4d7f1 inset,
|
|
20
|
+
0px 0px 6.4px 3px rgba(31, 82, 159, 0.5),
|
|
21
|
+
0px 6px 58px 0px rgba(0, 49, 122, 0.1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@media (max-width: 1440px) {
|
|
25
|
+
.app-wrapper {
|
|
26
|
+
margin: 10px 0;
|
|
27
|
+
padding: 14px;
|
|
28
|
+
border-radius: 8px;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
</style>
|