@sbc-connect/nuxt-base 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +11 -1
- package/CHANGELOG.md +45 -0
- package/LICENSE +28 -0
- package/README.md +36 -47
- package/app/app.config.ts +60 -5
- package/app/app.vue +16 -3
- package/app/components/Connect/BCGovLogo.vue +42 -0
- package/app/components/Connect/Breadcrumb.vue +61 -0
- package/app/components/Connect/Footer.vue +104 -0
- package/app/components/Connect/Header/LogoHomeLink.vue +20 -0
- package/app/components/Connect/Header/WhatsNew.vue +36 -0
- package/app/components/Connect/Header/Wrapper.vue +14 -0
- package/app/components/Connect/Header/index.vue +18 -0
- package/app/components/Connect/LocaleSelect.vue +37 -0
- package/app/components/Connect/Slideover/WhatsNew.vue +61 -0
- package/app/components/Connect/SystemBanner.vue +50 -0
- package/app/components/HelloWorld/Index.vue +2 -2
- package/app/composables/useConnectLaunchDarkly.ts +177 -0
- package/app/error.vue +53 -0
- package/app/interfaces/connect-breadcrumb.ts +5 -0
- package/app/interfaces/connect-whatsnew.ts +14 -0
- package/app/layouts/{default.vue → ConnectBase.vue} +4 -0
- package/app/plugins/launchdarkly.client.ts +9 -0
- package/app/plugins/sanitize.client.ts +13 -0
- package/app/plugins/whats-new.client.ts +45 -0
- package/app/spa-loading-template.html +39 -0
- package/app/utils/appendUrlParam.ts +4 -0
- package/i18n/locales/en-CA.ts +63 -0
- package/i18n/locales/fr-CA.ts +91 -0
- package/modules/assets/index.ts +2 -2
- package/modules/assets/runtime/assets/core-layout.css +3 -3
- package/modules/assets/runtime/assets/core-tw.css +71 -52
- package/nuxt.config.ts +89 -1
- package/package.json +19 -10
- package/eslint.config.ts +0 -3
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const { $sanitize } = useNuxtApp()
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
items: ConnectWhatsNewItem[]
|
|
6
|
+
}>()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<USlideover
|
|
11
|
+
:title="$t('connect.label.whatsNewSlideover')"
|
|
12
|
+
:description="$t('connect.text.whatsNewSlideoverDescription')"
|
|
13
|
+
:overlay="false"
|
|
14
|
+
:close="{
|
|
15
|
+
color: 'neutral',
|
|
16
|
+
variant: 'ghost',
|
|
17
|
+
class: 'cursor-pointer hover:bg-gray-100/50 focus-visible:bg-transparent focus-visible:ring-2 rounded-full',
|
|
18
|
+
}"
|
|
19
|
+
:ui="{
|
|
20
|
+
header: 'bg-brandLight',
|
|
21
|
+
title: 'text-brandDark',
|
|
22
|
+
body: 'flex-1 overflow-y-auto p-0 sm:p-0',
|
|
23
|
+
description: 'sr-only',
|
|
24
|
+
}"
|
|
25
|
+
>
|
|
26
|
+
<template #body>
|
|
27
|
+
<div class="overflow-y-auto text-neutral">
|
|
28
|
+
<div class="flex-1">
|
|
29
|
+
<ol v-if="items.length">
|
|
30
|
+
<li
|
|
31
|
+
v-for="item, i in items"
|
|
32
|
+
:key="i"
|
|
33
|
+
class="flex flex-col border-b border-gray-500 p-4 last:border-0"
|
|
34
|
+
>
|
|
35
|
+
<h3 class="text-lg font-bold">
|
|
36
|
+
{{ item.title }}
|
|
37
|
+
</h3>
|
|
38
|
+
<time class="text-sm">{{ item.date }}</time>
|
|
39
|
+
<!-- eslint-disable vue/no-v-html -->
|
|
40
|
+
<div
|
|
41
|
+
class="pt-3 vhtml"
|
|
42
|
+
v-html="$sanitize(item.description)"
|
|
43
|
+
/>
|
|
44
|
+
</li>
|
|
45
|
+
</ol>
|
|
46
|
+
<div v-else class="flex justify-center py-10">
|
|
47
|
+
<span>{{ $t('connect.text.whatsNewSlideoverEmpty') }}</span>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</template>
|
|
52
|
+
</USlideover>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<!-- must style globally for vhtml style to work -->
|
|
56
|
+
<style>
|
|
57
|
+
.vhtml a {
|
|
58
|
+
color: var(--ui-markBlue);
|
|
59
|
+
text-decoration: underline;
|
|
60
|
+
}
|
|
61
|
+
</style>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const ld = useConnectLaunchDarkly()
|
|
3
|
+
const { $sanitize } = useNuxtApp()
|
|
4
|
+
|
|
5
|
+
defineProps({
|
|
6
|
+
dismissible: { type: Boolean, default: false },
|
|
7
|
+
icon: { type: String, default: 'i-mdi-information' }
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const close = ref(false)
|
|
11
|
+
const message = ref('')
|
|
12
|
+
onMounted(async () => {
|
|
13
|
+
message.value = $sanitize(await ld.getStoredFlag('banner-text', '', 'await'))
|
|
14
|
+
})
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<template>
|
|
18
|
+
<div class="bg-brandLight px-2">
|
|
19
|
+
<UAlert
|
|
20
|
+
v-show="!!message && !close"
|
|
21
|
+
class="py-0"
|
|
22
|
+
:description="message"
|
|
23
|
+
:close="dismissible"
|
|
24
|
+
close-icon="i-mdi-close"
|
|
25
|
+
:ui="{
|
|
26
|
+
root: 'rounded-none bg-brandLight p-0 app-inner-container',
|
|
27
|
+
wrapper: 'bg-brandLight',
|
|
28
|
+
close: 'mt-2 text-neutralDark',
|
|
29
|
+
}"
|
|
30
|
+
@update:open="close = true"
|
|
31
|
+
>
|
|
32
|
+
<!-- dismissible ? { class: 'pr-2 text-neutralDark' } : null -->
|
|
33
|
+
<template #description>
|
|
34
|
+
<div class="flex gap-2 items-center py-2">
|
|
35
|
+
<UIcon class="size-7 shrink-0 text-neutralDark self-start" :name="icon" />
|
|
36
|
+
<!-- eslint-disable vue/no-v-html tailwindcss/no-custom-classname -->
|
|
37
|
+
<p class="vhtml text-neutralDark" v-html="message" />
|
|
38
|
+
</div>
|
|
39
|
+
</template>
|
|
40
|
+
</UAlert>
|
|
41
|
+
</div>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<!-- must style globally for vhtml style to work -->
|
|
45
|
+
<style>
|
|
46
|
+
.vhtml > a {
|
|
47
|
+
color: var(--ui-neutralDark);
|
|
48
|
+
text-decoration: underline;
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
@@ -7,8 +7,8 @@ const { myLayer } = useAppConfig()
|
|
|
7
7
|
Should have bg-primary
|
|
8
8
|
<h1>Hello World!</h1>
|
|
9
9
|
<pre>{{ myLayer }}</pre>
|
|
10
|
-
<p class="text-
|
|
11
|
-
Hello World text base should be
|
|
10
|
+
<p class="text-gray-900">
|
|
11
|
+
Hello World text base should be gray-900
|
|
12
12
|
</p>
|
|
13
13
|
</div>
|
|
14
14
|
</template>
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { initialize } from 'launchdarkly-js-client-sdk'
|
|
2
|
+
import type { LDClient, LDFlagSet, LDOptions, LDContext } from 'launchdarkly-js-client-sdk'
|
|
3
|
+
|
|
4
|
+
// state
|
|
5
|
+
// Defined outside of composable, so they are created only once and shared
|
|
6
|
+
const ldClient = shallowRef<LDClient | null>(null)
|
|
7
|
+
const ldFlagSet = shallowRef<LDFlagSet>({})
|
|
8
|
+
const ldInitialized = ref(false)
|
|
9
|
+
const isInitializing = ref(false)
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Initializes the LaunchDarkly client with an anonymous context.
|
|
13
|
+
*/
|
|
14
|
+
function init(): void {
|
|
15
|
+
const rtc = useRuntimeConfig().public
|
|
16
|
+
|
|
17
|
+
// Prevent re-initialization
|
|
18
|
+
if (ldInitialized.value || isInitializing.value) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
// Prevent initialization if missing client ID
|
|
22
|
+
if (!rtc.ldClientId) {
|
|
23
|
+
console.error('LaunchDarkly: ldClientId is not configured.')
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
isInitializing.value = true
|
|
28
|
+
|
|
29
|
+
const ldContext: LDContext = {
|
|
30
|
+
kind: 'user',
|
|
31
|
+
key: 'anonymous',
|
|
32
|
+
anonymous: true,
|
|
33
|
+
appSource: rtc.appName
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const options: LDOptions = {
|
|
37
|
+
streaming: false,
|
|
38
|
+
useReport: false,
|
|
39
|
+
diagnosticOptOut: true
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
ldClient.value = initialize(rtc.ldClientId, ldContext, options)
|
|
44
|
+
|
|
45
|
+
ldClient.value.on('initialized', () => {
|
|
46
|
+
ldFlagSet.value = ldClient.value?.allFlags() || {}
|
|
47
|
+
ldInitialized.value = true
|
|
48
|
+
isInitializing.value = false
|
|
49
|
+
console.info('LaunchDarkly: Anonymous initialization complete.')
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
ldClient.value.on('error', (error) => {
|
|
53
|
+
console.error('LaunchDarkly: Initialization error.', error)
|
|
54
|
+
isInitializing.value = false
|
|
55
|
+
})
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('LaunchDarkly: Failed to initialize.', error)
|
|
58
|
+
isInitializing.value = false
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Composable for the LaunchDarkly service.
|
|
64
|
+
*/
|
|
65
|
+
export const useConnectLaunchDarkly = () => {
|
|
66
|
+
// initialize only once
|
|
67
|
+
if (!ldInitialized.value && !isInitializing.value && import.meta.client) {
|
|
68
|
+
init()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Returns a flag's value. Can operate in two modes.
|
|
73
|
+
* @param name The name of the feature flag.
|
|
74
|
+
* @param defaultValue The value to use until the flag is loaded.
|
|
75
|
+
* @param mode - 'reactive' (default) returns a ref that updates automatically.
|
|
76
|
+
* 'await' returns a promise that resolves when the client is ready.
|
|
77
|
+
* @returns A readonly ref or a promise resolving to the flag's value.
|
|
78
|
+
*/
|
|
79
|
+
function getFeatureFlag<T>(
|
|
80
|
+
name: string,
|
|
81
|
+
defaultValue: T,
|
|
82
|
+
mode: 'await'
|
|
83
|
+
): Promise<T>
|
|
84
|
+
function getFeatureFlag<T>(
|
|
85
|
+
name: string,
|
|
86
|
+
defaultValue?: T,
|
|
87
|
+
mode?: 'reactive'
|
|
88
|
+
): Readonly<Ref<T>>
|
|
89
|
+
function getFeatureFlag<T>(
|
|
90
|
+
name: string,
|
|
91
|
+
defaultValue: T,
|
|
92
|
+
mode: 'reactive' | 'await' = 'reactive'
|
|
93
|
+
): Readonly<Ref<T>> | Promise<T> {
|
|
94
|
+
if (mode === 'await') {
|
|
95
|
+
if (!ldClient.value) {
|
|
96
|
+
return Promise.resolve(defaultValue)
|
|
97
|
+
}
|
|
98
|
+
return ldClient.value.waitUntilReady()
|
|
99
|
+
.then(() => ldClient.value ? ldClient.value.variation(name, defaultValue) : defaultValue)
|
|
100
|
+
.catch((error) => {
|
|
101
|
+
console.error(`LaunchDarkly: Error waiting for client while getting flag "${name}".`, error)
|
|
102
|
+
return defaultValue
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// reactive mode
|
|
107
|
+
return readonly(computed(() => {
|
|
108
|
+
if (!ldClient.value || !ldInitialized.value) {
|
|
109
|
+
return defaultValue
|
|
110
|
+
}
|
|
111
|
+
return ldClient.value.variation(name, defaultValue)
|
|
112
|
+
}))
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Returns a flag's value from the locally stored flag set. Can operate in two modes.
|
|
117
|
+
* @param name The name of the feature flag.
|
|
118
|
+
* @param defaultValue The value to use until the flag is loaded.
|
|
119
|
+
* @param mode - 'reactive' (default) returns a ref that updates automatically.
|
|
120
|
+
* 'await' returns a promise that resolves when the client is ready.
|
|
121
|
+
* @returns A readonly ref or a promise resolving to the flag's value.
|
|
122
|
+
*/
|
|
123
|
+
async function getStoredFlag<T>(name: string, defaultValue: T, mode: 'await'): Promise<T>
|
|
124
|
+
function getStoredFlag<T>(name: string, defaultValue?: T, mode?: 'reactive'): Readonly<Ref<T>>
|
|
125
|
+
function getStoredFlag<T>(
|
|
126
|
+
name: string,
|
|
127
|
+
defaultValue: T,
|
|
128
|
+
mode: 'reactive' | 'await' = 'reactive'
|
|
129
|
+
): Readonly<Ref<T>> | Promise<T> {
|
|
130
|
+
if (mode === 'await') {
|
|
131
|
+
if (!ldClient.value) {
|
|
132
|
+
return Promise.resolve(defaultValue)
|
|
133
|
+
}
|
|
134
|
+
return ldClient.value.waitUntilReady()
|
|
135
|
+
.then(() => ldFlagSet.value[name] ?? defaultValue)
|
|
136
|
+
.catch((error) => {
|
|
137
|
+
console.error(`LaunchDarkly: Error waiting for client while getting stored flag "${name}".`, error)
|
|
138
|
+
return defaultValue
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// reactive mode
|
|
143
|
+
return readonly(computed(() => {
|
|
144
|
+
if (!ldInitialized.value) {
|
|
145
|
+
return defaultValue
|
|
146
|
+
}
|
|
147
|
+
return ldFlagSet.value[name] ?? defaultValue
|
|
148
|
+
}))
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// TODO: or do we do this and then everytime the fn is called its required to use await?
|
|
152
|
+
// TODO: returning the computed means we dont need to add LD to middleware
|
|
153
|
+
// async function getStoredFlag(name: string): Promise<unknown> {
|
|
154
|
+
// await ldClient.value?.waitUntilReady()
|
|
155
|
+
// return ldFlagSet.value[name]
|
|
156
|
+
// }
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Resets the LaunchDarkly state and closes the client connection.
|
|
160
|
+
*/
|
|
161
|
+
const $reset = () => {
|
|
162
|
+
ldInitialized.value = false
|
|
163
|
+
isInitializing.value = false
|
|
164
|
+
ldClient.value?.close()
|
|
165
|
+
ldClient.value = null
|
|
166
|
+
ldFlagSet.value = {}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
getFeatureFlag,
|
|
171
|
+
getStoredFlag,
|
|
172
|
+
ldInitialized: readonly(ldInitialized),
|
|
173
|
+
ldFlagSet: readonly(ldFlagSet),
|
|
174
|
+
ldClient: readonly(ldClient),
|
|
175
|
+
$reset
|
|
176
|
+
}
|
|
177
|
+
}
|
package/app/error.vue
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { NuxtError } from '#app'
|
|
3
|
+
|
|
4
|
+
const { t } = useI18n()
|
|
5
|
+
const localePath = useLocalePath()
|
|
6
|
+
|
|
7
|
+
const props = defineProps({
|
|
8
|
+
error: { type: Object as () => NuxtError, default: undefined }
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
// TODO: update with other error codes?
|
|
12
|
+
const errorKey: string | number = props.error?.statusCode === 404 ? 404 : 'unknown'
|
|
13
|
+
|
|
14
|
+
// cant use definePageMeta in error.vue
|
|
15
|
+
useRoute().meta.hideBreadcrumbs = true
|
|
16
|
+
|
|
17
|
+
useHead({
|
|
18
|
+
title: errorKey === 404 ? t('connect.page.error.404.title') : t('connect.page.error.unknown.title')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const errorObj = {
|
|
22
|
+
name: props.error?.name || '',
|
|
23
|
+
cause: props.error?.cause || '',
|
|
24
|
+
message: props.error?.message || '',
|
|
25
|
+
statusCode: props.error?.statusCode || '',
|
|
26
|
+
statusMessage: props.error?.statusMessage || '',
|
|
27
|
+
stack: props.error?.stack || '',
|
|
28
|
+
data: props.error?.data || ''
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
onMounted(() => {
|
|
32
|
+
console.error('Application Error: ', errorObj)
|
|
33
|
+
})
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<template>
|
|
37
|
+
<UApp :toaster="{ position: 'bottom-center' }">
|
|
38
|
+
<NuxtLayout name="connect-base">
|
|
39
|
+
<div class="m-auto flex flex-col items-center gap-4 h-full justify-center">
|
|
40
|
+
<h1>
|
|
41
|
+
{{ $t(`connect.page.error.${errorKey}.h1`) }}
|
|
42
|
+
</h1>
|
|
43
|
+
<p>{{ $t(`connect.page.error.${errorKey}.content`) }}</p>
|
|
44
|
+
<UButton
|
|
45
|
+
:label="$t('connect.label.goHome')"
|
|
46
|
+
icon="i-mdi-home"
|
|
47
|
+
size="xl"
|
|
48
|
+
:to="localePath('/')"
|
|
49
|
+
/>
|
|
50
|
+
</div>
|
|
51
|
+
</NuxtLayout>
|
|
52
|
+
</UApp>
|
|
53
|
+
</template>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ConnectWhatsNewItem {
|
|
2
|
+
app: string
|
|
3
|
+
date: string
|
|
4
|
+
description: string
|
|
5
|
+
id: number
|
|
6
|
+
priority: boolean
|
|
7
|
+
read: boolean
|
|
8
|
+
title: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ConnectWhatsNewState {
|
|
12
|
+
viewed: boolean
|
|
13
|
+
items: ConnectWhatsNewItem[]
|
|
14
|
+
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="app-container">
|
|
3
|
+
<ConnectHeader />
|
|
4
|
+
<ConnectSystemBanner />
|
|
5
|
+
<ConnectBreadcrumb />
|
|
3
6
|
<div class="app-inner-container app-body">
|
|
4
7
|
<div class="flex flex-col lg:flex-row lg:gap-6 grow">
|
|
5
8
|
<div class="grow max-w-full overflow-hidden">
|
|
@@ -7,5 +10,6 @@
|
|
|
7
10
|
</div>
|
|
8
11
|
</div>
|
|
9
12
|
</div>
|
|
13
|
+
<ConnectFooter />
|
|
10
14
|
</div>
|
|
11
15
|
</template>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { useStorage } from '@vueuse/core'
|
|
2
|
+
import isEqual from 'lodash-es/isEqual'
|
|
3
|
+
|
|
4
|
+
export default defineNuxtPlugin({
|
|
5
|
+
name: 'connect-whats-new-plugin',
|
|
6
|
+
parallel: true,
|
|
7
|
+
setup(nuxtApp) {
|
|
8
|
+
// exit early if whats new === false
|
|
9
|
+
const whatsNew = useAppConfig().connect.header.whatsNew
|
|
10
|
+
if (!whatsNew) {
|
|
11
|
+
return
|
|
12
|
+
}
|
|
13
|
+
const rtc = useRuntimeConfig().public
|
|
14
|
+
const url = rtc.statusApiUrl + rtc.statusApiVersion
|
|
15
|
+
|
|
16
|
+
// load whats new only once when app mounts
|
|
17
|
+
nuxtApp.hook('app:mounted', async () => {
|
|
18
|
+
// set default localStorage state
|
|
19
|
+
const state = useStorage<ConnectWhatsNewState>(
|
|
20
|
+
'connect-whats-new', // storage key
|
|
21
|
+
{ viewed: false, items: [] }, // default value
|
|
22
|
+
localStorage, // could change this to sessionStorage
|
|
23
|
+
{ mergeDefaults: true } // merge anything already in localStorage with default value
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
// fetch items
|
|
28
|
+
const res = await $fetch<ConnectWhatsNewItem[]>(`${url}/whatsnew`, {
|
|
29
|
+
parseResponse: JSON.parse, // required to parse JSON correctly
|
|
30
|
+
headers: {
|
|
31
|
+
'App-Name': rtc.appName
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
// only update value if new items exist
|
|
36
|
+
if (!isEqual(state.value.items, res) && res.length > 0) {
|
|
37
|
+
state.value.items = res
|
|
38
|
+
state.value.viewed = false
|
|
39
|
+
}
|
|
40
|
+
} catch {
|
|
41
|
+
// silently handle errors
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
})
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<div class="loader"></div>
|
|
2
|
+
<style>
|
|
3
|
+
.loader {
|
|
4
|
+
display: block;
|
|
5
|
+
position: fixed;
|
|
6
|
+
z-index: 1031;
|
|
7
|
+
top: 50%;
|
|
8
|
+
left: 50%;
|
|
9
|
+
transform: translate(-50%, -50%);
|
|
10
|
+
width: 50px;
|
|
11
|
+
height: 50px;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
border: solid 5px transparent;
|
|
14
|
+
border-top-color: #1669bb;
|
|
15
|
+
border-left-color: #1669bb;
|
|
16
|
+
border-bottom-color: #efefef;
|
|
17
|
+
border-right-color: #efefef;
|
|
18
|
+
border-radius: 50%;
|
|
19
|
+
-webkit-animation: loader 400ms linear infinite;
|
|
20
|
+
animation: loader 400ms linear infinite;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@-webkit-keyframes loader {
|
|
24
|
+
0% {
|
|
25
|
+
-webkit-transform: translate(-50%, -50%) rotate(0deg);
|
|
26
|
+
}
|
|
27
|
+
100% {
|
|
28
|
+
-webkit-transform: translate(-50%, -50%) rotate(360deg);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
@keyframes loader {
|
|
32
|
+
0% {
|
|
33
|
+
transform: translate(-50%, -50%) rotate(0deg);
|
|
34
|
+
}
|
|
35
|
+
100% {
|
|
36
|
+
transform: translate(-50%, -50%) rotate(360deg);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
</style>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
/* Ordering should be alphabetical unless otherwise specified */
|
|
3
|
+
connect: {
|
|
4
|
+
breadcrumb: {
|
|
5
|
+
/* Only include breadcrumb values that extended apps may overwrite */
|
|
6
|
+
arialabel: 'Breadcrumb',
|
|
7
|
+
default: 'Service BC Connect'
|
|
8
|
+
},
|
|
9
|
+
footer: {
|
|
10
|
+
/* Only include footer values that extended apps may overwrite */
|
|
11
|
+
navLabel: 'Useful Links' // <nav> aria-label
|
|
12
|
+
},
|
|
13
|
+
header: {
|
|
14
|
+
/* Only include header values that extended apps may overwrite */
|
|
15
|
+
homeLink: 'Home', // aria-label
|
|
16
|
+
navLabel: 'Main Navigation', // <nav> aria-label
|
|
17
|
+
title: 'Service BC Connect'
|
|
18
|
+
},
|
|
19
|
+
label: {
|
|
20
|
+
accessibility: 'Accessibility',
|
|
21
|
+
appVersion: 'App Version',
|
|
22
|
+
bcApp: 'A BC Online Application',
|
|
23
|
+
bcGovLogo: 'Government of British Columbia Logo',
|
|
24
|
+
copyright: 'Copyright',
|
|
25
|
+
disclaimer: 'Disclaimer',
|
|
26
|
+
fees: 'Fees',
|
|
27
|
+
goBack: 'Go Back',
|
|
28
|
+
goHome: 'Go Home',
|
|
29
|
+
home: 'Home',
|
|
30
|
+
localeSelect: 'Select a Language, current language: English',
|
|
31
|
+
privacy: 'Privacy',
|
|
32
|
+
releaseNotes: 'Release Notes',
|
|
33
|
+
whatsNew: "What's New",
|
|
34
|
+
whatsNewAria: "What's New, {count} unread",
|
|
35
|
+
whatsNewSlideover: "What's New at BC Registries"
|
|
36
|
+
},
|
|
37
|
+
page: {
|
|
38
|
+
error: {
|
|
39
|
+
404: {
|
|
40
|
+
title: 'Page Not Found - Service BC Connect',
|
|
41
|
+
h1: '404 Page Not Found',
|
|
42
|
+
content: 'This page could not be found or does not exist.'
|
|
43
|
+
},
|
|
44
|
+
unknown: {
|
|
45
|
+
title: 'Unknown Error - Service BC Connect',
|
|
46
|
+
h1: 'Unknown Error',
|
|
47
|
+
content: 'An unknown error occured, please refresh the page or try again later.'
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
text: {
|
|
52
|
+
whatsNewSlideoverDescription: ' ',
|
|
53
|
+
whatsNewSlideoverEmpty: 'No new items.'
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
test: {
|
|
57
|
+
i18nBold: {
|
|
58
|
+
strong: 'This should have {boldStart} bold {boldEnd} text',
|
|
59
|
+
strongWithProps: 'This should have {boldStart} bold {boldEnd} text and allow a {prop}',
|
|
60
|
+
italic: 'Italic test {italicStart} goes here {italicEnd}.'
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
2
|
+
export default {
|
|
3
|
+
/* Ordering should be alphabetical unless otherwise specified */
|
|
4
|
+
connect: {
|
|
5
|
+
breadcrumb: {
|
|
6
|
+
/* Only include breadcrumb values that extended apps may overwrite */
|
|
7
|
+
arialabel: "Fil d'Ariane",
|
|
8
|
+
default: 'Service Connect CB'
|
|
9
|
+
},
|
|
10
|
+
footer: {
|
|
11
|
+
/* Only include footer values that extended apps may overwrite */
|
|
12
|
+
navLabel: 'Liens utiles' // <nav> aria-label
|
|
13
|
+
},
|
|
14
|
+
header: {
|
|
15
|
+
/* Only include header values that extended apps may overwrite */
|
|
16
|
+
homeLink: 'Accueil', // aria-label
|
|
17
|
+
navLabel: 'Navigation principale', // <nav> aria-label
|
|
18
|
+
title: 'Service Connect CB'
|
|
19
|
+
},
|
|
20
|
+
label: {
|
|
21
|
+
accessibility: 'Accessibilité',
|
|
22
|
+
appVersion: "Version de l'Application",
|
|
23
|
+
bcApp: 'Une application en ligne CB',
|
|
24
|
+
bcGovLogo: 'Logo du gouvernement de la Colombie-Britannique',
|
|
25
|
+
copyright: "Droits d'auteur",
|
|
26
|
+
disclaimer: 'Clause de non-responsabilité',
|
|
27
|
+
fees: 'Frais',
|
|
28
|
+
goBack: 'Retour',
|
|
29
|
+
home: 'Accueil',
|
|
30
|
+
localeSelect: 'Sélectionnez une langue, langue courante: Français',
|
|
31
|
+
privacy: 'Confidentialité',
|
|
32
|
+
releaseNotes: 'Notes de Version'
|
|
33
|
+
},
|
|
34
|
+
text: {}
|
|
35
|
+
},
|
|
36
|
+
btn: {
|
|
37
|
+
bcRegHome: 'Accueil des Registres de la CB',
|
|
38
|
+
createAccount: 'Créer un Compte',
|
|
39
|
+
editProfile: 'Editer le Profil',
|
|
40
|
+
logout: 'Se déconnecter',
|
|
41
|
+
login: 'Se connecter',
|
|
42
|
+
accountInfo: 'Infos Compte',
|
|
43
|
+
teamMembers: 'Membres Équipe',
|
|
44
|
+
transactions: 'Transactions',
|
|
45
|
+
notifications: {
|
|
46
|
+
main: 'Notifications',
|
|
47
|
+
aria: 'Notifications, {count} Nouveau'
|
|
48
|
+
},
|
|
49
|
+
accountOptionsMenu: 'Menu Options du Compte',
|
|
50
|
+
whatsNew: 'Quoi de Neuf',
|
|
51
|
+
mainMenu: 'Menu principal',
|
|
52
|
+
goHome: "Retour à l'Accueil"
|
|
53
|
+
},
|
|
54
|
+
label: {
|
|
55
|
+
accountSettings: 'Paramètres Compte',
|
|
56
|
+
bcRegOLServices: 'Registres et Services en ligne de la CB',
|
|
57
|
+
switchAccount: 'Changer de Compte',
|
|
58
|
+
selectLoginMethod: 'Sélectionnez la méthode de connexion',
|
|
59
|
+
bcsc: 'BC Services Card',
|
|
60
|
+
bceid: 'BCeID',
|
|
61
|
+
idir: 'IDIR',
|
|
62
|
+
whatsNewSlideover: 'Nouveautés aux Registres de la CB'
|
|
63
|
+
},
|
|
64
|
+
notifications: {
|
|
65
|
+
none: 'Aucune Notification',
|
|
66
|
+
teamMemberApproval: "{count} membre de l'équipe doit être approuvé pour accéder à ce compte. | {count} membres de l'équipe doivent être approuvés pour accéder à ce compte."
|
|
67
|
+
},
|
|
68
|
+
ConnectPage: {
|
|
69
|
+
error: {
|
|
70
|
+
404: {
|
|
71
|
+
title: 'Page Introuvable - Service Connect CB',
|
|
72
|
+
h1: '404 Page Introuvable',
|
|
73
|
+
content: 'Cette page est introuvable ou n’existe pas.'
|
|
74
|
+
},
|
|
75
|
+
unknown: {
|
|
76
|
+
title: 'Erreur Inconnue - Service Connect CB',
|
|
77
|
+
h1: 'Erreur Inconnue',
|
|
78
|
+
content: 'Une erreur inconnue s’est produite, veuillez actualiser la page ou réessayer plus tard.'
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
ConnectModalSessionExpiring: {
|
|
83
|
+
title: "Session Sur Le Point D'Expirer",
|
|
84
|
+
content: "Votre session est sur le point d'expirer en raison d'inactivité. Vous serez déconnecté dans {boldStart}0{boldEnd} secondes. Appuyez sur n’importe quelle touche pour continuer votre session. | Votre session est sur le point d'expirer en raison d'inactivité. Vous serez déconnecté dans {boldStart}1{boldEnd} seconde. Appuyez sur n’importe quelle touche pour continuer votre session. | Votre session est sur le point d'expirer en raison d'inactivité. Vous serez déconnecté dans {boldStart}{count}{boldEnd} secondes. Appuyez sur n’importe quelle touche pour continuer votre session.",
|
|
85
|
+
sessionExpired: 'Session Expirée',
|
|
86
|
+
continueBtn: {
|
|
87
|
+
main: 'Continuer la Session',
|
|
88
|
+
aria: "Votre session est sur le point d'expirer, appuyez sur n'importe quelle touche pour continuer votre session."
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
package/modules/assets/index.ts
CHANGED
|
@@ -13,12 +13,12 @@ export default defineNuxtModule<ModuleOptions>({
|
|
|
13
13
|
// Default configuration options of the Nuxt module
|
|
14
14
|
defaults: {},
|
|
15
15
|
async setup(_options, _nuxt) {
|
|
16
|
-
console.info('
|
|
16
|
+
console.info('Setting up assets module')
|
|
17
17
|
const resolver = createResolver(import.meta.url)
|
|
18
18
|
|
|
19
19
|
_nuxt.options.css.push(resolver.resolve('./runtime/assets/core-tw.css'))
|
|
20
20
|
_nuxt.options.css.push(resolver.resolve('./runtime/assets/core-layout.css'))
|
|
21
|
-
_nuxt.options.css.push(resolver.resolve('./runtime/assets/core-main.css'))
|
|
21
|
+
// _nuxt.options.css.push(resolver.resolve('./runtime/assets/core-main.css'))
|
|
22
22
|
await installModule('@nuxt/ui')
|
|
23
23
|
}
|
|
24
24
|
})
|