@live-change/user-frontend 0.9.177 → 0.9.180

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.
@@ -77,8 +77,13 @@
77
77
  "edit": "Edit",
78
78
  "view": "View",
79
79
  "close": "Close",
80
+ "ok": "OK",
81
+ "next": "Next",
80
82
  "testIndex": "Test Index",
81
- "addTestNotification": "Add test notification"
83
+ "addTestNotification": "Add test notification",
84
+ "rejected": "Rejected",
85
+ "rejectedDetail": "You have rejected",
86
+ "rememberMe": "Remember me"
82
87
  },
83
88
  "app": {
84
89
  "updateAvailable": "Update available!",
@@ -124,7 +129,9 @@
124
129
  "phone": "phone",
125
130
  "google": "Google",
126
131
  "linkedin": "LinkedIn",
127
- "github": "GitHub"
132
+ "github": "GitHub",
133
+ "accountConnected": "Account connected",
134
+ "accountConnectedSuccess": "Congratulations! You have successfully connected accounts."
128
135
  },
129
136
  "messageAuth": {
130
137
  "authenticationDone": "Authentication done",
@@ -140,23 +147,6 @@
140
147
  "linkExpiredDesc": "Your secret link already expired. To send another link click button below.",
141
148
  "resend": "Resend"
142
149
  },
143
- "common": {
144
- "or": "OR",
145
- "error": "Error",
146
- "success": "Success",
147
- "cancel": "Cancel",
148
- "save": "Save",
149
- "delete": "Delete",
150
- "edit": "Edit",
151
- "view": "View",
152
- "close": "Close",
153
- "ok": "OK",
154
- "next": "Next",
155
- "testIndex": "Test Index",
156
- "addTestNotification": "Add test notification",
157
- "rejected": "Rejected",
158
- "rejectedDetail": "You have rejected"
159
- },
160
150
  "deleteAccount": {
161
151
  "deleteAccount": "Delete account",
162
152
  "warning": "Account deletion is irreversible, check the box below only if you are 100% sure that you want to delete your account.",
@@ -235,5 +225,55 @@
235
225
  "openLink": "Or open authentication link:",
236
226
  "seeYouSoon": "See you soon",
237
227
  "teamSignature": "{brandName} Team"
228
+ },
229
+ "googleAuth": {
230
+ "title": "Google authentication",
231
+ "canceled": "Authentication canceled by user",
232
+ "waiting": "Waiting for server...",
233
+ "waitingForRedirect": "Authentication will open in this window.",
234
+ "error": "Error during authentication",
235
+ "errorWithColon": "Error during authentication:",
236
+ "unknownState": "Unknown authentication state: {state}",
237
+ "emailTaken": "Your account was created using email address. If you want to connect your Google account, you need to sign in with this email address. And connect your Google account using {link}.",
238
+ "emailTakenLink": "connected accounts page",
239
+ "invalidGrant": "Invalid grant. Please try again. You may used this link before, or google authentication failed.",
240
+ "connectedToAnotherUser": "This account is already connected to another user. Please sign in with your email address or google account.",
241
+ "emailAlreadyInUse": "Email is already in use",
242
+ "invalidGrantToast": "Invalid grant",
243
+ "connectedToAnotherUserToast": "Connected to another user",
244
+ "errorToast": "Error during google authentication"
245
+ },
246
+ "linkedinAuth": {
247
+ "title": "Linkedin authentication",
248
+ "canceled": "Authentication canceled by user",
249
+ "waiting": "Waiting for server...",
250
+ "waitingForRedirect": "Authentication will open in this window.",
251
+ "error": "Error during authentication",
252
+ "errorWithColon": "Error during authentication:",
253
+ "unknownState": "Unknown authentication state: {state}",
254
+ "errorToast": "Error during linkedin authentication"
255
+ },
256
+ "googleAccess": {
257
+ "title": "Google API Access",
258
+ "currentAccess": "You are currently granting us access to the following Google API features:",
259
+ "needAccess": "To use this feature, you need to grant us access to the Google APIs listed below:",
260
+ "clickButton": "Click the button below to go to the Google page where you can grant access.",
261
+ "authenticationButton": "Google Authentication",
262
+ "gainedTitle": "Signed In",
263
+ "gainedMessage": "Congratulations! You added offline access to your account. Now your account have access to:",
264
+ "next": "Next",
265
+ "redirectIn": "Redirect in {seconds}...",
266
+ "returnToIndex": "Return to {link}.",
267
+ "indexPage": "index page",
268
+ "signedInToast": "Signed in",
269
+ "signedInToastDetail": "Congratulations! You have successfully logged in to your account."
270
+ },
271
+ "password": {
272
+ "suggestions": "Suggestions",
273
+ "resetPasswordButton": "Reset password"
274
+ },
275
+ "signOut": {
276
+ "title": "Sign Out",
277
+ "signingOut": "Signing out"
238
278
  }
