@nathapp/na-cli 1.0.8 → 1.0.9

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 (158) hide show
  1. package/dist/templates/db-schema/.gitlab-ci.yml +139 -0
  2. package/dist/templates/db-schema/Makefile +885 -0
  3. package/dist/templates/k8s-deployment/.gitlab-ci.yml +158 -0
  4. package/dist/templates/k8s-deployment/Makefile +233 -0
  5. package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/script/Makefile +12 -0
  6. package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/script/Makefile +8 -0
  7. package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/script/Makefile +56 -0
  8. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/Makefile +9 -0
  9. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/script/Makefile +14 -0
  10. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/_t-0100-readiness-liveness.ts +84 -0
  11. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/hub.ts +372 -0
  12. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-contact.ts +158 -0
  13. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-contract.ts +328 -0
  14. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-kyc.ts +304 -0
  15. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-onboard-app.ts +823 -0
  16. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-onboard-web.ts +493 -0
  17. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-profile.ts +277 -0
  18. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-whitelist.ts +133 -0
  19. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/t-0200-start.ts +172 -0
  20. package/dist/templates/nestjs-api/.dockerignore +9 -0
  21. package/dist/templates/nestjs-api/.env +31 -0
  22. package/dist/templates/nestjs-api/.gitlab-ci.yml +180 -0
  23. package/dist/templates/nestjs-api/.nvmrc +1 -0
  24. package/dist/templates/nestjs-api/.prettierrc +4 -0
  25. package/dist/templates/nestjs-api/Makefile +95 -0
  26. package/dist/templates/nestjs-api/nest-cli.json +10 -0
  27. package/dist/templates/nestjs-api/ormconfig.ts +18 -0
  28. package/dist/templates/nestjs-api/src/app.controller.spec.ts +24 -0
  29. package/dist/templates/nestjs-api/src/app.controller.ts +27 -0
  30. package/dist/templates/nestjs-api/src/app.module.ts +31 -0
  31. package/dist/templates/nestjs-api/src/app.service.ts +27 -0
  32. package/dist/templates/nestjs-api/src/main.ts +31 -0
  33. package/dist/templates/nestjs-api/test/app.e2e-spec.ts +47 -0
  34. package/dist/templates/nestjs-api/tsconfig.build.json +5 -0
  35. package/dist/templates/nestjs-api/tsconfig.json +28 -0
  36. package/dist/templates/nestjs-api/tsconfig.spec.json +9 -0
  37. package/dist/templates/nestjs-library/.gitlab-ci.yml +134 -0
  38. package/dist/templates/nestjs-library/.nvmrc +1 -0
  39. package/dist/templates/nestjs-library/.prettierrc +6 -0
  40. package/dist/templates/nestjs-library/Makefile +60 -0
  41. package/dist/templates/nestjs-library/lib/index.ts +2 -0
  42. package/dist/templates/nestjs-library/test/app/controller/hello.controller.spec.ts +20 -0
  43. package/dist/templates/nestjs-library/test/app/controller/hello.controller.ts +7 -0
  44. package/dist/templates/nestjs-library/tsconfig.build.json +8 -0
  45. package/dist/templates/nestjs-library/tsconfig.json +21 -0
  46. package/dist/templates/nestjs-library/tsconfig.spec.json +9 -0
  47. package/dist/templates/ts-library/.dockerignore +2 -0
  48. package/dist/templates/ts-library/.eslintrc.js +24 -0
  49. package/dist/templates/ts-library/.gitlab-ci.yml +136 -0
  50. package/dist/templates/ts-library/.prettierrc +6 -0
  51. package/dist/templates/ts-library/Makefile +58 -0
  52. package/dist/templates/ts-library/index.ts +1 -0
  53. package/dist/templates/ts-library/lib/index.ts +1 -0
  54. package/dist/templates/ts-library/lib/samples/index.ts +5 -0
  55. package/dist/templates/ts-library/lib/samples/samples-function.ts +3 -0
  56. package/dist/templates/ts-library/test/sample.e2e-spec.ts +10 -0
  57. package/dist/templates/ts-library/tsconfig.build.json +4 -0
  58. package/dist/templates/ts-library/tsconfig.json +18 -0
  59. package/dist/templates/turbo-nestjs-vuexy/.dockerignore +2 -0
  60. package/dist/templates/turbo-nestjs-vuexy/.gitignore-rename +40 -0
  61. package/dist/templates/turbo-nestjs-vuexy/.npmrc-rename +0 -0
  62. package/dist/templates/turbo-nestjs-vuexy/Makefile +48 -0
  63. package/dist/templates/vuexy-portal/.dockerignore +2 -0
  64. package/dist/templates/vuexy-portal/.env +1 -0
  65. package/dist/templates/vuexy-portal/.gitlab-ci.yml +233 -0
  66. package/dist/templates/vuexy-portal/.npmrc-rename +2 -0
  67. package/dist/templates/vuexy-portal/.nvmrc +1 -0
  68. package/dist/templates/vuexy-portal/Makefile +55 -0
  69. package/dist/templates/vuexy-portal/src/@core/composable/createUrl.ts +20 -0
  70. package/dist/templates/vuexy-portal/src/@core/composable/useCookie.ts +43 -0
  71. package/dist/templates/vuexy-portal/src/@core/composable/useGenerateImageVariant.ts +25 -0
  72. package/dist/templates/vuexy-portal/src/@core/composable/useResponsiveSidebar.ts +29 -0
  73. package/dist/templates/vuexy-portal/src/@core/composable/useSkins.ts +42 -0
  74. package/dist/templates/vuexy-portal/src/@core/enums.ts +21 -0
  75. package/dist/templates/vuexy-portal/src/@core/index.ts +43 -0
  76. package/dist/templates/vuexy-portal/src/@core/initCore.ts +93 -0
  77. package/dist/templates/vuexy-portal/src/@core/libs/apex-chart/apexCharConfig.ts +701 -0
  78. package/dist/templates/vuexy-portal/src/@core/libs/chartjs/chartjsConfig.ts +372 -0
  79. package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/BarChart.ts +58 -0
  80. package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/BubbleChart.ts +58 -0
  81. package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/DoughnutChart.ts +58 -0
  82. package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/LineChart.ts +58 -0
  83. package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/PolarAreaChart.ts +58 -0
  84. package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/RadarChart.ts +58 -0
  85. package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/ScatterChart.ts +58 -0
  86. package/dist/templates/vuexy-portal/src/@core/stores/config.ts +80 -0
  87. package/dist/templates/vuexy-portal/src/@core/types.ts +49 -0
  88. package/dist/templates/vuexy-portal/src/@core/utils/formatters.ts +48 -0
  89. package/dist/templates/vuexy-portal/src/@core/utils/helpers.ts +32 -0
  90. package/dist/templates/vuexy-portal/src/@core/utils/plugins.ts +53 -0
  91. package/dist/templates/vuexy-portal/src/@core/utils/validators.ts +105 -0
  92. package/dist/templates/vuexy-portal/src/@core/utils/vuetify.ts +13 -0
  93. package/dist/templates/vuexy-portal/src/@custom/composables/toasts.ts +45 -0
  94. package/dist/templates/vuexy-portal/src/@custom/composables/validator.ts +160 -0
  95. package/dist/templates/vuexy-portal/src/@custom/enums/index.ts +0 -0
  96. package/dist/templates/vuexy-portal/src/@custom/types/common.ts +17 -0
  97. package/dist/templates/vuexy-portal/src/@custom/types/index.ts +0 -0
  98. package/dist/templates/vuexy-portal/src/@custom/types/pagination.ts +19 -0
  99. package/dist/templates/vuexy-portal/src/@custom/types/user.ts +5 -0
  100. package/dist/templates/vuexy-portal/src/@custom/utils/formatters.ts +83 -0
  101. package/dist/templates/vuexy-portal/src/@custom/utils/index.ts +0 -0
  102. package/dist/templates/vuexy-portal/src/@custom/utils/validators.ts +51 -0
  103. package/dist/templates/vuexy-portal/src/@layouts/components.ts +11 -0
  104. package/dist/templates/vuexy-portal/src/@layouts/config.ts +43 -0
  105. package/dist/templates/vuexy-portal/src/@layouts/enums.ts +27 -0
  106. package/dist/templates/vuexy-portal/src/@layouts/index.ts +49 -0
  107. package/dist/templates/vuexy-portal/src/@layouts/plugins/casl.ts +48 -0
  108. package/dist/templates/vuexy-portal/src/@layouts/stores/config.ts +115 -0
  109. package/dist/templates/vuexy-portal/src/@layouts/symbols.ts +1 -0
  110. package/dist/templates/vuexy-portal/src/@layouts/types.ts +126 -0
  111. package/dist/templates/vuexy-portal/src/@layouts/utils.ts +180 -0
  112. package/dist/templates/vuexy-portal/src/api/api.ts +1 -0
  113. package/dist/templates/vuexy-portal/src/api/commonApi.ts +25 -0
  114. package/dist/templates/vuexy-portal/src/api/index.ts +58 -0
  115. package/dist/templates/vuexy-portal/src/api/requestInterceptor.ts +21 -0
  116. package/dist/templates/vuexy-portal/src/api/responseInterceptor.ts +52 -0
  117. package/dist/templates/vuexy-portal/src/api/types.ts +14 -0
  118. package/dist/templates/vuexy-portal/src/api/useApi.ts +68 -0
  119. package/dist/templates/vuexy-portal/src/api/useFetchApi.ts +41 -0
  120. package/dist/templates/vuexy-portal/src/api/userApi.ts +11 -0
  121. package/dist/templates/vuexy-portal/src/composables/useApiFetch.ts +48 -0
  122. package/dist/templates/vuexy-portal/src/composables/useJwt.ts +108 -0
  123. package/dist/templates/vuexy-portal/src/main.ts +17 -0
  124. package/dist/templates/vuexy-portal/src/navigation/horizontal/index.ts +5 -0
  125. package/dist/templates/vuexy-portal/src/navigation/index.ts +7 -0
  126. package/dist/templates/vuexy-portal/src/navigation/vertical/index.ts +5 -0
  127. package/dist/templates/vuexy-portal/src/plugins/1.router/additional-routes.ts +23 -0
  128. package/dist/templates/vuexy-portal/src/plugins/1.router/guards.ts +50 -0
  129. package/dist/templates/vuexy-portal/src/plugins/1.router/index.ts +45 -0
  130. package/dist/templates/vuexy-portal/src/plugins/2.pinia.ts +8 -0
  131. package/dist/templates/vuexy-portal/src/plugins/casl/ability.ts +10 -0
  132. package/dist/templates/vuexy-portal/src/plugins/casl/composables/useAbility.ts +4 -0
  133. package/dist/templates/vuexy-portal/src/plugins/casl/index.ts +14 -0
  134. package/dist/templates/vuexy-portal/src/plugins/i18n/index.ts +29 -0
  135. package/dist/templates/vuexy-portal/src/plugins/iconify/build-icons.ts +299 -0
  136. package/dist/templates/vuexy-portal/src/plugins/iconify/index.ts +5 -0
  137. package/dist/templates/vuexy-portal/src/plugins/layouts.ts +13 -0
  138. package/dist/templates/vuexy-portal/src/plugins/toast/index.ts +9 -0
  139. package/dist/templates/vuexy-portal/src/plugins/vuetify/defaults.ts +192 -0
  140. package/dist/templates/vuexy-portal/src/plugins/vuetify/icons.ts +84 -0
  141. package/dist/templates/vuexy-portal/src/plugins/vuetify/index.ts +47 -0
  142. package/dist/templates/vuexy-portal/src/plugins/vuetify/theme.ts +155 -0
  143. package/dist/templates/vuexy-portal/src/plugins/webfontloader.ts +19 -0
  144. package/dist/templates/vuexy-portal/src/stores/auth.ts +22 -0
  145. package/dist/templates/vuexy-portal/src/stores/common.ts +41 -0
  146. package/dist/templates/vuexy-portal/src/stores/index.ts +0 -0
  147. package/dist/templates/vuexy-portal/src/utils/constants.ts +3 -0
  148. package/dist/templates/vuexy-portal/src/utils/paginationMeta.ts +10 -0
  149. package/dist/templates/vuexy-portal/themeConfig.ts +66 -0
  150. package/dist/templates/vuexy-portal/tsconfig.json +86 -0
  151. package/dist/templates/vuexy-portal/vite.config.ts +111 -0
  152. package/dist/utils/template.js +2 -0
  153. package/dist/utils/template.js.map +1 -1
  154. package/package.json +4 -1
  155. package/alias-script.sh +0 -30
  156. package/bunfig.toml +0 -3
  157. package/nax/config.json +0 -23
  158. package/nax/features/enhancements/prd.json +0 -61
