feeds-fun 1.18.1 → 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/package.json +5 -3
- package/src/App.vue +25 -1
- package/src/components/EntryForList.vue +6 -2
- package/src/components/FeedForList.vue +8 -5
- package/src/components/RuleForList.vue +3 -2
- package/src/components/collections/FeedItem.vue +10 -4
- package/src/components/main/Description.vue +7 -7
- package/src/components/main/Item.vue +1 -3
- package/src/components/main/NewsTitle.vue +1 -1
- package/src/components/page_footer/Footer.vue +106 -0
- package/src/components/page_header/ExternalLinks.vue +24 -46
- package/src/components/page_header/HomeButton.vue +14 -0
- package/src/components/side_pannel/CollapseButton.vue +7 -5
- package/src/components/tags/Base.vue +3 -1
- package/src/css/page_header.css +6 -2
- package/src/css/side_panel_layout.css +1 -1
- package/src/layouts/SidePanelLayout.vue +13 -9
- package/src/layouts/WideLayout.vue +2 -0
- package/src/logic/api.ts +15 -0
- package/src/logic/events.ts +17 -0
- package/src/logic/marketing.ts +54 -0
- package/src/logic/settings.ts +16 -0
- package/src/main.ts +14 -13
- package/src/plugins/CookieConsent.ts +170 -0
- package/src/router/index.ts +14 -0
- package/src/stores/globalState.ts +1 -1
- package/src/style.css +0 -2
- package/src/values/ExternalUrl.vue +4 -1
- package/src/values/Icon.vue +71 -0
- package/src/values/SocialLink.vue +81 -0
- package/src/views/AuthView.vue +22 -9
- package/src/views/CRMView.vue +41 -0
- package/src/views/MainView.vue +32 -17
- package/src/views/SettingsView.vue +33 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feeds-fun",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"author": "Aliaksei Yaletski (Tiendil) <a.eletsky@gmail.com> (https://tiendil.org/)",
|
|
5
5
|
"description": "Frontend for the Feeds Fun — web-based news reader",
|
|
6
6
|
"keywords": [
|
|
@@ -33,15 +33,17 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@chenfengyuan/vue-countdown": "^2.1.2",
|
|
36
|
+
"@tabler/icons-vue": "^3.31.0",
|
|
36
37
|
"@vueuse/core": "^11.2.0",
|
|
37
38
|
"axios": "^1.7.7",
|
|
38
39
|
"dompurify": "^3.1.7",
|
|
40
|
+
"lodash": "^4.17.21",
|
|
39
41
|
"pinia": "^2.2.6",
|
|
40
42
|
"set-interval-async": "^3.0.3",
|
|
41
43
|
"supertokens-web-js": "^0.5.0",
|
|
44
|
+
"vanilla-cookieconsent": "^3.1.0",
|
|
42
45
|
"vue": "^3.5.12",
|
|
43
|
-
"vue-router": "^4.4.5"
|
|
44
|
-
"lodash": "^4.17.21"
|
|
46
|
+
"vue-router": "^4.4.5"
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
|
47
49
|
"@rushstack/eslint-patch": "^1.10.4",
|
package/src/App.vue
CHANGED
|
@@ -2,7 +2,31 @@
|
|
|
2
2
|
<router-view />
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
|
-
<script setup lang="ts"
|
|
5
|
+
<script setup lang="ts">
|
|
6
|
+
import {onMounted} from "vue";
|
|
7
|
+
import {watchEffect} from "vue";
|
|
8
|
+
import {useRoute, useRouter} from "vue-router";
|
|
9
|
+
import {StorageSerializers, useStorage} from "@vueuse/core";
|
|
10
|
+
import {useGlobalState} from "@/stores/globalState";
|
|
11
|
+
import * as marketing from "@/logic/marketing";
|
|
12
|
+
import * as events from "@/logic/events";
|
|
13
|
+
|
|
14
|
+
const route = useRoute();
|
|
15
|
+
const router = useRouter();
|
|
16
|
+
const utmStorage = useStorage("ffun_utm", null, undefined, {serializer: StorageSerializers.object});
|
|
17
|
+
const globalState = useGlobalState();
|
|
18
|
+
|
|
19
|
+
watchEffect(() => {
|
|
20
|
+
marketing.processUTM(route, router, utmStorage);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
watchEffect(async () => {
|
|
24
|
+
if (utmStorage.value && globalState.isLoggedIn && Object.keys(utmStorage.value).length > 0) {
|
|
25
|
+
await events.trackUtm(utmStorage.value);
|
|
26
|
+
utmStorage.value = null;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
</script>
|
|
6
30
|
|
|
7
31
|
<style scoped>
|
|
8
32
|
.container {
|
|
@@ -8,14 +8,18 @@
|
|
|
8
8
|
href="#"
|
|
9
9
|
@click.prevent="markUnread()"
|
|
10
10
|
title="Mark as unread"
|
|
11
|
-
class="text-green-700
|
|
11
|
+
class="text-green-700">
|
|
12
|
+
<icon icon="chevrons-left" />
|
|
13
|
+
</a>
|
|
12
14
|
|
|
13
15
|
<a
|
|
14
16
|
v-else
|
|
15
17
|
href="#"
|
|
16
18
|
@click.prevent="markRead()"
|
|
17
19
|
title="Mark as read"
|
|
18
|
-
class="text-orange-700
|
|
20
|
+
class="text-orange-700">
|
|
21
|
+
<icon icon="chevrons-right" />
|
|
22
|
+
</a>
|
|
19
23
|
</div>
|
|
20
24
|
|
|
21
25
|
<div
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
<div class="ffun-body-list-icon-column">
|
|
6
6
|
<a
|
|
7
7
|
href="#"
|
|
8
|
-
class="
|
|
8
|
+
class="text-red-500 hover:text-red-600"
|
|
9
9
|
title="Unsubscribe"
|
|
10
10
|
@click.prevent="feedsStore.unsubscribe(feed.id)">
|
|
11
|
+
<icon icon="x" />
|
|
11
12
|
</a>
|
|
12
13
|
</div>
|
|
13
14
|
|
|
@@ -20,14 +21,16 @@
|
|
|
20
21
|
:time="feed.linkedAt" />
|
|
21
22
|
|
|
22
23
|
<div class="ffun-body-list-icon-column ml-3">
|
|
23
|
-
<
|
|
24
|
+
<icon
|
|
24
25
|
v-if="feed.isOk"
|
|
25
26
|
title="everything is ok"
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
icon="face-smile"
|
|
28
|
+
class="text-green-700" />
|
|
29
|
+
<icon
|
|
28
30
|
v-else
|
|
29
31
|
:title="feed.lastError || 'unknown error'"
|
|
30
|
-
|
|
32
|
+
icon="face-sad"
|
|
33
|
+
class="text-red-700" />
|
|
31
34
|
</div>
|
|
32
35
|
|
|
33
36
|
<body-list-favicon-column :url="feed.url" />
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
<div
|
|
4
4
|
v-if="rule !== null"
|
|
5
5
|
class="flex mb-1">
|
|
6
|
-
<div class="ffun-body-list-icon-column">
|
|
6
|
+
<div class="ffun-body-list-icon-column flex items-center">
|
|
7
7
|
<a
|
|
8
8
|
href="#"
|
|
9
|
-
class="
|
|
9
|
+
class="text-red-500 hover:text-red-600 flex items-center"
|
|
10
10
|
title="Remove this rule"
|
|
11
11
|
@click.prevent="deleteRule()">
|
|
12
|
+
<icon icon="x" />
|
|
12
13
|
</a>
|
|
13
14
|
</div>
|
|
14
15
|
|
|
@@ -1,22 +1,28 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="flex text-lg">
|
|
3
|
-
<div class="ffun-body-list-icon-column">
|
|
3
|
+
<div class="ffun-body-list-icon-column flex items-center justify-center">
|
|
4
4
|
<a
|
|
5
5
|
v-if="subscribed"
|
|
6
6
|
href="#"
|
|
7
7
|
@click.prevent="feedsStore.unsubscribe(feed.id)"
|
|
8
8
|
title="Unsubscribe from this feed"
|
|
9
|
-
class="text-red-500 hover:text-red-600
|
|
9
|
+
class="text-red-500 hover:text-red-600 flex items-center justify-center">
|
|
10
|
+
<icon icon="x" />
|
|
11
|
+
</a>
|
|
10
12
|
|
|
11
13
|
<a
|
|
12
14
|
v-else
|
|
13
15
|
href="#"
|
|
14
16
|
@click.prevent="feedsStore.subscribe(feed.url)"
|
|
15
17
|
title="Subscribe to this feed"
|
|
16
|
-
class="text-green-600 hover:text-green-700
|
|
18
|
+
class="text-green-600 hover:text-green-700 flex items-center justify-center">
|
|
19
|
+
<icon icon="plus" />
|
|
20
|
+
</a>
|
|
17
21
|
</div>
|
|
18
22
|
|
|
19
|
-
<body-list-favicon-column
|
|
23
|
+
<body-list-favicon-column
|
|
24
|
+
:url="feed.url"
|
|
25
|
+
class="flex items-center justify-center" />
|
|
20
26
|
|
|
21
27
|
<div class="flex-grow">
|
|
22
28
|
<external-url
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<!-- PC -->
|
|
3
3
|
<div class="hidden md:flex items-stretch rounded-xl overflow-hidden min-h-28 max-h-28 mx-2">
|
|
4
|
-
<div class="w-12 bg-blue-200 flex items-center justify-center text-4xl font-
|
|
5
|
-
|
|
4
|
+
<div class="w-12 bg-blue-200 flex items-center justify-center text-4xl font-medium">
|
|
5
|
+
{{ step }}
|
|
6
6
|
</div>
|
|
7
7
|
|
|
8
8
|
<div class="w-1/3 bg-blue-100 px-4 flex items-center text-xl font-medium">
|
|
9
9
|
<slot name="caption" />
|
|
10
10
|
</div>
|
|
11
11
|
|
|
12
|
-
<div class="flex-1 bg-slate-100 p-
|
|
12
|
+
<div class="flex-1 bg-slate-100 p-4 text-gray-800 flex items-center">
|
|
13
13
|
<div class="w-full">
|
|
14
14
|
<slot name="description" />
|
|
15
15
|
</div>
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
<!-- Mobile -->
|
|
20
20
|
<div class="flex flex-col md:hidden flex items-stretch rounded-xl overflow-hidden min-h-28 max-h-28 mx-2">
|
|
21
21
|
<div class="w-full flex">
|
|
22
|
-
<div class="w-12 bg-blue-200 flex items-center justify-center text-lg font-
|
|
23
|
-
|
|
22
|
+
<div class="w-12 bg-blue-200 flex items-center justify-center text-lg font-medium">
|
|
23
|
+
{{ step }}
|
|
24
24
|
</div>
|
|
25
25
|
|
|
26
26
|
<div class="flex-grow bg-blue-100 px-4 flex justify-center text-lg font-medium">
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
</div>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
|
-
<div class="flex-1 bg-slate-100 px-
|
|
31
|
+
<div class="flex-1 bg-slate-100 px-2 text-gray-800 flex items-center">
|
|
32
32
|
<div class="w-full">
|
|
33
33
|
<slot name="description" />
|
|
34
34
|
</div>
|
|
@@ -46,6 +46,6 @@
|
|
|
46
46
|
import * as events from "@/logic/events";
|
|
47
47
|
|
|
48
48
|
const properties = defineProps<{
|
|
49
|
-
|
|
49
|
+
step: string;
|
|
50
50
|
}>();
|
|
51
51
|
</script>
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<footer class="border-t border-gray-200">
|
|
3
|
+
<div class="mx-auto max-w-max px-4 py-2 grid grid-cols-2 sm:grid-cols-4 gap-8">
|
|
4
|
+
<div class="flex flex-col col-span-2 items-center sm:items-start">
|
|
5
|
+
<h3 class="text-lg font-semibold mb-4">Feeds Fun</h3>
|
|
6
|
+
<div class="flex flex-col space-y-2">
|
|
7
|
+
<div class="font-medium"> The project is in demo mode and free of charge </div>
|
|
8
|
+
|
|
9
|
+
<div>
|
|
10
|
+
© 2023‑{{ year }} Aliaksei Yaletski (<external-url
|
|
11
|
+
url="https://github.com/Tiendil"
|
|
12
|
+
text="Tiendil"
|
|
13
|
+
class="ffun-normal-link" />) and Feeds Fun contributors
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<div>
|
|
17
|
+
Site uses
|
|
18
|
+
<external-url
|
|
19
|
+
url="https://github.com/tabler/tabler-icons"
|
|
20
|
+
text="Tabler Icons"
|
|
21
|
+
class="ffun-normal-link" />, licensed under the
|
|
22
|
+
<external-url
|
|
23
|
+
url="https://github.com/tabler/tabler-icons/blob/main/LICENSE"
|
|
24
|
+
text="MIT License"
|
|
25
|
+
class="ffun-normal-link" />
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="flex flex-col items-center sm:items-start max-w-28">
|
|
31
|
+
<h3 class="text-lg font-semibold mb-4">Community</h3>
|
|
32
|
+
<div class="flex flex-col space-y-2">
|
|
33
|
+
<social-link
|
|
34
|
+
kind="blog"
|
|
35
|
+
mode="text"
|
|
36
|
+
class="hover:underline ffun-normal-link" />
|
|
37
|
+
<social-link
|
|
38
|
+
kind="reddit"
|
|
39
|
+
mode="text"
|
|
40
|
+
class="hover:underline ffun-normal-link" />
|
|
41
|
+
<social-link
|
|
42
|
+
kind="discord"
|
|
43
|
+
mode="text"
|
|
44
|
+
class="hover:underline ffun-normal-link" />
|
|
45
|
+
<social-link
|
|
46
|
+
kind="github"
|
|
47
|
+
mode="text"
|
|
48
|
+
class="hover:underline ffun-normal-link" />
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<div class="flex flex-col items-center sm:items-start">
|
|
53
|
+
<h3 class="text-lg font-semibold mb-4">For Users</h3>
|
|
54
|
+
|
|
55
|
+
<div class="flex flex-col space-y-2">
|
|
56
|
+
<div>You can ask for help on Discord, Reddit, or GitHub</div>
|
|
57
|
+
|
|
58
|
+
<a
|
|
59
|
+
v-if="settings.crmTerms"
|
|
60
|
+
:href="router.resolve({name: 'terms'}).href"
|
|
61
|
+
class="ffun-normal-link"
|
|
62
|
+
@click.prevent="router.push({name: 'terms'})">
|
|
63
|
+
Terms of Service
|
|
64
|
+
</a>
|
|
65
|
+
|
|
66
|
+
<a
|
|
67
|
+
v-if="settings.crmPrivacy"
|
|
68
|
+
:href="router.resolve({name: 'privacy'}).href"
|
|
69
|
+
class="ffun-normal-link"
|
|
70
|
+
@click.prevent="router.push({name: 'privacy'})">
|
|
71
|
+
Privacy Policy
|
|
72
|
+
</a>
|
|
73
|
+
|
|
74
|
+
<a
|
|
75
|
+
v-if="!settings.isSingleUserMode"
|
|
76
|
+
href="#"
|
|
77
|
+
class="ffun-normal-link"
|
|
78
|
+
@click.prevent="cookieConsent.showCookieConsent()">
|
|
79
|
+
Cookie Settings
|
|
80
|
+
</a>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</footer>
|
|
85
|
+
</template>
|
|
86
|
+
|
|
87
|
+
<script lang="ts" setup>
|
|
88
|
+
import {inject, computed} from "vue";
|
|
89
|
+
import {useRouter} from "vue-router";
|
|
90
|
+
|
|
91
|
+
import * as events from "@/logic/events";
|
|
92
|
+
import * as settings from "@/logic/settings";
|
|
93
|
+
import * as asserts from "@/logic/asserts";
|
|
94
|
+
import * as cookieConsent from "@/plugins/CookieConsent";
|
|
95
|
+
|
|
96
|
+
const router = useRouter();
|
|
97
|
+
|
|
98
|
+
const eventsView = inject<events.EventsViewName>("eventsViewName");
|
|
99
|
+
|
|
100
|
+
asserts.defined(eventsView);
|
|
101
|
+
|
|
102
|
+
const year = computed(() => {
|
|
103
|
+
const date = new Date();
|
|
104
|
+
return date.getFullYear();
|
|
105
|
+
});
|
|
106
|
+
</script>
|
|
@@ -1,51 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<social-link
|
|
3
3
|
v-if="showApi"
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class="ffun-page-header-link"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
><i class="ti ti-brand-reddit"></i
|
|
28
|
-
></a>
|
|
29
|
-
|
|
30
|
-
<a
|
|
31
|
-
v-if="settings.discordInvite"
|
|
32
|
-
:href="settings.discordInvite"
|
|
33
|
-
target="_blank"
|
|
34
|
-
class="ffun-page-header-link text-xl align-middle"
|
|
35
|
-
title="Discord"
|
|
36
|
-
@click="events.socialLinkClicked({linkType: 'discord', view: eventsView})"
|
|
37
|
-
><i class="ti ti-brand-discord"></i
|
|
38
|
-
></a>
|
|
39
|
-
|
|
40
|
-
<a
|
|
41
|
-
v-if="settings.githubRepo"
|
|
42
|
-
:href="settings.githubRepo"
|
|
43
|
-
target="_blank"
|
|
44
|
-
class="ffun-page-header-link text-xl align-middle"
|
|
45
|
-
title="GitHub"
|
|
46
|
-
@click="events.socialLinkClicked({linkType: 'github', view: eventsView})">
|
|
47
|
-
<i class="ti ti-brand-github"></i
|
|
48
|
-
></a>
|
|
4
|
+
kind="api"
|
|
5
|
+
mode="text"
|
|
6
|
+
class="ffun-page-header-link" />
|
|
7
|
+
|
|
8
|
+
<social-link
|
|
9
|
+
kind="blog"
|
|
10
|
+
mode="text"
|
|
11
|
+
class="ffun-page-header-link" />
|
|
12
|
+
|
|
13
|
+
<social-link
|
|
14
|
+
kind="reddit"
|
|
15
|
+
mode="icon"
|
|
16
|
+
class="ffun-page-header-link py-2 flex items-center justify-center" />
|
|
17
|
+
|
|
18
|
+
<social-link
|
|
19
|
+
kind="discord"
|
|
20
|
+
mode="icon"
|
|
21
|
+
class="ffun-page-header-link py-2 flex items-center justify-center" />
|
|
22
|
+
|
|
23
|
+
<social-link
|
|
24
|
+
kind="github"
|
|
25
|
+
mode="icon"
|
|
26
|
+
class="ffun-page-header-link py-2 flex items-center justify-center" />
|
|
49
27
|
</template>
|
|
50
28
|
|
|
51
29
|
<script lang="ts" setup>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<a
|
|
3
|
+
:href="router.resolve({name: 'main'}).href"
|
|
4
|
+
class="ffun-page-header-link"
|
|
5
|
+
@click.prevent="router.push({name: 'main'})">
|
|
6
|
+
Home</a
|
|
7
|
+
>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script lang="ts" setup>
|
|
11
|
+
import {useRouter} from "vue-router";
|
|
12
|
+
|
|
13
|
+
const router = useRouter();
|
|
14
|
+
</script>
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<a
|
|
3
3
|
href="#"
|
|
4
|
-
class="ffun-page-header-link
|
|
4
|
+
class="ffun-page-header-link py-2 flex items-center justify-center"
|
|
5
5
|
:title="title"
|
|
6
6
|
@click.prevent="onClick">
|
|
7
|
-
<
|
|
7
|
+
<icon
|
|
8
8
|
v-if="globalSettings.showSidebar"
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
icon="sidebar-left-collapse"
|
|
10
|
+
size="large" />
|
|
11
|
+
<icon
|
|
11
12
|
v-else
|
|
12
|
-
|
|
13
|
+
icon="sidebar-left-expand"
|
|
14
|
+
size="large" />
|
|
13
15
|
|
|
14
16
|
<span
|
|
15
17
|
v-if="showPoint"
|
package/src/css/page_header.css
CHANGED
|
@@ -20,14 +20,18 @@
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
.ffun-page-header-link {
|
|
23
|
-
@apply cursor-pointer no-underline ffun-x-header-text;
|
|
23
|
+
@apply cursor-pointer no-underline ffun-x-header-text whitespace-nowrap;
|
|
24
24
|
@apply underline-offset-4 hover:bg-blue-100 rounded;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
.ffun-page-header-link-
|
|
27
|
+
.ffun-page-header-link-active {
|
|
28
28
|
@apply underline underline-offset-4 ffun-x-header-text;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
.ffun-page-header-link-disabled {
|
|
32
|
+
@apply ffun-x-header-text text-slate-400;
|
|
33
|
+
}
|
|
34
|
+
|
|
31
35
|
.ffun-page-header-title {
|
|
32
36
|
@apply font-semibold ffun-x-header-text;
|
|
33
37
|
}
|
|
@@ -55,12 +55,7 @@
|
|
|
55
55
|
<div class="ffun-page-header-left-block">
|
|
56
56
|
<side-panel-collapse-button v-if="!globalSettings.showSidebar" />
|
|
57
57
|
|
|
58
|
-
<
|
|
59
|
-
v-if="homeButton"
|
|
60
|
-
:href="router.resolve({name: 'main', params: {}}).href"
|
|
61
|
-
class="ffun-page-header-link"
|
|
62
|
-
>Home</a
|
|
63
|
-
>
|
|
58
|
+
<page-header-home-button v-if="homeButton" />
|
|
64
59
|
|
|
65
60
|
<template v-if="globalState.isLoggedIn">
|
|
66
61
|
<template
|
|
@@ -76,7 +71,7 @@
|
|
|
76
71
|
</a>
|
|
77
72
|
|
|
78
73
|
<span
|
|
79
|
-
class="ffun-page-header-link-
|
|
74
|
+
class="ffun-page-header-link-active"
|
|
80
75
|
v-else
|
|
81
76
|
>{{ props.text }}</span
|
|
82
77
|
>
|
|
@@ -89,12 +84,19 @@
|
|
|
89
84
|
|
|
90
85
|
<div class="ffun-page-header-right-block">
|
|
91
86
|
<a
|
|
92
|
-
v-if="globalState.isLoggedIn"
|
|
87
|
+
v-if="globalState.isLoggedIn && !settings.isSingleUserMode"
|
|
93
88
|
href="#"
|
|
94
89
|
class="ffun-page-header-link"
|
|
95
90
|
@click.prevent="logout()"
|
|
96
91
|
>logout</a
|
|
97
92
|
>
|
|
93
|
+
|
|
94
|
+
<span
|
|
95
|
+
v-if="settings.isSingleUserMode"
|
|
96
|
+
href="#"
|
|
97
|
+
class="ffun-page-header-link-disabled"
|
|
98
|
+
>single-user mode</span
|
|
99
|
+
>
|
|
98
100
|
</div>
|
|
99
101
|
</div>
|
|
100
102
|
|
|
@@ -109,11 +111,13 @@
|
|
|
109
111
|
</footer>
|
|
110
112
|
</div>
|
|
111
113
|
</div>
|
|
114
|
+
|
|
115
|
+
<page-footer />
|
|
112
116
|
</template>
|
|
113
117
|
|
|
114
118
|
<script lang="ts" setup>
|
|
115
119
|
import {ref, computed, useSlots, onMounted, watch, watchEffect} from "vue";
|
|
116
|
-
import {useRouter
|
|
120
|
+
import {useRouter} from "vue-router";
|
|
117
121
|
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
118
122
|
import {useGlobalState} from "@/stores/globalState";
|
|
119
123
|
import {useSupertokens} from "@/stores/supertokens";
|
package/src/logic/api.ts
CHANGED
|
@@ -2,6 +2,8 @@ import * as _ from "lodash";
|
|
|
2
2
|
import axios, {AxiosError} from "axios";
|
|
3
3
|
import * as t from "@/logic/types";
|
|
4
4
|
import type * as e from "@/logic/enums";
|
|
5
|
+
import * as settings from "@/logic/settings";
|
|
6
|
+
import * as cookieConsent from "@/plugins/CookieConsent";
|
|
5
7
|
|
|
6
8
|
const ENTRY_POINT = "/api";
|
|
7
9
|
|
|
@@ -30,6 +32,7 @@ const API_SET_USER_SETTING = `${ENTRY_POINT}/set-user-setting`;
|
|
|
30
32
|
const API_GET_RESOURCE_HISTORY = `${ENTRY_POINT}/get-resource-history`;
|
|
31
33
|
const API_GET_INFO = `${ENTRY_POINT}/get-info`;
|
|
32
34
|
const API_TRACK_EVENT = `${ENTRY_POINT}/track-event`;
|
|
35
|
+
const API_REMOVE_USER = `${ENTRY_POINT}/remove-user`;
|
|
33
36
|
|
|
34
37
|
let _onSessionLost: () => void = () => {};
|
|
35
38
|
|
|
@@ -331,5 +334,17 @@ export async function getInfo() {
|
|
|
331
334
|
}
|
|
332
335
|
|
|
333
336
|
export async function trackEvent(data: {[key: string]: string | number | null}) {
|
|
337
|
+
if (!settings.trackEvents) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (!cookieConsent.isAnalyticsAllowed()) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
334
345
|
await post({url: API_TRACK_EVENT, data: {event: data}});
|
|
335
346
|
}
|
|
347
|
+
|
|
348
|
+
export async function removeUser() {
|
|
349
|
+
await post({url: API_REMOVE_USER, data: {}});
|
|
350
|
+
}
|
package/src/logic/events.ts
CHANGED
|
@@ -83,3 +83,20 @@ export async function tagStateChanged({
|
|
|
83
83
|
source: source
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
|
+
|
|
87
|
+
export async function trackUtm({
|
|
88
|
+
utm_source,
|
|
89
|
+
utm_medium,
|
|
90
|
+
utm_campaign
|
|
91
|
+
}: {
|
|
92
|
+
utm_source: string;
|
|
93
|
+
utm_medium: string;
|
|
94
|
+
utm_campaign: string;
|
|
95
|
+
}) {
|
|
96
|
+
await api.trackEvent({
|
|
97
|
+
name: "user_utm",
|
|
98
|
+
utm_source: utm_source,
|
|
99
|
+
utm_medium: utm_medium,
|
|
100
|
+
utm_campaign: utm_campaign
|
|
101
|
+
});
|
|
102
|
+
}
|