@fy-/fws-vue 0.3.56 → 0.3.58

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.
@@ -176,16 +176,6 @@ const userFlow = async (params: paramsType = { initial: false }) => {
176
176
  eventBus.emit("login-loading", false);
177
177
  };
178
178
 
179
- const getContrastingTextColor = (backgroundColor: string) => {
180
- const r = parseInt(backgroundColor.substring(1, 3), 16);
181
- const g = parseInt(backgroundColor.substring(3, 5), 16);
182
- const b = parseInt(backgroundColor.substring(5, 7), 16);
183
-
184
- const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
185
-
186
- return luminance > 0.5 ? "#000000" : "#FFFFFF";
187
- };
188
-
189
179
  onMounted(async () => {
190
180
  await userFlow({ initial: true });
191
181
  });
@@ -223,7 +213,7 @@ onMounted(async () => {
223
213
  class="flex border border-fv-neutral-300 dark:border-fv-neutral-700 shadow items-center gap-2 justify-start btn neutral defaults w-full mx-auto !font-semibold"
224
214
  :style="`background: ${
225
215
  field.button['background-color']
226
- }; color: ${getContrastingTextColor(
216
+ }; color: ${$getContrastingTextColor(
227
217
  field.button['background-color'],
228
218
  )}`"
229
219
  >
@@ -0,0 +1,161 @@
1
+ <script setup lang="ts">
2
+ import { useTranslation } from "../../composables/translations";
3
+ import { useEventBus } from "../../composables/event-bus";
4
+ import { useUserStore } from "../../stores/user";
5
+ import { useRest, APIResult } from "../../composables/rest";
6
+ import DefaultModal from "../ui/DefaultModal.vue";
7
+
8
+ import { ref, computed, onMounted } from "vue";
9
+ const rest = useRest();
10
+ const eventBus = useEventBus();
11
+ const userStore = useUserStore();
12
+ const isAuth = computed(() => userStore.isAuth);
13
+ const data = ref();
14
+ const providersData = ref();
15
+ const usedProviders = ref<Record<string, boolean>>({});
16
+ const getOAuth2Providers = async () => {
17
+ eventBus.emit("main-loading", true);
18
+ const d = await rest("User/OAuth2/Providers", "GET");
19
+ if (d && d.result == "success") {
20
+ providersData.value = d.data;
21
+ }
22
+ eventBus.emit("main-loading", false);
23
+ };
24
+ const getOAuth2Redirect = async (providerUUID: string) => {
25
+ eventBus.emit("main-loading", true);
26
+ const d = await rest(`User/OAuth2/Provider/${providerUUID}`, "GET");
27
+ if (d && d.result == "success") {
28
+ window.location.href = d.data;
29
+ }
30
+ eventBus.emit("main-loading", false);
31
+ };
32
+ const translate = useTranslation();
33
+ const deleteOAuth2Connection = async (providerUUID: string) => {
34
+ eventBus.emit("showConfirm", {
35
+ title: translate("remove_provider_confirm_title"),
36
+ desc: translate("remove_provider_confirm_desc_warning"),
37
+ onConfirm: async () => {
38
+ eventBus.emit("main-loading", true);
39
+ const d = await rest(`User/OAuth2/Provider/${providerUUID}`, "DELETE");
40
+ if (d && d.result == "success") {
41
+ getOAuth2User();
42
+ }
43
+ eventBus.emit("main-loading", false);
44
+ },
45
+ });
46
+ };
47
+ const getOAuth2User = async () => {
48
+ eventBus.emit("main-loading", true);
49
+ if (!isAuth.value) {
50
+ return;
51
+ }
52
+ const d = await rest("User/OAuth2", "GET");
53
+ usedProviders.value = {};
54
+ if (d && d.result == "success") {
55
+ data.value = d.data;
56
+ data.value.forEach((p: any) => {
57
+ usedProviders.value[p.ProviderUUID] = true;
58
+ });
59
+ }
60
+ eventBus.emit("main-loading", false);
61
+ };
62
+ onMounted(() => {
63
+ getOAuth2User();
64
+ getOAuth2Providers();
65
+ });
66
+ </script>
67
+
68
+ <template>
69
+ <div class="flex flex-col gap-3">
70
+ <DefaultModal id="providers" :title="$t('providers_modal_title')">
71
+ <template v-for="provider in providersData" :key="provider.UUID">
72
+ <div
73
+ class="flex items-center gap-3"
74
+ v-if="!usedProviders[provider.UUID]"
75
+ >
76
+ <button
77
+ @click="
78
+ () => {
79
+ getOAuth2Redirect(provider.UUID);
80
+ }
81
+ "
82
+ class="flex border border-fv-neutral-300 dark:border-fv-neutral-700 shadow items-center gap-2 justify-start btn neutral defaults w-full mx-auto !font-semibold"
83
+ :style="`background: ${
84
+ provider.Data.Button.button['background-color']
85
+ }; color: ${$getContrastingTextColor(
86
+ provider.Data.Button.button['background-color'],
87
+ )}`"
88
+ >
89
+ <img
90
+ :key="`${provider.Data.Button.label}oauth`"
91
+ class="h-12 w-12 block p-2 mr-3"
92
+ :alt="provider.Data.Button.info.Name"
93
+ :src="provider.Data.Button.button.logo"
94
+ />
95
+ <div>
96
+ {{
97
+ $t("user_flow_signin_with", {
98
+ provider: provider.Data.Button.name,
99
+ })
100
+ }}
101
+ </div>
102
+ </button>
103
+ </div>
104
+ </template>
105
+ </DefaultModal>
106
+ <h2 class="text-xl flex items-center justify-between">
107
+ <span>{{ $t("oauth2_providers_title") }}</span>
108
+ <button
109
+ class="btn primary medium !py-1 !px-3"
110
+ @click="
111
+ () => {
112
+ $eventBus.emit('providersModal', true);
113
+ }
114
+ "
115
+ >
116
+ {{ $t("add_oauth2_con_cta") }}
117
+ </button>
118
+ </h2>
119
+ <p
120
+ class="text-red-900 dark:text-red-300 text-sm bg-red-200/[.2] dark:bg-red-900/[.2] p-2 rounded shadow"
121
+ v-if="
122
+ $route.query.error &&
123
+ $route.query.error === 'user_oauth2_connection_exists'
124
+ "
125
+ >
126
+ {{ $t("oauth2_error_user_oauth2_connection_exists") }}
127
+ </p>
128
+ <div v-if="data && data.length == 0">
129
+ <p>{{ $t("providers_empty") }}</p>
130
+ </div>
131
+ <div
132
+ v-for="provider in data"
133
+ class="flex items-center gap-3"
134
+ :key="provider.ProviderUUID"
135
+ >
136
+ <img
137
+ :src="provider.Provider.Button.button.logo"
138
+ class="w-14 h-14 p-1 rounded-full"
139
+ :style="`background-color: ${provider.Provider.Button.button['background-color']}`"
140
+ />
141
+ <div>
142
+ <h3 class="text-xl">
143
+ {{ provider.Provider.Button.name }}
144
+ <small class="text-xs">({{ provider.ServiceID }})</small>
145
+ </h3>
146
+ <div class="flex gap-2 mt-1">
147
+ <button
148
+ class="btn danger small"
149
+ @click="
150
+ () => {
151
+ deleteOAuth2Connection(provider.ProviderUUID);
152
+ }
153
+ "
154
+ >
155
+ {{ $t("remove_oauth2_con_cta") }}
156
+ </button>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ </div>
161
+ </template>
@@ -313,6 +313,7 @@ onUnmounted(() => {
313
313
  />
314
314
  <component
315
315
  v-else
316
+ @click="$eventBus.emit(`${id}GalleryImage`, i - 1)"
316
317
  :is="imageComponent"
317
318
  :image="getThumbnailUrl(images[i - 1]).image"
318
319
  :variant="getThumbnailUrl(images[i - 1]).variant"
@@ -357,6 +358,7 @@ onUnmounted(() => {
357
358
  :variant="getThumbnailUrl(images[i + j - 2]).variant"
358
359
  :alt="getThumbnailUrl(images[i + j - 2]).alt"
359
360
  class="h-auto max-w-full rounded-lg cursor-pointer"
361
+ @click="$eventBus.emit(`${id}GalleryImage`, i + j - 2)"
360
362
  />
361
363
  </div>
362
364
  </template>
@@ -376,6 +378,7 @@ onUnmounted(() => {
376
378
  :variant="getThumbnailUrl(images[i - 1]).variant"
377
379
  :alt="getThumbnailUrl(images[i - 1]).alt"
378
380
  class="h-auto max-w-full rounded-lg cursor-pointer"
381
+ @click="$eventBus.emit(`${id}GalleryImage`, i - 1)"
379
382
  />
380
383
  </div>
381
384
  </template>
@@ -8,7 +8,15 @@ const cropText = (str: string, ml = 100, end = "...") => {
8
8
  }
9
9
  return str;
10
10
  };
11
+ const getContrastingTextColor = (backgroundColor: string) => {
12
+ const r = parseInt(backgroundColor.substring(1, 3), 16);
13
+ const g = parseInt(backgroundColor.substring(3, 5), 16);
14
+ const b = parseInt(backgroundColor.substring(5, 7), 16);
11
15
 
16
+ const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
17
+
18
+ return luminance > 0.5 ? "#000000" : "#FFFFFF";
19
+ };
12
20
  const formatBytes = (bytes: number, decimals = 2) => {
13
21
  if (!+bytes) return "0 Bytes";
14
22
 
@@ -76,4 +84,11 @@ const formatTimeago = (dt: Date | string | number) => {
76
84
  return formatDateTimeago(new Date(_dt), getLocale().replace("_", "-"));
77
85
  };
78
86
 
79
- export { cropText, formatBytes, formatDate, formatDatetime, formatTimeago };
87
+ export {
88
+ cropText,
89
+ formatBytes,
90
+ formatDate,
91
+ formatDatetime,
92
+ formatTimeago,
93
+ getContrastingTextColor,
94
+ };
package/index.ts CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  formatDate,
20
20
  formatDatetime,
21
21
  formatTimeago,
22
+ getContrastingTextColor,
22
23
  } from "./composables/templating";
23
24
  import { useRest } from "./composables/rest";
24
25
  export * from "./stores/serverRouter";
@@ -48,7 +49,7 @@ import DataTable from "./components/fws/DataTable.vue";
48
49
  import FilterData from "./components/fws/FilterData.vue";
49
50
  import CmsArticleBoxed from "./components/fws/CmsArticleBoxed.vue";
50
51
  import CmsArticleSingle from "./components/fws/CmsArticleSingle.vue";
51
-
52
+ import UserOAuth2 from "./components/fws/UserOAuth2.vue";
52
53
  // Css
53
54
  import "./style.css";
54
55
 
@@ -71,6 +72,8 @@ function createFWS(): Plugin {
71
72
  app.config.globalProperties.$formatTimeago = formatTimeago;
72
73
  app.config.globalProperties.$formatDatetime = formatDatetime;
73
74
  app.config.globalProperties.$formatDate = formatDate;
75
+ app.config.globalProperties.$getContrastingTextColor =
76
+ getContrastingTextColor;
74
77
 
75
78
  app.component("ClientOnly", ClientOnly);
76
79
  }
@@ -87,6 +90,7 @@ declare module "vue" {
87
90
  $formatTimeago: typeof formatTimeago;
88
91
  $formatDatetime: typeof formatDatetime;
89
92
  $formatDate: typeof formatDate;
93
+ $getContrastingTextColor: typeof getContrastingTextColor;
90
94
  }
91
95
  export interface GlobalComponents {
92
96
  ClientOnly: typeof ClientOnly;
@@ -130,6 +134,7 @@ export {
130
134
 
131
135
  // FWS
132
136
  UserFlow,
137
+ UserOAuth2,
133
138
  DataTable,
134
139
  FilterData,
135
140
  CmsArticleBoxed,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fy-/fws-vue",
3
- "version": "0.3.56",
3
+ "version": "0.3.58",
4
4
  "author": "Florian 'Fy' Gasquez <m@fy.to>",
5
5
  "license": "MIT",
6
6
  "repository": {