239
279
  }
@@ -77,8 +77,13 @@
77
77
  "edit": "Edytuj",
78
78
  "view": "Pokaż",
79
79
  "close": "Zamknij",
80
+ "ok": "OK",
81
+ "next": "Dalej",
80
82
  "testIndex": "Indeks testowy",
81
- "addTestNotification": "Dodaj testowe powiadomienie"
83
+ "addTestNotification": "Dodaj testowe powiadomienie",
84
+ "rejected": "Odrzucone",
85
+ "rejectedDetail": "Odrzuciłeś",
86
+ "rememberMe": "Zapamiętaj mnie"
82
87
  },
83
88
  "app": {
84
89
  "updateAvailable": "Dostępna aktualizacja!",
@@ -124,7 +129,9 @@
124
129
  "phone": "telefon",
125
130
  "google": "Google",
126
131
  "linkedin": "LinkedIn",
127
- "github": "GitHub"
132
+ "github": "GitHub",
133
+ "accountConnected": "Konto połączone",
134
+ "accountConnectedSuccess": "Gratulacje! Pomyślnie połączyłeś konta."
128
135
  },
129
136
  "messageAuth": {
130
137
  "authenticationDone": "Uwierzytelnianie zakończone",
@@ -140,23 +147,6 @@
140
147
  "linkExpiredDesc": "Twój tajny link już wygasł. Aby wysłać kolejny link, kliknij przycisk poniżej.",
141
148
  "resend": "Wyślij ponownie"
142
149
  },
143
- "common": {
144
- "or": "LUB",
145
- "error": "Błąd",
146
- "success": "Sukces",
147
- "cancel": "Anuluj",
148
- "save": "Zapisz",
149
- "delete": "Usuń",
150
- "edit": "Edytuj",
151
- "view": "Pokaż",
152
- "close": "Zamknij",
153
- "ok": "OK",
154
- "next": "Dalej",
155
- "testIndex": "Indeks testowy",
156
- "addTestNotification": "Dodaj testowe powiadomienie",
157
- "rejected": "Odrzucone",
158
- "rejectedDetail": "Odrzuciłeś"
159
- },
160
150
  "deleteAccount": {
161
151
  "deleteAccount": "Usuń konto",
162
152
  "warning": "Usunięcie konta jest nieodwracalne, zaznacz pole poniżej tylko jeśli jesteś w 100% pewny, że chcesz usunąć swoje konto.",
@@ -235,5 +225,55 @@
235
225
  "openLink": "Lub otwórz link uwierzytelniania:",
236
226
  "seeYouSoon": "Do zobaczenia",
237
227
  "teamSignature": "Zespół {brandName}"
228
+ },
229
+ "googleAuth": {
230
+ "title": "Uwierzytelnianie Google",
231
+ "canceled": "Uwierzytelnianie anulowane przez użytkownika",
232
+ "waiting": "Oczekiwanie na serwer...",
233
+ "waitingForRedirect": "Uwierzytelnianie otworzy się w tym oknie.",
234
+ "error": "Błąd podczas uwierzytelniania",
235
+ "errorWithColon": "Błąd podczas uwierzytelniania:",
236
+ "unknownState": "Nieznany stan uwierzytelniania: {state}",
237
+ "emailTaken": "Twoje konto zostało utworzone przy użyciu adresu email. Jeśli chcesz połączyć swoje konto Google, musisz zalogować się tym adresem email. I połączyć swoje konto Google używając {link}.",
238
+ "emailTakenLink": "strony połączonych kont",
239
+ "invalidGrant": "Nieprawidłowy grant. Spróbuj ponownie. Możesz użyć tego linku wcześniej lub uwierzytelnianie Google nie powiodło się.",
240
+ "connectedToAnotherUser": "To konto jest już połączone z innym użytkownikiem. Zaloguj się swoim adresem email lub kontem Google.",
241
+ "emailAlreadyInUse": "Email jest już w użyciu",
242
+ "invalidGrantToast": "Nieprawidłowy grant",
243
+ "connectedToAnotherUserToast": "Połączone z innym użytkownikiem",
244
+ "errorToast": "Błąd podczas uwierzytelniania Google"
245
+ },
246
+ "linkedinAuth": {
247
+ "title": "Uwierzytelnianie LinkedIn",
248
+ "canceled": "Uwierzytelnianie anulowane przez użytkownika",
249
+ "waiting": "Oczekiwanie na serwer...",
250
+ "waitingForRedirect": "Uwierzytelnianie otworzy się w tym oknie.",
251
+ "error": "Błąd podczas uwierzytelniania",
252
+ "errorWithColon": "Błąd podczas uwierzytelniania:",
253
+ "unknownState": "Nieznany stan uwierzytelniania: {state}",
254
+ "errorToast": "Błąd podczas uwierzytelniania LinkedIn"
255
+ },
256
+ "googleAccess": {
257
+ "title": "Dostęp do Google API",
258
+ "currentAccess": "Obecnie udzielasz nam dostępu do następujących funkcji Google API:",
259
+ "needAccess": "Aby użyć tej funkcji, musisz udzielić nam dostępu do wymienionych poniżej Google API:",
260
+ "clickButton": "Kliknij przycisk poniżej, aby przejść do strony Google, gdzie możesz udzielić dostępu.",
261
+ "authenticationButton": "Uwierzytelnianie Google",
262
+ "gainedTitle": "Zalogowany",
263
+ "gainedMessage": "Gratulacje! Dodałeś dostęp offline do swojego konta. Teraz Twoje konto ma dostęp do:",
264
+ "next": "Dalej",
265
+ "redirectIn": "Przekierowanie za {seconds}...",
266
+ "returnToIndex": "Wróć do {link}.",
267
+ "indexPage": "strony głównej",
268
+ "signedInToast": "Zalogowany",
269
+ "signedInToastDetail": "Gratulacje! Pomyślnie zalogowałeś się do swojego konta."
270
+ },
271
+ "password": {
272
+ "suggestions": "Sugestie",
273
+ "resetPasswordButton": "Resetuj hasło"
274
+ },
275
+ "signOut": {
276
+ "title": "Wyloguj się",
277
+ "signingOut": "Wylogowywanie"
238
278
  }
