@inriver/inri 1.0.0

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 (114) hide show
  1. package/.eslintrc.js +5 -0
  2. package/componentProperties.d.ts +8 -0
  3. package/configs/base-eslint-config.js +36 -0
  4. package/configs/base-tailwind-config.js +149 -0
  5. package/i18n.ts +11 -0
  6. package/index.ts +25 -0
  7. package/package.json +36 -0
  8. package/src/components/CAutoBreadcrumbs.vue +72 -0
  9. package/src/components/CBtn.vue +98 -0
  10. package/src/components/CColorPicker.vue +55 -0
  11. package/src/components/CContextMenu.vue +29 -0
  12. package/src/components/CDatePicker.vue +51 -0
  13. package/src/components/CDeleteTileBtn.vue +52 -0
  14. package/src/components/CDialog.vue +253 -0
  15. package/src/components/CDialogCloseBtn.vue +9 -0
  16. package/src/components/CDirtyCheck.vue +68 -0
  17. package/src/components/CDrawer.vue +44 -0
  18. package/src/components/CDrawerButton.vue +91 -0
  19. package/src/components/CExpansionItem.vue +57 -0
  20. package/src/components/CExpansionItemWithCheckbox.vue +41 -0
  21. package/src/components/CFileDropzone.vue +114 -0
  22. package/src/components/CGrid.vue +101 -0
  23. package/src/components/CHeader.vue +10 -0
  24. package/src/components/CHeaderLinks.vue +61 -0
  25. package/src/components/CHeaderMenuLink.vue +51 -0
  26. package/src/components/CHeaderSearch.vue +142 -0
  27. package/src/components/CIconBtn.vue +70 -0
  28. package/src/components/CMenuItem.vue +66 -0
  29. package/src/components/CPageContainer.vue +11 -0
  30. package/src/components/CPageError.vue +24 -0
  31. package/src/components/CPageSpinner.vue +18 -0
  32. package/src/components/CSearch.vue +45 -0
  33. package/src/components/CSection.vue +29 -0
  34. package/src/components/CSectionTitle.vue +8 -0
  35. package/src/components/CSelect.vue +208 -0
  36. package/src/components/CSlideEffect.vue +62 -0
  37. package/src/components/CSpinner.vue +107 -0
  38. package/src/components/CTableActions.vue +16 -0
  39. package/src/components/CTileBtn.vue +178 -0
  40. package/src/components/CTimePicker.vue +42 -0
  41. package/src/components/CToggleGridView.vue +26 -0
  42. package/src/components/CToggleSidebarBtn.vue +19 -0
  43. package/src/components/CTooltip.vue +44 -0
  44. package/src/components/CTreeNode.vue +39 -0
  45. package/src/components/cards/CBannerCard.vue +103 -0
  46. package/src/components/cards/CSmallCard.vue +149 -0
  47. package/src/components/internal-components/ConfirmDialog.vue +78 -0
  48. package/src/composables/useDialog.ts +47 -0
  49. package/src/composables/useDirtyCheck.ts +25 -0
  50. package/src/composables/useDoubleClickListener.ts +28 -0
  51. package/src/composables/useSelectable.ts +62 -0
  52. package/src/composables/useTruncateChips.ts +46 -0
  53. package/src/i18n/de/index.ts +17 -0
  54. package/src/i18n/en/index.ts +84 -0
  55. package/src/i18n/es/index.ts +7 -0
  56. package/src/i18n/fr/index.ts +7 -0
  57. package/src/init/initInriFramework.ts +25 -0
  58. package/src/init/useInriApp.ts +55 -0
  59. package/src/layouts/CLayoutBlank.vue +7 -0
  60. package/src/layouts/CLayoutWithBackButton.vue +50 -0
  61. package/src/layouts/CLayoutWithSidebars.vue +46 -0
  62. package/src/layouts/layout-fragments/CPageAutoBreadcrumbs.vue +6 -0
  63. package/src/layouts/layout-fragments/CPageBackButton.vue +18 -0
  64. package/src/layouts/layout-fragments/CPageBlank.vue +20 -0
  65. package/src/layouts/layout-fragments/CPageFlexCol.vue +5 -0
  66. package/src/layouts/layout-fragments/CPageLeftSidebar.vue +5 -0
  67. package/src/layouts/layout-fragments/CPageMainContent.vue +5 -0
  68. package/src/layouts/layout-fragments/CPageOuterWrapper.vue +5 -0
  69. package/src/layouts/layout-fragments/CPageRightSidebar.vue +5 -0
  70. package/src/layouts/layout-fragments/CPageTitle.vue +34 -0
  71. package/src/plugins/dialog.ts +45 -0
  72. package/src/plugins/errors/ErrorFactories.ts +59 -0
  73. package/src/plugins/errors/Errors.ts +156 -0
  74. package/src/plugins/errors/Exception.ts +6 -0
  75. package/src/plugins/errors/globalErrorHandler.ts +21 -0
  76. package/src/plugins/errors/handleError.ts +34 -0
  77. package/src/plugins/errors/logger.ts +16 -0
  78. package/src/plugins/errors/vueErrorHandler.ts +26 -0
  79. package/src/plugins/globalAppConfig.ts +25 -0
  80. package/src/plugins/i18n.ts +46 -0
  81. package/src/plugins/inriIcons.ts +58 -0
  82. package/src/plugins/inriverQuasarComponentConfigurations.ts +67 -0
  83. package/src/plugins/library.ts +119 -0
  84. package/src/plugins/notify.ts +153 -0
  85. package/src/plugins/quasar-user-options.ts +19 -0
  86. package/src/plugins/validationRules.ts +292 -0
  87. package/src/shims-vue.d.ts +6 -0
  88. package/src/stores/inriStore.ts +54 -0
  89. package/src/stores/interfaceLanguageStore.ts +27 -0
  90. package/src/styles/_css-variables.scss +101 -0
  91. package/src/styles/_reset.scss +67 -0
  92. package/src/styles/_transitions.scss +9 -0
  93. package/src/styles/_utils.scss +15 -0
  94. package/src/styles/components/_breadcrumbs.scss +3 -0
  95. package/src/styles/components/_checkboxes.scss +17 -0
  96. package/src/styles/components/_chips.scss +17 -0
  97. package/src/styles/components/_forms.scss +203 -0
  98. package/src/styles/components/_menu.scss +12 -0
  99. package/src/styles/components/_notifications.scss +24 -0
  100. package/src/styles/components/_q-editor.scss +14 -0
  101. package/src/styles/components/_radio-buttons.scss +17 -0
  102. package/src/styles/components/_tables.scss +92 -0
  103. package/src/styles/components/_tooltips.scss +5 -0
  104. package/src/styles/components/_tree.scss +86 -0
  105. package/src/styles/components/_truncated-chips.scss +39 -0
  106. package/src/styles/main.scss +45 -0
  107. package/src/styles/quasar.variables.scss +50 -0
  108. package/src/typings.d.ts +70 -0
  109. package/src/utils/colorUtils.ts +73 -0
  110. package/src/utils/errorUtils.ts +37 -0
  111. package/src/utils/fileUtils.ts +57 -0
  112. package/src/utils/helpers.ts +6 -0
  113. package/src/utils/routeUtils.ts +23 -0
  114. package/tsconfig.json +37 -0
