@vc-shell/framework 1.0.169 → 1.0.171

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 (82) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/core/composables/useNotifications/index.ts +12 -5
  3. package/core/types/index.ts +2 -2
  4. package/dist/core/composables/useNotifications/index.d.ts.map +1 -1
  5. package/dist/core/types/index.d.ts +2 -2
  6. package/dist/core/types/index.d.ts.map +1 -1
  7. package/dist/framework.js +20534 -19207
  8. package/dist/index.css +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/shared/components/change-password/change-password.vue.d.ts.map +1 -1
  11. package/dist/shared/components/common/popup/vc-popup-error.vue.d.ts +29 -0
  12. package/dist/shared/components/common/popup/vc-popup-error.vue.d.ts.map +1 -0
  13. package/dist/shared/components/common/popup/vc-popup-warning.vue.d.ts +32 -0
  14. package/dist/shared/components/common/popup/vc-popup-warning.vue.d.ts.map +1 -0
  15. package/dist/shared/components/popup-handler/composables/usePopup/index.d.ts.map +1 -1
  16. package/dist/shared/components/user-dropdown-button/index.d.ts +4 -4
  17. package/dist/shared/components/user-dropdown-button/user-dropdown-button.vue.d.ts.map +1 -1
  18. package/dist/shared/modules/assets/index.d.ts.map +1 -1
  19. package/dist/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts.map +1 -1
  20. package/dist/shared/modules/assets-manager/index.d.ts.map +1 -1
  21. package/dist/shared/modules/dynamic/composables/useToolbarReducer/index.d.ts +2 -2
  22. package/dist/shared/modules/dynamic/composables/useToolbarReducer/index.d.ts.map +1 -1
  23. package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts +1 -1
  24. package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts.map +1 -1
  25. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts +3 -2
  26. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts.map +1 -1
  27. package/dist/shared/modules/dynamic/types/index.d.ts +7 -1
  28. package/dist/shared/modules/dynamic/types/index.d.ts.map +1 -1
  29. package/dist/shared/pages/LoginPage/components/login/Login.vue.d.ts.map +1 -1
  30. package/dist/tsconfig.tsbuildinfo +1 -1
  31. package/dist/ui/components/atoms/vc-container/vc-container.vue.d.ts.map +1 -1
  32. package/dist/ui/components/atoms/vc-icon/index.d.ts +1 -28
  33. package/dist/ui/components/atoms/vc-icon/index.d.ts.map +1 -1
  34. package/dist/ui/components/molecules/vc-slider/vc-slider.vue.d.ts.map +1 -1
  35. package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts +8 -8
  36. package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts.map +1 -1
  37. package/dist/ui/components/organisms/vc-gallery/_internal/vc-gallery-item/vc-gallery-item.vue.d.ts +1 -1
  38. package/dist/ui/components/organisms/vc-gallery/_internal/vc-gallery-preview/vc-gallery-preview.vue.d.ts.map +1 -1
  39. package/dist/ui/components/organisms/vc-gallery/vc-gallery.vue.d.ts +1 -1
  40. package/dist/ui/components/organisms/vc-popup/vc-popup.vue.d.ts +52 -42
  41. package/dist/ui/components/organisms/vc-popup/vc-popup.vue.d.ts.map +1 -1
  42. package/dist/ui/components/organisms/vc-table/_internal/vc-table-mobile-item/vc-table-mobile-item.vue.d.ts +11 -4
  43. package/dist/ui/components/organisms/vc-table/_internal/vc-table-mobile-item/vc-table-mobile-item.vue.d.ts.map +1 -1
  44. package/dist/ui/components/organisms/vc-table/vc-table.vue.d.ts +6 -3
  45. package/dist/ui/components/organisms/vc-table/vc-table.vue.d.ts.map +1 -1
  46. package/package.json +6 -4
  47. package/shared/components/change-password/change-password.vue +17 -11
  48. package/shared/components/common/popup/vc-popup-error.vue +44 -0
  49. package/shared/components/common/popup/vc-popup-warning.vue +47 -0
  50. package/shared/components/popup-handler/components/vc-popup-container/vc-popup-container.vue +1 -0
  51. package/shared/components/popup-handler/composables/usePopup/index.ts +7 -8
  52. package/shared/components/user-dropdown-button/user-dropdown-button.vue +1 -0
  53. package/shared/modules/assets/index.ts +1 -2
  54. package/shared/modules/assets-manager/components/assets-manager/assets-manager.vue +24 -22
  55. package/shared/modules/assets-manager/index.ts +1 -2
  56. package/shared/modules/dynamic/composables/useToolbarReducer/index.ts +2 -2
  57. package/shared/modules/dynamic/pages/dynamic-blade-form.vue +25 -3
  58. package/shared/modules/dynamic/pages/dynamic-blade-list.vue +48 -5
  59. package/shared/modules/dynamic/types/index.ts +9 -1
  60. package/shared/pages/LoginPage/components/login/Login.vue +8 -5
  61. package/ui/components/atoms/vc-container/vc-container.vue +41 -8
  62. package/ui/components/atoms/vc-icon/index.ts +1 -3
  63. package/ui/components/molecules/vc-slider/vc-slider.vue +4 -4
  64. package/ui/components/organisms/vc-blade/vc-blade.vue +4 -5
  65. package/ui/components/organisms/vc-gallery/_internal/vc-gallery-preview/vc-gallery-preview.vue +59 -45
  66. package/ui/components/organisms/vc-popup/vc-popup.vue +173 -141
  67. package/ui/components/organisms/vc-table/_internal/vc-table-mobile-item/vc-table-mobile-item.vue +171 -160
  68. package/ui/components/organisms/vc-table/vc-table.vue +13 -8
  69. package/dist/shared/modules/assets/locales/index.d.ts +0 -3
  70. package/dist/shared/modules/assets/locales/index.d.ts.map +0 -1
  71. package/dist/shared/modules/assets-manager/locales/index.d.ts +0 -3
  72. package/dist/shared/modules/assets-manager/locales/index.d.ts.map +0 -1
  73. package/dist/ui/components/organisms/vc-popup/_internal/vc-popup-error/vc-popup-error.vue.d.ts +0 -17
  74. package/dist/ui/components/organisms/vc-popup/_internal/vc-popup-error/vc-popup-error.vue.d.ts.map +0 -1
  75. package/dist/ui/components/organisms/vc-popup/_internal/vc-popup-warning/vc-popup-warning.vue.d.ts +0 -20
  76. package/dist/ui/components/organisms/vc-popup/_internal/vc-popup-warning/vc-popup-warning.vue.d.ts.map +0 -1
  77. package/shared/modules/assets/locales/en.json +0 -32
  78. package/shared/modules/assets/locales/index.ts +0 -2
  79. package/shared/modules/assets-manager/locales/en.json +0 -28
  80. package/shared/modules/assets-manager/locales/index.ts +0 -2
  81. package/ui/components/organisms/vc-popup/_internal/vc-popup-error/vc-popup-error.vue +0 -31
  82. package/ui/components/organisms/vc-popup/_internal/vc-popup-warning/vc-popup-warning.vue +0 -36
