bfg-common 1.5.748 → 1.5.749

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 (106) hide show
  1. package/CODE_STYLE.md +109 -109
  2. package/assets/img/icons/icons-sprite-dark-3.svg +227 -227
  3. package/assets/img/icons/icons-sprite-dark-5.svg +488 -488
  4. package/assets/img/icons/icons-sprite-light-3.svg +227 -227
  5. package/assets/img/icons/icons-sprite-light-5.svg +488 -488
  6. package/components/atoms/TheIcon3.vue +50 -50
  7. package/components/atoms/collapse/CollapseNav.vue +170 -170
  8. package/components/atoms/perPage/PerPage.vue +58 -58
  9. package/components/atoms/table/dataGrid/DataGridPagination.vue +97 -97
  10. package/components/atoms/table/dataGrid/lib/config/settingsTable.ts +94 -94
  11. package/components/atoms/table/dataGrid/lib/utils/export.ts +16 -16
  12. package/components/common/backup/storage/actions/add/lib/utils.ts +51 -51
  13. package/components/common/browse/blocks/contents/filesNew/Skeleton.vue +18 -18
  14. package/components/common/browse/blocks/lib/models/types.ts +1 -1
  15. package/components/common/browse/lib/models/interfaces.ts +5 -5
  16. package/components/common/diagramMain/Header.vue +4 -0
  17. package/components/common/diagramMain/network/Contents.vue +497 -497
  18. package/components/common/layout/console/Console.vue +70 -70
  19. package/components/common/layout/theHeader/userMenu/modals/preferences/lib/models/types.ts +7 -7
  20. package/components/common/pages/backups/DetailView.vue +52 -52
  21. package/components/common/pages/backups/lib/models/interfaces.ts +36 -36
  22. package/components/common/pages/backups/modals/Modals.vue +243 -243
  23. package/components/common/pages/backups/modals/createBackup/configuration/maxBandwidth/lib/config/options.ts +6 -6
  24. package/components/common/pages/backups/modals/createBackup/lib/config/readyToCompleteOptions.ts +69 -69
  25. package/components/common/pages/backups/modals/lib/config/restore.ts +116 -116
  26. package/components/common/pages/backups/modals/lib/models/interfaces.ts +187 -187
  27. package/components/common/pages/backups/modals/restore/Restore.vue +302 -302
  28. package/components/common/pages/backups/modals/restore/disks/Disks.vue +50 -50
  29. package/components/common/pages/backups/modals/restore/lib/config/readyToCompleteOptions.ts +94 -94
  30. package/components/common/pages/backups/modals/restore/lib/config/steps.ts +130 -130
  31. package/components/common/pages/backups/modals/restore/name/lib/models/interfaces.ts +6 -6
  32. package/components/common/pages/backups/modals/restore/types/New.vue +95 -95
  33. package/components/common/pages/backups/modals/restore/types/Old.vue +62 -62
  34. package/components/common/pages/backups/modals/restore/types/Types.vue +31 -31
  35. package/components/common/pages/home/lib/models/interfaces.ts +48 -48
  36. package/components/common/pages/home/widgets/hosts/Hosts.vue +27 -27
  37. package/components/common/pages/home/widgets/hosts/lib/config/items.ts +23 -23
  38. package/components/common/pages/home/widgets/vms/VmsOld.vue +35 -35
  39. package/components/common/pages/home/widgets/vms/lib/config/items.ts +19 -19
  40. package/components/common/pages/scheduledTasks/lib/utils/utils.ts +84 -84
  41. package/components/common/pages/tasks/Tasks.vue +125 -125
  42. package/components/common/pages/tasks/table/Table.vue +373 -373
  43. package/components/common/pages/tasks/table/lib/config/config.ts +279 -279
  44. package/components/common/pages/tasks/table/lib/models/interfaces.ts +9 -9
  45. package/components/common/readyToComplete/ReadyToComplete.vue +17 -17
  46. package/components/common/select/radio/RadioGroup.vue +137 -137
  47. package/components/common/spiceConsole/Drawer.vue +420 -420
  48. package/components/common/spiceConsole/SpiceConsole.vue +184 -184
  49. package/components/common/spiceConsole/lib/models/interfaces.ts +5 -5
  50. package/components/common/tools/Actions.vue +207 -207
  51. package/components/common/treeView/TreeView.vue +52 -52
  52. package/components/common/vm/actions/clone/lib/config/steps.ts +295 -295
  53. package/components/common/vm/actions/clone/new/New.vue +438 -438
  54. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/shares/lib/config/options.ts +28 -28
  55. package/components/common/vm/actions/common/customizeHardware/virtualHardware/memory/Memory.vue +283 -283
  56. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/order/Order.vue +156 -156
  57. package/components/common/vm/actions/common/select/compatibility/Old.vue +107 -107
  58. package/components/common/vm/actions/common/select/createType/lib/models/interfaces.ts +5 -5
  59. package/components/common/vm/actions/common/select/options/New.vue +264 -264
  60. package/components/common/vm/actions/common/select/options/Options.vue +58 -58
  61. package/components/common/vm/actions/common/select/storage/Old.vue +125 -125
  62. package/components/common/vm/actions/common/select/storage/new/New.vue +311 -311
  63. package/components/common/vm/actions/common/select/storage/new/lib/models/interfaces.ts +5 -5
  64. package/components/common/vm/actions/common/select/storage/new/lib/utils/utils.ts +21 -21
  65. package/components/common/vm/actions/common/select/template/old/Old.vue +50 -50
  66. package/components/common/vm/actions/editSettings/new/Skeleton.vue +88 -88
  67. package/components/common/wizards/common/compatibility/Compatibility.vue +35 -35
  68. package/components/common/wizards/common/steps/computeResource/New.vue +93 -93
  69. package/components/common/wizards/common/steps/name/Name.vue +178 -178
  70. package/components/common/wizards/common/steps/name/New.vue +221 -221
  71. package/components/common/wizards/common/steps/name/Old.vue +121 -121
  72. package/components/common/wizards/common/steps/name/lib/models/interfaces.ts +4 -4
  73. package/components/common/wizards/common/steps/name/location/New.vue +40 -40
  74. package/components/common/wizards/datastore/add/Add.vue +227 -227
  75. package/components/common/wizards/datastore/add/lib/utils.ts +85 -85
  76. package/components/common/wizards/datastore/add/steps/typeMode/lib/config/typeOptions.ts +43 -43
  77. package/components/common/wizards/network/add/Add.vue +25 -5
  78. package/components/common/wizards/network/add/lib/config/config.ts +1 -1
  79. package/components/common/wizards/network/add/lib/config/initialData.ts +5 -3
  80. package/components/common/wizards/network/add/lib/config/selectConnectionTypeStep.ts +1 -0
  81. package/components/common/wizards/network/add/steps/selectTargetDevice/SelectTargetDeviceNew.vue +2 -1
  82. package/components/common/wizards/network/add/steps/selectTargetDevice/SelectTargetDeviceOld.vue +18 -6
  83. package/composables/useAppVersion.ts +21 -21
  84. package/composables/useBrowse.ts +24 -24
  85. package/composables/useLocal.ts +6 -6
  86. package/composables/useLocalCommon.ts +39 -39
  87. package/lib/models/types.ts +59 -59
  88. package/package.json +1 -1
  89. package/plugins/console.ts +21 -21
  90. package/plugins/mouse.ts +21 -21
  91. package/plugins/panelStates.ts +70 -70
  92. package/plugins/text.ts +59 -59
  93. package/plugins/time.ts +58 -58
  94. package/public/spice-console/application/clientgui.js +854 -854
  95. package/public/spice-console/application/packetfactory.js +211 -211
  96. package/public/spice-console/application/virtualmouse.js +147 -147
  97. package/public/spice-console/lib/images/bitmap.js +203 -203
  98. package/public/spice-console/network/spicechannel.js +440 -440
  99. package/public/spice-console/process/cursorprocess.js +128 -128
  100. package/public/spice-console/process/inputprocess.js +227 -227
  101. package/public/spice-console/process/mainprocess.js +212 -212
  102. package/public/spice-console/run.js +210 -210
  103. package/store/main/mutations.ts +7 -7
  104. package/store/main/state.ts +7 -7
  105. package/store/tasks/mappers/recentTasks.ts +123 -123
  106. package/store/tasks/mutations.ts +82 -82