@@ -0,0 +1,25 @@
1
+ import '../styles/main.scss'
2
+ import 'windi.css'
3
+ import { App } from 'vue'
4
+ import { Quasar } from 'quasar'
5
+ import quasarUserOptions from '../plugins/quasar-user-options'
6
+ import { registerComponents } from '../plugins/library'
7
+ import { registerAppConfigurations } from '../plugins/globalAppConfig'
8
+ import { i18n } from '../plugins/i18n'
9
+ import logger from '../plugins/errors/logger'
10
+ import { VueErrorHandler } from '../plugins/errors/vueErrorHandler'
11
+ import '../plugins/errors/globalErrorHandler'
12
+
13
+ export const initInriFramework = (Vue: App): void => {
14
+ // Register C-components
15
+ registerComponents(Vue)
16
+
17
+ // Register global application configurations
18
+ registerAppConfigurations(Vue)
19
+
20
+ Vue.use(Quasar, quasarUserOptions)
21
+ Vue.use(i18n)
22
+ Vue.use(VueErrorHandler)
23
+
24
+ logger.init()
25
+ }
@@ -0,0 +1,55 @@
1
+ import { initInriIcons } from '../plugins/inriIcons'
2
+ import { useRouter, RouteLocationNormalized } from 'vue-router'
3
+ import { watch } from 'vue'
4
+ import { getRouteTitle } from '../utils/routeUtils'
5
+ import { useMeta } from 'quasar'
6
+ import { useInriStore } from '../stores/inriStore'
7
+
8
+ export default function useInriApp () {
9
+ const router = useRouter()
10
+ const inriStore = useInriStore()
11
+
12
+ initInriIcons()
13
+
14
+ router.beforeResolve((to) => {
15
+ setPageTitle(to)
16
+ setRouteTheme(to)
17
+ })
18
+
19
+ watch(inriStore.isAnyDirty, (value) => (
20
+ setDirtyPageTitle(value)
21
+ ))
22
+
23
+ // Methods
24
+ function setPageTitle (to: RouteLocationNormalized) {
25
+ let pageTitle = ''
26
+
27
+ if (to.meta.title) {
28
+ pageTitle = getRouteTitle(to)
29
+ } else if (to.matched[0]) {
30
+ pageTitle = getRouteTitle(to.matched[0])
31
+ } else {
32
+ pageTitle = ''
33
+ }
34
+
35
+ document.title = pageTitle.length ? `inriver - ${pageTitle}` : 'inriver'
36
+ }
37
+
38
+ function setDirtyPageTitle (isDirty) {
39
+ if (isDirty) {
40
+ document.title = `* ${document.title}`
41
+ } else {
42
+ document.title = document.title.replace('* ', '')
43
+ }
44
+ }
45
+
46
+ function setRouteTheme (to) {
47
+ // This will create something like <body theme="route-demo-theme">
48
+ // It can then be used as a CSS selector for overriding colors
49
+ useMeta({
50
+ bodyAttr: {
51
+ theme: to.meta?.theme ? to.meta.theme : '',
52
+ },
53
+ })
54
+ }
55
+ }
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <c-page-blank>
3
+ <c-page-main-content class="px-15">
4
+ <slot />
5
+ </c-page-main-content>
6
+ </c-page-blank>
7
+ </template>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <c-page-blank class="border-t">
3
+ <c-page-flex-col>
4
+ <div
5
+ v-if="!hideTitle"
6
+ class="flex"
7
+ >
8
+ <c-page-back-button />
9
+ <c-page-title :title="title" />
10
+ </div>
11
+
12
+ <c-page-outer-wrapper>
13
+ <c-page-left-sidebar :style="{ width: leftSidebarWidth + 'px' }">
14
+ <slot name="left-sidebar" />
15
+ </c-page-left-sidebar>
16
+
17
+ <c-page-flex-col>
18
+ <c-page-auto-breadcrumbs v-if="showBreadcrumbs" />
19
+
20
+ <c-page-main-content>
21
+ <slot />
22
+ </c-page-main-content>
23
+ </c-page-flex-col>
24
+ </c-page-outer-wrapper>
25
+ </c-page-flex-col>
26
+
27
+ <c-page-right-sidebar :style="{ width: rightSidebarWidth + 'px' }">
28
+ <slot name="right-sidebar" />
29
+ </c-page-right-sidebar>
30
+ </c-page-blank>
31
+ </template>
32
+
33
+ <script setup lang="ts">
34
+ defineProps({
35
+ title: {
36
+ type: String,
37
+ default: undefined,
38
+ },
39
+ showBreadcrumbs: Boolean,
40
+ hideTitle: Boolean,
41
+ leftSidebarWidth: {
42
+ type: [String, Number],
43
+ default: '60',
44
+ },
45
+ rightSidebarWidth: {
46
+ type: [String, Number],
47
+ default: '60',
48
+ },
49
+ })
50
+ </script>
@@ -0,0 +1,46 @@
1
+ <template>
2
+ <c-page-blank class="border-t">
3
+ <c-page-flex-col>
4
+ <c-page-outer-wrapper>
5
+ <c-page-left-sidebar :style="{ width: leftSidebarWidth + 'px' }">
6
+ <slot name="left-sidebar" />
7
+ </c-page-left-sidebar>
8
+
9
+ <c-page-flex-col>
10
+ <div v-if="!hideTitle">
11
+ <c-page-title :title="title" />
12
+ </div>
13
+
14
+ <c-page-auto-breadcrumbs v-if="showBreadcrumbs" />
15
+
16
+ <c-page-main-content>
17
+ <slot />
18
+ </c-page-main-content>
19
+ </c-page-flex-col>
20
+ </c-page-outer-wrapper>
21
+ </c-page-flex-col>
22
+
23
+ <c-page-right-sidebar :style="{ width: rightSidebarWidth + 'px' }">
24
+ <slot name="right-sidebar" />
25
+ </c-page-right-sidebar>
26
+ </c-page-blank>
27
+ </template>
28
+
29
+ <script setup lang="ts">
30
+ defineProps({
31
+ title: {
32
+ type: String,
33
+ default: undefined,
34
+ },
35
+ showBreadcrumbs: Boolean,
36
+ hideTitle: Boolean,
37
+ leftSidebarWidth: {
38
+ type: [String, Number],
39
+ default: '60',
40
+ },
41
+ rightSidebarWidth: {
42
+ type: [String, Number],
43
+ default: '60',
44
+ },
45
+ })
46
+ </script>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <div>
3
+ <c-auto-breadcrumbs class="px-6 h-12 flex content-center" />
4
+ <q-separator />
5
+ </div>
6
+ </template>
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <c-tile-btn
3
+ v-if="parentRoute"
4
+ data-id="page-back-btn"
5
+ icon="inri-arrow"
6
+ class="rotate-180"
7
+ :tooltip-right="$t('inri.navigate_back')"
8
+ :to="{ name: parentRoute }"
9
+ />
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ import { computed } from 'vue'
14
+ import { useRoute } from 'vue-router'
15
+
16
+ const route = useRoute()
17
+ const parentRoute = computed(() => route.meta?.parent)
18
+ </script>
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <div class="c-page">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script lang="ts">
8
+ export default {
9
+ name: 'CFragmentPage',
10
+ }
11
+ </script>
12
+
13
+ <style scoped>
14
+ .c-page {
15
+ position: absolute;
16
+ width: 100%;
17
+ height: 100%;
18
+ display: flex;
19
+ }
20
+ </style>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="flex-1 flex flex-col h-full overflow-hidden flex-nowrap">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <aside class="min-w-15 border-r overflow-y-overlay overflow-x-hidden h-full">
3
+ <slot />
4
+ </aside>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <section class="h-full overflow-y-overlay flex-1 flex flex-col no-wrap">
3
+ <slot />
4
+ </section>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="flex overflow-hidden h-full">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <aside class="min-w-15 border-l overflow-y-overlay overflow-x-hidden h-full">
3
+ <slot />
4
+ </aside>
5
+ </template>
@@ -0,0 +1,34 @@
1
+ <template>
2
+ <div
3
+ class="flex-1 flex h-15 items-center overflow-hidden px-6"
4
+ :class="noBorder || 'border-b'"
5
+ >
6
+ <h1
7
+ data-id="page-title"
8
+ class="truncate flex-1"
9
+ >
10
+ {{ title || routeTitle }}
11
+ </h1>
12
+ </div>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ import { getRouteTitle } from '../../utils/routeUtils'
17
+ import { computed } from 'vue'
18
+ import { useRoute } from 'vue-router'
19
+
20
+ const route = useRoute()
21
+
22
+ defineProps({
23
+ title: {
24
+ type: String,
25
+ default: undefined,
26
+ },
27
+ noBorder: {
28
+ type: Boolean,
29
+ default: false,
30
+ },
31
+ })
32
+
33
+ const routeTitle = computed(() => getRouteTitle(route))
34
+ </script>
@@ -0,0 +1,45 @@
1
+ import { Dialog } from 'quasar'
2
+ import ConfirmDialog from '../components/internal-components/ConfirmDialog.vue'
3
+ import { i18n } from './i18n'
4
+
5
+ const t = i18n.global.t
6
+
7
+ interface ConfirmDialogProps {
8
+ title?: string,
9
+ text: string,
10
+ confirmButtonText?: string,
11
+ cancelButtonText?: string,
12
+ confirmButtonColor?: string,
13
+ }
14
+
15
+ export default {
16
+ confirm: (props: ConfirmDialogProps) => {
17
+ return Dialog.create({
18
+ component: ConfirmDialog,
19
+ componentProps: {
20
+ ...props,
21
+ },
22
+ })
23
+ },
24
+ info: (props: ConfirmDialogProps) => {
25
+ return Dialog.create({
26
+ component: ConfirmDialog,
27
+ componentProps: {
28
+ ...props,
29
+ confirmButtonText: props.confirmButtonText || t('inri.common.ok'),
30
+ hideCancelButton: true,
31
+ },
32
+ })
33
+ },
34
+ delete: (props: ConfirmDialogProps) => {
35
+ return Dialog.create({
36
+ component: ConfirmDialog,
37
+ componentProps: {
38
+ ...props,
39
+ title: props.title || t('inri.dialog.confirm_delete_title'),
40
+ confirmButtonText: props.confirmButtonText || t('inri.common.delete'),
41
+ confirmButtonColor: 'negative',
42
+ },
43
+ })
44
+ },
45
+ }
@@ -0,0 +1,59 @@
1
+ import {
2
+ BaseError,
3
+ BaseErrorArguments,
4
+ GenericError,
5
+ AxiosError,
6
+ UnauthorizedError,
7
+ NotFoundError,
8
+ FolderNotFoundError,
9
+ ServiceUnavailableError,
10
+ } from './Errors'
11
+ import axios from 'axios'
12
+
13
+ export class ErrorFactory {
14
+ static createHelpfulError (args: BaseErrorArguments): BaseError {
15
+ if (axios.isAxiosError(args.err)) {
16
+ return args.err.response
17
+ ? this.createHelpfulErrorResponse(args.err.response.status, args)
18
+ : new AxiosError(args)
19
+ }
20
+
21
+ return new GenericError(args)
22
+ }
23
+
24
+ static createHelpfulErrorResponse (errorCode: number, args: BaseErrorArguments): AxiosError {
25
+ switch (errorCode) {
26
+ case 401:
27
+ return new UnauthorizedError(args)
28
+ case 404:
29
+ return new NotFoundError(args)
30
+ case 408:
31
+ case 503:
32
+ case 504:
33
+ return new ServiceUnavailableError(args)
34
+ default:
35
+ return new AxiosError(args)
36
+ }
37
+ }
38
+ }
39
+
40
+ export class FolderErrorFactory extends ErrorFactory {
41
+ static createHelpfulError (args: BaseErrorArguments) {
42
+ return super.createHelpfulError(args)
43
+ }
44
+
45
+ static createHelpfulErrorResponse (errorCode: number, args: BaseErrorArguments): AxiosError {
46
+ switch (errorCode) {
47
+ case 401:
48
+ return new UnauthorizedError(args)
49
+ case 404:
50
+ return new FolderNotFoundError(args)
51
+ case 408:
52
+ case 503:
53
+ case 504:
54
+ return new ServiceUnavailableError(args)
55
+ default:
56
+ return new AxiosError(args)
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,156 @@
1
+ import { i18n } from '../i18n'
2
+
3
+ const $t = i18n.global.t
4
+ const $te = i18n.global.te
5
+
6
+ // ---------
7
+ // Interfaces
8
+ // ---------
9
+ export interface BaseError {
10
+ title: string,
11
+ msg: string,
12
+ err: any,
13
+ isAxiosError: boolean,
14
+ status?: number
15
+ }
16
+
17
+ export interface BaseErrorArguments {
18
+ defaultTitle?: string,
19
+ defaultMsg?: string,
20
+ title?: string,
21
+ msg?: string,
22
+ err: any
23
+ }
24
+
25
+ // ---------
26
+ // Implementations
27
+ // ---------
28
+ export class GenericError implements BaseError {
29
+ title: string
30
+ msg: string
31
+ err: any
32
+ isAxiosError = false
33
+
34
+ constructor (
35
+ public args: BaseErrorArguments,
36
+ private defaultTitle = $t('inri.error.error'),
37
+ private defaultMsg = $t('inri.error.error_occurred'),
38
+ ) {
39
+ this.defaultTitle = args?.defaultTitle || this.defaultTitle
40
+ this.defaultMsg = args?.defaultMsg || this.defaultMsg
41
+ this.title = args?.title ?? this.defaultTitle
42
+ this.msg = args?.msg ?? this.defaultMsg
43
+ this.err = args.err
44
+
45
+ this.processError()
46
+ }
47
+
48
+ private processError () {
49
+ let errorMessage
50
+
51
+ if (this.err.type === 'unhandledrejection') {
52
+ errorMessage = this.err.reason?.toString() || $t('inri.error.unknown_error')
53
+ } else {
54
+ errorMessage = this.err.msg || this.err.toString()
55
+ }
56
+
57
+ if (this.msg === this.defaultMsg) {
58
+ this.msg = errorMessage
59
+ }
60
+ }
61
+ }
62
+
63
+ export class AxiosError implements BaseError {
64
+ title: string
65
+ msg: string
66
+ err: any
67
+ isAxiosError = true
68
+ status = -1
69
+
70
+ constructor (
71
+ public args: BaseErrorArguments,
72
+ private defaultTitle = $t('inri.error.network_error'),
73
+ private defaultMsg = $t('inri.error.error_occurred'),
74
+ ) {
75
+ this.title = args?.title ?? this.defaultTitle
76
+ this.msg = args?.msg ?? this.defaultMsg
77
+ this.err = args.err
78
+
79
+ this.processError()
80
+ }
81
+
82
+ private processError () {
83
+ let errorMessage
84
+
85
+ if (this.err.response) {
86
+ // The request was made and the server responded with a status code
87
+ // that falls out of the range of 2xx
88
+
89
+ this.status = this.err.response.status
90
+ errorMessage = $te(`inri.error.${this.err.response.data?.errorDescription}`)
91
+ ? $t(`inri.error.${this.err.response.data?.errorDescription}`)
92
+ : null
93
+ } else if (this.err.request) {
94
+ // The request was made but no response was received
95
+ // `this.err.request` is an instance of XMLHttpRequest in the browser and an instance of
96
+ // http.ClientRequest in node.js
97
+
98
+ this.status = this.err.request.status
99
+ errorMessage = this.err.request.statusText
100
+ } else {
101
+ // Something happened in setting up the request that triggered an Error
102
+
103
+ errorMessage = this.err.message
104
+ }
105
+
106
+ if (errorMessage && this.msg === this.defaultMsg) {
107
+ this.msg = errorMessage
108
+ }
109
+ }
110
+ }
111
+
112
+ // ---------
113
+ // Extensions
114
+ // ---------
115
+ export class UnauthorizedError extends AxiosError {
116
+ constructor (public args: BaseErrorArguments) {
117
+ super(
118
+ args,
119
+ $t('inri.error.unauthorized'),
120
+ $t('inri.error.session_expired'),
121
+ )
122
+ }
123
+ }
124
+
125
+ export class NotFoundError extends AxiosError {
126
+ constructor (public args: BaseErrorArguments) {
127
+ super(
128
+ args,
129
+ $t('inri.error.not_found'),
130
+ $t('inri.error.requested_asset_not_found'),
131
+ )
132
+ }
133
+ }
134
+
135
+ export class ServiceUnavailableError extends AxiosError {
136
+ constructor (public args: BaseErrorArguments) {
137
+ super(
138
+ args,
139
+ $t('inri.error.service_unavailable'),
140
+ $t('inri.error.service_unavailable_try_again'),
141
+ )
142
+ }
143
+ }
144
+
145
+ // ---------
146
+ // Specific error subtypes
147
+ // ---------
148
+ export class FolderNotFoundError extends AxiosError {
149
+ constructor (public args: BaseErrorArguments) {
150
+ super(
151
+ args,
152
+ $t('inri.error.not_found'),
153
+ $t('inri.error.could_not_retrieve_assets'),
154
+ )
155
+ }
156
+ }
@@ -0,0 +1,6 @@
1
+ export class Exception {
2
+ constructor (public msg: string, public error) {
3
+ this.msg = msg
4
+ this.error = error
5
+ }
6
+ }
@@ -0,0 +1,21 @@
1
+ import handleError from './handleError'
2
+
3
+ // Handle errors outside of components
4
+ window.addEventListener('error', (event) => {
5
+ handleError(
6
+ {
7
+ err: event,
8
+ caughtBy: 'window eventListener on error',
9
+ },
10
+ )
11
+ })
12
+
13
+ // Handle rejected promises outside components
14
+ window.addEventListener('unhandledrejection', (event) => {
15
+ handleError(
16
+ {
17
+ err: event,
18
+ caughtBy: 'window eventListener on unhandledrejection',
19
+ },
20
+ )
21
+ })
@@ -0,0 +1,34 @@
1
+ import { Exception } from './Exception'
2
+ import { ErrorFactory } from './ErrorFactories'
3
+ import logger from './logger'
4
+ import notify from '../notify'
5
+ import dialog from '../dialog'
6
+
7
+ export default function handleError (errInfoObj, vueInfoObj?) {
8
+ const err = errInfoObj.err
9
+
10
+ if (err instanceof Exception) {
11
+ const parsedError = ErrorFactory.createHelpfulError({
12
+ defaultMsg: err.msg,
13
+ err: err.error,
14
+ })
15
+
16
+ dialog.info({
17
+ title: parsedError.title,
18
+ text: parsedError.msg,
19
+ })
20
+
21
+ errInfoObj.handledBy = 'handleError'
22
+ logger.logTrace(errInfoObj, vueInfoObj)
23
+ } else if (err) {
24
+ const parsedError = ErrorFactory.createHelpfulError({ err })
25
+ notify.error(parsedError.msg)
26
+
27
+ if (err.type === 'unhandledrejection') {
28
+ errInfoObj.handledBy = '-'
29
+ logger.logTrace(errInfoObj, vueInfoObj)
30
+ } else {
31
+ logger.logException(err)
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,16 @@
1
+ export default {
2
+ init () {
3
+ // TODO: Init logger
4
+ },
5
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
6
+ logTrace (errInfoObj, vueInfoObj?) {
7
+ console.log('LOGGING TRACE')
8
+ console.log(errInfoObj)
9
+ // TODO: Log something
10
+ },
11
+ logException (error) {
12
+ console.log('LOGGING EXCEPTION')
13
+ console.log(error)
14
+ // TODO: Log something
15
+ },
16
+ }
@@ -0,0 +1,26 @@
1
+ import handleError from './handleError'
2
+ import { Exception } from './Exception'
3
+ import { ComponentPublicInstance } from 'vue'
4
+
5
+ export function VueErrorHandler (app) {
6
+ // Exception handling within Vue components
7
+ app.config.errorHandler = (err, vm: ComponentPublicInstance | null, info: string) => {
8
+ let exception
9
+
10
+ if (err instanceof Exception) {
11
+ exception = err
12
+ } else {
13
+ exception = new Exception(err.message, err)
14
+ }
15
+
16
+ handleError(
17
+ {
18
+ err: exception,
19
+ caughtBy: 'app.config.errorHandler',
20
+ },
21
+ {
22
+ info: info,
23
+ },
24
+ )
25
+ }
26
+ }