feeds-fun 0.6.0 → 1.2.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 +25 -23
- package/postcss.config.js +6 -0
- package/public/news-filtering-example.png +0 -0
- package/src/components/ConfigFlag.vue +6 -14
- package/src/components/ConfigSelector.vue +3 -1
- package/src/components/DiscoveryForm.vue +9 -2
- package/src/components/EntriesList.vue +15 -4
- package/src/components/EntryForList.vue +76 -65
- package/src/components/FeedForList.vue +15 -32
- package/src/components/FeedInfo.vue +11 -4
- package/src/components/FeedsCollections.vue +23 -15
- package/src/components/FeedsList.vue +7 -18
- package/src/components/FfunTag.vue +6 -13
- package/src/components/NotificationCollections.vue +7 -0
- package/src/components/NotificationOpenaiApiKey.vue +28 -0
- package/src/components/Notifications.vue +32 -0
- package/src/components/OPMLUpload.vue +3 -0
- package/src/components/RuleConstructor.vue +16 -24
- package/src/components/RuleForList.vue +47 -0
- package/src/components/RulesList.vue +7 -43
- package/src/components/SimplePagination.vue +4 -6
- package/src/components/SupertokensLogin.vue +50 -25
- package/src/components/TagsFilter.vue +13 -25
- package/src/components/TagsList.vue +27 -25
- package/src/components/UserSetting.vue +41 -38
- package/src/components/UserSettingForNotification.vue +63 -0
- package/src/inputs/Marker.vue +3 -7
- package/src/inputs/ScoreSelector.vue +11 -12
- package/src/layouts/SidePanelLayout.vue +42 -96
- package/src/layouts/WideLayout.vue +2 -25
- package/src/logic/settings.ts +0 -9
- package/src/main.ts +12 -19
- package/src/stores/entries.ts +1 -6
- package/src/style.css +92 -0
- package/src/values/Score.vue +1 -10
- package/src/views/AuthView.vue +3 -7
- package/src/views/CollectionsView.vue +2 -0
- package/src/views/FeedsView.vue +8 -3
- package/src/views/MainView.vue +37 -83
- package/src/views/NewsView.vue +30 -13
- package/src/views/RulesView.vue +0 -2
- package/src/views/SettingsView.vue +35 -22
- package/tailwind.config.js +14 -0
- package/src/components/EntryInfo.vue +0 -23
- package/src/components/FfunGithubButtons.vue +0 -22
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ffun-info-attention">
|
|
3
|
+
<p>
|
|
4
|
+
Because, for now, our service is free to use and OpenAI API costs money, we politely ask you to set up your own
|
|
5
|
+
OpenAI API key.
|
|
6
|
+
</p>
|
|
7
|
+
<p>
|
|
8
|
+
You can do this on the
|
|
9
|
+
<a
|
|
10
|
+
href="#"
|
|
11
|
+
@click.prevent="router.push({name: e.MainPanelMode.Settings, params: {}})"
|
|
12
|
+
>settings</a
|
|
13
|
+
>
|
|
14
|
+
page.
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<user-setting-for-notification
|
|
18
|
+
kind="openai_hide_message_about_setting_up_key"
|
|
19
|
+
button-text="Hide this message" />
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script lang="ts" setup>
|
|
24
|
+
import {useRouter} from "vue-router";
|
|
25
|
+
import * as e from "@/logic/enums";
|
|
26
|
+
|
|
27
|
+
const router = useRouter();
|
|
28
|
+
</script>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<notification-openai-api-key v-if="showOpenAIKeyNotification" />
|
|
3
|
+
<notification-collections v-if="showCollectionsNotification" />
|
|
4
|
+
</template>
|
|
5
|
+
|
|
6
|
+
<script lang="ts" setup>
|
|
7
|
+
import {computed, ref, onUnmounted, watch} from "vue";
|
|
8
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
9
|
+
|
|
10
|
+
const properties = defineProps<{
|
|
11
|
+
openaiApiKey: boolean;
|
|
12
|
+
collections: boolean;
|
|
13
|
+
}>();
|
|
14
|
+
|
|
15
|
+
const globalSettings = useGlobalSettingsStore();
|
|
16
|
+
|
|
17
|
+
const showApiKeyMessage = computed(() => {
|
|
18
|
+
return (
|
|
19
|
+
globalSettings.userSettings &&
|
|
20
|
+
!globalSettings.userSettings.openai_api_key.value &&
|
|
21
|
+
!globalSettings.userSettings.openai_hide_message_about_setting_up_key.value
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const showCollectionsNotification = computed(() => {
|
|
26
|
+
return properties.collections;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const showOpenAIKeyNotification = computed(() => {
|
|
30
|
+
return !showCollectionsNotification.value && properties.openaiApiKey && showApiKeyMessage.value;
|
|
31
|
+
});
|
|
32
|
+
</script>
|
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
v-for="tag of tags"
|
|
7
|
-
:key="tag">
|
|
8
|
-
<ffun-tag
|
|
9
|
-
:uid="tag"
|
|
10
|
-
mode="required" />
|
|
11
|
-
</template>
|
|
12
|
-
|
|
13
|
-
<br />
|
|
14
|
-
|
|
15
|
-
<score-selector v-model="currentScore" />
|
|
16
|
-
|
|
17
|
-
|
|
2
|
+
<div class="">
|
|
3
|
+
<score-selector
|
|
4
|
+
class="inline-block mr-2"
|
|
5
|
+
v-model="currentScore" />
|
|
18
6
|
|
|
19
7
|
<a
|
|
8
|
+
class="ffun-form-button"
|
|
20
9
|
href="#"
|
|
21
10
|
v-if="canCreateRule"
|
|
22
11
|
@click.prevent="createOrUpdateRule()"
|
|
@@ -27,9 +16,12 @@
|
|
|
27
16
|
|
|
28
17
|
<script lang="ts" setup>
|
|
29
18
|
import {computed, ref} from "vue";
|
|
19
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
30
20
|
import * as api from "@/logic/api";
|
|
31
21
|
const properties = defineProps<{tags: string[]}>();
|
|
32
22
|
|
|
23
|
+
const globalSettings = useGlobalSettingsStore();
|
|
24
|
+
|
|
33
25
|
const emit = defineEmits(["rule-constructor:created"]);
|
|
34
26
|
|
|
35
27
|
// fibonacci numbers
|
|
@@ -43,14 +35,14 @@
|
|
|
43
35
|
|
|
44
36
|
async function createOrUpdateRule() {
|
|
45
37
|
await api.createOrUpdateRule({tags: properties.tags, score: currentScore.value});
|
|
38
|
+
|
|
39
|
+
// this line leads to the reloading of news and any other data
|
|
40
|
+
// not an elegant solution, but it works with the current API implementation
|
|
41
|
+
// TODO: try to refactor to only update scores of news:
|
|
42
|
+
// - without reloading
|
|
43
|
+
// - maybe, without reordering too
|
|
44
|
+
globalSettings.updateDataVersion();
|
|
45
|
+
|
|
46
46
|
emit("rule-constructor:created");
|
|
47
47
|
}
|
|
48
48
|
</script>
|
|
49
|
-
|
|
50
|
-
<style scoped>
|
|
51
|
-
.rule-constructor {
|
|
52
|
-
padding: 0.25rem;
|
|
53
|
-
margin: 0.25rem;
|
|
54
|
-
border: 1px solid #ccc;
|
|
55
|
-
}
|
|
56
|
-
</style>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-if="rule !== null"
|
|
4
|
+
class="flex mb-1">
|
|
5
|
+
<div class="flex-shrink-0 min-w-fit mr-2">
|
|
6
|
+
<a
|
|
7
|
+
href="#"
|
|
8
|
+
class="ffun-normal-link"
|
|
9
|
+
@click.prevent="deleteRule()">
|
|
10
|
+
remove
|
|
11
|
+
</a>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<rule-score-updater
|
|
15
|
+
class="flex-shrink-0 mr-2"
|
|
16
|
+
:score="rule.score"
|
|
17
|
+
:rule-id="rule.id"
|
|
18
|
+
:tags="rule.tags" />
|
|
19
|
+
|
|
20
|
+
<div class="flex-grow">
|
|
21
|
+
<template
|
|
22
|
+
v-for="tag of rule.tags"
|
|
23
|
+
:key="tag">
|
|
24
|
+
<ffun-tag :uid="tag" />
|
|
25
|
+
</template>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script lang="ts" setup>
|
|
31
|
+
import {computed, ref} from "vue";
|
|
32
|
+
import type * as t from "@/logic/types";
|
|
33
|
+
import * as e from "@/logic/enums";
|
|
34
|
+
import * as api from "@/logic/api";
|
|
35
|
+
import {computedAsync} from "@vueuse/core";
|
|
36
|
+
import DOMPurify from "dompurify";
|
|
37
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
38
|
+
|
|
39
|
+
const globalSettings = useGlobalSettingsStore();
|
|
40
|
+
|
|
41
|
+
const properties = defineProps<{rule: t.Rule}>();
|
|
42
|
+
|
|
43
|
+
async function deleteRule() {
|
|
44
|
+
await api.deleteRule({id: properties.rule.id});
|
|
45
|
+
globalSettings.updateDataVersion();
|
|
46
|
+
}
|
|
47
|
+
</script>
|
|
@@ -1,38 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
<tbody>
|
|
10
|
-
<tr
|
|
11
|
-
v-for="rule in rules"
|
|
12
|
-
:key="rule.id">
|
|
13
|
-
<td>
|
|
14
|
-
<rule-score-updater
|
|
15
|
-
:score="rule.score"
|
|
16
|
-
:rule-id="rule.id"
|
|
17
|
-
:tags="rule.tags" />
|
|
18
|
-
</td>
|
|
19
|
-
<td>
|
|
20
|
-
<template
|
|
21
|
-
v-for="tag of rule.tags"
|
|
22
|
-
:key="tag">
|
|
23
|
-
<ffun-tag :uid="tag" />
|
|
24
|
-
</template>
|
|
25
|
-
</td>
|
|
26
|
-
<td>
|
|
27
|
-
<a
|
|
28
|
-
href="#"
|
|
29
|
-
@click.prevent="deleteRule(rule.id)"
|
|
30
|
-
>delete</a
|
|
31
|
-
>
|
|
32
|
-
</td>
|
|
33
|
-
</tr>
|
|
34
|
-
</tbody>
|
|
35
|
-
</table>
|
|
2
|
+
<ul>
|
|
3
|
+
<li
|
|
4
|
+
v-for="rule in rules"
|
|
5
|
+
:key="rule.id">
|
|
6
|
+
<rule-for-list :rule="rule" />
|
|
7
|
+
</li>
|
|
8
|
+
</ul>
|
|
36
9
|
</template>
|
|
37
10
|
|
|
38
11
|
<script lang="ts" setup>
|
|
@@ -42,13 +15,4 @@
|
|
|
42
15
|
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
43
16
|
|
|
44
17
|
defineProps<{rules: Array<t.Rule>}>();
|
|
45
|
-
|
|
46
|
-
const globalSettings = useGlobalSettingsStore();
|
|
47
|
-
|
|
48
|
-
async function deleteRule(id: t.RuleId) {
|
|
49
|
-
await api.deleteRule({id: id});
|
|
50
|
-
globalSettings.updateDataVersion();
|
|
51
|
-
}
|
|
52
18
|
</script>
|
|
53
|
-
|
|
54
|
-
<style></style>
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
+
{{ realShowEntries }} of {{ total }}
|
|
4
|
+
|
|
3
5
|
<button
|
|
6
|
+
class="ffun-form-button ml-2"
|
|
4
7
|
v-if="canShowMore"
|
|
5
8
|
@click.prevent="showMore()">
|
|
6
9
|
next {{ realShowPerPage }}
|
|
7
10
|
</button>
|
|
8
11
|
|
|
9
|
-
<span v-if="canShowMore && canHide"> | </span>
|
|
10
|
-
|
|
11
12
|
<button
|
|
13
|
+
class="ffun-form-button ml-2"
|
|
12
14
|
v-if="canHide"
|
|
13
15
|
@click.prevent="hideAll()"
|
|
14
16
|
>hide</button
|
|
@@ -19,8 +21,6 @@
|
|
|
19
21
|
style="line-height: 0.5rem"
|
|
20
22
|
> </div
|
|
21
23
|
>
|
|
22
|
-
|
|
23
|
-
shown {{ realShowEntries }} / {{ total }}
|
|
24
24
|
</div>
|
|
25
25
|
</template>
|
|
26
26
|
|
|
@@ -77,5 +77,3 @@
|
|
|
77
77
|
return showEntries.value < properties.total;
|
|
78
78
|
});
|
|
79
79
|
</script>
|
|
80
|
-
|
|
81
|
-
<style></style>
|
|
@@ -1,46 +1,62 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div>
|
|
2
|
+
<div v-if="globalState.isLoggedIn">
|
|
3
|
+
<p class="">You have already logged in.</p>
|
|
4
|
+
<button
|
|
5
|
+
class="text-blue-600 hover:text-blue-800 text-xl pt-0"
|
|
6
|
+
@click.prevent="goToWorkspace()"
|
|
7
|
+
>Go To Feeds ⇒</button
|
|
8
|
+
>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<div v-else>
|
|
3
12
|
<template v-if="!requested">
|
|
4
|
-
<p>
|
|
13
|
+
<p class="text-left">We'll send you an email with a login link.</p>
|
|
5
14
|
|
|
6
|
-
<p>If you don't have an account, one will be created.</p>
|
|
15
|
+
<p class="text-left">If you don't have an account, one will be created.</p>
|
|
7
16
|
|
|
8
|
-
<form
|
|
17
|
+
<form
|
|
18
|
+
@submit.prevent="login()"
|
|
19
|
+
class="w-full flex">
|
|
9
20
|
<input
|
|
21
|
+
class="ffun-input flex-grow p-1 mr-2"
|
|
10
22
|
type="email"
|
|
11
23
|
v-model="email"
|
|
12
24
|
required
|
|
13
|
-
placeholder="
|
|
14
|
-
<button
|
|
25
|
+
placeholder="me@example.com" />
|
|
26
|
+
<button
|
|
27
|
+
class="ffun-form-button"
|
|
28
|
+
type="submit"
|
|
29
|
+
>Login</button
|
|
30
|
+
>
|
|
15
31
|
</form>
|
|
16
32
|
</template>
|
|
17
33
|
|
|
18
34
|
<template v-else>
|
|
19
|
-
<p>
|
|
20
|
-
|
|
35
|
+
<p class="">
|
|
36
|
+
Login link was sent to <strong>{{ email }}</strong>
|
|
37
|
+
|
|
38
|
+
<a
|
|
39
|
+
class="ml-1"
|
|
40
|
+
@click.prevent="onChangeEmail()"
|
|
41
|
+
>change</a
|
|
42
|
+
>
|
|
21
43
|
</p>
|
|
22
44
|
|
|
23
45
|
<button
|
|
46
|
+
v-if="!counting"
|
|
24
47
|
type="button"
|
|
25
|
-
class="btn btn-primary"
|
|
26
|
-
|
|
27
|
-
<vue-countdown
|
|
28
|
-
v-if="counting"
|
|
29
|
-
:time="supertokens.allowResendAfter"
|
|
30
|
-
@end="onCountdownEnd"
|
|
31
|
-
v-slot="{totalSeconds}">
|
|
32
|
-
Resend the email in {{ totalSeconds }} seconds.
|
|
33
|
-
</vue-countdown>
|
|
34
|
-
<span
|
|
35
|
-
v-else
|
|
36
|
-
@click.prevent="resend()"
|
|
37
|
-
>Resend email</span
|
|
38
|
-
>
|
|
48
|
+
class="btn btn-primary ffun-form-button">
|
|
49
|
+
<span @click.prevent="resend()">Resend email</span>
|
|
39
50
|
</button>
|
|
40
51
|
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
52
|
+
<vue-countdown
|
|
53
|
+
v-else
|
|
54
|
+
:time="supertokens.allowResendAfter"
|
|
55
|
+
@end="onCountdownEnd"
|
|
56
|
+
class=""
|
|
57
|
+
v-slot="{totalSeconds}">
|
|
58
|
+
Resend in {{ totalSeconds }} seconds
|
|
59
|
+
</vue-countdown>
|
|
44
60
|
</template>
|
|
45
61
|
</div>
|
|
46
62
|
</template>
|
|
@@ -54,7 +70,12 @@
|
|
|
54
70
|
import DOMPurify from "dompurify";
|
|
55
71
|
import {useEntriesStore} from "@/stores/entries";
|
|
56
72
|
import {useSupertokens} from "@/stores/supertokens";
|
|
73
|
+
import {useGlobalState} from "@/stores/globalState";
|
|
74
|
+
import {useRouter} from "vue-router";
|
|
57
75
|
import * as settings from "@/logic/settings";
|
|
76
|
+
const router = useRouter();
|
|
77
|
+
|
|
78
|
+
const globalState = useGlobalState();
|
|
58
79
|
|
|
59
80
|
const supertokens = useSupertokens();
|
|
60
81
|
|
|
@@ -106,6 +127,10 @@
|
|
|
106
127
|
await supertokens.clearLoginAttempt();
|
|
107
128
|
}
|
|
108
129
|
|
|
130
|
+
function goToWorkspace() {
|
|
131
|
+
router.push({name: e.MainPanelMode.Entries, params: {}});
|
|
132
|
+
}
|
|
133
|
+
|
|
109
134
|
onMounted(async () => {
|
|
110
135
|
if (settings.authMode === settings.AuthMode.SingleUser) {
|
|
111
136
|
return true;
|
|
@@ -2,40 +2,40 @@
|
|
|
2
2
|
<div>
|
|
3
3
|
<ul
|
|
4
4
|
v-if="displayedSelectedTags.length > 0"
|
|
5
|
-
|
|
5
|
+
class="pl-0 mb-0">
|
|
6
6
|
<li
|
|
7
|
-
class="filter-element"
|
|
8
7
|
v-for="tag of displayedSelectedTags"
|
|
9
|
-
:key="tag"
|
|
8
|
+
:key="tag"
|
|
9
|
+
class="whitespace-nowrap line-clamp-1">
|
|
10
|
+
<a
|
|
11
|
+
href="#"
|
|
12
|
+
@click.prevent="deselect(tag)"
|
|
13
|
+
>[X]</a
|
|
14
|
+
>
|
|
10
15
|
<ffun-tag
|
|
16
|
+
class="ml-1"
|
|
11
17
|
:uid="tag"
|
|
12
18
|
:count="tags[tag] ?? 0"
|
|
13
19
|
count-mode="no"
|
|
14
20
|
:mode="tagStates[tag]"
|
|
15
21
|
@tag:clicked="onTagClicked">
|
|
16
|
-
<template #start>
|
|
17
|
-
<a
|
|
18
|
-
href="#"
|
|
19
|
-
@click.prevent="deselect(tag)"
|
|
20
|
-
>[X]</a
|
|
21
|
-
>
|
|
22
|
-
</template>
|
|
23
22
|
</ffun-tag>
|
|
24
23
|
</li>
|
|
25
24
|
</ul>
|
|
26
25
|
|
|
27
26
|
<input
|
|
27
|
+
class="ffun-input w-full"
|
|
28
28
|
type="text"
|
|
29
29
|
placeholder="Input part of tag..."
|
|
30
30
|
v-model="tagNameFilter" />
|
|
31
31
|
|
|
32
32
|
<ul
|
|
33
33
|
v-if="displayedTags.length > 0"
|
|
34
|
-
|
|
34
|
+
class="pl-0 mb-0">
|
|
35
35
|
<li
|
|
36
|
-
class="filter-element"
|
|
37
36
|
v-for="tag of displayedTags"
|
|
38
|
-
:key="tag"
|
|
37
|
+
:key="tag"
|
|
38
|
+
class="truncate">
|
|
39
39
|
<ffun-tag
|
|
40
40
|
:uid="tag"
|
|
41
41
|
:count="tags[tag]"
|
|
@@ -172,15 +172,3 @@
|
|
|
172
172
|
emit("tag:stateChanged", {tag: tag, state: tagStates.value[tag]});
|
|
173
173
|
}
|
|
174
174
|
</script>
|
|
175
|
-
|
|
176
|
-
<style scoped>
|
|
177
|
-
.filter-element {
|
|
178
|
-
overflow: hidden;
|
|
179
|
-
white-space: nowrap;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
.filter-element value-tag {
|
|
183
|
-
overflow: hidden;
|
|
184
|
-
text-overflow: ellipsis;
|
|
185
|
-
}
|
|
186
|
-
</style>
|
|
@@ -1,32 +1,36 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
+
<div class="text-sm">
|
|
4
|
+
<ffun-tag
|
|
5
|
+
v-for="tag of displayedTags"
|
|
6
|
+
:key="tag"
|
|
7
|
+
:uid="tag"
|
|
8
|
+
:mode="tagMode(tag)"
|
|
9
|
+
:count="tagsCount[tag]"
|
|
10
|
+
count-mode="tooltip"
|
|
11
|
+
@tag:clicked="onTagClicked" />
|
|
12
|
+
|
|
13
|
+
<a
|
|
14
|
+
class="ffun-normal-link"
|
|
15
|
+
href="#"
|
|
16
|
+
v-if="canShowAll"
|
|
17
|
+
@click.prevent="showAll = true"
|
|
18
|
+
>{{ tagsNumber - showLimit }} more</a
|
|
19
|
+
>
|
|
20
|
+
|
|
21
|
+
<a
|
|
22
|
+
class="ffun-normal-link"
|
|
23
|
+
href="#"
|
|
24
|
+
v-if="canHide"
|
|
25
|
+
@click.prevent="showAll = false"
|
|
26
|
+
>hide</a
|
|
27
|
+
>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
3
30
|
<rule-constructor
|
|
4
31
|
v-if="selectedTagsList.length > 0"
|
|
5
32
|
:tags="selectedTagsList"
|
|
6
33
|
@rule-constructor:created="onRuleCreated" />
|
|
7
|
-
|
|
8
|
-
<ffun-tag
|
|
9
|
-
v-for="tag of displayedTags"
|
|
10
|
-
:key="tag"
|
|
11
|
-
:uid="tag"
|
|
12
|
-
:mode="tagMode(tag)"
|
|
13
|
-
:count="tagsCount[tag]"
|
|
14
|
-
count-mode="tooltip"
|
|
15
|
-
@tag:clicked="onTagClicked" />
|
|
16
|
-
|
|
17
|
-
<a
|
|
18
|
-
href="#"
|
|
19
|
-
v-if="canShowAll"
|
|
20
|
-
@click.prevent="showAll = true"
|
|
21
|
-
>{{ tagsNumber - showLimit }} more</a
|
|
22
|
-
>
|
|
23
|
-
|
|
24
|
-
<a
|
|
25
|
-
href="#"
|
|
26
|
-
v-if="canHide"
|
|
27
|
-
@click.prevent="showAll = false"
|
|
28
|
-
>hide</a
|
|
29
|
-
>
|
|
30
34
|
</div>
|
|
31
35
|
</template>
|
|
32
36
|
|
|
@@ -159,5 +163,3 @@
|
|
|
159
163
|
selectedTags.value = {};
|
|
160
164
|
}
|
|
161
165
|
</script>
|
|
162
|
-
|
|
163
|
-
<style></style>
|
|
@@ -1,44 +1,52 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
v-if="setting !== null"
|
|
4
|
-
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
4
|
+
class="mb-4">
|
|
5
|
+
<span class="font-semibold mr-1">{{ setting.name }}</span>
|
|
6
|
+
|
|
7
|
+
<input
|
|
8
|
+
class="ffun-input"
|
|
9
|
+
v-if="editing"
|
|
10
|
+
type="input"
|
|
11
|
+
v-model="value" />
|
|
12
|
+
|
|
13
|
+
<input
|
|
14
|
+
v-else-if="setting.type !== 'boolean'"
|
|
15
|
+
class="ffun-input"
|
|
16
|
+
disabled
|
|
17
|
+
:value="verboseValue" />
|
|
18
|
+
|
|
19
|
+
<config-flag
|
|
20
|
+
v-if="setting.type == 'boolean'"
|
|
21
|
+
style="min-width: 2.5rem"
|
|
22
|
+
:flag="setting.value"
|
|
23
|
+
@update:flag="updateFlag($event)"
|
|
24
|
+
on-text="No"
|
|
25
|
+
off-text="Yes" />
|
|
23
26
|
|
|
27
|
+
<template v-else-if="!editing">
|
|
24
28
|
<button
|
|
25
|
-
|
|
26
|
-
@click.prevent="
|
|
27
|
-
>
|
|
29
|
+
class="ffun-form-button ml-1"
|
|
30
|
+
@click.prevent="startEditing()"
|
|
31
|
+
>Edit</button
|
|
28
32
|
>
|
|
29
33
|
</template>
|
|
30
34
|
|
|
31
|
-
<template v-else-if="!editing">
|
|
32
|
-
<button @click.prevent="startEditing()">Edit</button>
|
|
33
|
-
</template>
|
|
34
|
-
|
|
35
35
|
<template v-else>
|
|
36
|
-
<button
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
<button
|
|
37
|
+
@click.prevent="save()"
|
|
38
|
+
class="ffun-form-button ml-1"
|
|
39
|
+
>Save</button
|
|
40
|
+
>
|
|
41
|
+
<button
|
|
42
|
+
@click.prevent="cancel()"
|
|
43
|
+
class="ffun-form-button ml-1"
|
|
44
|
+
>Cancel</button
|
|
45
|
+
>
|
|
39
46
|
</template>
|
|
40
47
|
|
|
41
48
|
<div
|
|
49
|
+
class="ffun-normalized-text"
|
|
42
50
|
v-if="setting.description"
|
|
43
51
|
v-html="setting.description" />
|
|
44
52
|
</div>
|
|
@@ -74,7 +82,7 @@
|
|
|
74
82
|
|
|
75
83
|
const verboseValue = computed(() => {
|
|
76
84
|
if (setting.value === null) {
|
|
77
|
-
return "
|
|
85
|
+
return "no value";
|
|
78
86
|
}
|
|
79
87
|
|
|
80
88
|
const v = setting.value.value;
|
|
@@ -85,7 +93,7 @@
|
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
if (v == null || v == "") {
|
|
88
|
-
return "
|
|
96
|
+
return "no value";
|
|
89
97
|
}
|
|
90
98
|
|
|
91
99
|
if (type == "secret") {
|
|
@@ -115,13 +123,8 @@
|
|
|
115
123
|
editing.value = true;
|
|
116
124
|
}
|
|
117
125
|
|
|
118
|
-
async function
|
|
119
|
-
value.value =
|
|
120
|
-
await save();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async function turnOff() {
|
|
124
|
-
value.value = false;
|
|
126
|
+
async function updateFlag(newValue: any) {
|
|
127
|
+
value.value = newValue;
|
|
125
128
|
await save();
|
|
126
129
|
}
|
|
127
130
|
</script>
|