@hostlink/nuxt-light 1.18.3 → 1.19.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.
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "light",
3
3
  "configKey": "light",
4
- "version": "1.18.3",
4
+ "version": "1.19.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.8.4",
7
7
  "unbuild": "2.0.0"
@@ -1,7 +1,7 @@
1
1
  <script setup>
2
2
  import { ref } from 'vue'
3
3
  import { useQuasar, useDialogPluginComponent } from 'quasar'
4
- import { m, api } from '#imports';
4
+ import { api } from '#imports';
5
5
  import { useI18n } from 'vue-i18n';
6
6
  const { t } = useI18n();
7
7
  const $q = useQuasar()
@@ -0,0 +1,54 @@
1
+ <script setup lang="ts">
2
+ import { useLight, m } from "#imports"
3
+ const light = useLight()
4
+
5
+
6
+ export interface LSystemSettingAuthenticationProps {
7
+ authentication_password_based: string,
8
+ authentication_google_client_id: string,
9
+ authentication_facebook_app_id: string,
10
+ authentication_microsoft_client_id: string,
11
+ }
12
+
13
+
14
+ withDefaults(defineProps<LSystemSettingAuthenticationProps>(), {
15
+ authentication_password_based: "1",
16
+ authentication_google_client_id: "",
17
+ authentication_facebook_app_id: "",
18
+ authentication_microsoft_client_id: ""
19
+ })
20
+
21
+ const emits = defineEmits(["submit"])
22
+
23
+ const onSubmit = async (d: LSystemSettingAuthenticationProps) => {
24
+
25
+ //at least one authentication method should be enabled
26
+ if (d.authentication_password_based === "0" && !d.authentication_google_client_id && !d.authentication_facebook_app_id && !d.authentication_microsoft_client_id) {
27
+
28
+ light.notify({ message: "At least one authentication method should be enabled", color: "negative" })
29
+ return
30
+
31
+ }
32
+
33
+
34
+
35
+ emits("submit", d)
36
+ }
37
+
38
+ </script>
39
+ <template>
40
+
41
+
42
+ <form-kit type="l-form" :bordered="false" @submit="onSubmit" :value="$props">
43
+
44
+ <form-kit label="Password based" type="l-checkbox" name="authentication_password_based" true-value="1"
45
+ false-value="0" />
46
+ <q-separator />
47
+
48
+ <form-kit label="Google Client ID" type="l-input" name="authentication_google_client_id" />
49
+
50
+ <form-kit label="Facebook App ID" type="l-input" name="authentication_facebook_app_id" />
51
+
52
+ <form-kit label="Microsoft Client ID" type="l-input" name="authentication_microsoft_client_id" />
53
+ </form-kit>
54
+ </template>
@@ -1,7 +1,6 @@
1
1
  <script setup>
2
- import { provide, ref } from 'vue'
3
- import { useLight, watch } from "#imports";
4
-
2
+ import { ref } from 'vue'
3
+ import { reloadNuxtApp, useLight, watch } from "#imports";
5
4
  import { useQuasar } from 'quasar'
6
5
  import { q } from '#imports'
7
6
  import { useRoute } from "vue-router";
@@ -25,22 +24,47 @@ try {
25
24
  logged: true,
26
25
  twoFactorAuthentication: true,
27
26
  googleClientId: true,
28
- forgetPasswordEnabled: true
27
+ forgetPasswordEnabled: true,
28
+ microsoftClientId: true,
29
+ passwordBasedEnabled: true,
30
+ facebookAppId: true,
29
31
  }
30
32
  })).app;
31
33
  light.company = app.value.company;
32
34
  light.companyLogo = app.value.companyLogo;
33
35
  } catch (e) {
34
-
35
36
  quasar.dialog({
36
37
  title: 'Error',
37
- message: 'Error loading api data. Please reload the page.',
38
+ message: e.message,
38
39
  ok: 'Reload',
39
40
  }).onOk(() => {
40
41
  window.location.reload();
41
42
  });
42
43
  }
43
44
 
45
+ if (app.value.facebookAppId) {
46
+
47
+ //load facebook sdk
48
+
49
+ (function (d, s, id) {
50
+ var js, fjs = d.getElementsByTagName(s)[0];
51
+ if (d.getElementById(id)) { return; }
52
+ js = d.createElement(s); js.id = id;
53
+ js.src = "https://connect.facebook.net/en_US/sdk.js";
54
+ fjs.parentNode.insertBefore(js, fjs);
55
+ }(document, 'script', 'facebook-jssdk')
56
+ );
57
+
58
+ window.fbAsyncInit = function () {
59
+ FB.init({
60
+ appId: app.value.facebookAppId,
61
+ xfbml: true,
62
+ version: 'v21.0'
63
+ });
64
+ }
65
+ }
66
+
67
+
44
68
 