@@ -0,0 +1,5 @@
1
+ export interface ChangePasswordForm {
2
+ existingPassword: string
3
+
4
+ password: string
5
+ }
@@ -0,0 +1,83 @@
1
+ import { CustomerAddress } from "../types/customer"
2
+
3
+ export const formatCurrency = (value: number | string, currency: string = 'MYR', locale: string = 'en-US') => {
4
+ if (typeof value === 'string')
5
+ value = Number(value)
6
+
7
+ return new Intl.NumberFormat(locale, {
8
+ style: 'currency',
9
+ currency: currency === 'RM' ? 'MYR' : currency,
10
+ }).format(value)
11
+ }
12
+
13
+ export const formatNumber = (value: number | string, locale: string = 'en-US') => {
14
+ if (typeof value === 'string')
15
+ value = Number(value)
16
+
17
+ return new Intl.NumberFormat(locale).format(value)
18
+ }
19
+
20
+ export const formatNumberDecimal = (value: number | string, decimalPlaces: number = 2) => {
21
+ if (typeof value === 'string')
22
+ value = Number(value)
23
+
24
+ return value.toFixed(decimalPlaces)
25
+ }
26
+
27
+ export const formatAddress = (
28
+ address1: string,
29
+ address2?: string,
30
+ address3?: string,
31
+ city?: string,
32
+ postalCode?: string,
33
+ state?: string,
34
+ country?: string,
35
+ linebreak = ',',
36
+ ): string => {
37
+ let formattedAddress = ''
38
+
39
+ if (address1)
40
+ formattedAddress += `${address1}${linebreak}`
41
+
42
+ if (address2)
43
+ formattedAddress += `${address2}${linebreak}`
44
+
45
+ if (address3)
46
+ formattedAddress += `${address3}${linebreak}`
47
+
48
+ formattedAddress += `${postalCode} ${city}${linebreak}`
49
+
50
+ if (state)
51
+ formattedAddress += `${state}${linebreak}`
52
+
53
+ if (country)
54
+ formattedAddress += `${country}`
55
+
56
+ return formattedAddress
57
+ }
58
+
59
+ export const formatCustomerAddress = (
60
+ customerAddress: CustomerAddress,
61
+ linebreak = ',',
62
+ ): string => {
63
+ const {
64
+ address1,
65
+ address2,
66
+ address3,
67
+ city,
68
+ postcode,
69
+ stateName,
70
+ countryName,
71
+ } = customerAddress
72
+
73
+ return formatAddress(
74
+ address1,
75
+ address2,
76
+ address3,
77
+ city,
78
+ postcode,
79
+ stateName,
80
+ countryName,
81
+ linebreak,
82
+ )
83
+ }
@@ -0,0 +1,51 @@
1
+ /* eslint-disable @stylistic/js/operator-linebreak */
2
+ import type { Country } from '../types/common'
3
+
4
+ export const conditionalRequiredValidator = (value: unknown, condition: boolean) => {
5
+ if (!condition)
6
+ return true
7
+
8
+ return requiredValidator(value)
9
+ }
10
+
11
+ // 👉 mobile Validator
12
+ export const mobileValidator = (country: Country | string, value: unknown) => {
13
+ if (isEmpty(value))
14
+ return true
15
+ let countryIso2 = ''
16
+ let autoDialCode = '' // only auto add dialcode when country Object is provided
17
+ if (typeof country === 'string') {
18
+ countryIso2 = country
19
+ }
20
+ else {
21
+ countryIso2 = country.countryCode
22
+ autoDialCode = country.dialCode
23
+ }
24
+
25
+ const regex
26
+ = countryIso2.toLocaleLowerCase() === 'my'
27
+ ? // malaysia mobile phone
28
+ /^(\+?6?01)[02-46-9]-*\d{7}$|^(\+?6?01)1-*\d{8}$/
29
+ : // other mobile no +919367788755, 8989829304, +16308520397
30
+ /^\+?\(?\d{3}\)?\d{3}[-\s.]?\d{3,8}$/
31
+
32
+ if (Array.isArray(value))
33
+ return value.every(val => regex.test(String(`${autoDialCode}${val}`))) || 'The mobile number field must be a valid mobile number'
34
+
35
+ return regex.test(String(`${autoDialCode}${value}`)) || 'The Mobile Number field must be a valid mobile number'
36
+ }
37
+
38
+ export const positiveCurrencyValidator = (value: unknown, mustGreaterZero = false) => {
39
+ if (isEmpty(value))
40
+ return true
41
+
42
+ // /^\d+(\.\d{1,2})?$/
43
+ // eslint-disable-next-line regexp/no-unused-capturing-group
44
+ const regex = /^\d+(\.\d{1,2})?$/
45
+
46
+ const isValidCurrency = regex.test(String(value))
47
+
48
+ const valid = mustGreaterZero && isValidCurrency ? Number(value) > 0 : isValidCurrency
49
+
50
+ return valid || 'The currency field must be a valid currency and must be greater than 0'
51
+ }
@@ -0,0 +1,11 @@
1
+ export { default as HorizontalNav } from './components/HorizontalNav.vue'
2
+ export { default as HorizontalNavGroup } from './components/HorizontalNavGroup.vue'
3
+ export { default as HorizontalNavLayout } from './components/HorizontalNavLayout.vue'
4
+ export { default as HorizontalNavLink } from './components/HorizontalNavLink.vue'
5
+ export { default as HorizontalNavPopper } from './components/HorizontalNavPopper.vue'
6
+ export { default as TransitionExpand } from './components/TransitionExpand.vue'
7
+ export { default as VerticalNav } from './components/VerticalNav.vue'
8
+ export { default as VerticalNavGroup } from './components/VerticalNavGroup.vue'
9
+ export { default as VerticalNavLayout } from './components/VerticalNavLayout.vue'
10
+ export { default as VerticalNavLink } from './components/VerticalNavLink.vue'
11
+ export { default as VerticalNavSectionTitle } from './components/VerticalNavSectionTitle.vue'
@@ -0,0 +1,43 @@
1
+ import { breakpointsVuetify } from '@vueuse/core'
2
+ import { AppContentLayoutNav, ContentWidth, FooterType, HorizontalNavType, NavbarType } from '@layouts/enums'
3
+ import type { LayoutConfig } from '@layouts/types'
4
+
5
+ export const layoutConfig: LayoutConfig = {
6
+ app: {
7
+ title: 'my-layout',
8
+ logo: h('img', { src: '/src/assets/logo.svg' }),
9
+ contentWidth: ContentWidth.Boxed,
10
+ contentLayoutNav: AppContentLayoutNav.Vertical,
11
+ overlayNavFromBreakpoint: breakpointsVuetify.md,
12
+
13
+ // isRTL: false,
14
+ i18n: {
15
+ enable: true,
16
+ },
17
+ iconRenderer: h('div'),
18
+ },
19
+ navbar: {
20
+ type: NavbarType.Sticky,
21
+ navbarBlur: true,
22
+ },
23
+ footer: {
24
+ type: FooterType.Static,
25
+ },
26
+ verticalNav: {
27
+ isVerticalNavCollapsed: false,
28
+ defaultNavItemIconProps: { icon: 'tabler-circle' },
29
+ },
30
+ horizontalNav: {
31
+ type: HorizontalNavType.Sticky,
32
+ transition: 'none',
33
+ popoverOffset: 0,
34
+ },
35
+ icons: {
36
+ chevronDown: { icon: 'tabler-chevron-down' },
37
+ chevronRight: { icon: 'tabler-chevron-right' },
38
+ close: { icon: 'tabler-x' },
39
+ verticalNavPinned: { icon: 'tabler-circle-dot' },
40
+ verticalNavUnPinned: { icon: 'tabler-circle' },
41
+ sectionTitlePlaceholder: { icon: 'tabler-minus' },
42
+ },
43
+ }
@@ -0,0 +1,27 @@
1
+ export const ContentWidth = {
2
+ Fluid: 'fluid',
3
+ Boxed: 'boxed',
4
+ } as const
5
+
6
+ export const NavbarType = {
7
+ Sticky: 'sticky',
8
+ Static: 'static',
9
+ Hidden: 'hidden',
10
+ } as const
11
+
12
+ export const FooterType = {
13
+ Sticky: 'sticky',
14
+ Static: 'static',
15
+ Hidden: 'hidden',
16
+ } as const
17
+
18
+ export const AppContentLayoutNav = {
19
+ Vertical: 'vertical',
20
+ Horizontal: 'horizontal',
21
+ } as const
22
+
23
+ export const HorizontalNavType = {
24
+ Sticky: 'sticky',
25
+ Static: 'static',
26
+ Hidden: 'hidden',
27
+ } as const
@@ -0,0 +1,49 @@
1
+ import type { PartialDeep } from 'type-fest'
2
+ import type { Plugin } from 'vue'
3
+ import { layoutConfig } from '@layouts/config'
4
+ import { cookieRef, useLayoutConfigStore } from '@layouts/stores/config'
5
+ import type { LayoutConfig } from '@layouts/types'
6
+ import { _setDirAttr } from '@layouts/utils'
7
+
8
+ // 🔌 Plugin
9
+ export const createLayouts = (userConfig: PartialDeep<LayoutConfig>): Plugin => {
10
+ return (): void => {
11
+ const configStore = useLayoutConfigStore()
12
+
13
+ // Non reactive Values
14
+ layoutConfig.app.title = userConfig.app?.title ?? layoutConfig.app.title
15
+ layoutConfig.app.logo = userConfig.app?.logo ?? layoutConfig.app.logo as any
16
+ layoutConfig.app.overlayNavFromBreakpoint = userConfig.app?.overlayNavFromBreakpoint ?? layoutConfig.app.overlayNavFromBreakpoint
17
+ layoutConfig.app.i18n.enable = userConfig.app?.i18n?.enable ?? layoutConfig.app.i18n.enable
18
+ layoutConfig.app.iconRenderer = userConfig.app?.iconRenderer as LayoutConfig['app']['iconRenderer'] ?? layoutConfig.app.iconRenderer
19
+
20
+ layoutConfig.verticalNav.defaultNavItemIconProps = userConfig.verticalNav?.defaultNavItemIconProps ?? layoutConfig.verticalNav.defaultNavItemIconProps
21
+
22
+ layoutConfig.icons.chevronDown = userConfig.icons?.chevronDown ?? layoutConfig.icons.chevronDown
23
+ layoutConfig.icons.chevronRight = userConfig.icons?.chevronRight ?? layoutConfig.icons.chevronRight
24
+ layoutConfig.icons.close = userConfig.icons?.close ?? layoutConfig.icons.close
25
+ layoutConfig.icons.verticalNavPinned = userConfig.icons?.verticalNavPinned ?? layoutConfig.icons.verticalNavPinned
26
+ layoutConfig.icons.verticalNavUnPinned = userConfig.icons?.verticalNavUnPinned ?? layoutConfig.icons.verticalNavUnPinned
27
+ layoutConfig.icons.sectionTitlePlaceholder = userConfig.icons?.sectionTitlePlaceholder ?? layoutConfig.icons.sectionTitlePlaceholder
28
+
29
+ // Reactive Values (Store)
30
+ configStore.$patch({
31
+ appContentLayoutNav: cookieRef('appContentLayoutNav', userConfig.app?.contentLayoutNav ?? layoutConfig.app.contentLayoutNav).value,
32
+ appContentWidth: cookieRef('appContentWidth', userConfig.app?.contentWidth ?? layoutConfig.app.contentWidth).value,
33
+ footerType: cookieRef('footerType', userConfig.footer?.type ?? layoutConfig.footer.type).value,
34
+ navbarType: cookieRef('navbarType', userConfig.navbar?.type ?? layoutConfig.navbar.type).value,
35
+ isNavbarBlurEnabled: cookieRef('isNavbarBlurEnabled', userConfig.navbar?.navbarBlur ?? layoutConfig.navbar.navbarBlur).value,
36
+ isVerticalNavCollapsed: cookieRef('isVerticalNavCollapsed', userConfig.verticalNav?.isVerticalNavCollapsed ?? layoutConfig.verticalNav.isVerticalNavCollapsed).value,
37
+
38
+ // isAppRTL: userConfig.app?.isRTL ?? config.app.isRTL,
39
+ // isLessThanOverlayNavBreakpoint: false,
40
+ horizontalNavType: cookieRef('horizontalNavType', userConfig.horizontalNav?.type ?? layoutConfig.horizontalNav.type).value,
41
+ })
42
+
43
+ // _setDirAttr(config.app.isRTL ? 'rtl' : 'ltr')
44
+ _setDirAttr(configStore.isAppRTL ? 'rtl' : 'ltr')
45
+ }
46
+ }
47
+
48
+ export * from './components'
49
+ export { layoutConfig }
@@ -0,0 +1,48 @@
1
+ import { useAbility } from '@casl/vue'
2
+ import type { RouteLocationNormalized } from 'vue-router'
3
+ import type { NavGroup } from '@layouts/types'
4
+
5
+ /**
6
+ * Returns ability result if ACL is configured or else just return true
7
+ * We should allow passing string | undefined to can because for admin ability we omit defining action & subject
8
+ *
9
+ * Useful if you don't know if ACL is configured or not
10
+ * Used in @core files to handle absence of ACL without errors
11
+ *
12
+ * @param {string} action CASL Actions // https://casl.js.org/v4/en/guide/intro#basics
13
+ * @param {string} subject CASL Subject // https://casl.js.org/v4/en/guide/intro#basics
14
+ */
15
+ export const can = (action: string | undefined, subject: string | undefined) => {
16
+ const vm = getCurrentInstance()
17
+
18
+ if (!vm)
19
+ return false
20
+
21
+ const localCan = vm.proxy && '$can' in vm.proxy
22
+
23
+ // @ts-expect-error We will get TS error in below line because we aren't using $can in component instance
24
+ return localCan ? vm.proxy?.$can(action, subject) : true
25
+ }
26
+
27
+ /**
28
+ * Check if user can view item based on it's ability
29
+ * Based on item's action and subject & Hide group if all of it's children are hidden
30
+ * @param {object} item navigation object item
31
+ */
32
+ export const canViewNavMenuGroup = (item: NavGroup) => {
33
+ const hasAnyVisibleChild = item.children.some(i => can(i.action, i.subject))
34
+
35
+ // If subject and action is defined in item => Return based on children visibility (Hide group if no child is visible)
36
+ // Else check for ability using provided subject and action along with checking if has any visible child
37
+ if (!(item.action && item.subject))
38
+ return hasAnyVisibleChild
39
+
40
+ return can(item.action, item.subject) && hasAnyVisibleChild
41
+ }
42
+
43
+ export const canNavigate = (to: RouteLocationNormalized) => {
44
+ const ability = useAbility()
45
+
46
+ // @ts-expect-error We should allow passing string | undefined to can because for admin ability we omit defining action & subject
47
+ return to.matched.some(route => ability.can(route.meta.action, route.meta.subject))
48
+ }
@@ -0,0 +1,115 @@
1
+ import { AppContentLayoutNav, NavbarType } from '@layouts/enums'
2
+ import { injectionKeyIsVerticalNavHovered } from '@layouts/symbols'
3
+ import { _setDirAttr } from '@layouts/utils'
4
+
5
+ // ℹ️ We should not import themeConfig here but in urgency we are doing it for now
6
+ import { layoutConfig } from '@themeConfig'
7
+
8
+ export const namespaceConfig = (str: string) => `${layoutConfig.app.title}-${str}`
9
+
10
+ export const cookieRef = <T>(key: string, defaultValue: T) => {
11
+ return useCookie<T>(namespaceConfig(key), { default: () => defaultValue })
12
+ }
13
+
14
+ export const useLayoutConfigStore = defineStore('layoutConfig', () => {
15
+ const route = useRoute()
16
+
17
+ // 👉 Navbar Type
18
+ const navbarType = ref(layoutConfig.navbar.type)
19
+
20
+ // 👉 Navbar Type
21
+ const isNavbarBlurEnabled = cookieRef('isNavbarBlurEnabled', layoutConfig.navbar.navbarBlur)
22
+
23
+ // 👉 Vertical Nav Collapsed
24
+ const isVerticalNavCollapsed = cookieRef('isVerticalNavCollapsed', layoutConfig.verticalNav.isVerticalNavCollapsed)
25
+
26
+ // 👉 App Content Width
27
+ const appContentWidth = cookieRef('appContentWidth', layoutConfig.app.contentWidth)
28
+
29
+ // 👉 App Content Layout Nav
30
+ const appContentLayoutNav = ref(layoutConfig.app.contentLayoutNav)
31
+
32
+ watch(appContentLayoutNav, val => {
33
+ // If Navbar type is hidden while switching to horizontal nav => Reset it to sticky
34
+ if (val === AppContentLayoutNav.Horizontal) {
35
+ if (navbarType.value === NavbarType.Hidden)
36
+ navbarType.value = NavbarType.Sticky
37
+
38
+ isVerticalNavCollapsed.value = false
39
+ }
40
+ })
41
+
42
+ // 👉 Horizontal Nav Type
43
+ const horizontalNavType = ref(layoutConfig.horizontalNav.type)
44
+
45
+ // 👉 Horizontal Nav Popover Offset
46
+ const horizontalNavPopoverOffset = ref(layoutConfig.horizontalNav.popoverOffset)
47
+
48
+ // 👉 Footer Type
49
+ const footerType = ref(layoutConfig.footer.type)
50
+
51
+ // 👉 Misc
52
+ const isLessThanOverlayNavBreakpoint = computed(() => useMediaQuery(`(max-width: ${layoutConfig.app.overlayNavFromBreakpoint}px)`).value)
53
+
54
+ // 👉 Layout Classes
55
+ const _layoutClasses = computed(() => {
56
+ const { y: windowScrollY } = useWindowScroll()
57
+
58
+ return [
59
+ `layout-nav-type-${appContentLayoutNav.value}`,
60
+ `layout-navbar-${navbarType.value}`,
61
+ `layout-footer-${footerType.value}`,
62
+ {
63
+ 'layout-vertical-nav-collapsed':
64
+ isVerticalNavCollapsed.value
65
+ && appContentLayoutNav.value === 'vertical'
66
+ && !isLessThanOverlayNavBreakpoint.value,
67
+ },
68
+ { [`horizontal-nav-${horizontalNavType.value}`]: appContentLayoutNav.value === 'horizontal' },
69
+ `layout-content-width-${appContentWidth.value}`,
70
+ { 'layout-overlay-nav': isLessThanOverlayNavBreakpoint.value },
71
+ { 'window-scrolled': unref(windowScrollY) },
72
+ route.meta.layoutWrapperClasses ? route.meta.layoutWrapperClasses : null,
73
+ ]
74
+ })
75
+
76
+ // 👉 RTL
77
+ // const isAppRTL = ref(layoutConfig.app.isRTL)
78
+ const isAppRTL = ref(false)
79
+
80
+ watch(isAppRTL, val => {
81
+ _setDirAttr(val ? 'rtl' : 'ltr')
82
+ })
83
+
84
+ // 👉 Is Vertical Nav Mini
85
+ /*
86
+ This function will return true if current state is mini. Mini state means vertical nav is:
87
+ - Collapsed
88
+ - Isn't hovered by mouse
89
+ - nav is not less than overlay breakpoint (hence, isn't overlay menu)
90
+
91
+ ℹ️ We are getting `isVerticalNavHovered` as param instead of via `inject` because
92
+ we are using this in `VerticalNav.vue` component which provide it and I guess because
93
+ same component is providing & injecting we are getting undefined error
94
+ */
95
+ const isVerticalNavMini = (isVerticalNavHovered: Ref<boolean> | null = null) => {
96
+ const isVerticalNavHoveredLocal = isVerticalNavHovered || inject(injectionKeyIsVerticalNavHovered) || ref(false)
97
+
98
+ return computed(() => isVerticalNavCollapsed.value && !isVerticalNavHoveredLocal.value && !isLessThanOverlayNavBreakpoint.value)
99
+ }
100
+
101
+ return {
102
+ appContentWidth,
103
+ appContentLayoutNav,
104
+ navbarType,
105
+ isNavbarBlurEnabled,
106
+ isVerticalNavCollapsed,
107
+ horizontalNavType,
108
+ horizontalNavPopoverOffset,
109
+ footerType,
110
+ isLessThanOverlayNavBreakpoint,
111
+ isAppRTL,
112
+ _layoutClasses,
113
+ isVerticalNavMini,
114
+ }
115
+ })
@@ -0,0 +1 @@
1
+ export const injectionKeyIsVerticalNavHovered: InjectionKey<Ref<boolean>> = Symbol('isVerticalNavHovered')
@@ -0,0 +1,126 @@
1
+ import type { OffsetOptions } from '@floating-ui/dom'
2
+ import type { RouteLocationRaw } from 'vue-router'
3
+ import type { AppContentLayoutNav, ContentWidth, FooterType, HorizontalNavType, NavbarType } from '@layouts/enums'
4
+
5
+ export interface LayoutConfig {
6
+ app: {
7
+ title: Lowercase<string>
8
+ logo: VNode
9
+ contentWidth: typeof ContentWidth[keyof typeof ContentWidth]
10
+ contentLayoutNav: typeof AppContentLayoutNav[keyof typeof AppContentLayoutNav]
11
+ overlayNavFromBreakpoint: number
12
+
13
+ // isRTL: boolean
14
+ i18n: {
15
+ enable: boolean
16
+ }
17
+ iconRenderer: Component
18
+ }
19
+ navbar: {
20
+ type: typeof NavbarType[keyof typeof NavbarType]
21
+ navbarBlur: boolean
22
+ }
23
+ footer: {
24
+ type: typeof FooterType[keyof typeof FooterType]
25
+ }
26
+ verticalNav: {
27
+ isVerticalNavCollapsed: boolean
28
+ defaultNavItemIconProps: unknown
29
+ }
30
+ horizontalNav: {
31
+ type: typeof HorizontalNavType[keyof typeof HorizontalNavType]
32
+ transition: string | Component
33
+ popoverOffset?: OffsetOptions
34
+ }
35
+ icons: {
36
+ chevronDown: any
37
+ chevronRight: any
38
+ close: any
39
+ verticalNavPinned: any
40
+ verticalNavUnPinned: any
41
+ sectionTitlePlaceholder: any
42
+ }
43
+ }
44
+
45
+ export interface AclProperties {
46
+ action: string
47
+ subject: string
48
+ }
49
+
50
+ // 👉 Vertical nav section title
51
+ export interface NavSectionTitle extends Partial<AclProperties> {
52
+ heading: string
53
+ }
54
+
55
+ // 👉 Vertical nav link
56
+ declare type ATagTargetAttrValues = '_blank' | '_self' | '_parent' | '_top' | 'framename'
57
+ declare type ATagRelAttrValues =
58
+ | 'alternate'
59
+ | 'author'
60
+ | 'bookmark'
61
+ | 'external'
62
+ | 'help'
63
+ | 'license'
64
+ | 'next'
65
+ | 'nofollow'
66
+ | 'noopener'
67
+ | 'noreferrer'
68
+ | 'prev'
69
+ | 'search'
70
+ | 'tag'
71
+
72
+ export interface NavLinkProps {
73
+ to?: RouteLocationRaw | string | null
74
+ href?: string
75
+ target?: ATagTargetAttrValues
76
+ rel?: ATagRelAttrValues
77
+ }
78
+
79
+ export interface NavLink extends NavLinkProps, Partial<AclProperties> {
80
+ title: string
81
+ icon?: unknown
82
+ badgeContent?: string
83
+ badgeClass?: string
84
+ disable?: boolean
85
+ }
86
+
87
+ // 👉 Vertical nav group
88
+ export interface NavGroup extends Partial<AclProperties> {
89
+ title: string
90
+ icon?: unknown
91
+ badgeContent?: string
92
+ badgeClass?: string
93
+ children: (NavLink | NavGroup)[]
94
+ disable?: boolean
95
+ }
96
+
97
+ export declare type VerticalNavItems = (NavLink | NavGroup | NavSectionTitle)[]
98
+ export declare type HorizontalNavItems = (NavLink | NavGroup)[]
99
+
100
+ // 👉 Components ========================
101
+
102
+ export interface I18nLanguage {
103
+ label: string
104
+ i18nLang: string
105
+ isRTL: boolean
106
+ }
107
+
108
+ // avatar | text | icon
109
+ // Thanks: https://stackoverflow.com/a/60617060/10796681
110
+ export type Notification = {
111
+ id: number
112
+ title: string
113
+ subtitle: string
114
+ time: string
115
+ color?: string
116
+ isSeen: boolean
117
+ } & (
118
+ | { img: string; text?: never; icon?: never }
119
+ | { img?: never; text: string; icon?: never }
120
+ | { img?: never; text?: never; icon: string }
121
+ )
122
+
123
+ export interface ThemeSwitcherTheme {
124
+ name: string
125
+ icon: string
126
+ }