@@ -1,20 +1,20 @@
1
- import type {UI_I_Card, UI_I_Vms} from "~/components/common/pages/home/lib/models/interfaces";
2
-
3
- export const itemsFunc = (vms: UI_I_Vms): UI_I_Card[] => [
4
- {
5
- value: vms.powered_on,
6
- text: 'powered_on',
7
- icon: 'vsphere-icon-vm-on',
8
- },
9
- {
10
- value: vms.powered_off,
11
- text: 'powered_off',
12
- icon: 'icon-vm-power-off',
13
- },
14
-
15
- {
16
- value: vms.suspended,
17
- text: 'suspended',
18
- icon: 'vsphere-icon-vm-suspended',
19
- },
1
+ import type {UI_I_Card, UI_I_Vms} from "~/components/common/pages/home/lib/models/interfaces";
2
+
3
+ export const itemsFunc = (vms: UI_I_Vms): UI_I_Card[] => [
4
+ {
5
+ value: vms.powered_on,
6
+ text: 'powered_on',
7
+ icon: 'vsphere-icon-vm-on',
8
+ },
9
+ {
10
+ value: vms.powered_off,
11
+ text: 'powered_off',
12
+ icon: 'icon-vm-power-off',
13
+ },
14
+
15
+ {
16
+ value: vms.suspended,
17
+ text: 'suspended',
18
+ icon: 'vsphere-icon-vm-suspended',
19
+ },
20
20
  ]
@@ -1,84 +1,84 @@
1
- import type { UI_T_Project } from '~/lib/models/types'
2
- import type {
3
- UI_I_Localization,
4
- UI_I_SendTaskParams,
5
- } from '~/lib/models/interfaces'
6
- import type { UI_I_ScheduleNewTasksForm } from '~/components/common/pages/scheduledTasks/modals/lib/models/interfaces'
7
- import { base64 } from '~/lib/utils/base64'
8
- import type {
9
- UI_I_CreateScheduledTaskArgs,
10
- UI_I_ScheduledTasksTableItem,
11
- } from '~/components/common/pages/scheduledTasks/lib/models/interfaces'
12
- import type { UI_T_ScheduledTasksActionsType } from '~/components/common/pages/scheduledTasks/lib/models/types'
13
-
14
- export const defineScheduleTaskModalTitle = (
15
- type: UI_T_ScheduledTasksActionsType,
16
- isEdit: boolean
17
- ): string => {
18
- const localization: UI_I_Localization = useLocal()
19
- const { scheduleNewTasks, scheduleTaskEdit } = localization.common
20
-
21
- const typeTitleMap: Partial<Record<UI_T_ScheduledTasksActionsType, string>> =
22
- {
23
- 'power-on': localization.common.powerOn,
24
- 'power-off': localization.common.powerOff,
25
- 'shut-down-guest-os': localization.common.shutDownGuestOs,
26
- 'restart-guest-os': localization.common.restartGuestOs,
27
- suspend: localization.common.suspend,
28
- reset: localization.common.reset,
29
- 'take-snapshot': localization.common.takeSnapshot,
30
- }
31
-
32
- const title = typeTitleMap[type]
33
- const modalMode = isEdit ? scheduleTaskEdit : scheduleNewTasks
34
-
35
- return `${modalMode} (${title})`
36
- }
37
- export const scheduledTasks = (
38
- form: UI_I_ScheduleNewTasksForm,
39
- args: UI_I_SendTaskParams,
40
- target: string,
41
- isEdit: boolean,
42
- data: UI_I_ScheduledTasksTableItem,
43
- project: UI_T_Project
44
- ): UI_I_SendTaskParams => {
45
- const methodArgs = {
46
- method: args.method,
47
- params: {
48
- target: args.target,
49
- args: args.args ? base64.encode(args.args) : '',
50
- },
51
- }
52
-
53
- let method = ''
54
- switch (project) {
55
- case 'sphere':
56
- method = isEdit
57
- ? 'VirtualMachines.UpdateScheduledTask'
58
- : 'VirtualMachines.CreateScheduledTask'
59
- break
60
- case 'procurator':
61
- method = isEdit ? 'vm.update_sched_task' : 'vm.create_sched_task'
62
- break
63
- }
64
-
65
- const taskArgs: UI_I_CreateScheduledTaskArgs = {
66
- target,
67
- name: form.task_name,
68
- description: form.description,
69
- toggle: form.toggle,
70
- cron_2: form.cron,
71
- notify_emails: form.ntfn_target,
72
- args: base64.encode(methodArgs),
73
- ...(isEdit && {
74
- rid: data.rid,
75
- last_modified: data.last_modified,
76
- }),
77
- }
78
-
79
- return {
80
- method,
81
- target,
82
- args: taskArgs,
83
- }
84
- }
1
+ import type { UI_T_Project } from '~/lib/models/types'
2
+ import type {
3
+ UI_I_Localization,
4
+ UI_I_SendTaskParams,
5
+ } from '~/lib/models/interfaces'
6
+ import type { UI_I_ScheduleNewTasksForm } from '~/components/common/pages/scheduledTasks/modals/lib/models/interfaces'
7
+ import { base64 } from '~/lib/utils/base64'
8
+ import type {
9
+ UI_I_CreateScheduledTaskArgs,
10
+ UI_I_ScheduledTasksTableItem,
11
+ } from '~/components/common/pages/scheduledTasks/lib/models/interfaces'
12
+ import type { UI_T_ScheduledTasksActionsType } from '~/components/common/pages/scheduledTasks/lib/models/types'
13
+
14
+ export const defineScheduleTaskModalTitle = (
15
+ type: UI_T_ScheduledTasksActionsType,
16
+ isEdit: boolean
17
+ ): string => {
18
+ const localization: UI_I_Localization = useLocal()
19
+ const { scheduleNewTasks, scheduleTaskEdit } = localization.common
20
+
21
+ const typeTitleMap: Partial<Record<UI_T_ScheduledTasksActionsType, string>> =
22
+ {
23
+ 'power-on': localization.common.powerOn,
24
+ 'power-off': localization.common.powerOff,
25
+ 'shut-down-guest-os': localization.common.shutDownGuestOs,
26
+ 'restart-guest-os': localization.common.restartGuestOs,
27
+ suspend: localization.common.suspend,
28
+ reset: localization.common.reset,
29
+ 'take-snapshot': localization.common.takeSnapshot,
30
+ }
31
+
32
+ const title = typeTitleMap[type]
33
+ const modalMode = isEdit ? scheduleTaskEdit : scheduleNewTasks
34
+
35
+ return `${modalMode} (${title})`
36
+ }
37
+ export const scheduledTasks = (
38
+ form: UI_I_ScheduleNewTasksForm,
39
+ args: UI_I_SendTaskParams,
40
+ target: string,
41
+ isEdit: boolean,
42
+ data: UI_I_ScheduledTasksTableItem,
43
+ project: UI_T_Project
44
+ ): UI_I_SendTaskParams => {
45
+ const methodArgs = {
46
+ method: args.method,
47
+ params: {
48
+ target: args.target,
49
+ args: args.args ? base64.encode(args.args) : '',
50
+ },
51
+ }
52
+
53
+ let method = ''
54
+ switch (project) {
55
+ case 'sphere':
56
+ method = isEdit
57
+ ? 'VirtualMachines.UpdateScheduledTask'
58
+ : 'VirtualMachines.CreateScheduledTask'
59
+ break
60
+ case 'procurator':
61
+ method = isEdit ? 'vm.update_sched_task' : 'vm.create_sched_task'
62
+ break
63
+ }
64
+
65
+ const taskArgs: UI_I_CreateScheduledTaskArgs = {
66
+ target,
67
+ name: form.task_name,
68
+ description: form.description,
69
+ toggle: form.toggle,
70
+ cron_2: form.cron,
71
+ notify_emails: form.ntfn_target,
72
+ args: base64.encode(methodArgs),
73
+ ...(isEdit && {
74
+ rid: data.rid,
75
+ last_modified: data.last_modified,
76
+ }),
77
+ }
78
+
79
+ return {
80
+ method,
81
+ target,
82
+ args: taskArgs,
83
+ }
84
+ }
@@ -1,125 +1,125 @@
1
- <template>
2
- <div class="tasks table-container-tasks-table flex flex-col">
3
- <div class="tasks__headline">
4
- {{ localization.mainNavigation.tasks }}
5
- </div>
6
-
7
- <common-pages-tasks-table
8
- :table-data="tasksList?.items || []"
9
- :total-pages="tasksList?.total_pages || 1"
10
- :total-items="tasksList?.total_items || 0"
11
- :loading="isLoading"
12
- :project="props.project"
13
- :config="props.config"
14
- @pagination="onUpdatePagination"
15
- @sort="onSortTable"
16
- @col-search="onColSearching"
17
- />
18
- </div>
19
- </template>
20
-
21
- <script lang="ts" setup>
22
- import { useOnline } from '@vueuse/core'
23
- import type { UI_I_Localization } from '~/lib/models/interfaces'
24
- import type {
25
- UI_I_Pagination,
26
- UI_I_DataTableQuery,
27
- } from '~/lib/models/table/interfaces'
28
- import type { UI_I_Task } from '~/lib/models/store/tasks/interfaces'
29
- import type { UI_T_Project } from '~/lib/models/types'
30
- import type { UI_I_TaskConfig } from '~/components/common/pages/tasks/table/lib/models/interfaces'
31
-
32
- const props = defineProps<{
33
- project: UI_T_Project
34
- config: UI_I_TaskConfig
35
- }>()
36
-
37
- const localization = computed<UI_I_Localization>(() => useLocal())
38
- const { $store }: any = useNuxtApp()
39
-
40
- const pagination = ref<UI_I_Pagination>({
41
- page: 1,
42
- pageSize: 100,
43
- })
44
- const sort = ref<string | null>(null)
45
- const filter = ref<string | null>(null)
46
- const pauseGlobalRefresh = (): void => {
47
- const tasksLastRequestType = $store.getters['tasks/getTasksLastRequestType']
48
- $store.dispatch('main/A_PAUSE_GLOBAL_REFRESH', tasksLastRequestType)
49
- }
50
-
51
- const tasksList = computed<UI_I_Task>(() => $store.getters['tasks/getTaskList'])
52
-
53
- const getTasks = async (): Promise<void> => {
54
- pauseGlobalRefresh()
55
-
56
- const payload: UI_I_DataTableQuery = {
57
- ...pagination.value,
58
- sortBy: sort.value || '',
59
- filter: filter.value || '',
60
- }
61
- await $store.dispatch('tasks/A_GET_TASKS', payload)
62
- }
63
- const onUpdatePagination = (event: UI_I_Pagination): void => {
64
- pagination.value = event
65
- getTasks()
66
- }
67
- const onSortTable = (event: string): void => {
68
- sort.value = event
69
- getTasks()
70
- }
71
- const onColSearching = (value: string): void => {
72
- filter.value = value
73
- getTasks()
74
- }
75
-
76
- const isLoading = computed<boolean>(() =>
77
- $store.getters['tasks/getLoading']('tasks')
78
- )
79
-
80
- const isOnline = useOnline()
81
- watch(isOnline, (newValue: boolean) => {
82
- if (newValue) {
83
- getTasks()
84
- }
85
- })
86
-
87
- onUnmounted(() => {
88
- pauseGlobalRefresh()
89
- })
90
- </script>
91
-
92
- <style lang="scss" scoped>
93
- .tasks {
94
- height: inherit;
95
- background-color: var(--background-color);
96
- padding: 10px 16px 16px;
97
-
98
- &__headline {
99
- font-family: 'Inter', sans-serif;
100
- font-weight: 400;
101
- font-size: 22px;
102
- line-height: 26.63px;
103
- color: var(--title-form-first-color);
104
- margin-bottom: 22px;
105
- }
106
-
107
- //:deep(.data-table-header) {
108
- // z-index: var(--z-sticky) !important; // TODO надо удалить потом (clr style)
109
- //}
110
- }
111
-
112
- :deep(.table-container) {
113
- grid-template-rows: min-content auto min-content;
114
- }
115
-
116
- :deep(.data-table-skeleton) {
117
- height: inherit;
118
- display: flex;
119
- flex-direction: column;
120
-
121
- .footer-row {
122
- margin-top: auto;
123
- }
124
- }
125
- </style>
1
+ <template>
2
+ <div class="tasks table-container-tasks-table flex flex-col">
3
+ <div class="tasks__headline">
4
+ {{ localization.mainNavigation.tasks }}
5
+ </div>
6
+
7
+ <common-pages-tasks-table
8
+ :table-data="tasksList?.items || []"
9
+ :total-pages="tasksList?.total_pages || 1"
10
+ :total-items="tasksList?.total_items || 0"
11
+ :loading="isLoading"
12
+ :project="props.project"
13
+ :config="props.config"
14
+ @pagination="onUpdatePagination"
15
+ @sort="onSortTable"
16
+ @col-search="onColSearching"
17
+ />
18
+ </div>
19
+ </template>
20
+
21
+ <script lang="ts" setup>
22
+ import { useOnline } from '@vueuse/core'
23
+ import type { UI_I_Localization } from '~/lib/models/interfaces'
24
+ import type {
25
+ UI_I_Pagination,
26
+ UI_I_DataTableQuery,
27
+ } from '~/lib/models/table/interfaces'
28
+ import type { UI_I_Task } from '~/lib/models/store/tasks/interfaces'
29
+ import type { UI_T_Project } from '~/lib/models/types'
30
+ import type { UI_I_TaskConfig } from '~/components/common/pages/tasks/table/lib/models/interfaces'
31
+
32
+ const props = defineProps<{
33
+ project: UI_T_Project
34
+ config: UI_I_TaskConfig
35
+ }>()
36
+
37
+ const localization = computed<UI_I_Localization>(() => useLocal())
38
+ const { $store }: any = useNuxtApp()
39
+
40
+ const pagination = ref<UI_I_Pagination>({
41
+ page: 1,
42
+ pageSize: 100,
43
+ })
44
+ const sort = ref<string | null>(null)
45
+ const filter = ref<string | null>(null)
46
+ const pauseGlobalRefresh = (): void => {
47
+ const tasksLastRequestType = $store.getters['tasks/getTasksLastRequestType']
48
+ $store.dispatch('main/A_PAUSE_GLOBAL_REFRESH', tasksLastRequestType)
49
+ }
50
+
51
+ const tasksList = computed<UI_I_Task>(() => $store.getters['tasks/getTaskList'])
52
+
53
+ const getTasks = async (): Promise<void> => {
54
+ pauseGlobalRefresh()
55
+
56
+ const payload: UI_I_DataTableQuery = {
57
+ ...pagination.value,
58
+ sortBy: sort.value || '',
59
+ filter: filter.value || '',
60
+ }
61
+ await $store.dispatch('tasks/A_GET_TASKS', payload)
62
+ }
63
+ const onUpdatePagination = (event: UI_I_Pagination): void => {
64
+ pagination.value = event
65
+ getTasks()
66
+ }
67
+ const onSortTable = (event: string): void => {
68
+ sort.value = event
69
+ getTasks()
70
+ }
71
+ const onColSearching = (value: string): void => {
72
+ filter.value = value
73
+ getTasks()
74
+ }
75
+
76
+ const isLoading = computed<boolean>(() =>
77
+ $store.getters['tasks/getLoading']('tasks')
78
+ )
79
+
80
+ const isOnline = useOnline()
81
+ watch(isOnline, (newValue: boolean) => {
82
+ if (newValue) {
83
+ getTasks()
84
+ }
85
+ })
86
+
87
+ onUnmounted(() => {
88
+ pauseGlobalRefresh()
89
+ })
90
+ </script>
91
+
92
+ <style lang="scss" scoped>
93
+ .tasks {
94
+ height: inherit;
95
+ background-color: var(--background-color);
96
+ padding: 10px 16px 16px;
97
+
98
+ &__headline {
99
+ font-family: 'Inter', sans-serif;
100
+ font-weight: 400;
101
+ font-size: 22px;
102
+ line-height: 26.63px;
103
+ color: var(--title-form-first-color);
104
+ margin-bottom: 22px;
105
+ }
106
+
107
+ //:deep(.data-table-header) {
108
+ // z-index: var(--z-sticky) !important; // TODO надо удалить потом (clr style)
109
+ //}
110
+ }
111
+
112
+ :deep(.table-container) {
113
+ grid-template-rows: min-content auto min-content;
114
+ }
115
+
116
+ :deep(.data-table-skeleton) {
117
+ height: inherit;
118
+ display: flex;
119
+ flex-direction: column;
120
+
121
+ .footer-row {
122
+ margin-top: auto;
123
+ }
124
+ }
125
+ </style>