239
279
  }
@@ -1,14 +1,15 @@
1
1
  <template>
2
2
  <div class="w-full lg:w-6/12 md:w-9/12 max-w-[32rem]" v-shared-element:form="{ duration: '300ms', includeChildren: true }">
3
3
  <div class="bg-surface-0 dark:bg-surface-900 rounded-border shadow p-6">
4
- <div class="text-surface-900 dark:text-surface-0 font-medium mb-6 text-xl">Account connected</div>
5
- <div class="mt-0 p-0 leading-normal">Congratulations! You have successfully connected accounts.</div>
4
+ <div class="text-surface-900 dark:text-surface-0 font-medium mb-6 text-xl">{{ t('connected.accountConnected') }}</div>
5
+ <div class="mt-0 p-0 leading-normal">{{ t('connected.accountConnectedSuccess') }}</div>
6
6
  </div>
7
7
  </div>
8
8
  </template>
9
9
 
10
10
  <script setup>
11
-
11
+ import { useI18n } from 'vue-i18n'
12
+ const { t } = useI18n()
12
13
  </script>
13
14
 
14
15
  <style>
@@ -152,12 +152,12 @@
152
152
 
153
153
  await Promise.all([ ...contactPromises, ...accountPromises ])
154
154
 
155
- const contacts = computed(() => contactsTypes.map((c,i) => c.contacts.value.map(v => ({
155
+ const contacts = computed(() => contactsTypes.map((c,i) => (c.contacts.value || []).map(v => ({
156
156
  contactType: c,
157
157
  ...(v)
158
158
  }))).flat())
159
159
 
160
- const accounts = computed(() => accountTypes.map((c,i) => c.accounts.value.map(v => ({
160
+ const accounts = computed(() => accountTypes.map((c,i) => (c.accounts.value || []).map(v => ({
161
161
  accountType: c,
162
162
  ...(v)
163
163
  }))).flat())
@@ -1,10 +1,10 @@
1
1
  <template>
2
2
  <div v-if="additionalScopes.length > 0" class="w-full flex flex-row justify-center">
3
3
  <div class="bg-surface-0 dark:bg-surface-900 rounded-border shadow p-6 w-[30rem]">
4
- <div class="text-surface-900 dark:text-surface-0 font-medium mb-4 text-xl mb-6">Google API Access</div>
4
+ <div class="text-surface-900 dark:text-surface-0 font-medium mb-4 text-xl mb-6">{{ t('googleAccess.title') }}</div>
5
5
  <div v-if="currentAccess.length > 0">
6
6
  <p class="mt-0 p-0 leading-normal">
7
- You are currently granting us access to the following Google API features:
7
+ {{ t('googleAccess.currentAccess') }}
8
8
  </p>
9
9
  <ul>
10
10
  <li v-for="scope in currentAccess">
@@ -14,7 +14,7 @@
14
14
  </div>
15
15
  <div>
16
16
  <p>
17
- To use this feature, you need to grant us access to the Google APIs listed below:
17
+ {{ t('googleAccess.needAccess') }}
18
18
  </p>
19
19
  <ul>
20
20
  <li v-for="scope in additionalScopes" class="font-semibold text-gray-700">
@@ -22,7 +22,7 @@
22
22
  </li>
23
23
  </ul>
24
24
  <p>
25
- Click the button below to go to the Google page where you can grant access.
25
+ {{ t('googleAccess.clickButton') }}
26
26
  </p>
27
27
  </div>
28
28
  <router-link
@@ -32,7 +32,7 @@
32
32
  accessType: 'offline',
33
33
  scopes: allScopes
34
34
  } }">
35
- <Button icon="pi pi-key" label="Google Authentication" />
35
+ <Button icon="pi pi-key" :label="t('googleAccess.authenticationButton')" />
36
36
  </router-link>
37
37
  </div>
38
38
  </div>
@@ -43,6 +43,9 @@
43
43
 
44
44
  import Button from 'primevue/button'
45
45
 
46
+ import { useI18n } from 'vue-i18n'
47
+ const { t } = useI18n()
48
+
46
49
  import { onMounted, ref } from 'vue'
47
50
  const isMounted = ref(false)
48
51
  onMounted(() => isMounted.value = true)
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <div class="w-full lg:w-6/12 md:w-9/12 max-w-[32rem]" v-shared-element:form="{ duration: '300ms', includeChildren: true }">
3
3
  <div class="bg-surface-0 dark:bg-surface-900 rounded-border shadow p-6">
4
- <div class="text-surface-900 dark:text-surface-0 font-medium mb-4 text-xl mb-6">Signed In</div>
4
+ <div class="text-surface-900 dark:text-surface-0 font-medium mb-4 text-xl mb-6">{{ t('googleAccess.gainedTitle') }}</div>
5
5
  <p class="mt-0 p-0 leading-normal">
6
- Congratulations! You added offline access to your account. Now your account have access to:
6
+ {{ t('googleAccess.gainedMessage') }}
7
7
  <ul>
8
8
  <li v-for="access in accessList">
9
9
  {{ access }}
@@ -13,14 +13,18 @@
13
13
  </p>
14
14
  <div v-if="afterGoogleAccessGained" class="flex flex-row items-center">
15
15
  <router-link :to="afterGoogleAccessGained" class="no-underline">
16
- <Button label="Next" v-ripple />
16
+ <Button :label="t('googleAccess.next')" v-ripple />
17
17
  </router-link>
18
18
  <p class="ml-6" v-if="isMounted && redirectTime">
19
- Redirect in {{ pluralize('second', Math.ceil((redirectTime - currentTime) / 1000), true) }}...
19
+ {{ t('googleAccess.redirectIn', { seconds: pluralize('second', Math.ceil((redirectTime - currentTime) / 1000), true) }) }}
20
20
  </p>
21
21
  </div>
22
22
  <div v-else>
23
- Return to <router-link to="/">index page</router-link>.
23
+ <i18n-t keypath="googleAccess.returnToIndex" tag="span">
24
+ <template #link>
25
+ <router-link to="/">{{ t('googleAccess.indexPage') }}</router-link>
26
+ </template>
27
+ </i18n-t>
24
28
  </div>
25
29
  </div>
26
30
  </div>
@@ -30,6 +34,9 @@
30
34
 
31
35
  import Button from 'primevue/button'
32
36
 
37
+ import { useI18n } from 'vue-i18n'
38
+ const { t } = useI18n()
39
+
33
40
  import { onMounted, ref } from 'vue'
34
41
  const isMounted = ref(false)
35
42
  onMounted(() => isMounted.value = true)
@@ -43,6 +50,9 @@
43
50
  import { usePath, live, useApi } from "@live-change/vue3-ssr"
44
51
  const api = useApi()
45
52
 
53
+ import { useToast } from 'primevue/usetoast'
54
+ const toast = useToast()
55
+
46
56
  const userClientConfig = api.getServiceDefinition('user')?.clientConfig
47
57
 
48
58
  import pluralize from 'pluralize'
@@ -68,8 +78,8 @@
68
78
  setTimeout(() => { // it could be next tick
69
79
  toast.add({
70
80
  severity: 'info', life: 6000,
71
- summary: 'Signed in',
72
- detail: 'Congratulations! You have successfully logged in to your account.'
81
+ summary: t('googleAccess.signedInToast'),
82
+ detail: t('googleAccess.signedInToastDetail')
73
83
  })
74
84
  router.push(route)
75
85
  }, 100)
@@ -33,12 +33,12 @@
33
33
  v-model="data.passwordHash">
34
34
  <template #footer>
35
35
  <Divider />
36
- <p class="p-mt-2">Suggestions</p>
36
+ <p class="p-mt-2">{{ t('password.suggestions') }}</p>
37
37
  <ul class="p-pl-2 p-ml-2 p-mt-0" style="line-height: 1.5">
38
- <li>At least one lowercase</li>
39
- <li>At least one uppercase</li>
40
- <li>At least one numeric</li>
41
- <li>Minimum 8 characters</li>
38
+ <li>{{ t('auth.suggestionLowercase') }}</li>
39
+ <li>{{ t('auth.suggestionUppercase') }}</li>
40
+ <li>{{ t('auth.suggestionNumeric') }}</li>
41
+ <li>{{ t('auth.suggestionMinLength') }}</li>
42
42
  </ul>
43
43
  </template>
44
44
  </Password>
@@ -56,7 +56,7 @@
56
56
 
57
57
  </template>
58
58
 
59
- <Button type="submit" label="Reset password" icon="pi pi-key" class="w-full"></Button>
59
+ <Button type="submit" :label="t('password.resetPasswordButton')" icon="pi pi-key" class="w-full"></Button>
60
60
 
61
61
  </command-form>
62
62
  </div>
@@ -3,28 +3,28 @@
3
3
  <div class="bg-surface-0 dark:bg-surface-900 p-6 shadow rounded-border">
4
4
 
5
5
  <div class="text-center mb-8">
6
- <div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">Google authentication</div>
6
+ <div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">{{ t('googleAuth.title') }}</div>
7
7
  </div>
8
8
 
9
9
  <div v-if="state === 'canceled'" class="text-center">
10
- <div>Authentication canceled by user</div>
10
+ <div>{{ t('googleAuth.canceled') }}</div>
11
11
  <div class="flex flex-row">
12
- <Button @click="back" label="Go back" icon="pi pi-arrow-left" class="w-full p-button-secondary mb-1" />
13
- <Button @click="googleAuth" label="Try again" icon="pi pi-google" class="w-full p-button-secondary mb-1" />
12
+ <Button @click="back" :label="t('auth.goBack')" icon="pi pi-arrow-left" class="w-full p-button-secondary mb-1" />
13
+ <Button @click="googleAuth" :label="t('auth.tryAgain')" icon="pi pi-google" class="w-full p-button-secondary mb-1" />
14
14
  </div>
15
15
  </div>
16
16
  <div v-else-if="state === 'waiting'" class="text-center">
17
- Authentication will open in this window.
17
+ {{ t('googleAuth.waitingForRedirect') }}
18
18
  </div>
19
19
  <div v-else-if="state === 'working'" class="text-center">
20
- Waiting for server...
20
+ {{ t('googleAuth.waiting') }}
21
21
  </div>
22
22
  <div v-else-if="state === 'error'" class="text-center">
23
- <div>Error during authentication:</div>
23
+ <div>{{ t('googleAuth.errorWithColon') }}</div>
24
24
  <div>{{ error }}</div>
25
25
  </div>
26
26
  <div v-else>
27
- Unknown authentication state: {{ state }}
27
+ {{ t('googleAuth.unknownState', { state }) }}
28
28
  </div>
29
29
 
30
30
  </div>
@@ -37,6 +37,9 @@
37
37
  import { useRouter } from 'vue-router'
38
38
  const router = useRouter()
39
39
 
40
+ import { useI18n } from 'vue-i18n'
41
+ const { t } = useI18n()
42
+
40
43
  const workingZone = inject('workingZone')
41
44
 
42
45
  import { googleAuthRedirect } from '../utils/googleAuth.js'
@@ -66,6 +69,8 @@
66
69
  function googleAuth() {
67
70
  state.value = 'waiting'
68
71
 
72
+ localStorage.googleAuthScopes = JSON.stringify(scopes.value)
73
+
69
74
  workingZone.addPromise('google auth', new Promise((resolve, reject) => {
70
75
  setTimeout(() => {
71
76
  state.value = 'error'
@@ -3,32 +3,48 @@
3
3
  <div class="bg-surface-0 dark:bg-surface-900 p-6 shadow rounded-border">
4
4
 
5
5
  <div class="text-center mb-8">
6
- <div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">Google authentication</div>
6
+ <div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">{{ t('googleAuth.title') }}</div>
7
7
  </div>
8
8
 
9
9
  <div v-if="state === 'canceled'" class="text-center">
10
- <div>Authentication canceled by user</div>
10
+ <div>{{ t('googleAuth.canceled') }}</div>
11
11
  <div class="flex flex-row">
12
- <Button @click="back" label="Go back" icon="pi pi-arrow-left"
12
+ <Button @click="back" :label="t('auth.goBack')" icon="pi pi-arrow-left"
13
13
  class="w-full p-button-secondary mb-1" />
14
14
  </div>
15
15
  </div>
16
16
  <div v-else-if="state === 'working'" class="text-center">
17
- Waiting for server...
17
+ {{ t('googleAuth.waiting') }}
18
18
  </div>
19
19
  <div v-else-if="state === 'error'" class="text-center">
20
- <div>Error during authentication</div>
20
+ <div>{{ t('googleAuth.error') }}</div>
21
21
  <div>{{ error }}</div>
22
22
  </div>
23
23
  <div v-else-if="state === 'emailTaken'" class="text-center">
24
24
  <div>
25
- Your account was created using email address. If you want to connect your Google account,
26
- you need to sign in with this email address. And connect your Google account using
27
- <router-link :to="{ name: 'user:connected' }">connected accounts page</router-link>.
25
+ <i18n-t keypath="googleAuth.emailTaken" tag="span">
26
+ <template #link>
27
+ <router-link :to="{ name: 'user:connected' }">{{ t('googleAuth.emailTakenLink') }}</router-link>
28
+ </template>
29
+ </i18n-t>
30
+ </div>
31
+ </div>
32
+ <div v-else-if="state === 'invalidGrant'" class="text-center">
33
+ <div>
34
+ {{ t('googleAuth.invalidGrant') }}
35
+ <div class="flex flex-row">
36
+ <Button @click="back" :label="t('auth.goBack')" icon="pi pi-arrow-left" class="w-full p-button-secondary mb-1" />
37
+ <Button @click="googleAuth" :label="t('auth.tryAgain')" icon="pi pi-google" class="w-full p-button-secondary mb-1" />
38
+ </div>
39
+ </div>
40
+ </div>
41
+ <div v-else-if="state === 'connectedToAnotherUser'" class="text-center">
42
+ <div>
43
+ {{ t('googleAuth.connectedToAnotherUser') }}
28
44
  </div>
29
45
  </div>
30
46
  <div v-else>
31
- Unknown authentication state: {{ state }}
47
+ {{ t('googleAuth.unknownState', { state }) }}
32
48
  </div>
33
49
 
34
50
  </div>
@@ -44,6 +60,9 @@
44
60
  import { useToast } from 'primevue/usetoast'
45
61
  const toast = useToast()
46
62
 
63
+ import { useI18n } from 'vue-i18n'
64
+ const { t } = useI18n()
65
+
47
66
  const workingZone = inject('workingZone')
48
67
 
49
68
  import { useRouter, useRoute } from 'vue-router'
@@ -81,6 +100,7 @@
81
100
  while(user && api.client.value.user !== user) {
82
101
  await new Promise(resolve => setTimeout(resolve, 100))
83
102
  }
103
+ localStorage.removeItem('googleAuthScopes')
84
104
  if(actionDone === 'signIn') {
85
105
  router.push({ name: 'user:signInFinished' })
86
106
  } else if(actionDone === 'signUp') {
@@ -94,12 +114,22 @@
94
114
  }
95
115
  } catch(err) {
96
116
  if(err?.properties?.email == 'emailTaken') {
97
- toast.add({ severity: 'error', summary: 'Error', detail: 'Email is already in use', life: 3000 })
117
+ toast.add({ severity: 'error', summary: t('common.error'), detail: t('googleAuth.emailAlreadyInUse'), life: 3000 })
98
118
  state.value = 'emailTaken'
99
119
  return
100
120
  }
121
+ if((typeof err == 'string') && err.startsWith('invalid_grant')) {
122
+ toast.add({ severity: 'error', summary: t('common.error'), detail: t('googleAuth.invalidGrantToast'), life: 3000 })
123
+ state.value = 'invalidGrant'
124
+ return
125
+ }
126
+ if(err === 'connectedToAnotherUser') {
127
+ toast.add({ severity: 'error', summary: t('common.error'), detail: t('googleAuth.connectedToAnotherUserToast'), life: 3000 })
128
+ state.value = 'connectedToAnotherUser'
129
+ return
130
+ }
101
131
  console.error("Google auth error", err)
102
- toast.add({ severity: 'error', summary: 'Error', detail: 'Error during google authentication', life: 3000 })
132
+ toast.add({ severity: 'error', summary: t('common.error'), detail: t('googleAuth.errorToast'), life: 3000 })
103
133
  state.value = 'error'
104
134
  error.value = err
105
135
  }
@@ -110,6 +140,15 @@
110
140
  router.go(-1)
111
141
  }
112
142
 
143
+ async function googleAuth() {
144
+ if(localStorage.googleAuthScopes) {
145
+ const scopes = JSON.parse(localStorage.googleAuthScopes)
146
+ router.push({ name: 'user:googleAuthScopes', params: { action: action.value, accessType: 'offline', scopes: scopes } })
147
+ } else {
148
+ router.push({ name: 'user:googleAuth', params: { action: action.value } })
149
+ }
150
+ }
151
+
113
152
  </script>
114
153
 
115
154
  <style scoped>
@@ -3,28 +3,28 @@
3
3
  <div class="bg-surface-0 dark:bg-surface-900 p-6 shadow rounded-border">
4
4
 
5
5
  <div class="text-center mb-8">
6
- <div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">Linkedin authentication</div>
6
+ <div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">{{ t('linkedinAuth.title') }}</div>
7
7
  </div>
8
8
 
9
9
  <div v-if="state === 'canceled'" class="text-center">
10
- <div class="mb-1">Authentication canceled by user</div>
10
+ <div class="mb-1">{{ t('linkedinAuth.canceled') }}</div>
11
11
  <div class="flex flex-row">
12
- <Button @click="back" label="Go back" icon="pi pi-arrow-left" class="w-full p-button-secondary mb-1" />
13
- <Button @click="linkedinAuth" label="Try again" icon="pi pi-linkedin" class="w-full p-button-secondary mb-1" />
12
+ <Button @click="back" :label="t('auth.goBack')" icon="pi pi-arrow-left" class="w-full p-button-secondary mb-1" />
13
+ <Button @click="linkedinAuth" :label="t('auth.tryAgain')" icon="pi pi-linkedin" class="w-full p-button-secondary mb-1" />
14
14
  </div>
15
15
  </div>
16
16
  <div v-else-if="state === 'waiting'" class="text-center">
17
- Authentication will open in this window.
17
+ {{ t('linkedinAuth.waitingForRedirect') }}
18
18
  </div>
19
19
  <div v-else-if="state === 'working'" class="text-center">
20
- Waiting for server...
20
+ {{ t('linkedinAuth.waiting') }}
21
21
  </div>
22
22
  <div v-else-if="state === 'error'" class="text-center">
23
- <div>Error during authentication:</div>
23
+ <div>{{ t('linkedinAuth.errorWithColon') }}</div>
24
24
  <div>{{ error }}</div>
25
25
  </div>
26
26
  <div v-else>
27
- Unknown authentication state: {{ state }}
27
+ {{ t('linkedinAuth.unknownState', { state }) }}
28
28
  </div>
29
29
 
30
30
  </div>
@@ -37,6 +37,9 @@
37
37
  import { useRouter } from 'vue-router'
38
38
  const router = useRouter()
39
39
 
40
+ import { useI18n } from 'vue-i18n'
41
+ const { t } = useI18n()
42
+
40
43
  const workingZone = inject('workingZone')
41
44
 
42
45
  import { linkedinAuthRedirect } from '../utils/linkedinAuth.js'
@@ -3,25 +3,25 @@
3
3
  <div class="bg-surface-0 dark:bg-surface-900 p-6 shadow rounded-border">
4
4
 
5
5
  <div class="text-center mb-8">
6
- <div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">Linkedin authentication</div>
6
+ <div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">{{ t('linkedinAuth.title') }}</div>
7
7
  </div>
8
8
 
9
9
  <div v-if="state === 'canceled'" class="text-center">
10
- <div class="mb-2 text-red-500">Authentication canceled by user</div>
10
+ <div class="mb-2 text-red-500">{{ t('linkedinAuth.canceled') }}</div>
11
11
  <div class="flex flex-row">
12
- <Button @click="back" label="Go back" icon="pi pi-arrow-left"
12
+ <Button @click="back" :label="t('auth.goBack')" icon="pi pi-arrow-left"
13
13
  class="w-full p-button-secondary mb-1" />
14
14
  </div>
15
15
  </div>
16
16
  <div v-else-if="state === 'working'" class="text-center">
17
- Waiting for server...
17
+ {{ t('linkedinAuth.waiting') }}
18
18
  </div>
19
19
  <div v-else-if="state === 'error'" class="text-center">
20
- <div>Error during authentication</div>
20
+ <div>{{ t('linkedinAuth.error') }}</div>
21
21
  <div>{{ error }}</div>
22
22
  </div>
23
23
  <div v-else>
24
- Unknown authentication state: {{ state }}
24
+ {{ t('linkedinAuth.unknownState', { state }) }}
25
25
  </div>
26
26
 
27
27
  </div>
@@ -37,6 +37,9 @@
37
37
  import { useToast } from 'primevue/usetoast'
38
38
  const toast = useToast()
39
39
 
40
+ import { useI18n } from 'vue-i18n'
41
+ const { t } = useI18n()
42
+
40
43
  const workingZone = inject('workingZone')
41
44
 
42
45
  import { useRouter, useRoute } from 'vue-router'
@@ -88,7 +91,7 @@
88
91
  }
89
92
  } catch(error) {
90
93
  console.error("Linkedin auth error", error)
91
- toast.add({ severity: 'error', summary: 'Error', detail: 'Error during linkedin authentication', life: 3000 })
94
+ toast.add({ severity: 'error', summary: t('common.error'), detail: t('linkedinAuth.errorToast'), life: 3000 })
92
95
  state.value = 'error'
93
96
  error.value = error
94
97
  }
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <div class="w-full lg:w-6/12 md:w-9/12 max-w-[32rem]" v-shared-element:form="{ duration: '300ms', includeChildren: true }">
3
3
  <div class="bg-surface-0 dark:bg-surface-900 rounded-border shadow p-6">
4
- <div class="text-surface-900 dark:text-surface-0 font-medium mb-4 text-xl mb-6">Sign Out</div>
5
- <p class="mt-0 p-0 leading-normal">Signing out</p>
4
+ <div class="text-surface-900 dark:text-surface-0 font-medium mb-4 text-xl mb-6">{{ t('signOut.title') }}</div>
5
+ <p class="mt-0 p-0 leading-normal">{{ t('signOut.signingOut') }}</p>
6
6
  <ProgressSpinner v-if="isMounted" class="m-4" />
7
7
  </div>
8
8
  </div>
@@ -11,6 +11,9 @@
11
11
  <script setup>
12
12
  import ProgressSpinner from "primevue/progressspinner"
13
13
 
14
+ import { useI18n } from 'vue-i18n'
15
+ const { t } = useI18n()
16
+
14
17
  import { onMounted, ref } from 'vue'
15
18
  const isMounted = ref(false)
16
19
  onMounted(() => isMounted.value = true)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/user-frontend",
3
- "version": "0.9.177",
3
+ "version": "0.9.180",
4
4
  "scripts": {
5
5
  "memDev": "tsx --inspect --expose-gc server/start.js memDev --enableSessions --initScript ./init.js --dbAccess",
6
6
  "localDevInit": "tsx server/start.js localDev --enableSessions --initScript ./init.js --dbAccess",
@@ -36,29 +36,29 @@
36
36
  },
37
37
  "type": "module",
38
38
  "dependencies": {
39
- "@live-change/cli": "^0.9.177",
40
- "@live-change/dao": "^0.9.177",
41
- "@live-change/dao-vue3": "^0.9.177",
42
- "@live-change/dao-websocket": "^0.9.177",
43
- "@live-change/email-service": "^0.9.177",
44
- "@live-change/framework": "^0.9.177",
45
- "@live-change/identicon-service": "^0.9.177",
46
- "@live-change/image-frontend": "^0.9.177",
47
- "@live-change/message-authentication-service": "^0.9.177",
48
- "@live-change/notification-service": "^0.9.177",
49
- "@live-change/password-authentication-service": "^0.9.177",
50
- "@live-change/pattern": "^0.9.177",
51
- "@live-change/secret-code-service": "^0.9.177",
52
- "@live-change/secret-link-service": "^0.9.177",
53
- "@live-change/security-frontend": "^0.9.177",
54
- "@live-change/security-service": "^0.9.177",
55
- "@live-change/session-service": "^0.9.177",
56
- "@live-change/timer-service": "^0.9.177",
57
- "@live-change/upload-service": "^0.9.177",
58
- "@live-change/user-identification-service": "^0.9.177",
59
- "@live-change/user-service": "^0.9.177",
60
- "@live-change/vue3-components": "^0.9.177",
61
- "@live-change/vue3-ssr": "^0.9.177",
39
+ "@live-change/cli": "^0.9.180",
40
+ "@live-change/dao": "^0.9.180",
41
+ "@live-change/dao-vue3": "^0.9.180",
42
+ "@live-change/dao-websocket": "^0.9.180",
43
+ "@live-change/email-service": "^0.9.180",
44
+ "@live-change/framework": "^0.9.180",
45
+ "@live-change/identicon-service": "^0.9.180",
46
+ "@live-change/image-frontend": "^0.9.180",
47
+ "@live-change/message-authentication-service": "^0.9.180",
48
+ "@live-change/notification-service": "^0.9.180",
49
+ "@live-change/password-authentication-service": "^0.9.180",
50
+ "@live-change/pattern": "^0.9.180",
51
+ "@live-change/secret-code-service": "^0.9.180",
52
+ "@live-change/secret-link-service": "^0.9.180",
53
+ "@live-change/security-frontend": "^0.9.180",
54
+ "@live-change/security-service": "^0.9.180",
55
+ "@live-change/session-service": "^0.9.180",
56
+ "@live-change/timer-service": "^0.9.180",
57
+ "@live-change/upload-service": "^0.9.180",
58
+ "@live-change/user-identification-service": "^0.9.180",
59
+ "@live-change/user-service": "^0.9.180",
60
+ "@live-change/vue3-components": "^0.9.180",
61
+ "@live-change/vue3-ssr": "^0.9.180",
62
62
  "@vueuse/core": "^12.3.0",
63
63
  "codeceptjs-assert": "^0.0.5",
64
64
  "codeceptjs-video-helper": "0.1.3",
@@ -79,7 +79,7 @@
79
79
  "wtfnode": "^0.9.1"
80
80
  },
81
81
  "devDependencies": {
82
- "@live-change/codeceptjs-helper": "^0.9.177",
82
+ "@live-change/codeceptjs-helper": "^0.9.180",
83
83
  "codeceptjs": "^3.6.10",
84
84
  "generate-password": "1.7.1",
85
85
  "playwright": "1.49.1",
@@ -90,5 +90,5 @@
90
90
  "author": "Michał Łaszczewski <michal@laszczewski.pl>",
91
91
  "license": "BSD-3-Clause",
92
92
  "description": "",
93
- "gitHead": "d75c8c63935b7b78623248d255820b1da2676929"
93
+ "gitHead": "c6ee30c8f36f989714e8fc7ec71daadb895b2b6e"
94
94
  }