@@ -1,6 +1,5 @@
1
1
  import { createAppModule } from "../../../core/plugins/modularity";
2
2
  import * as components from "./components";
3
- import * as locales from "./locales";
4
3
 
5
4
  // Declare globally
6
5
  declare module "@vue/runtime-core" {
@@ -9,6 +8,6 @@ declare module "@vue/runtime-core" {
9
8
  }
10
9
  }
11
10
 
12
- export const AssetsDetailsModule = createAppModule(components, locales);
11
+ export const AssetsDetailsModule = createAppModule(components);
13
12
 
14
13
  export * from "./components";
@@ -25,6 +25,7 @@
25
25
  :header="false"
26
26
  :footer="false"
27
27
  :item-action-builder="!readonly ? actionBuilder : undefined"
28
+ :enable-item-actions="!readonly"
28
29
  :multiselect="!readonly"
29
30
  class="tw-h-full tw-w-full"
30
31
  @item-click="onItemClick"
@@ -34,14 +35,21 @@
34
35
  <!-- Empty template -->
35
36
  <template #empty>
36
37
  <div class="tw-w-full tw-h-full tw-box-border tw-flex tw-flex-col tw-items-center tw-justify-center">
37
- <VcIcon
38
- icon="fas fa-cloud-upload-alt"
39
- class="tw-text-[100px] tw-text-[#41afe6]"
40
- ></VcIcon>
41
- <div class="tw-m-4 tw-text-xl tw-font-medium">
42
- {{ t("ASSETS_MANAGER.EMPTY.NO_ASSETS") }}
43
- </div>
44
- <VcButton @click="toggleUploader">{{ t("ASSETS_MANAGER.EMPTY.UPLOAD") }}</VcButton>
38
+ <template v-if="!readonly">
39
+ <VcIcon
40
+ icon="fas fa-cloud-upload-alt"
41
+ class="tw-text-[100px] tw-text-[#41afe6]"
42
+ ></VcIcon>
43
+ <div class="tw-m-4 tw-text-xl tw-font-medium">
44
+ {{ t("ASSETS_MANAGER.EMPTY.UPLOAD_ASSETS") }}
45
+ </div>
46
+ <VcButton @click="toggleUploader">{{ t("ASSETS_MANAGER.EMPTY.UPLOAD") }}</VcButton>
47
+ </template>
48
+ <template v-else>
49
+ <div class="tw-m-4 tw-text-xl tw-font-medium">
50
+ {{ t("ASSETS_MANAGER.EMPTY.NO_ASSETS") }}
51
+ </div>
52
+ </template>
45
53
  </div>