45
69
 
46
70
  </script>
@@ -48,6 +72,7 @@ try {
48
72
  <q-layout v-if="!app.logged">
49
73
  <q-page-container class="bg-grey-2" style="color:#1f1f1f">
50
74
  <q-page padding>
75
+ <div id="fb-root"></div>
51
76
  <l-login v-bind="app" @login="app.logged = true"></l-login>
52
77
  </q-page>
53
78
  </q-page-container>
@@ -0,0 +1,28 @@
1
+ <script setup>
2
+
3
+ import { ref, onMounted } from 'vue';
4
+ const button = ref(null);
5
+ const emits = defineEmits(["login"]);
6
+
7
+ onMounted(() => {
8
+ if (window.FB) {
9
+ window.FB.XFBML.parse()
10
+ }
11
+
12
+ })
13
+
14
+ window.onFacebookLogin = () => {
15
+
16
+
17
+
18
+
19
+ window.FB.getAccessToken(accessToken => {
20
+ emits('login', accessToken)
21
+ })
22
+ }
23
+
24
+ </script>
25
+ <template>
26
+ <div class="fb-login-button" data-size="large" data-button-type="" data-layout="" data-auto-logout-link="false"
27
+ data-use-continue-as="false" ref="button" data-onlogin="onFacebookLogin()"></div>
28
+ </template>
@@ -1,19 +1,23 @@
1
1
  <script setup>
2
2
  import { ref, reactive, onMounted } from 'vue'
3
3
  import { useQuasar } from 'quasar';
4
- import { api, useHead } from '#imports';
4
+ import { api, useHead, m, useLight } from '#imports';
5
5
  import { useI18n } from 'vue-i18n';
6
6
 
7
+
7
8
  const { t } = useI18n();
8
9
 
9
10
  const emits = defineEmits(["login"]);
10
11
 
11
12
  const props = defineProps({
12
13
  twoFactorAuthentication: Boolean,
13
- googleClientId: String,
14
+ googleClientId: String | undefined,
14
15
  forgetPasswordEnabled: Boolean,
15
16
  company: String,
16
- companyLogo: String
17
+ companyLogo: String,
18
+ microsoftClientId: String | undefined,
19
+ passwordBasedEnabled: Boolean,
20
+ facebookAppId: String | undefined,
17
21
  })
18
22
 
19
23
  useHead({
@@ -46,10 +50,15 @@ const loginWithCode = (username, password) => {
46
50
 
47
51
  }
48
52
 
53
+ const loading = ref(false);
54
+
49
55
  const submit = async () => {
50
56
  if (await form1.value.validate()) {
51
57
 
58
+
59
+
52
60
  try {
61
+ loading.value = true;
53
62
  await api.auth.login(data.username, data.password, data.code)
54
63
  //window.self.location.reload();
55
64
  //
@@ -68,6 +77,8 @@ const submit = async () => {
68
77
  color: "negative",
69
78
  icon: "sym_o_error",
70
79
  });
80
+ } finally {
81
+ loading.value = false;
71
82
 
72
83
 
73
84
  }
@@ -159,6 +170,7 @@ const handleGoogleCredentialResponse = async (response) => {
159
170
  }
160
171
 
161
172
  onMounted(() => {
173
+
162
174
  if (props.googleClientId) {
163
175
  if (!window.google) {
164
176
  $q.notify({
@@ -191,6 +203,34 @@ onMounted(() => {
191
203
  );
192
204
  }
193
205
  })
206
+
207
+
208
+
209
+ const microsoftLogin = async (resp) => {
210
+ try {
211
+ await api.auth.microsoftLogin(resp.accessToken);
212
+ emits("login");
213
+ } catch (e) {
214
+ $q.notify({
215
+ message: e.message,
216
+ color: "negative",
217
+ });
218
+
219
+ }
220
+
221
+ }
222
+
223
+ const facebookLogin = (accessToken) => {
224
+ m("facebookLogin", { access_token: accessToken }).then(() => {
225
+ emits("login");
226
+ }).catch((e) => {
227
+ $q.notify({
228
+ message: e.message,
229
+ color: "negative",
230
+ });
231
+ });
232
+ }
233
+
194
234
  </script>
195
235
 
196
236
  <template>
@@ -204,7 +244,7 @@ onMounted(() => {
204
244
  <div class="text-h6">
205
245
  {{ company }}
206
246
  </div>
207
- <q-form ref="form1">
247
+ <q-form ref="form1" v-if="passwordBasedEnabled">
208
248
  <div class="q-gutter-sm">
209
249
  <l-input v-model.trim="data.username" label="Username" :rules="[v => !!v || $t('Username is required')]"
210
250
  clearable :outlined="false" stackLabel autocomplete="username">
@@ -229,15 +269,24 @@ onMounted(() => {
229
269
  </q-form>
230
270
  </q-card-section>
231
271
  <q-card-actions>
232
- <l-btn label="Login" outline rounded color="primary" icon="sym_o_login" @click="submit" />
272
+ <l-btn label="Login" outline rounded color="primary" icon="sym_o_login" @click="submit"
273
+ v-if="passwordBasedEnabled" />
233
274
  <l-btn v-if="hasBioLogin" outline rounded color="primary" icon="sym_o_fingerprint" @click="bioLogin" />
234
275
  <l-btn label="Forget password" outline rounded color="primary" icon="sym_o_lock_reset" @click="forgetPassword"
235
276
  v-if="forgetPasswordEnabled" />
236
277
  </q-card-actions>
237
- <q-card-actions v-if="props.googleClientId">
278
+ <q-card-actions v-if="googleClientId">
238
279
  <div>
239
280
  <div id="g_id_signin"></div>
240
281
  </div>
241
282
  </q-card-actions>
283
+
284
+ <q-card-actions v-if="microsoftClientId">
285
+ <l-microsoft-button :client-id="microsoftClientId" @login="microsoftLogin"></l-microsoft-button>
286
+ </q-card-actions>
287
+
288
+ <q-card-actions v-if="facebookAppId">
289
+ <l-facebook-button @login="facebookLogin" />
290
+ </q-card-actions>
242
291
  </q-card>
243
292
  </template>
@@ -0,0 +1,119 @@
1
+ <script setup lang="ts">
2
+ import { PublicClientApplication } from '@azure/msal-browser';
3
+ import { useQuasar } from 'quasar';
4
+ const $q = useQuasar()
5
+
6
+ const props = defineProps({
7
+ clientId: {
8
+ type: String,
9
+ required: true
10
+ },
11
+ })
12
+
13
+ const emits = defineEmits(["login"]);
14
+
15
+ const onClick = async () => {
16
+ const myMSALObject = new PublicClientApplication({
17
+ auth: {
18
+ clientId: props.clientId,
19
+ authority: "https://login.microsoftonline.com/common",
20
+ redirectUri: window.location.origin,
21
+ },
22
+ cache: {
23
+ cacheLocation: "memoryStorage",
24
+ storeAuthStateInCookie: false,
25
+ }
26
+ });
27
+
28
+ try {
29
+ await myMSALObject.initialize();
30
+
31
+ const resp = await myMSALObject.loginPopup({
32
+ scopes: ["user.read"]
33
+ });
34
+
35
+ emits("login", resp);
36
+
37
+ } catch (e: any) {
38
+ $q.dialog({
39
+ title: "Error",
40
+ message: e.message,
41
+ color: "negative",
42
+ });
43
+ }
44
+
45
+
46
+ }
47
+
48
+ </script>
49
+
50
+ <template>
51
+ <a @click="onClick" class="cursor-pointer">
52
+ <svg xmlns="http://www.w3.org/2000/svg" width="215" height="41" viewBox="0 0 215 41">
53
+ <title>MS-SymbolLockup</title>
54
+ <rect width="215" height="41" fill="#fff" />
55
+ <path d="M214,1V40H1V1H214m1-1H0V41H215V0Z" fill="#8c8c8c" />
56
+ <path
57
+ d="M45.812,25.082V23.288a2.849,2.849,0,0,0,.576.4,4.5,4.5,0,0,0,.707.3,5.513,5.513,0,0,0,.747.187,3.965,3.965,0,0,0,.688.065,2.937,2.937,0,0,0,1.637-.365,1.2,1.2,0,0,0,.538-1.062,1.16,1.16,0,0,0-.179-.649,1.928,1.928,0,0,0-.5-.5,5.355,5.355,0,0,0-.757-.435q-.437-.209-.935-.436c-.356-.19-.687-.383-1-.578a4.358,4.358,0,0,1-.8-.648,2.728,2.728,0,0,1-.534-.8,2.6,2.6,0,0,1-.194-1.047,2.416,2.416,0,0,1,.333-1.285,2.811,2.811,0,0,1,.879-.9,4.026,4.026,0,0,1,1.242-.528,5.922,5.922,0,0,1,1.42-.172,5.715,5.715,0,0,1,2.4.374v1.721a3.832,3.832,0,0,0-2.3-.645,4.106,4.106,0,0,0-.773.074,2.348,2.348,0,0,0-.689.241,1.5,1.5,0,0,0-.494.433,1.054,1.054,0,0,0-.19.637,1.211,1.211,0,0,0,.146.608,1.551,1.551,0,0,0,.429.468,4.276,4.276,0,0,0,.688.414c.271.134.584.28.942.436q.547.285,1.036.6a4.881,4.881,0,0,1,.856.7,3.015,3.015,0,0,1,.586.846,2.464,2.464,0,0,1,.217,1.058,2.635,2.635,0,0,1-.322,1.348,2.608,2.608,0,0,1-.868.892,3.82,3.82,0,0,1-1.257.5,6.988,6.988,0,0,1-1.5.155c-.176,0-.392-.014-.649-.04s-.518-.067-.787-.117a7.772,7.772,0,0,1-.761-.187A2.4,2.4,0,0,1,45.812,25.082Z"
58
+ fill="#5e5e5e" />
59
+ <path
60
+ d="M55.129,16.426a1.02,1.02,0,0,1-.714-.272.89.89,0,0,1-.3-.688.916.916,0,0,1,.3-.7,1.008,1.008,0,0,1,.714-.278,1.039,1.039,0,0,1,.732.278.909.909,0,0,1,.3.7.9.9,0,0,1-.3.678A1.034,1.034,0,0,1,55.129,16.426Zm.842,9.074h-1.7V18h1.7Z"
61
+ fill="#5e5e5e" />
62
+ <path
63
+ d="M65.017,24.9q0,4.131-4.153,4.131a6.187,6.187,0,0,1-2.556-.491V26.986a4.726,4.726,0,0,0,2.337.7,2.342,2.342,0,0,0,2.672-2.628V24.24h-.029a2.947,2.947,0,0,1-4.742.436,4.041,4.041,0,0,1-.838-2.684,4.738,4.738,0,0,1,.9-3.04,3,3,0,0,1,2.476-1.128,2.384,2.384,0,0,1,2.2,1.216h.029V18h1.7Zm-1.684-2.835v-.973a1.91,1.91,0,0,0-.524-1.352A1.718,1.718,0,0,0,61.5,19.18a1.793,1.793,0,0,0-1.512.714,3.217,3.217,0,0,0-.546,2,2.774,2.774,0,0,0,.524,1.769,1.678,1.678,0,0,0,1.387.662,1.805,1.805,0,0,0,1.429-.632A2.391,2.391,0,0,0,63.333,22.064Z"
64
+ fill="#5e5e5e" />
65
+ <path
66
+ d="M73.908,25.5h-1.7V21.273q0-2.1-1.486-2.1a1.622,1.622,0,0,0-1.282.582,2.162,2.162,0,0,0-.5,1.469V25.5H67.229V18h1.707v1.245h.029A2.673,2.673,0,0,1,71.4,17.824a2.265,2.265,0,0,1,1.868.795,3.57,3.57,0,0,1,.644,2.3Z"
67
+ fill="#5e5e5e" />
68
+ <path
69
+ d="M80.962,16.426a1.02,1.02,0,0,1-.714-.272.89.89,0,0,1-.3-.688.916.916,0,0,1,.3-.7,1.008,1.008,0,0,1,.714-.278,1.039,1.039,0,0,1,.732.278.909.909,0,0,1,.3.7.9.9,0,0,1-.3.678A1.034,1.034,0,0,1,80.962,16.426ZM81.8,25.5H80.1V18h1.7Z"
70
+ fill="#5e5e5e" />
71
+ <path
72
+ d="M90.7,25.5H89V21.273q0-2.1-1.486-2.1a1.622,1.622,0,0,0-1.282.582,2.157,2.157,0,0,0-.506,1.469V25.5H84.023V18H85.73v1.245h.03a2.673,2.673,0,0,1,2.431-1.421,2.265,2.265,0,0,1,1.868.795,3.57,3.57,0,0,1,.644,2.3Z"
73
+ fill="#5e5e5e" />
74
+ <path
75
+ d="M106.984,18l-2.212,7.5h-1.78l-1.361-5.083a3.215,3.215,0,0,1-.1-.659H101.5a3.069,3.069,0,0,1-.131.644l-1.48,5.1H98.145L95.939,18H97.7l1.363,5.405a3.16,3.16,0,0,1,.087.645H99.2a3.384,3.384,0,0,1,.117-.659L100.832,18h1.6l1.347,5.428a3.732,3.732,0,0,1,.095.644h.052a3.387,3.387,0,0,1,.11-.644L105.365,18Z"
76
+ fill="#5e5e5e" />
77
+ <path
78
+ d="M109.1,16.426a1.018,1.018,0,0,1-.714-.272.886.886,0,0,1-.3-.688.912.912,0,0,1,.3-.7,1.006,1.006,0,0,1,.714-.278,1.039,1.039,0,0,1,.732.278.912.912,0,0,1,.3.7.9.9,0,0,1-.3.678A1.034,1.034,0,0,1,109.1,16.426Zm.841,9.074h-1.7V18h1.7Z"
79
+ fill="#5e5e5e" />
80
+ <path
81
+ d="M116.117,25.42a2.955,2.955,0,0,1-1.31.248q-2.182,0-2.183-2.094V19.333h-1.253V18h1.253V16.264l1.7-.483V18h1.794v1.333h-1.794v3.75a1.484,1.484,0,0,0,.241.952,1.006,1.006,0,0,0,.807.285,1.167,1.167,0,0,0,.746-.248Z"
82
+ fill="#5e5e5e" />
83
+ <path
84
+ d="M124.248,25.5h-1.7V21.4q0-2.226-1.487-2.226a1.556,1.556,0,0,0-1.26.644,2.568,2.568,0,0,0-.513,1.649V25.5h-1.707V14.4h1.707v4.849h.029a2.685,2.685,0,0,1,2.432-1.421q2.5,0,2.5,3.055Z"
85
+ fill="#5e5e5e" />
86
+ <path
87
+ d="M141.907,25.5h-1.728V18.7q0-.835.1-2.043h-.029a6.992,6.992,0,0,1-.285.988L136.831,25.5h-1.2l-3.143-7.793a7.236,7.236,0,0,1-.277-1.047h-.029q.057.63.058,2.058V25.5h-1.611V15h2.453l2.762,7a10.884,10.884,0,0,1,.41,1.2h.036c.181-.551.327-.962.44-1.23L139.541,15h2.366Z"
88
+ fill="#5e5e5e" />
89
+ <path
90
+ d="M145.158,16.426a1.022,1.022,0,0,1-.714-.272.89.89,0,0,1-.3-.688.916.916,0,0,1,.3-.7,1.009,1.009,0,0,1,.714-.278,1.043,1.043,0,0,1,.733.278.911.911,0,0,1,.3.7.9.9,0,0,1-.3.678A1.038,1.038,0,0,1,145.158,16.426ZM146,25.5h-1.7V18H146Z"
91
+ fill="#5e5e5e" />
92
+ <path
93
+ d="M153.589,25.156a4.2,4.2,0,0,1-2.131.52,3.606,3.606,0,0,1-2.695-1.044,3.691,3.691,0,0,1-1.026-2.706,4.07,4.07,0,0,1,1.1-2.978,3.944,3.944,0,0,1,2.948-1.124,4.3,4.3,0,0,1,1.81.36v1.582a2.743,2.743,0,0,0-1.67-.586,2.32,2.32,0,0,0-1.766.728,2.665,2.665,0,0,0-.688,1.908,2.536,2.536,0,0,0,.648,1.838,2.3,2.3,0,0,0,1.739.674,2.716,2.716,0,0,0,1.729-.652Z"
94
+ fill="#5e5e5e" />
95
+ <path
96
+ d="M159.625,19.619a1.4,1.4,0,0,0-.887-.242,1.513,1.513,0,0,0-1.259.682,3.04,3.04,0,0,0-.506,1.852V25.5h-1.7V18h1.7v1.545H157a2.606,2.606,0,0,1,.766-1.233,1.724,1.724,0,0,1,1.154-.444,1.432,1.432,0,0,1,.7.14Z"
97
+ fill="#5e5e5e" />
98
+ <path
99
+ d="M164.02,25.676a3.719,3.719,0,0,1-2.773-1.051,3.8,3.8,0,0,1-1.036-2.787,3.7,3.7,0,0,1,3.991-4.014,3.6,3.6,0,0,1,2.739,1.033,3.986,3.986,0,0,1,.982,2.864,3.932,3.932,0,0,1-1.059,2.875A3.8,3.8,0,0,1,164.02,25.676Zm.08-6.5a1.938,1.938,0,0,0-1.575.7,2.913,2.913,0,0,0-.579,1.919,2.744,2.744,0,0,0,.586,1.856,1.965,1.965,0,0,0,1.568.678,1.87,1.87,0,0,0,1.542-.666,2.956,2.956,0,0,0,.538-1.9,3,3,0,0,0-.538-1.911A1.858,1.858,0,0,0,164.1,19.18Z"
100
+ fill="#5e5e5e" />
101
+ <path
102
+ d="M169.182,25.266V23.691a3.392,3.392,0,0,0,2.1.725q1.539,0,1.538-.908a.714.714,0,0,0-.132-.436,1.241,1.241,0,0,0-.355-.318,2.784,2.784,0,0,0-.527-.25q-.3-.108-.677-.248a7.052,7.052,0,0,1-.832-.389,2.545,2.545,0,0,1-.615-.465,1.745,1.745,0,0,1-.37-.59,2.145,2.145,0,0,1-.125-.769,1.775,1.775,0,0,1,.256-.955,2.223,2.223,0,0,1,.69-.7,3.289,3.289,0,0,1,.98-.425,4.511,4.511,0,0,1,1.136-.143,5.181,5.181,0,0,1,1.86.315v1.487a3.136,3.136,0,0,0-1.816-.542,2.317,2.317,0,0,0-.582.066,1.472,1.472,0,0,0-.443.183.886.886,0,0,0-.286.282.669.669,0,0,0-.1.363.77.77,0,0,0,.1.41.93.93,0,0,0,.3.3,2.654,2.654,0,0,0,.483.234q.282.105.649.23a9.4,9.4,0,0,1,.867.4,2.886,2.886,0,0,1,.656.465,1.806,1.806,0,0,1,.417.6,2.034,2.034,0,0,1,.147.81,1.847,1.847,0,0,1-.264,1,2.205,2.205,0,0,1-.7.7,3.292,3.292,0,0,1-1.015.413,5.222,5.222,0,0,1-1.212.136A5.115,5.115,0,0,1,169.182,25.266Z"
103
+ fill="#5e5e5e" />
104
+ <path
105
+ d="M179.443,25.676a3.717,3.717,0,0,1-2.772-1.051,3.793,3.793,0,0,1-1.036-2.787,3.7,3.7,0,0,1,3.991-4.014,3.6,3.6,0,0,1,2.739,1.033,3.986,3.986,0,0,1,.982,2.864,3.932,3.932,0,0,1-1.059,2.875A3.8,3.8,0,0,1,179.443,25.676Zm.08-6.5a1.936,1.936,0,0,0-1.574.7,2.908,2.908,0,0,0-.579,1.919,2.739,2.739,0,0,0,.586,1.856,1.964,1.964,0,0,0,1.567.678,1.868,1.868,0,0,0,1.542-.666,2.95,2.95,0,0,0,.539-1.9,2.99,2.99,0,0,0-.539-1.911A1.857,1.857,0,0,0,179.523,19.18Z"
106
+ fill="#5e5e5e" />
107
+ <path
108
+ d="M189.067,15.781a1.533,1.533,0,0,0-.784-.2q-1.237,0-1.237,1.4V18h1.743v1.333h-1.736V25.5h-1.7V19.333h-1.282V18h1.282V16.784a2.362,2.362,0,0,1,.777-1.871,2.82,2.82,0,0,1,1.94-.684,2.879,2.879,0,0,1,1,.138Z"
109
+ fill="#5e5e5e" />
110
+ <path
111
+ d="M194.23,25.42a2.955,2.955,0,0,1-1.31.248q-2.182,0-2.183-2.094V19.333h-1.253V18h1.253V16.264l1.7-.483V18h1.793v1.333h-1.793v3.75a1.484,1.484,0,0,0,.241.952,1,1,0,0,0,.806.285,1.165,1.165,0,0,0,.746-.248Z"
112
+ fill="#5e5e5e" />
113
+ <rect x="13" y="11" width="9" height="9" fill="#f25022" />
114
+ <rect x="13" y="21" width="9" height="9" fill="#00a4ef" />
115
+ <rect x="23" y="11" width="9" height="9" fill="#7fba00" />
116
+ <rect x="23" y="21" width="9" height="9" fill="#ffb900" />
117
+ </svg>
118
+ </a>
119
+ </template>
@@ -50,7 +50,6 @@ const onDelete = async () => {
50
50
 
51
51
  }
52
52
 
53
- console.log(light)
54
53
  useHead({
55
54
  title: light.company + " - " + title,
56
55
  })
@@ -1,6 +1,8 @@
1
1
  <script setup>
2
2
  import { ref } from 'vue'
3
- import { q, m } from '#imports'
3
+ import { q, m, useLight } from '#imports';
4
+
5
+ const light = useLight()
4
6
 
5
7
  const { app } = await q({ app: { config: ["name", "value"] } })
6
8
  const obj = app.config.reduce((acc, cur) => {
@@ -11,6 +13,24 @@ const obj = app.config.reduce((acc, cur) => {
11
13
  obj.revision = obj.revision ? obj.revision.split(',') : []
12
14
 
13
15
  const tab = ref('general')
16
+
17
+ const onSubmit = async (d) => {
18
+ let data = [];
19
+ Object.keys(d).forEach((key) => {
20
+ data.push({
21
+ name: key,
22
+ value: d[key]
23
+ })
24
+ })
25
+ await m("updateAppConfigs", { data })
26
+
27
+ light.notify({ message: "Settings saved", color: "positive" })
28
+
29
+ //update the modelValue
30
+ Object.keys(d).forEach((key) => {
31
+ obj[key] = d[key]
32
+ })
33
+ }
14
34
  </script>
15
35
  <template>
16
36
  <l-page>
@@ -24,6 +44,7 @@ const tab = ref('general')
24
44
  <q-tab name="Modules" icon="sym_o_apps" :label="$t('Modules')" />
25
45
  <q-tab name="mail" icon="sym_o_email" :label="$t('Mail')" />
26
46
  <q-tab name="forget-password" icon="sym_o_lock" :label="$t('Forget password')" />
47
+ <q-tab name="authentication" icon="sym_o_passkey" :label="$t('Authentication')" />
27
48
  <q-tab name="developer" icon="sym_o_code" :label="$t('Developer')" />
28
49
  </q-tabs>
29
50
  </template>
@@ -34,6 +55,7 @@ const tab = ref('general')
34
55
  <l-system-setting-modules v-if="tab == 'Modules'" v-model="obj" />
35
56
  <l-system-setting-developer v-if="tab == 'developer'" v-model="obj" />
36
57
  <l-system-setting-forget-password v-if="tab == 'forget-password'" v-model="obj" />
58
+ <l-system-setting-authentication v-if="tab == 'authentication'" v-bind="obj" @submit="onSubmit" />
37
59
  </template>
38
60
  </q-splitter>
39
61
  </l-card>
@@ -1,13 +1,23 @@
1
1
  <script setup>
2
2
  import { reactive, onMounted, nextTick } from "vue"
3
3
  import { useQuasar } from "quasar";
4
- import { q, m, api, useLight } from '#imports'
4
+ import { q, m, useLight } from '#imports'
5
5
  import { useI18n } from 'vue-i18n'
6
6
 
7
7
  const light = useLight()
8
8
  const { t } = useI18n()
9
9
  const quasar = useQuasar();
10
- let { app, my } = await q({ app: ['googleClientId'], my: ["gmail"] })
10
+ let { app, my } = await q({
11
+ app: {
12
+ googleClientId: true,
13
+ microsoftClientId: true,
14
+ facebookAppId: true,
15
+ }, my: {
16
+ google: true,
17
+ microsoft: true,
18
+ facebook: true,
19
+ }
20
+ })
11
21
 
12
22
  const $q = useQuasar();
13
23
  my = reactive(my);
@@ -17,7 +27,7 @@ const handleGoogleCredentialResponse = async (response) => {
17
27
  await m("googleRegister", { credential: response.credential })
18
28
 
19
29
  const resp = await q("my", ["gmail"]);
20
- my.gmail = resp.gmail;
30
+ my.google = resp.google;
21
31
 
22
32
  light.notify({
23
33
  message: "Google account linked",
@@ -84,33 +94,146 @@ const onUnlink = async () => {
84
94
  my.gmail = null;
85
95
  window.location.reload();
86
96
  })
97
+ }
98
+
99
+ const ms = reactive({});
100
+
101
+ const onUnlinkMicrosoft = async () => {
102
+ //confirm
103
+ light.dialog({
104
+ title: "Unlink",
105
+ color: "negative",
106
+ message: "Are you sure you want to unlink your Microsoft account?",
107
+ ok: "Yes",
108
+ cancel: "No",
109
+ }).onOk(async () => {
110
+ await m("unlinkMicrosoft");
111
+ my.microsoft = null;
112
+ window.location.reload();
113
+ })
114
+ }
115
+
116
+ const onLinkMicrosoft = async (resp) => {
117
+ try {
118
+ await m("microsoftRegister", { account_id: resp.account.localAccountId });
119
+ light.notify({
120
+ message: "Microsoft account linked",
121
+ color: "positive",
122
+ });
87
123
 
124
+ window.location.reload();
125
+ } catch (e) {
126
+ light.notify({
127
+ message: e.message,
128
+ color: "negative",
129
+ });
130
+ }
131
+ }
132
+
133
+ const onLinkFacebook = (accessToken) => {
134
+ try {
135
+ m("facebookRegister", { access_token: accessToken })
136
+ light.notify({
137
+ message: "Facebook account linked",
138
+ color: "positive",
139
+ });
140
+ } catch (e) {
141
+ light.notify({
142
+ message: e.message,
143
+ color: "negative",
144
+ });
145
+ }
146
+
147
+ }
148
+
149
+ const onUnlinkFacebook = async () => {
150
+ //confirm
151
+ light.dialog({
152
+ title: "Unlink",
153
+ color: "negative",
154
+ message: "Are you sure you want to unlink your Facebook account?",
155
+ ok: "Yes",
156
+ cancel: "No",
157
+ }).onOk(async () => {
158
+ await m("unlinkFacebook");
159
+ my.facebook = null;
160
+ window.location.reload();
161
+ })
88
162
  }
89
163
 
90
164
  </script>
91
165
  <template>
92
- <q-card>
93
- <template v-if="app.googleClientId">
94
- <template v-if="my.gmail">
95
- <q-card-section>
166
+ <q-card :bordered="false">
167
+ <q-card-section>
168
+ <h2 class="text-h6">Google</h2>
169
+ <template v-if="app.googleClientId">
170
+ <template v-if="my.google">
171
+
96
172
  {{ $t('You have already linked your Google account.') }}<br />
97
- Your gmail id is {{ my.gmail }}
98
- </q-card-section>
173
+ Your gmail id is {{ my.google }}<br />
174
+ <l-btn label="Unlink" @click="onUnlink" icon="sym_o_link_off"></l-btn>
99
175
 
100
- <q-card-actions>
101
- <l-btn label="Unlink" @click="onUnlink" icon="sym_o_delete"></l-btn>
102
- </q-card-actions>
176
+ </template>
103
177
 
178
+ <template v-else>
179
+ {{ $t('Click the button below to link your Google account.') }}
180
+ <div id="g_id_signin"></div>
181
+ </template>
104
182
  </template>
105
183
 
106
- <q-card-section v-else>
107
- {{ $t('Click the button below to link your Google account.') }}
108
- <div id="g_id_signin"></div>
109
- </q-card-section>
110
- </template>
184
+ <template v-else>
185
+ Google login is not available. Please set authentication google client id in server settings.
186
+ </template>
187
+ </q-card-section>
188
+
111
189
 
112
- <q-card-section v-else>
113
- Google login is not available. Please set GOOGLE_CLIENT_ID in server settings.
190
+ <q-separator />
191
+
192
+ <q-card-section>
193
+ <h2 class="text-h6">Microsoft</h2>
194
+ <template v-if="app.microsoftClientId">
195
+ <template v-if="my.microsoft">
196
+ {{ $t('You have already linked your Microsoft account.') }}<br />
197
+ Your account id is {{ my.microsoft }}
198
+ <br />
199
+ <l-btn label="Unlink" @click="onUnlinkMicrosoft" icon="sym_o_link_off"></l-btn>
200
+ </template>
201
+ <template v-else>
202
+ <div>{{ $t('Click the button below to link your Microsoft account.') }}</div>
203
+ <div>
204
+ <l-microsoft-button :client-id="app.microsoftClientId" @login="onLinkMicrosoft" />
205
+ </div>
206
+ </template>
207
+ </template>
208
+ <template v-else>
209
+ Micorsoft login is not available. Please set authentication microsft client id in server settings.
210
+ </template>
114
211
  </q-card-section>
212
+
213
+
214
+ <q-separator />
215
+ <q-card-section>
216
+ <h2 class="text-h6">Facebook</h2>
217
+ <template v-if="app.facebookAppId">
218
+ <template v-if="my.facebook">
219
+ {{ $t('You have already linked your Facebook account.') }}<br />
220
+ Your account id is {{ my.facebook }}
221
+ <l-btn label="Unlink" @click="onUnlinkFacebook" icon="sym_o_link_off"></l-btn>
222
+ </template>
223
+ <template v-else>
224
+ <div>{{ $t('Click the button below to link your Facebook account.') }}</div>
225
+ <l-facebook-button @login="onLinkFacebook" />
226
+ </template>
227
+ </template>
228
+ <template v-else>
229
+ Facebook login is not available. Please set authentication facebook app id in server settings.
230
+ </template>
231
+ </q-card-section>
232
+
233
+
234
+
235
+
236
+
237
+
115
238
  </q-card>
116
239
  </template>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostlink/nuxt-light",
3
- "version": "1.18.3",
3
+ "version": "1.19.0",
4
4
  "description": "HostLink Nuxt Light Framework",
5
5
  "repository": {
6
6
  "type": "git",
@@ -32,8 +32,9 @@
32
32
  "test:watch": "vitest watch"
33
33
  },
34
34
  "dependencies": {
35
+ "@azure/msal-browser": "^3.26.1",
35
36
  "@formkit/drag-and-drop": "^0.1.6",
36
- "@hostlink/light": "^2.0.2",
37
+ "@hostlink/light": "^2.1.0",
37
38
  "@nuxt/kit": "^3.7.4",
38
39
  "@nuxt/module-builder": "^0.8.3",
39
40
  "@quasar/extras": "^1.16.11",
@@ -47,6 +48,7 @@
47
48
  "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz"
48
49
  },
49
50
  "devDependencies": {
51
+ "@azure/identity": "^4.5.0",
50
52
  "@nuxt/devtools": "latest",
51
53
  "@nuxt/eslint-config": "^0.2.0",
52
54
  "@nuxt/schema": "^3.7.4",