feeds-fun 1.18.2 → 1.19.1
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 +3 -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/notifications/Block.vue +3 -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 +10 -0
- package/src/logic/enums.ts +2 -1
- package/src/logic/settings.ts +12 -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 +34 -19
- package/src/views/SettingsView.vue +33 -0
package/src/main.ts
CHANGED
|
@@ -6,6 +6,8 @@ import router from "./router";
|
|
|
6
6
|
|
|
7
7
|
import "./style.css";
|
|
8
8
|
|
|
9
|
+
import * as CookieConsent from "./plugins/CookieConsent";
|
|
10
|
+
|
|
9
11
|
import FeedsList from "./components/FeedsList.vue";
|
|
10
12
|
import EntriesList from "./components/EntriesList.vue";
|
|
11
13
|
import RulesList from "./components/RulesList.vue";
|
|
@@ -33,7 +35,9 @@ import TagsFilter from "./components/tags/TagsFilter.vue";
|
|
|
33
35
|
import RuleTag from "./components/tags/RuleTag.vue";
|
|
34
36
|
import FakeTag from "./components/tags/FakeTag.vue";
|
|
35
37
|
|
|
38
|
+
import PageHeaderHomeButton from "./components/page_header/HomeButton.vue";
|
|
36
39
|
import PageHeaderExternalLinks from "./components/page_header/ExternalLinks.vue";
|
|
40
|
+
import PageFooter from "./components/page_footer/Footer.vue";
|
|
37
41
|
|
|
38
42
|
import NotificationsApiKey from "./components/notifications/ApiKey.vue";
|
|
39
43
|
import NotificationsCreateRuleHelp from "./components/notifications/CreateRuleHelp.vue";
|
|
@@ -56,6 +60,8 @@ import ExternalUrl from "./values/ExternalUrl.vue";
|
|
|
56
60
|
import ValueFeedId from "./values/FeedId.vue";
|
|
57
61
|
import ValueDateTime from "./values/DateTime.vue";
|
|
58
62
|
import ValueScore from "./values/Score.vue";
|
|
63
|
+
import Icon from "./values/Icon.vue";
|
|
64
|
+
import SocialLink from "./values/SocialLink.vue";
|
|
59
65
|
|
|
60
66
|
import BodyListReverseTimeColumn from "./components/body_list/ReverseTimeColumn.vue";
|
|
61
67
|
import BodyListFaviconColumn from "./components/body_list/FaviconColumn.vue";
|
|
@@ -105,7 +111,9 @@ app.component("TagsFilter", TagsFilter);
|
|
|
105
111
|
app.component("RuleTag", RuleTag);
|
|
106
112
|
app.component("FakeTag", FakeTag);
|
|
107
113
|
|
|
114
|
+
app.component("PageHeaderHomeButton", PageHeaderHomeButton);
|
|
108
115
|
app.component("PageHeaderExternalLinks", PageHeaderExternalLinks);
|
|
116
|
+
app.component("PageFooter", PageFooter);
|
|
109
117
|
|
|
110
118
|
app.component("NotificationsApiKey", NotificationsApiKey);
|
|
111
119
|
app.component("NotificationsCreateRuleHelp", NotificationsCreateRuleHelp);
|
|
@@ -128,6 +136,8 @@ app.component("ExternalUrl", ExternalUrl);
|
|
|
128
136
|
app.component("ValueFeedId", ValueFeedId);
|
|
129
137
|
app.component("ValueDateTime", ValueDateTime);
|
|
130
138
|
app.component("ValueScore", ValueScore);
|
|
139
|
+
app.component("Icon", Icon);
|
|
140
|
+
app.component("SocialLink", SocialLink);
|
|
131
141
|
|
|
132
142
|
app.component("BodyListReverseTimeColumn", BodyListReverseTimeColumn);
|
|
133
143
|
app.component("BodyListFaviconColumn", BodyListFaviconColumn);
|
|
@@ -149,6 +159,10 @@ app.component("vue-countdown", VueCountdown);
|
|
|
149
159
|
app.use(createPinia());
|
|
150
160
|
app.use(router);
|
|
151
161
|
|
|
162
|
+
if (!settings.isSingleUserMode) {
|
|
163
|
+
app.use(CookieConsent.plugin, CookieConsent.defaultConfig);
|
|
164
|
+
}
|
|
165
|
+
|
|
152
166
|
app.mount("#app");
|
|
153
167
|
|
|
154
168
|
import * as api from "@/logic/api";
|
|
@@ -196,16 +210,3 @@ async function onSessionLost() {
|
|
|
196
210
|
}
|
|
197
211
|
|
|
198
212
|
api.init({onSessionLost: onSessionLost});
|
|
199
|
-
|
|
200
|
-
/////////////////////
|
|
201
|
-
// plausible
|
|
202
|
-
/////////////////////
|
|
203
|
-
|
|
204
|
-
if (settings.plausibleEnabled) {
|
|
205
|
-
const script = document.createElement("script");
|
|
206
|
-
script.src = settings.plausibleScript;
|
|
207
|
-
script.async = true;
|
|
208
|
-
script.defer = true;
|
|
209
|
-
script.setAttribute("data-domain", settings.plausibleDomain);
|
|
210
|
-
document.body.appendChild(script);
|
|
211
|
-
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import "vanilla-cookieconsent/dist/cookieconsent.css";
|
|
2
|
+
import * as CookieConsent from "vanilla-cookieconsent";
|
|
3
|
+
|
|
4
|
+
import * as settings from "@/logic/settings";
|
|
5
|
+
|
|
6
|
+
export const plugin = {
|
|
7
|
+
install(app: any, pluginConfig: any): void {
|
|
8
|
+
app.config.globalProperties.$CookieConsent = CookieConsent;
|
|
9
|
+
CookieConsent.run(pluginConfig);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function showCookieConsent() {
|
|
14
|
+
CookieConsent.show(true);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isAnalyticsAllowed(): boolean {
|
|
18
|
+
return CookieConsent.acceptedCategory("analytics");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const plausibleId = "plausible-script";
|
|
22
|
+
|
|
23
|
+
function syncPlausible(): void {
|
|
24
|
+
if (!settings.plausibleEnabled) {
|
|
25
|
+
disablePlausible();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!isAnalyticsAllowed()) {
|
|
30
|
+
disablePlausible();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
enablePlausible();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function isPlausibleEnabled() {
|
|
38
|
+
return document.getElementById(plausibleId) !== null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function disablePlausible() {
|
|
42
|
+
if (!isPlausibleEnabled()) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// The simplest and straightforward way to disable smth is to reload the page
|
|
47
|
+
// We expect that users will not reevaluate the cookie consent modal often
|
|
48
|
+
window.location.reload();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function enablePlausible() {
|
|
52
|
+
if (isPlausibleEnabled()) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.log("setup Plausible script");
|
|
57
|
+
|
|
58
|
+
const script = document.createElement("script");
|
|
59
|
+
script.id = plausibleId;
|
|
60
|
+
script.src = settings.plausibleScript;
|
|
61
|
+
script.async = true;
|
|
62
|
+
script.defer = true;
|
|
63
|
+
script.setAttribute("data-domain", settings.plausibleDomain);
|
|
64
|
+
document.body.appendChild(script);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const _description = `
|
|
68
|
+
<p>We use cookies and local storage for session tracking (required) and optional analytics.</p>
|
|
69
|
+
<p>Please let us collect analytics to better understand how you use us and become the best news reader ever.</p>
|
|
70
|
+
<p>You can find more information in our <a href="/privacy" target="_blank" rel="noopener noreferrer">privacy policy</a>.</p>
|
|
71
|
+
`;
|
|
72
|
+
|
|
73
|
+
export const defaultConfig = {
|
|
74
|
+
revision: 1,
|
|
75
|
+
|
|
76
|
+
onConsent(): void {
|
|
77
|
+
syncPlausible();
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
onChange(): void {
|
|
81
|
+
syncPlausible();
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
categories: {
|
|
85
|
+
necessary: {
|
|
86
|
+
enabled: true,
|
|
87
|
+
readOnly: true
|
|
88
|
+
},
|
|
89
|
+
analytics: {
|
|
90
|
+
enabled: true,
|
|
91
|
+
readOnly: false
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
language: {
|
|
96
|
+
default: "en",
|
|
97
|
+
translations: {
|
|
98
|
+
en: {
|
|
99
|
+
consentModal: {
|
|
100
|
+
title: "We use cookies and local storage",
|
|
101
|
+
description: _description,
|
|
102
|
+
acceptAllBtn: "Accept all",
|
|
103
|
+
acceptNecessaryBtn: "Reject all",
|
|
104
|
+
showPreferencesBtn: "Manage preferences"
|
|
105
|
+
},
|
|
106
|
+
preferencesModal: {
|
|
107
|
+
title: "Manage privacy preferences",
|
|
108
|
+
acceptAllBtn: "Accept all",
|
|
109
|
+
acceptNecessaryBtn: "Reject all",
|
|
110
|
+
savePreferencesBtn: "Accept current selection",
|
|
111
|
+
closeIconLabel: "Close",
|
|
112
|
+
sections: [
|
|
113
|
+
{
|
|
114
|
+
description: _description
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
title: "Strictly necessary data",
|
|
118
|
+
description: "This data is essential for the proper functioning of the website and cannot be disabled.",
|
|
119
|
+
|
|
120
|
+
linkedCategory: "necessary",
|
|
121
|
+
|
|
122
|
+
cookieTable: {
|
|
123
|
+
headers: {
|
|
124
|
+
name: "Data",
|
|
125
|
+
description: "Description"
|
|
126
|
+
},
|
|
127
|
+
body: [
|
|
128
|
+
{
|
|
129
|
+
name: "Session information",
|
|
130
|
+
description:
|
|
131
|
+
"We store your session information which is absolutely necessary for the website to work."
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
title: "Performance and analytics",
|
|
138
|
+
description: "These services collect information about how you use our website.",
|
|
139
|
+
linkedCategory: "analytics",
|
|
140
|
+
|
|
141
|
+
cookieTable: {
|
|
142
|
+
headers: {
|
|
143
|
+
name: "Service",
|
|
144
|
+
domain: "Domain",
|
|
145
|
+
description: "Description"
|
|
146
|
+
},
|
|
147
|
+
body: [
|
|
148
|
+
settings.plausibleEnabled
|
|
149
|
+
? {
|
|
150
|
+
name: "Plausible",
|
|
151
|
+
domain: "plausible.io",
|
|
152
|
+
description:
|
|
153
|
+
"EU-based, cookie-free service that helps us measure traffic and improve usability, without collecting personal data."
|
|
154
|
+
}
|
|
155
|
+
: null,
|
|
156
|
+
{
|
|
157
|
+
name: "Feeds Fun",
|
|
158
|
+
domain: "feeds.fun",
|
|
159
|
+
description:
|
|
160
|
+
"We collect our own analytics to improve the service. We do not share this data with third parties."
|
|
161
|
+
}
|
|
162
|
+
].filter((x) => x !== null)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
package/src/router/index.ts
CHANGED
|
@@ -8,7 +8,9 @@ import DiscoveryView from "../views/DiscoveryView.vue";
|
|
|
8
8
|
import CollectionsView from "../views/CollectionsView.vue";
|
|
9
9
|
import SettingsView from "../views/SettingsView.vue";
|
|
10
10
|
import PublicCollectionView from "../views/PublicCollectionView.vue";
|
|
11
|
+
import CRMView from "../views/CRMView.vue";
|
|
11
12
|
import * as e from "@/logic/enums";
|
|
13
|
+
import * as settings from "@/logic/settings";
|
|
12
14
|
|
|
13
15
|
// lazy view loading does not work with router.push function
|
|
14
16
|
// first attempt to router.push into not loaded view, will cause its loading, but will not change components
|
|
@@ -61,6 +63,18 @@ const router = createRouter({
|
|
|
61
63
|
name: "public-collection",
|
|
62
64
|
component: PublicCollectionView
|
|
63
65
|
},
|
|
66
|
+
{
|
|
67
|
+
path: "/terms",
|
|
68
|
+
name: "terms",
|
|
69
|
+
component: CRMView,
|
|
70
|
+
props: {content: settings.crmTerms, kind: "terms"}
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
path: "/privacy",
|
|
74
|
+
name: "privacy",
|
|
75
|
+
component: CRMView,
|
|
76
|
+
props: {content: settings.crmPrivacy, kind: "privacy"}
|
|
77
|
+
},
|
|
64
78
|
{
|
|
65
79
|
path: "/:pathMatch(.*)*",
|
|
66
80
|
redirect: "/"
|
|
@@ -10,7 +10,7 @@ export const useGlobalState = defineStore("globalState", () => {
|
|
|
10
10
|
const supertokens = useSupertokens();
|
|
11
11
|
|
|
12
12
|
const isLoggedIn = computed(() => {
|
|
13
|
-
if (settings.
|
|
13
|
+
if (settings.isSingleUserMode) {
|
|
14
14
|
return true;
|
|
15
15
|
}
|
|
16
16
|
|
package/src/style.css
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
:is="componentName"
|
|
4
|
+
class="inline-block"
|
|
5
|
+
v-bind="iconProperties" />
|
|
6
|
+
</template>
|
|
7
|
+
|
|
8
|
+
<script lang="ts" setup>
|
|
9
|
+
import {computed} from "vue";
|
|
10
|
+
import {
|
|
11
|
+
IconArrowNarrowRight,
|
|
12
|
+
IconArrowRight,
|
|
13
|
+
IconPlus,
|
|
14
|
+
IconDots,
|
|
15
|
+
IconBrandReddit,
|
|
16
|
+
IconBrandDiscord,
|
|
17
|
+
IconBrandGithub,
|
|
18
|
+
IconExternalLink,
|
|
19
|
+
IconChevronsLeft,
|
|
20
|
+
IconChevronsRight,
|
|
21
|
+
IconLayoutSidebarLeftCollapse,
|
|
22
|
+
IconLayoutSidebarLeftExpand,
|
|
23
|
+
IconX,
|
|
24
|
+
IconMoodSmile,
|
|
25
|
+
IconMoodSad
|
|
26
|
+
} from "@tabler/icons-vue";
|
|
27
|
+
|
|
28
|
+
const iconMap = {
|
|
29
|
+
reddit: IconBrandReddit,
|
|
30
|
+
discord: IconBrandDiscord,
|
|
31
|
+
github: IconBrandGithub,
|
|
32
|
+
"arrow-narrow-right": IconArrowNarrowRight,
|
|
33
|
+
"arrow-right": IconArrowRight,
|
|
34
|
+
plus: IconPlus,
|
|
35
|
+
dots: IconDots,
|
|
36
|
+
"external-link": IconExternalLink,
|
|
37
|
+
"chevrons-right": IconChevronsRight,
|
|
38
|
+
"chevrons-left": IconChevronsLeft,
|
|
39
|
+
"sidebar-left-collapse": IconLayoutSidebarLeftCollapse,
|
|
40
|
+
"sidebar-left-expand": IconLayoutSidebarLeftExpand,
|
|
41
|
+
x: IconX,
|
|
42
|
+
"face-smile": IconMoodSmile,
|
|
43
|
+
"face-sad": IconMoodSad
|
|
44
|
+
} as const;
|
|
45
|
+
|
|
46
|
+
type IconName = keyof typeof iconMap;
|
|
47
|
+
|
|
48
|
+
const sizeMap = {
|
|
49
|
+
small: 16,
|
|
50
|
+
medium: 20,
|
|
51
|
+
large: 24
|
|
52
|
+
} as const;
|
|
53
|
+
|
|
54
|
+
type IconSize = keyof typeof sizeMap;
|
|
55
|
+
|
|
56
|
+
const properties = defineProps<{icon: IconName; size?: IconSize}>();
|
|
57
|
+
|
|
58
|
+
const componentName = computed(() => {
|
|
59
|
+
if (properties.icon in iconMap) {
|
|
60
|
+
return iconMap[properties.icon];
|
|
61
|
+
} else {
|
|
62
|
+
throw new Error(`Icon ${properties.icon} not found`);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const iconProperties = computed(() => {
|
|
67
|
+
return {
|
|
68
|
+
size: sizeMap[properties.size ?? "medium"]
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
</script>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<a
|
|
3
|
+
v-if="link.enabled"
|
|
4
|
+
:href="link.url"
|
|
5
|
+
target="_blank"
|
|
6
|
+
@click="events.socialLinkClicked({linkType: link.eventType, view: eventsView})">
|
|
7
|
+
<span v-if="mode === 'text'">
|
|
8
|
+
{{ link.text }}
|
|
9
|
+
|
|
10
|
+
<icon
|
|
11
|
+
icon="external-link"
|
|
12
|
+
size="small" />
|
|
13
|
+
</span>
|
|
14
|
+
|
|
15
|
+
<icon
|
|
16
|
+
v-else
|
|
17
|
+
:icon="link.icon" />
|
|
18
|
+
</a>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script lang="ts" setup>
|
|
22
|
+
import {inject, computed} from "vue";
|
|
23
|
+
|
|
24
|
+
import * as events from "@/logic/events";
|
|
25
|
+
import * as settings from "@/logic/settings";
|
|
26
|
+
import * as asserts from "@/logic/asserts";
|
|
27
|
+
|
|
28
|
+
const links = {
|
|
29
|
+
api: {
|
|
30
|
+
enabled: true,
|
|
31
|
+
url: "/api/docs",
|
|
32
|
+
text: "API",
|
|
33
|
+
icon: null,
|
|
34
|
+
eventType: "api"
|
|
35
|
+
},
|
|
36
|
+
blog: {
|
|
37
|
+
enabled: settings.blog !== null,
|
|
38
|
+
url: settings.blog,
|
|
39
|
+
text: "Blog",
|
|
40
|
+
icon: null,
|
|
41
|
+
eventType: "blog"
|
|
42
|
+
},
|
|
43
|
+
reddit: {
|
|
44
|
+
enabled: settings.redditSubreddit !== null,
|
|
45
|
+
url: settings.redditSubreddit,
|
|
46
|
+
text: "Reddit",
|
|
47
|
+
icon: "reddit",
|
|
48
|
+
eventType: "reddit"
|
|
49
|
+
},
|
|
50
|
+
discord: {
|
|
51
|
+
enabled: settings.discordInvite !== null,
|
|
52
|
+
url: settings.discordInvite,
|
|
53
|
+
text: "Discord",
|
|
54
|
+
icon: "discord",
|
|
55
|
+
eventType: "discord"
|
|
56
|
+
},
|
|
57
|
+
github: {
|
|
58
|
+
enabled: settings.githubRepo !== null,
|
|
59
|
+
url: settings.githubRepo,
|
|
60
|
+
text: "GitHub",
|
|
61
|
+
icon: "github",
|
|
62
|
+
eventType: "github"
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
type LinkKind = keyof typeof links;
|
|
67
|
+
|
|
68
|
+
const properties = defineProps<{kind: LinkKind; mode: "icon" | "text"}>();
|
|
69
|
+
|
|
70
|
+
const eventsView = inject<events.EventsViewName>("eventsViewName");
|
|
71
|
+
|
|
72
|
+
asserts.defined(eventsView);
|
|
73
|
+
|
|
74
|
+
const link = computed(() => {
|
|
75
|
+
if (properties.kind in links) {
|
|
76
|
+
return links[properties.kind];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
throw new Error(`Link kind "${properties.kind}" not found`);
|
|
80
|
+
});
|
|
81
|
+
</script>
|
package/src/views/AuthView.vue
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<wide-layout>
|
|
3
|
-
<
|
|
3
|
+
<div class="ffun-page-header">
|
|
4
|
+
<div class="ffun-page-header-center-block">
|
|
5
|
+
<page-header-external-links :show-api="false" />
|
|
6
|
+
</div>
|
|
7
|
+
</div>
|
|
4
8
|
|
|
5
|
-
<
|
|
6
|
-
<p v-if="!linkProcessed">Checking login status...</p>
|
|
9
|
+
<hr />
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
<main-block>
|
|
12
|
+
<h1 class="m-0 text-5xl">Feeds Fun</h1>
|
|
13
|
+
<p class="mt-2 text-2xl">Transparent Personalized News</p>
|
|
14
|
+
</main-block>
|
|
15
|
+
|
|
16
|
+
<main-block>
|
|
17
|
+
<div class="max-w-xl md:mx-auto ffun-info-good text-center mx-2">
|
|
18
|
+
<p>Checking login status...</p>
|
|
19
|
+
</div>
|
|
20
|
+
</main-block>
|
|
10
21
|
</wide-layout>
|
|
11
22
|
</template>
|
|
12
23
|
|
|
@@ -28,12 +39,14 @@
|
|
|
28
39
|
|
|
29
40
|
provide("eventsViewName", "auth");
|
|
30
41
|
|
|
31
|
-
const linkProcessed = ref(false);
|
|
32
|
-
|
|
33
42
|
function goToWorkspace() {
|
|
34
43
|
router.push({name: globalSettings.mainPanelMode, params: {}});
|
|
35
44
|
}
|
|
36
45
|
|
|
46
|
+
function goToMain() {
|
|
47
|
+
router.push({name: "main", params: {}});
|
|
48
|
+
}
|
|
49
|
+
|
|
37
50
|
onBeforeMount(async () => {
|
|
38
51
|
if (globalState.isLoggedIn) {
|
|
39
52
|
goToWorkspace();
|
|
@@ -46,6 +59,7 @@
|
|
|
46
59
|
|
|
47
60
|
async function onSignFailed() {
|
|
48
61
|
await supertokens.clearLoginAttempt();
|
|
62
|
+
goToMain();
|
|
49
63
|
}
|
|
50
64
|
|
|
51
65
|
if (await supertokens.hasInitialMagicLinkBeenSent()) {
|
|
@@ -54,9 +68,8 @@
|
|
|
54
68
|
onSignIn: onSignIn,
|
|
55
69
|
onSignFailed: onSignFailed
|
|
56
70
|
});
|
|
57
|
-
linkProcessed.value = true;
|
|
58
71
|
} else {
|
|
59
|
-
|
|
72
|
+
goToMain();
|
|
60
73
|
}
|
|
61
74
|
});
|
|
62
75
|
</script>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<wide-layout>
|
|
3
|
+
<div class="ffun-page-header">
|
|
4
|
+
<div class="ffun-page-header-center-block">
|
|
5
|
+
<page-header-home-button />
|
|
6
|
+
<page-header-external-links :show-api="false" />
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<hr />
|
|
11
|
+
|
|
12
|
+
<main-block>
|
|
13
|
+
<h1 class="m-0 text-5xl">Feeds Fun</h1>
|
|
14
|
+
<p class="mt-2 text-2xl">Transparent Personalized News</p>
|
|
15
|
+
</main-block>
|
|
16
|
+
|
|
17
|
+
<hr />
|
|
18
|
+
|
|
19
|
+
<main-block>
|
|
20
|
+
<div
|
|
21
|
+
v-html="actualContent"
|
|
22
|
+
class="prose max-w-none" />
|
|
23
|
+
</main-block>
|
|
24
|
+
</wide-layout>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script lang="ts" setup>
|
|
28
|
+
import {computed, provide} from "vue";
|
|
29
|
+
|
|
30
|
+
const properties = defineProps<{content: string | null; kind: string}>();
|
|
31
|
+
|
|
32
|
+
provide("eventsViewName", properties.kind);
|
|
33
|
+
|
|
34
|
+
const actualContent = computed(() => {
|
|
35
|
+
if (properties.content === null) {
|
|
36
|
+
return "You MUST define a content for this page in case you host public version of Feeds Fun.";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return properties.content;
|
|
40
|
+
});
|
|
41
|
+
</script>
|