46
54
  </template>
47
55
 
@@ -73,7 +81,7 @@
73
81
  </div>
74
82
  </template>
75
83
 
76
- <!-- Overide order column -->
84
+ <!-- Override order column -->
77
85
  <template #item_sortOrder="{ item }">
78
86
  <div>
79
87
  {{ item.sortOrder }}
@@ -176,7 +184,7 @@ const props = withDefaults(defineProps<Props>(), {
176
184
  param: undefined,
177
185
  });
178
186
 
179
- const emit = defineEmits<Emits>();
187
+ defineEmits<Emits>();
180
188
 
181
189
  defineOptions({
182
190
  name: "AssetsManager",
@@ -196,15 +204,6 @@ const modified = ref(false);
196
204
  const { openBlade, resolveBladeByName } = useBladeNavigation();
197
205
 
198
206
  const bladeToolbar = ref<IBladeToolbar[]>([
199
- {
200
- id: "save",
201
- title: computed(() => t("ASSETS_MANAGER.TOOLBAR.SAVE")),
202
- icon: "fas fa-save",
203
- clickHandler() {
204
- emit("close:blade");
205
- },
206
- disabled: computed(() => !modified.value || readonly.value),
207
- },
208
207
  {
209
208
  id: "add",
210
209
  title: computed(() => t("ASSETS_MANAGER.TOOLBAR.ADD")),
@@ -213,6 +212,7 @@ const bladeToolbar = ref<IBladeToolbar[]>([
213
212
  toggleUploader();
214
213
  },
215
214
  disabled: computed(() => readonly.value),
215
+ isVisible: computed(() => !readonly.value),
216
216
  },
217
217
  {
218
218
  id: "delete",
@@ -224,6 +224,7 @@ const bladeToolbar = ref<IBladeToolbar[]>([
224
224
  }
225
225
  },
226
226
  disabled: computed(() => !selectedItems.value.length || readonly.value),
227
+ isVisible: computed(() => !readonly.value),
227
228
  },
228
229
  ]);
229
230
 
@@ -363,7 +364,8 @@ const actionBuilder = (): IActionBuilderResult<ICommonAsset>[] => {
363
364
  result.push({
364
365
  icon: "fas fa-edit",
365
366
  title: computed(() => t("ASSETS_MANAGER.TABLE.ACTIONS.EDIT")),
366
- variant: "success",
367
+ type: "success",
368
+ position: "right",
367
369
  clickHandler(item: ICommonAsset) {
368
370
  onItemClick(item);
369
371
  },
@@ -372,8 +374,8 @@ const actionBuilder = (): IActionBuilderResult<ICommonAsset>[] => {
372
374
  result.push({
373
375
  icon: "fas fa-trash",
374
376
  title: computed(() => t("ASSETS_MANAGER.TABLE.ACTIONS.DELETE")),
375
- variant: "danger",
376
- leftActions: true,
377
+ type: "danger",
378
+ position: "left",
377
379
  async clickHandler(item: ICommonAsset) {
378
380
  defaultAssets.value = await props.options.assetsRemoveHandler([item]);
379
381
  selectedItems.value = [];
@@ -1,6 +1,5 @@
1
1
  import { createAppModule } from "../../../core/plugins/modularity";
2
2
  import * as components from "./components";
3
- import * as locales from "./locales";
4
3
 
5
4
  // Declare globally
6
5
  declare module "@vue/runtime-core" {
@@ -9,6 +8,6 @@ declare module "@vue/runtime-core" {
9
8
  }
10
9
  }
11
10
 
12
- export const AssetsManagerModule = createAppModule(components, locales);
11
+ export const AssetsManagerModule = createAppModule(components);
13
12
 
14
13
  export * from "./components";
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { IBladeToolbar } from "../../../../../core/types";
3
3
  import * as _ from "lodash-es";
4
- import { SettingsSchema } from "../../types";
4
+ import { SettingsSchema, ToolbarSchema } from "../../types";
5
5
  import { BaseBladeScope, DetailsBladeContext, ListBladeContext } from "../../factories/types";
6
6
  import { useI18n } from "vue-i18n";
7
7
  import { toValue } from "@vueuse/core";
@@ -13,7 +13,7 @@ export const useToolbarReducer = (args: {
13
13
  customToolbarConfig: BaseBladeScope["toolbarOverrides"];
14
14
  context: UnwrapNestedRefs<DetailsBladeContext> | UnwrapNestedRefs<ListBladeContext>;
15
15
  scope: ComputedRef<BaseBladeScope> | undefined;
16
- }): UnwrapNestedRefs<ComputedRef<IBladeToolbar[]>> | undefined => {
16
+ }): UnwrapNestedRefs<ComputedRef<(IBladeToolbar & ToolbarSchema)[]>> | undefined => {
17
17
  if (!args) return;
18
18
 
19
19
  const { t } = useI18n({ useScope: "global" });
@@ -79,9 +79,10 @@ import {
79
79
  type Component,
80
80
  ConcreteComponent,
81
81
  toRefs,
82
+ provide,
82
83
  } from "vue";
83
84
  import { DynamicDetailsSchema, FormContentSchema, SettingsSchema } from "../types";
84
- import { reactiveComputed, useMounted, useTemplateRefsList } from "@vueuse/core";
85
+ import { reactiveComputed, toReactive, useMounted, useTemplateRefsList } from "@vueuse/core";
85
86
  import {
86
87
  DetailsBladeContext,
87
88
  DetailsBaseBladeScope,
@@ -97,6 +98,8 @@ import { useToolbarReducer } from "../composables/useToolbarReducer";
97
98
  import { useBeforeUnload } from "../../../../core/composables/useBeforeUnload";
98
99
  import * as _ from "lodash-es";
99
100
  import { IBladeToolbar } from "../../../../core/types";
101
+ import { useNotifications } from "../../../../core/composables";
102
+ import { notification } from "../../../components";
100
103
 
101
104
  interface Props {
102
105
  expanded?: boolean;
@@ -150,6 +153,25 @@ const { loading, item, validationState, scope, load, remove, saveChanges, bladeT
150
153
  const title = ref();
151
154
  const isReady = ref(false);
152
155
  const activeWidgetExposed = ref<CoreBladeExposed>();
156
+ const settings = computed(() => props.model?.settings);
157
+
158
+ const { moduleNotifications, markAsRead } = useNotifications(settings.value?.pushNotificationType);
159
+
160
+ watch(
161
+ moduleNotifications,
162
+ (newVal) => {
163
+ newVal.forEach((message) => {
164
+ if (message.title && props.composables) {
165
+ notification.success(message.title, {
166
+ onClose() {
167
+ markAsRead(message);
168
+ },
169
+ });
170
+ }
171
+ });
172
+ },
173
+ { deep: true },
174
+ );
153
175
 
154
176
  watch(
155
177
  () => bladeTitle?.value,
@@ -172,8 +194,6 @@ const validated = computed(() => {
172
194
 
173
195
  useBeforeUnload(validated);
174
196
 
175
- const settings = computed(() => props.model?.settings);
176
-
177
197
  const form = computed(
178
198
  (): FormContentSchema => props.model?.content.find((x) => x?.component === "vc-form") as FormContentSchema,
179
199
  );
@@ -337,6 +357,8 @@ onBeforeClose(async () => {
337
357
  }
338
358
  });
339
359
 
360
+ provide("bladeContext", toReactive(bladeContext));
361
+
340
362
  defineExpose({
341
363
  title: bladeTitle ?? "",
342
364
  updateActiveWidgetCount,
@@ -44,6 +44,8 @@
44
44
  :items="itemsProxy as Record<string, any>[]"
45
45
  :multiselect="isWidgetView ? false : tableData?.multiselect"
46
46
  :header="isWidgetView ? false : tableData?.header"
47
+ :item-action-builder="actionBuilder"
48
+ :enable-item-actions="!!tableData?.actions"
47
49
  :footer="!isWidgetView"
48
50
  :sort="sort"
49
51
  :pages="pagination?.pages"
@@ -55,6 +57,7 @@
55
57
  :active-filter-count="activeFilterCount"
56
58
  :reorderable-rows="isWidgetView ? false : tableData?.reorderableRows"
57
59
  :pull-to-reload="!isWidgetView"
60
+ :select-all="tableData?.selectAll"
58
61
  @item-click="onItemClick"
59
62
  @pagination-click="onPaginationClick"
60
63
  @selection-changed="onSelectionChanged"
@@ -63,6 +66,7 @@
63
66
  @scroll:ptr="reload"
64
67
  @search:change="onSearchList"
65
68
  @row:reorder="sortRows"
69
+ @select:all="handleSelectAllItems"
66
70
  >
67
71
  <template
68
72
  v-if="isFilterVisible"
@@ -76,6 +80,7 @@
76
80
  <template v-if="tableTemplates?.notFound">
77
81
  <component
78
82
  :is="tableTemplates.notFound"
83
+ :context="bladeContext"
79
84
  @reset="resetSearch"
80
85
  ></component>
81
86
  </template>
@@ -101,6 +106,7 @@
101
106
  :class="{
102
107
  'tw-py-6': isWidgetView,
103
108
  }"
109
+ :context="bladeContext"
104
110
  @add="openDetailsBlade"
105
111
  ></component>
106
112
  </template>
@@ -156,19 +162,21 @@ import {
156
162
  ComputedRef,
157
163
  onBeforeMount,
158
164
  toRefs,
165
+ provide,
159
166
  } from "vue";
160
167
  import { useI18n } from "vue-i18n";
161
- import { DynamicGridSchema, ListContentSchema, SettingsSchema } from "../types";
168
+ import { DynamicGridSchema, ListContentSchema, SettingsSchema, ToolbarSchema } from "../types";
162
169
  import { useFilterBuilder, useTableTemplates } from "../composables";
163
170
  import { useFunctions, useNotifications } from "../../../../core/composables";
164
- import { ITableColumns } from "../../../../core/types";
171
+ import { IActionBuilderResult, IBladeToolbar, ITableColumns } from "../../../../core/types";
165
172
  import { useToolbarReducer } from "../composables/useToolbarReducer";
166
173
  import { notification, usePopup } from "../../../components";
167
174
  import { ListBaseBladeScope, ListBladeContext, UseList } from "../factories/types";
168
175
  import { IParentCallArgs } from "../../../index";
169
176
  import * as _ from "lodash-es";
170
- import { useMounted } from "@vueuse/core";
177
+ import { toReactive, useMounted } from "@vueuse/core";
171
178
  import { safeIn } from "../helpers/safeIn";
179
+ import { isRef } from "vue";
172
180
 
173
181
  export interface Props {
174
182
  expanded?: boolean;
@@ -209,7 +217,6 @@ const searchValue = ref();
209
217
  const selectedItemId = shallowRef();
210
218
  const sort = shallowRef("createdDate:DESC");
211
219
  const selectedIds = shallowRef<string[]>([]);
212
- const isDesktop = inject("isDesktop") as Ref<boolean>;
213
220
  const itemsProxy = ref<Record<string, any>[]>();
214
221
  const modified = shallowRef(false);
215
222
 
@@ -357,7 +364,7 @@ const toolbarComputed =
357
364
  await removeItems();
358
365
  },
359
366
  disabled: computed(() => !selectedIds.value?.length),
360
- isVisible: isDesktop.value,
367
+ // isVisible: computed(() => isDesktop.value),
361
368
  },
362
369
  },
363
370
  customToolbarConfig: toValue(scope)?.toolbarOverrides,
@@ -586,6 +593,42 @@ function updateActiveWidgetCount() {
586
593
  });
587
594
  }
588
595
 
596
+ async function handleSelectAllItems(all: boolean) {
597
+ allSelected.value = all;
598
+ }
599
+
600
+ // TODO add to documentation
601
+ function actionBuilder(): IActionBuilderResult[] | undefined {
602
+ const result = tableData?.value?.actions?.map((action) => {
603
+ return {
604
+ icon: action.icon,
605
+ title: computed(() => t(action.title)),
606
+ type: action.type,
607
+ position: action.position,
608
+ clickHandler: async (itemVal: (typeof items.value)[number]) => {
609
+ try {
610
+ if (isRef(toolbarComputed) && toolbarComputed.value && toolbarComputed.value.length > 0) {
611
+ const toolbarItem = toolbarComputed.value.find((x) => x.method === action.method);
612
+ selectedIds.value = [itemVal.id];
613
+ if (toolbarItem) {
614
+ await toolbarItem.clickHandler?.();
615
+ } else {
616
+ await toValue(scope)?.[action.method]?.(itemVal);
617
+ }
618
+ selectedIds.value = [];
619
+ }
620
+ } catch (error) {
621
+ throw new Error(`Method ${action.method} is not defined in scope or toolbarOverrides`);
622
+ }
623
+ },
624
+ };
625
+ });
626
+
627
+ return result;
628
+ }
629
+
630
+ provide("bladeContext", toReactive(bladeContext));
631
+
589
632
  defineExpose({
590
633
  reload,
591
634
  title,
@@ -58,7 +58,7 @@ export interface SettingsDetails extends SettingsBase {
58
58
 
59
59
  export type IViewComponentName = "DynamicBladeForm" | "DynamicBladeList";
60
60
 
61
- type ToolbarSchema = {
61
+ export type ToolbarSchema = {
62
62
  id: string;
63
63
  title: string;
64
64
  icon: string;
@@ -162,6 +162,14 @@ export interface ListContentSchema {
162
162
  };
163
163
  })[];
164
164
  reorderableRows?: boolean;
165
+ // TODO Add to documentation
166
+ selectAll?: boolean;
167
+ // TODO Add to documentation
168
+ actions?: (ToolbarSchema & {
169
+ position: "right" | "left";
170
+ type: "danger" | "success";
171
+ method: string;
172
+ })[];
165
173
  mobileTemplate?: {
166
174
  component: string;
167
175
  };
@@ -7,14 +7,13 @@
7
7
  <template v-if="isLogin">
8
8
  <VcForm @submit.prevent="login">
9
9
  <Field
10
- v-slot="{ field, errorMessage, handleChange, errors }"
10
+ v-slot="{ errorMessage, handleChange, errors }"
11
11
  :label="t('LOGIN.FIELDS.LOGIN.LABEL')"
12
12
  name="username"
13
13
  :model-value="form.username"
14
14
  rules="required"
15
15
  >
16
16
  <VcInput
17
- v-bind="field"
18
17
  ref="loginField"
19
18
  v-model="form.username"
20
19
  class="tw-mb-4 tw-mt-1"
@@ -27,14 +26,13 @@
27
26
  />
28
27
  </Field>
29
28
  <Field
30
- v-slot="{ field, errorMessage, handleChange, errors }"
29
+ v-slot="{ errorMessage, handleChange, errors }"
31
30
  :label="t('LOGIN.FIELDS.PASSWORD.LABEL')"
32
31
  name="password"
33
32
  :model-value="form.password"
34
33
  rules="required"
35
34
  >
36
35
  <VcInput
37
- v-bind="field"
38
36
  ref="passwordField"
39
37
  v-model="form.password"
40
38
  class="tw-mb-4"
@@ -78,6 +76,7 @@
78
76
  <div
79
77
  class="tw-flex tw-items-center tw-text-center tw-uppercase tw-text-[color:var(--separator-text)] before:tw-content-[''] before:tw-flex-1 before:tw-border-b before:tw-border-b-[color:var(--separator)] before:tw-mr-2 after:tw-content-[''] after:tw-flex-1 after:tw-border-b after:tw-border-b-[color:var(--separator)] after:tw-ml-2"
80
78
  >
79
+ <!-- TODO add to localization -->
81
80
  OR
82
81
  </div>
83
82
  <div class="tw-flex tw-justify-center tw-mt-4 tw-flex-wrap tw-gap-2">
@@ -198,7 +197,7 @@ const props = defineProps<Props>();
198
197
 
199
198
  const router = useRouter();
200
199
 
201
- useForm({ validateOnMount: false });
200
+ const { setFieldError, resetForm, setErrors, validateField } = useForm({ validateOnMount: false });
202
201
  const { uiSettings, loading: customizationLoading } = useSettings();
203
202
  const { t } = useI18n({ useScope: "global" });
204
203
  let useLogin;
@@ -253,6 +252,7 @@ const forgotPasswordForm = reactive({
253
252
 
254
253
  const login = async () => {
255
254
  if (isValid.value) {
255
+ signInResult.value.error = "";
256
256
  signInResult.value = (await signIn(form.username, form.password)) as SignInResult & {
257
257
  status?: number;
258
258
  error?: any;
@@ -264,6 +264,8 @@ const login = async () => {
264
264
  if (signInResult.value.status) {
265
265
  if (signInResult.value.status === 401) {
266
266
  signInResult.value.error = "The login or password is incorrect.";
267
+ form.password = "";
268
+ validateField("password");
267
269
  } else {
268
270
  signInResult.value.error = "Authentication error (code: " + signInResult.value.status + ").";
269
271
  }
@@ -288,6 +290,7 @@ const forgot = async () => {
288
290
 
289
291
  const togglePassRequest = () => {
290
292
  isLogin.value = !isLogin.value;
293
+ signInResult.value.error = "";
291
294
  if (isLogin.value) {
292
295
  forgotPasswordRequestSent.value = false;
293
296
  forgotPasswordForm.loginOrEmail = "";
@@ -19,15 +19,18 @@
19
19
  }"
20
20
  >
21
21
  <div
22
+ v-if="usePtr && dist > 0"
22
23
  class="vc-container__overscroll"
23
24
  :class="{ 'vc-container__overscroll_passed': status === 'loosing' }"
24
25
  :style="{ height: dist ? `${dist}px` : '0px' }"
25
26
  >
26
27
  <VcIcon
27
- icon="fas fa-spinner"
28
- :style="{ 'tw-font-size': `${dist / 2}px` }"
29
- class="vc-container__overscroll-icon"
28
+ :icon="status === 'pulling' ? 'fas fa-arrow-down' : 'fas fa-sync'"
29
+ :class="[iconClass]"
30
+ :style="{ transform: status === 'pulling' ? `rotate(${dist * 3}deg)` : '' }"
30
31
  ></VcIcon>
32
+ <span v-if="status === 'pulling'">{{ $t("COMPONENTS.ATOMS.VC_CONTAINER.PULL_TO_REFRESH") }}</span>
33
+ <span v-else-if="status === 'loosing'">{{ $t("COMPONENTS.ATOMS.VC_CONTAINER.REFRESHING") }}</span>
31
34
  </div>
32
35
  <slot></slot>
33
36
  </div>
@@ -73,6 +76,15 @@ onMounted(() => {
73
76
 
74
77
  const touchable = computed(() => status.value !== "refresh" && status.value !== "success");
75
78
 
79
+ const iconClass = computed(() => {
80
+ if (status.value === "loosing") {
81
+ return "vc-container__overscroll-icon_refresh";
82
+ } else if (status.value === "pulling") {
83
+ return "vc-container__overscroll-icon_pulling";
84
+ }
85
+ return "vc-container__overscroll-icon";
86
+ });
87
+
76
88
  const scrollTop = () => {
77
89
  if (component.value) {
78
90
  component.value.scroll(0, 0);
@@ -178,15 +190,27 @@ defineExpose({
178
190
  }
179
191
 
180
192
  &__overscroll {
181
- @apply tw-relative tw-w-full tw-flex tw-items-start tw-justify-center tw-overflow-hidden;
193
+ @apply tw-relative tw-w-full tw-flex tw-items-start tw-justify-center tw-overflow-hidden tw-gap-2;
182
194
 
183
- &-icon {
184
- @apply tw-text-[color:#a1c0d4] tw-animate-spin;
195
+ &_passed {
196
+ @apply tw-text-[#43b0e6];
185
197
  }
198
+ }
186
199
 
187
- &_passed &-icon {
188
- @apply tw-text-[#43b0e6];
200
+ &__overscroll-icon {
201
+ @apply tw-text-[color:#a1c0d4];
202
+
203
+ &_pulling {
204
+ @apply tw-text-[color:#a1c0d4];
189
205
  }
206
+
207
+ &_refresh {
208
+ animation: tw-spin 2s linear infinite;
209
+ }
210
+ }
211
+
212
+ &__overscroll span {
213
+ @apply tw-mb-2 tw-text-sm tw-text-gray-500;
190
214
  }
191
215
 
192
216
  &__inner {
@@ -214,4 +238,13 @@ defineExpose({
214
238
  @apply tw-p-0;
215
239
  }
216
240
  }
241
+
242
+ @keyframes tw-spin {
243
+ from {
244
+ transform: rotate(0deg);
245
+ }
246
+ to {
247
+ transform: rotate(360deg);
248
+ }
249
+ }
217
250
  </style>
@@ -1,3 +1 @@
1
- import _Icon from "./vc-icon.vue";
2
-
3
- export const VcIcon = _Icon as typeof _Icon;
1
+ export { default as VcIcon } from "./vc-icon.vue";
@@ -25,16 +25,16 @@
25
25
  <div v-show="navigation">
26
26
  <div class="vc-slider__prev tw-left-0">
27
27
  <slot name="prevBtn">
28
- <div class="vc-slider__btn">
28
+ <button class="vc-slider__btn">
29
29
  <VcIcon icon="fas fa-chevron-left"></VcIcon>
30
- </div>
30
+ </button>
31
31
  </slot>
32
32
  </div>
33
33
  <div class="vc-slider__next tw-right-0">
34
34
  <slot name="nextBtn">
35
- <div class="vc-slider__btn">
35
+ <button class="vc-slider__btn">
36
36
  <VcIcon icon="fas fa-chevron-right"></VcIcon>
37
- </div>
37
+ </button>
38
38
  </slot>
39
39
  </div>
40
40
  </div>
@@ -66,7 +66,8 @@ import { usePopup } from "./../../../../shared";
66
66
  import { useI18n } from "vue-i18n";
67
67
  import VcBladeHeader from "./_internal/vc-blade-header/vc-blade-header.vue";
68
68
  import VcBladeToolbar from "./_internal/vc-blade-toolbar/vc-blade-toolbar.vue";
69
- import { VcButton, VcIcon, VcPopup } from "./../../";
69
+ import { VcButton, VcIcon } from "./../../";
70
+ import vcPopupError from "../../../../shared/components/common/popup/vc-popup-error.vue";
70
71
 
71
72
  export interface Props {
72
73
  icon?: string;
@@ -102,14 +103,12 @@ const { maximized, error }: { maximized?: Ref<boolean>; error?: Ref<string> } =
102
103
  const { t } = useI18n({ useScope: "global" });
103
104
 
104
105
  const { open } = usePopup({
105
- component: VcPopup,
106
+ component: vcPopupError,
106
107
  props: {
107
- type: "error",
108
- variant: "small",
109
108
  title: t("COMPONENTS.ORGANISMS.VC_BLADE.ERROR_POPUP.TITLE"),
110
109
  },
111
110
  slots: {
112
- default: computed(() => error?.value),
111
+ content: computed(() => error?.value),
113
112
  },
114
113
  });
115
114
  </script>