feeds-fun 0.0.4
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/.eslintrc.cjs +15 -0
- package/.prettierrc.json +13 -0
- package/.vscode/extensions.json +3 -0
- package/README.md +52 -0
- package/env.d.ts +1 -0
- package/index.html +13 -0
- package/package.json +50 -0
- package/public/favicon.ico +0 -0
- package/src/App.vue +33 -0
- package/src/components/ConfigFlag.vue +22 -0
- package/src/components/ConfigSelector.vue +25 -0
- package/src/components/DiscoveryForm.vue +81 -0
- package/src/components/EntriesList.vue +51 -0
- package/src/components/EntryForList.vue +156 -0
- package/src/components/EntryInfo.vue +23 -0
- package/src/components/FeedForList.vue +115 -0
- package/src/components/FeedInfo.vue +35 -0
- package/src/components/FeedsCollections.vue +53 -0
- package/src/components/FeedsList.vue +27 -0
- package/src/components/FfunGithubButtons.vue +22 -0
- package/src/components/FfunTag.vue +95 -0
- package/src/components/OPMLUpload.vue +46 -0
- package/src/components/OpenaiTokensUsage.vue +61 -0
- package/src/components/RuleConstructor.vue +56 -0
- package/src/components/RuleScoreUpdater.vue +33 -0
- package/src/components/RulesList.vue +52 -0
- package/src/components/SimplePagination.vue +81 -0
- package/src/components/SupertokensLogin.vue +118 -0
- package/src/components/TagsFilter.vue +130 -0
- package/src/components/TagsFilterElement.vue +89 -0
- package/src/components/TagsList.vue +125 -0
- package/src/components/UserSetting.vue +129 -0
- package/src/inputs/Marker.vue +70 -0
- package/src/inputs/ScoreSelector.vue +38 -0
- package/src/layouts/SidePanelLayout.vue +231 -0
- package/src/layouts/WideLayout.vue +44 -0
- package/src/logic/api.ts +253 -0
- package/src/logic/constants.ts +8 -0
- package/src/logic/enums.ts +92 -0
- package/src/logic/settings.ts +37 -0
- package/src/logic/timer.ts +25 -0
- package/src/logic/types.ts +371 -0
- package/src/logic/utils.ts +39 -0
- package/src/main.ts +145 -0
- package/src/router/index.ts +61 -0
- package/src/stores/entries.ts +217 -0
- package/src/stores/globalSettings.ts +74 -0
- package/src/stores/globalState.ts +23 -0
- package/src/stores/supertokens.ts +144 -0
- package/src/stores/tags.ts +54 -0
- package/src/values/DateTime.vue +27 -0
- package/src/values/FeedId.vue +22 -0
- package/src/values/Score.vue +42 -0
- package/src/values/URL.vue +25 -0
- package/src/views/AuthView.vue +66 -0
- package/src/views/CollectionsView.vue +23 -0
- package/src/views/DiscoveryView.vue +26 -0
- package/src/views/FeedsView.vue +124 -0
- package/src/views/MainView.vue +67 -0
- package/src/views/NewsView.vue +96 -0
- package/src/views/RulesView.vue +33 -0
- package/src/views/SettingsView.vue +81 -0
- package/tsconfig.app.json +12 -0
- package/tsconfig.json +14 -0
- package/tsconfig.node.json +8 -0
- package/tsconfig.vitest.json +9 -0
- package/vite.config.ts +26 -0
- package/vitest.config.ts +15 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<side-panel-layout :reload-button="false">
|
|
3
|
+
<template #main-header> Collections </template>
|
|
4
|
+
|
|
5
|
+
<feeds-collections />
|
|
6
|
+
</side-panel-layout>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script lang="ts" setup>
|
|
10
|
+
import {computed, ref, onUnmounted, watch} from "vue";
|
|
11
|
+
import {computedAsync} from "@vueuse/core";
|
|
12
|
+
import * as api from "@/logic/api";
|
|
13
|
+
import * as t from "@/logic/types";
|
|
14
|
+
import * as e from "@/logic/enums";
|
|
15
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
16
|
+
import {useEntriesStore} from "@/stores/entries";
|
|
17
|
+
|
|
18
|
+
const globalSettings = useGlobalSettingsStore();
|
|
19
|
+
|
|
20
|
+
globalSettings.mainPanelMode = e.MainPanelMode.Collections;
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<style></style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<side-panel-layout :reload-button="false">
|
|
3
|
+
<template #main-header> Discovery </template>
|
|
4
|
+
|
|
5
|
+
<opml-upload />
|
|
6
|
+
|
|
7
|
+
<hr />
|
|
8
|
+
|
|
9
|
+
<discovery-form />
|
|
10
|
+
</side-panel-layout>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script lang="ts" setup>
|
|
14
|
+
import {computed, ref, onUnmounted, watch} from "vue";
|
|
15
|
+
import {computedAsync} from "@vueuse/core";
|
|
16
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
17
|
+
import * as api from "@/logic/api";
|
|
18
|
+
import * as t from "@/logic/types";
|
|
19
|
+
import * as e from "@/logic/enums";
|
|
20
|
+
|
|
21
|
+
const globalSettings = useGlobalSettingsStore();
|
|
22
|
+
|
|
23
|
+
globalSettings.mainPanelMode = e.MainPanelMode.Discovery;
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<style></style>
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<side-panel-layout>
|
|
3
|
+
<template #side-menu-item-1>
|
|
4
|
+
Show descriptions:
|
|
5
|
+
<config-flag
|
|
6
|
+
v-model:flag="globalSettings.showFeedsDescriptions"
|
|
7
|
+
on-text="yes"
|
|
8
|
+
off-text="no" />
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<template #side-menu-item-2>
|
|
12
|
+
Sorted by
|
|
13
|
+
<config-selector
|
|
14
|
+
:values="e.FeedsOrderProperties"
|
|
15
|
+
v-model:property="globalSettings.feedsOrder" />
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<template #side-menu-item-3>
|
|
19
|
+
Show failed
|
|
20
|
+
<config-flag
|
|
21
|
+
v-model:flag="globalSettings.failedFeedsFirst"
|
|
22
|
+
on-text="first"
|
|
23
|
+
off-text="last" />
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<template #main-header>
|
|
27
|
+
Feeds
|
|
28
|
+
<span v-if="sortedFeeds"> [{{ sortedFeeds.length }}] </span>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<template #main-footer> </template>
|
|
32
|
+
|
|
33
|
+
<feeds-list
|
|
34
|
+
v-if="sortedFeeds"
|
|
35
|
+
:feeds="sortedFeeds" />
|
|
36
|
+
</side-panel-layout>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<script lang="ts" setup>
|
|
40
|
+
import _ from "lodash";
|
|
41
|
+
import {computed, ref, onUnmounted, watch} from "vue";
|
|
42
|
+
import {computedAsync} from "@vueuse/core";
|
|
43
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
44
|
+
import * as api from "@/logic/api";
|
|
45
|
+
import type * as t from "@/logic/types";
|
|
46
|
+
import * as e from "@/logic/enums";
|
|
47
|
+
|
|
48
|
+
const globalSettings = useGlobalSettingsStore();
|
|
49
|
+
|
|
50
|
+
globalSettings.mainPanelMode = e.MainPanelMode.Feeds;
|
|
51
|
+
|
|
52
|
+
const feeds = computedAsync(async () => {
|
|
53
|
+
// force refresh
|
|
54
|
+
globalSettings.dataVersion;
|
|
55
|
+
return await api.getFeeds();
|
|
56
|
+
}, null);
|
|
57
|
+
|
|
58
|
+
const sortedFeeds = computed(() => {
|
|
59
|
+
if (!feeds.value) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let sorted = feeds.value.slice();
|
|
64
|
+
|
|
65
|
+
const orderProperties = e.FeedsOrderProperties.get(globalSettings.feedsOrder);
|
|
66
|
+
|
|
67
|
+
if (!orderProperties) {
|
|
68
|
+
throw new Error(`Invalid order properties: ${globalSettings.feedsOrder}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const orderField = orderProperties.orderField;
|
|
72
|
+
|
|
73
|
+
const direction = {asc: -1, desc: 1}[orderProperties.orderDirection];
|
|
74
|
+
|
|
75
|
+
if (direction === undefined) {
|
|
76
|
+
throw new Error(`Invalid order direction: ${orderProperties.orderDirection}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
sorted = sorted.sort((a: t.Feed, b: t.Feed) => {
|
|
80
|
+
if (a.isOk && !b.isOk) {
|
|
81
|
+
if (globalSettings.failedFeedsFirst) {
|
|
82
|
+
return 1;
|
|
83
|
+
}
|
|
84
|
+
return -1;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!a.isOk && b.isOk) {
|
|
88
|
+
if (globalSettings.failedFeedsFirst) {
|
|
89
|
+
return -1;
|
|
90
|
+
}
|
|
91
|
+
return 1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const valueA = _.get(a, orderField, null);
|
|
95
|
+
const valueB = _.get(b, orderField, null);
|
|
96
|
+
|
|
97
|
+
if (valueA === null && valueB === null) {
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (valueA === null) {
|
|
102
|
+
return 1 * direction;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (valueB === null) {
|
|
106
|
+
return -1 * direction;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (valueA < valueB) {
|
|
110
|
+
return 1 * direction;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (valueA > valueB) {
|
|
114
|
+
return -1 * direction;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return 0;
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
return sorted;
|
|
121
|
+
});
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
<style></style>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<wide-layout>
|
|
3
|
+
<template #header> Feeds Fun </template>
|
|
4
|
+
|
|
5
|
+
<div v-if="globalState.isLoggedIn">
|
|
6
|
+
<p>You have already logged in.</p>
|
|
7
|
+
<button @click.prevent="goToWorkspace()">Go To Feeds</button>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<div v-else>
|
|
11
|
+
<supertokens-login />
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<br />
|
|
15
|
+
|
|
16
|
+
<ffun-github-buttons :repository="settings.githubRepo" />
|
|
17
|
+
|
|
18
|
+
<h2>What is it?</h2>
|
|
19
|
+
|
|
20
|
+
<ul style="text-align: left">
|
|
21
|
+
<li>Web-based news reader. Self-hosted, if it is your way.</li>
|
|
22
|
+
<li>Automatically assigns tags to news entries.</li>
|
|
23
|
+
<li>You create rules to score news by tags.</li>
|
|
24
|
+
<li>Then filter and sort news how you want.</li>
|
|
25
|
+
</ul>
|
|
26
|
+
|
|
27
|
+
<h2>You are in control</h2>
|
|
28
|
+
|
|
29
|
+
<ul style="text-align: left">
|
|
30
|
+
<li>No black box recommendation algorithms.</li>
|
|
31
|
+
<li>No "smart" reordering of your news.</li>
|
|
32
|
+
<li>No ads.</li>
|
|
33
|
+
<li>No selling of your data.</li>
|
|
34
|
+
</ul>
|
|
35
|
+
|
|
36
|
+
<h2>What will it become?</h2>
|
|
37
|
+
|
|
38
|
+
<ul style="text-align: left">
|
|
39
|
+
<li>Will become much prettier.</li>
|
|
40
|
+
<li> Will collect not only RSS/ATOM but any news feeds, including private if you allow. </li>
|
|
41
|
+
<li>Will suggest new rules to score & new feeds, if you allow.</li>
|
|
42
|
+
</ul>
|
|
43
|
+
</wide-layout>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<script lang="ts" setup>
|
|
47
|
+
import {useRouter} from "vue-router";
|
|
48
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
49
|
+
import {useSupertokens} from "@/stores/supertokens";
|
|
50
|
+
import {useGlobalState} from "@/stores/globalState";
|
|
51
|
+
import {computedAsync} from "@vueuse/core";
|
|
52
|
+
import * as settings from "@/logic/settings";
|
|
53
|
+
import * as e from "@/logic/enums";
|
|
54
|
+
|
|
55
|
+
const globalSettings = useGlobalSettingsStore();
|
|
56
|
+
const globalState = useGlobalState();
|
|
57
|
+
|
|
58
|
+
const supertokens = useSupertokens();
|
|
59
|
+
|
|
60
|
+
const router = useRouter();
|
|
61
|
+
|
|
62
|
+
function goToWorkspace() {
|
|
63
|
+
router.push({name: e.MainPanelMode.Entries, params: {}});
|
|
64
|
+
}
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<style></style>
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<side-panel-layout>
|
|
3
|
+
<template #side-menu-item-1>
|
|
4
|
+
For the last
|
|
5
|
+
<config-selector
|
|
6
|
+
:values="e.LastEntriesPeriodProperties"
|
|
7
|
+
v-model:property="globalSettings.lastEntriesPeriod" />
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<template #side-menu-item-2>
|
|
11
|
+
Sorted by
|
|
12
|
+
<config-selector
|
|
13
|
+
:values="e.EntriesOrderProperties"
|
|
14
|
+
v-model:property="globalSettings.entriesOrder" />
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<template #side-menu-item-3>
|
|
18
|
+
Show tags:
|
|
19
|
+
<config-flag
|
|
20
|
+
v-model:flag="globalSettings.showEntriesTags"
|
|
21
|
+
on-text="yes"
|
|
22
|
+
off-text="no" />
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<template #side-menu-item-4>
|
|
26
|
+
Show already read:
|
|
27
|
+
<config-flag
|
|
28
|
+
v-model:flag="globalSettings.showRead"
|
|
29
|
+
on-text="yes"
|
|
30
|
+
off-text="no" />
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<template #side-footer>
|
|
34
|
+
<tags-filter
|
|
35
|
+
v-if="globalSettings.mainPanelMode == e.MainPanelMode.Entries"
|
|
36
|
+
:tags="entriesStore.reportTagsCount" />
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<template #main-header>
|
|
40
|
+
News
|
|
41
|
+
<span v-if="entriesNumber > 0">[{{ entriesNumber }}]</span>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<template #main-footer> </template>
|
|
45
|
+
|
|
46
|
+
<template v-if="!hasEntries && !entriesStore.firstTimeEntriesLoading">
|
|
47
|
+
<p>It looks like you have no news to read.</p>
|
|
48
|
+
<p> Try to subscribe for the feeds collections that we are preparing for you! </p>
|
|
49
|
+
<feeds-collections />
|
|
50
|
+
</template>
|
|
51
|
+
|
|
52
|
+
<entries-list
|
|
53
|
+
:entriesIds="entriesStore.entriesReport"
|
|
54
|
+
:time-field="timeField"
|
|
55
|
+
:show-tags="globalSettings.showEntriesTags"
|
|
56
|
+
:showFromStart="25"
|
|
57
|
+
:showPerPage="25" />
|
|
58
|
+
</side-panel-layout>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<script lang="ts" setup>
|
|
62
|
+
import {computed, ref, onUnmounted, watch} from "vue";
|
|
63
|
+
import {computedAsync} from "@vueuse/core";
|
|
64
|
+
import * as api from "@/logic/api";
|
|
65
|
+
import * as t from "@/logic/types";
|
|
66
|
+
import * as e from "@/logic/enums";
|
|
67
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
68
|
+
import {useEntriesStore} from "@/stores/entries";
|
|
69
|
+
|
|
70
|
+
const globalSettings = useGlobalSettingsStore();
|
|
71
|
+
const entriesStore = useEntriesStore();
|
|
72
|
+
|
|
73
|
+
globalSettings.mainPanelMode = e.MainPanelMode.Entries;
|
|
74
|
+
|
|
75
|
+
globalSettings.updateDataVersion();
|
|
76
|
+
|
|
77
|
+
const entriesNumber = computed(() => {
|
|
78
|
+
return entriesStore.entriesReport.length;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const hasEntries = computed(() => {
|
|
82
|
+
return entriesNumber.value > 0;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const timeField = computed(() => {
|
|
86
|
+
const orderProperties = e.EntriesOrderProperties.get(globalSettings.entriesOrder);
|
|
87
|
+
|
|
88
|
+
if (orderProperties === undefined) {
|
|
89
|
+
throw new Error(`Unknown entries order: ${globalSettings.entriesOrder}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return orderProperties.timeField;
|
|
93
|
+
});
|
|
94
|
+
</script>
|
|
95
|
+
|
|
96
|
+
<style></style>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<side-panel-layout :reload-button="false">
|
|
3
|
+
<template #main-header>
|
|
4
|
+
Rules
|
|
5
|
+
<span v-if="rules">[{{ rules.length }}]</span>
|
|
6
|
+
</template>
|
|
7
|
+
|
|
8
|
+
<rules-list
|
|
9
|
+
v-if="rules"
|
|
10
|
+
:rules="rules" />
|
|
11
|
+
</side-panel-layout>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script lang="ts" setup>
|
|
15
|
+
import {computed, ref, onUnmounted, watch} from "vue";
|
|
16
|
+
import {computedAsync} from "@vueuse/core";
|
|
17
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
18
|
+
import * as api from "@/logic/api";
|
|
19
|
+
import * as t from "@/logic/types";
|
|
20
|
+
import * as e from "@/logic/enums";
|
|
21
|
+
|
|
22
|
+
const globalSettings = useGlobalSettingsStore();
|
|
23
|
+
|
|
24
|
+
globalSettings.mainPanelMode = e.MainPanelMode.Rules;
|
|
25
|
+
|
|
26
|
+
const rules = computedAsync(async () => {
|
|
27
|
+
// force refresh
|
|
28
|
+
globalSettings.dataVersion;
|
|
29
|
+
return await api.getRules();
|
|
30
|
+
}, null);
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<style></style>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<side-panel-layout :reload-button="false">
|
|
3
|
+
<h2>Info</h2>
|
|
4
|
+
|
|
5
|
+
<ul>
|
|
6
|
+
<li><strong>User id</strong>: {{ userId }}</li>
|
|
7
|
+
</ul>
|
|
8
|
+
|
|
9
|
+
<h2>Settings</h2>
|
|
10
|
+
|
|
11
|
+
<template #main-header> Settings </template>
|
|
12
|
+
|
|
13
|
+
<user-setting
|
|
14
|
+
v-for="(value, kind) of globalSettings.userSettings"
|
|
15
|
+
:kind="kind" />
|
|
16
|
+
|
|
17
|
+
<h2>OpenAI usage</h2>
|
|
18
|
+
|
|
19
|
+
<p>Token usage for your OpenAI key per month.</p>
|
|
20
|
+
|
|
21
|
+
<ul>
|
|
22
|
+
<li> <strong>Used tokens</strong>: the number of tokens in processed requests. </li>
|
|
23
|
+
<li>
|
|
24
|
+
<strong>Reserved tokens</strong>: the number of tokens reserved for requests that currently are processing or
|
|
25
|
+
were not processed correctly.
|
|
26
|
+
</li>
|
|
27
|
+
<li>
|
|
28
|
+
<strong>Total tokens</strong>: the total number of tokens used in the month. Should be not less than the actual
|
|
29
|
+
used tokens, but can be bigger because we reserve more tokens than actually use.
|
|
30
|
+
</li>
|
|
31
|
+
</ul>
|
|
32
|
+
|
|
33
|
+
<p v-if="openAIUsage == null">Loading...</p>
|
|
34
|
+
|
|
35
|
+
<p v-else-if="openAIUsage.length == 0">No usage data</p>
|
|
36
|
+
|
|
37
|
+
<table v-else>
|
|
38
|
+
<thead>
|
|
39
|
+
<tr>
|
|
40
|
+
<th style="padding-left: 1rem">Period</th>
|
|
41
|
+
<th style="padding-left: 1rem">Used tokens</th>
|
|
42
|
+
<th style="padding-left: 1rem">Reserved tokens</th>
|
|
43
|
+
<th style="padding-left: 1rem">Total tokens</th>
|
|
44
|
+
<th style="padding-left: 1rem">% from current maximum</th>
|
|
45
|
+
</tr>
|
|
46
|
+
</thead>
|
|
47
|
+
<tbody>
|
|
48
|
+
<openai-tokens-usage
|
|
49
|
+
:usage="usage"
|
|
50
|
+
v-for="usage of openAIUsage" />
|
|
51
|
+
</tbody>
|
|
52
|
+
</table>
|
|
53
|
+
</side-panel-layout>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<script lang="ts" setup>
|
|
57
|
+
import {computed, ref, onUnmounted, watch} from "vue";
|
|
58
|
+
import {computedAsync} from "@vueuse/core";
|
|
59
|
+
import * as api from "@/logic/api";
|
|
60
|
+
import * as t from "@/logic/types";
|
|
61
|
+
import * as e from "@/logic/enums";
|
|
62
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
63
|
+
|
|
64
|
+
const globalSettings = useGlobalSettingsStore();
|
|
65
|
+
|
|
66
|
+
globalSettings.mainPanelMode = e.MainPanelMode.Settings;
|
|
67
|
+
|
|
68
|
+
const openAIUsage = computedAsync(async () => {
|
|
69
|
+
return await api.getResourceHistory({kind: "openai_tokens"});
|
|
70
|
+
}, null);
|
|
71
|
+
|
|
72
|
+
const userId = computed(() => {
|
|
73
|
+
if (globalSettings.info == null) {
|
|
74
|
+
return "—";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return globalSettings.info.userId;
|
|
78
|
+
});
|
|
79
|
+
</script>
|
|
80
|
+
|
|
81
|
+
<style></style>
|
package/tsconfig.json
ADDED
package/vite.config.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { fileURLToPath, URL } from 'node:url'
|
|
2
|
+
|
|
3
|
+
import { defineConfig } from 'vite'
|
|
4
|
+
import vue from '@vitejs/plugin-vue'
|
|
5
|
+
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
plugins: [vue()],
|
|
8
|
+
resolve: {
|
|
9
|
+
alias: {
|
|
10
|
+
'@': fileURLToPath(new URL('./src', import.meta.url))
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
server: {
|
|
15
|
+
proxy: {
|
|
16
|
+
'/api': {
|
|
17
|
+
target: 'http://backend:8000/',
|
|
18
|
+
changeOrigin: true,
|
|
19
|
+
},
|
|
20
|
+
'/supertokens': {
|
|
21
|
+
target: 'http://backend:8000/',
|
|
22
|
+
changeOrigin: true,
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
})
|
package/vitest.config.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url'
|
|
2
|
+
import { mergeConfig } from 'vite'
|
|
3
|
+
import { configDefaults, defineConfig } from 'vitest/config'
|
|
4
|
+
import viteConfig from './vite.config'
|
|
5
|
+
|
|
6
|
+
export default mergeConfig(
|
|
7
|
+
viteConfig,
|
|
8
|
+
defineConfig({
|
|
9
|
+
test: {
|
|
10
|
+
environment: 'jsdom',
|
|
11
|
+
exclude: [...configDefaults.exclude, 'e2e/*'],
|
|
12
|
+
root: fileURLToPath(new URL('./', import.meta.url))
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
)
|