feeds-fun 1.17.1 → 1.18.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.
Files changed (42) hide show
  1. package/package.json +1 -1
  2. package/src/components/EntriesList.vue +11 -0
  3. package/src/components/EntryForList.vue +17 -6
  4. package/src/components/RuleForList.vue +2 -2
  5. package/src/components/RulesList.vue +18 -9
  6. package/src/components/TokensCost.vue +0 -2
  7. package/src/components/collections/DetailedItem.vue +9 -0
  8. package/src/components/collections/PublicIntro.vue +63 -0
  9. package/src/components/collections/PublicSelector.vue +43 -0
  10. package/src/components/main/Block.vue +1 -1
  11. package/src/components/main/Item.vue +1 -1
  12. package/src/components/notifications/LoadedOldNews.vue +47 -0
  13. package/src/components/page_header/ExternalLinks.vue +11 -6
  14. package/src/components/side_pannel/CollapseButton.vue +56 -0
  15. package/src/components/tags/EntryTag.vue +4 -3
  16. package/src/components/tags/FilterTag.vue +6 -3
  17. package/src/components/tags/RuleTag.vue +4 -3
  18. package/src/components/tags/TagsFilter.vue +17 -5
  19. package/src/css/panels.css +5 -5
  20. package/src/css/side_panel_layout.css +4 -0
  21. package/src/layouts/SidePanelLayout.vue +51 -26
  22. package/src/layouts/WideLayout.vue +0 -4
  23. package/src/logic/api.ts +23 -0
  24. package/src/logic/enums.ts +28 -12
  25. package/src/logic/events.ts +56 -8
  26. package/src/logic/tagsFilterState.ts +61 -1
  27. package/src/logic/types.ts +15 -2
  28. package/src/logic/utils.ts +104 -1
  29. package/src/main.ts +10 -0
  30. package/src/router/index.ts +16 -3
  31. package/src/stores/collections.ts +17 -1
  32. package/src/stores/entries.ts +154 -19
  33. package/src/stores/globalSettings.ts +11 -8
  34. package/src/views/AuthView.vue +3 -1
  35. package/src/views/CollectionsView.vue +13 -2
  36. package/src/views/DiscoveryView.vue +3 -1
  37. package/src/views/FeedsView.vue +3 -1
  38. package/src/views/MainView.vue +18 -1
  39. package/src/views/NewsView.vue +36 -97
  40. package/src/views/PublicCollectionView.vue +237 -0
  41. package/src/views/RulesView.vue +31 -29
  42. package/src/views/SettingsView.vue +3 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "feeds-fun",
3
- "version": "1.17.1",
3
+ "version": "1.18.1",
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": [
@@ -7,6 +7,7 @@
7
7
  :key="entryId"
8
8
  class="ffun-body-list-entry">
9
9
  <entry-for-list
10
+ :show-score="showScore"
10
11
  :entryId="entryId"
11
12
  :time-field="timeField"
12
13
  :tags-count="tagsCount" />
@@ -22,6 +23,14 @@
22
23
  :counterOnNewLine="false"
23
24
  v-model:showEntries="showEntries" />
24
25
  </template>
26
+
27
+ <template v-else>
28
+ <div
29
+ v-if="!loading"
30
+ class="ffun-info-common">
31
+ No news to show.
32
+ </div>
33
+ </template>
25
34
  </div>
26
35
  </template>
27
36
 
@@ -31,10 +40,12 @@
31
40
  import {computedAsync} from "@vueuse/core";
32
41
 
33
42
  const properties = defineProps<{
43
+ loading: boolean;
34
44
  entriesIds: Array<t.EntryId>;
35
45
  timeField: string;
36
46
  showFromStart: number;
37
47
  showPerPage: number;
48
+ showScore: boolean;
38
49
  tagsCount: {[key: string]: number};
39
50
  }>();
40
51
 
@@ -18,7 +18,9 @@
18
18
  class="text-orange-700 ti ti-chevrons-right" />
19
19
  </div>
20
20
 
21
- <div class="flex-shrink-0 w-8 text-center pr-1">
21
+ <div
22
+ v-if="showScore"
23
+ class="flex-shrink-0 w-8 text-center pr-1">
22
24
  <value-score
23
25
  :value="entry.score"
24
26
  :entry-id="entry.id" />
@@ -40,8 +42,8 @@
40
42
  :tags="entry.tags"
41
43
  :tags-count="tagsCount"
42
44
  :show-all="showBody"
43
- @request-to-show-all="entriesStore.displayEntry({entryId: entry.id})"
44
- :contributions="entry.scoreContributions" />
45
+ @request-to-show-all="entriesStore.displayEntry({entryId: entry.id, view: eventsView})"
46
+ :contributions="showScore ? entry.scoreContributions : {}" />
45
47
  </div>
46
48
 
47
49
  <body-list-reverse-time-column
@@ -61,23 +63,29 @@
61
63
 
62
64
  <script lang="ts" setup>
63
65
  import _ from "lodash";
64
- import {computed, ref, useTemplateRef, onMounted} from "vue";
66
+ import {computed, ref, useTemplateRef, onMounted, inject} from "vue";
65
67
  import type * as t from "@/logic/types";
66
68
  import * as events from "@/logic/events";
67
69
  import * as e from "@/logic/enums";
68
70
  import * as utils from "@/logic/utils";
71
+ import * as asserts from "@/logic/asserts";
69
72
  import {computedAsync} from "@vueuse/core";
70
73
  import DOMPurify from "dompurify";
71
74
  import {useEntriesStore} from "@/stores/entries";
72
75
 
73
76
  const entriesStore = useEntriesStore();
74
77
 
78
+ const eventsView = inject<events.EventsViewName>("eventsViewName");
79
+
80
+ asserts.defined(eventsView);
81
+
75
82
  const topElement = useTemplateRef("entryTop");
76
83
 
77
84
  const properties = defineProps<{
78
85
  entryId: t.EntryId;
79
86
  timeField: string;
80
87
  tagsCount: {[key: string]: number};
88
+ showScore: boolean;
81
89
  }>();
82
90
 
83
91
  const entry = computed(() => {
@@ -129,10 +137,13 @@
129
137
  });
130
138
 
131
139
  async function newsLinkOpenedEvent() {
132
- await events.newsLinkOpened({entryId: entry.value.id});
140
+ asserts.defined(eventsView);
141
+ await events.newsLinkOpened({entryId: entry.value.id, view: eventsView});
133
142
  }
134
143
 
135
144
  async function onTitleClick(event: MouseEvent) {
145
+ asserts.defined(eventsView);
146
+
136
147
  if (!event.ctrlKey) {
137
148
  event.preventDefault();
138
149
  event.stopPropagation();
@@ -140,7 +151,7 @@
140
151
  if (showBody.value) {
141
152
  entriesStore.hideEntry({entryId: entry.value.id});
142
153
  } else {
143
- await entriesStore.displayEntry({entryId: entry.value.id});
154
+ await entriesStore.displayEntry({entryId: entry.value.id, view: eventsView});
144
155
 
145
156
  if (topElement.value) {
146
157
  const rect = topElement.value.getBoundingClientRect();
@@ -20,7 +20,7 @@
20
20
 
21
21
  <div class="flex-grow">
22
22
  <rule-tag
23
- v-for="tag of rule.allTags"
23
+ v-for="tag of rule.tags"
24
24
  :key="tag"
25
25
  :uid="tag"
26
26
  :css-modifier="cssModifiers[tag]" />
@@ -79,7 +79,7 @@
79
79
 
80
80
  const cssModifiers: {[key: string]: string} = {};
81
81
 
82
- for (const tag of properties.rule.allTags) {
82
+ for (const tag of properties.rule.tags) {
83
83
  if (properties.rule.excludedTags.includes(tag)) {
84
84
  cssModifiers[tag] = "negative";
85
85
  continue;
@@ -1,12 +1,21 @@
1
1
  <template>
2
- <ul>
3
- <li
4
- v-for="rule in rules"
5
- :key="rule.id"
6
- class="ffun-body-list-entry">
7
- <rule-for-list :rule="rule" />
8
- </li>
9
- </ul>
2
+ <template v-if="rules && rules.length > 0">
3
+ <ul>
4
+ <li
5
+ v-for="rule in rules"
6
+ :key="rule.id"
7
+ class="ffun-body-list-entry">
8
+ <rule-for-list :rule="rule" />
9
+ </li>
10
+ </ul>
11
+ </template>
12
+ <template v-else>
13
+ <p
14
+ v-if="!loading"
15
+ class="ffun-info-common"
16
+ >No rules to show.</p
17
+ >
18
+ </template>
10
19
  </template>
11
20
 
12
21
  <script lang="ts" setup>
@@ -15,5 +24,5 @@
15
24
  import * as e from "@/logic/enums";
16
25
  import {useGlobalSettingsStore} from "@/stores/globalSettings";
17
26
 
18
- defineProps<{rules: Array<t.Rule>}>();
27
+ defineProps<{rules: Array<t.Rule> | null; loading: boolean}>();
19
28
  </script>
@@ -22,8 +22,6 @@
22
22
 
23
23
  const globalSettings = useGlobalSettingsStore();
24
24
 
25
- globalSettings.mainPanelMode = e.MainPanelMode.Settings;
26
-
27
25
  const period = computed(() => {
28
26
  return properties.usage.intervalStartedAt.toLocaleString("default", {month: "long", year: "numeric"});
29
27
  });
@@ -34,6 +34,12 @@
34
34
  >Hide feeds</button
35
35
  >
36
36
 
37
+ <a
38
+ :href="router.resolve({name: 'public-collection', params: {collectionSlug: collection.slug}}).href"
39
+ class="ffun-normal-link ml-2"
40
+ >Read news in the collection</a
41
+ >
42
+
37
43
  <collections-subscribing-progress
38
44
  :loading="loading"
39
45
  :loaded="loaded"
@@ -43,6 +49,7 @@
43
49
 
44
50
  <script lang="ts" setup>
45
51
  import {computed, ref} from "vue";
52
+ import {useRouter} from "vue-router";
46
53
  import type * as t from "@/logic/types";
47
54
  import * as e from "@/logic/enums";
48
55
  import * as api from "@/logic/api";
@@ -52,6 +59,8 @@
52
59
  import {useGlobalSettingsStore} from "@/stores/globalSettings";
53
60
  import {useCollectionsStore} from "@/stores/collections";
54
61
 
62
+ const router = useRouter();
63
+
55
64
  const properties = defineProps<{
56
65
  collectionId: t.CollectionId;
57
66
  }>();
@@ -0,0 +1,63 @@
1
+ <template>
2
+ <div class="ffun-info-good">
3
+ <h4>Hi there!</h4>
4
+
5
+ <p>
6
+ Welcome to <strong>Feeds Fun</strong> and our curated <strong>{{ collection.name }}</strong> news collection!
7
+ </p>
8
+
9
+ <p>
10
+ <strong>Feeds Fun</strong> ranks news based on tags, so you always see what matters most. We offer public
11
+ collections to showcase our tagging system in action. Hope you'll enjoy it!
12
+ </p>
13
+
14
+ <p v-if="tag1Uid && tag2Uid">
15
+ Try out the tag filters on the left, for example, filter news by tag
16
+ <entry-tag
17
+ :uid="tag1Uid"
18
+ css-modifier="neutral"
19
+ :count="tag1Count" />
20
+
21
+ or even by a more specific tag
22
+
23
+ <entry-tag
24
+ :uid="tag2Uid"
25
+ css-modifier="neutral"
26
+ :count="tag2Count" />
27
+ </p>
28
+
29
+ <p>
30
+ If you like the results, <a :href="router.resolve({name: 'main'}).href">register</a> to create your own scoring
31
+ rules and automatically prioritize the news you’re most interested in.
32
+ </p>
33
+
34
+ <p> You can find more about scoring rules on the <a :href="router.resolve({name: 'main'}).href">main page</a>. </p>
35
+
36
+ <p><strong>All news in this collection is always up-to-date and tagged.</strong> </p>
37
+ </div>
38
+ </template>
39
+
40
+ <script lang="ts" setup>
41
+ import {computed} from "vue";
42
+ import {useRouter} from "vue-router";
43
+ import type * as t from "@/logic/types";
44
+ import {useCollectionsStore} from "@/stores/collections";
45
+
46
+ const properties = defineProps<{
47
+ tag1Uid: string | null;
48
+ tag1Count: number;
49
+ tag2Uid: string | null;
50
+ tag2Count: number;
51
+ collectionId: t.CollectionId;
52
+ }>();
53
+
54
+ const router = useRouter();
55
+
56
+ const collections = useCollectionsStore();
57
+
58
+ const collection = computed(() => {
59
+ return collections.collections[properties.collectionId];
60
+ });
61
+ </script>
62
+
63
+ <style></style>
@@ -0,0 +1,43 @@
1
+ <template>
2
+ <select
3
+ class="ffun-input"
4
+ @change="updateCollection($event)">
5
+ <option
6
+ v-for="collection of collections.collectionsOrdered"
7
+ :value="collection.id"
8
+ :selected="collection.id === collectionId">
9
+ {{ collection.name }}
10
+ </option>
11
+ </select>
12
+ </template>
13
+
14
+ <script lang="ts" setup>
15
+ import * as e from "@/logic/enums";
16
+ import type * as t from "@/logic/types";
17
+ import {computed, ref, onUnmounted, watch, provide} from "vue";
18
+ import {useRoute, useRouter} from "vue-router";
19
+ import {useCollectionsStore} from "@/stores/collections";
20
+
21
+ const collections = useCollectionsStore();
22
+
23
+ const route = useRoute();
24
+ const router = useRouter();
25
+
26
+ const properties = defineProps<{collectionId: t.CollectionId}>();
27
+
28
+ const collection = computed(() => collections.collections[properties.collectionId]);
29
+
30
+ function updateCollection(event: Event) {
31
+ const target = event.target as HTMLSelectElement;
32
+
33
+ const targetCollection = collections.collections[target.value as t.CollectionId];
34
+
35
+ router.push({
36
+ replace: true,
37
+ name: route.name,
38
+ params: {collectionSlug: targetCollection.slug, tags: []}
39
+ });
40
+ }
41
+ </script>
42
+
43
+ <style></style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="text-center max-w-3xl mx-auto my-3 md:my-5 space-y-3 md:space-y-5">
2
+ <div class="text-center max-w-3xl mx-auto my-5 space-y-5">
3
3
  <slot></slot>
4
4
  </div>
5
5
  </template>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="flex flex-col items-stretch rounded-xl overflow-hidden min-h-28 max-h-28 mx-2">
2
+ <div class="flex flex-col items-stretch rounded-xl overflow-hidden min-h-32 max-h-32 mx-2">
3
3
  <div class="bg-blue-100 py-1 items-center text-xl font-medium">
4
4
  <slot name="caption" />
5
5
  </div>
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <!-- TODO: Hide when loading new news from the server -->
3
+ <!-- Currently, after changing the period, this message does not disappear -->
4
+ <!-- until the backend returns a new response -->
5
+ <!-- It confuses users because the period size is changing in the text at the beginning of the request. -->
6
+ <div
7
+ v-if="allEntriesAreOlderThanPeriod"
8
+ class="ffun-info-common">
9
+ <p> We have not found any news that is newer than {{ period.text }}, so we loaded some older ones. </p>
10
+ </div>
11
+ </template>
12
+
13
+ <script lang="ts" setup>
14
+ import {computed, ref, onUnmounted, watch, provide} from "vue";
15
+ import {useRoute, useRouter} from "vue-router";
16
+ import {computedAsync} from "@vueuse/core";
17
+ import * as api from "@/logic/api";
18
+ import * as tagsFilterState from "@/logic/tagsFilterState";
19
+ import * as e from "@/logic/enums";
20
+ import * as utils from "@/logic/utils";
21
+ import type * as t from "@/logic/types";
22
+ import {useGlobalSettingsStore} from "@/stores/globalSettings";
23
+ import {useEntriesStore} from "@/stores/entries";
24
+ import _ from "lodash";
25
+
26
+ const entriesStore = useEntriesStore();
27
+
28
+ const properties = defineProps<{
29
+ entries: t.EntryId[];
30
+ period: e.LastEntriesPeriodProperty;
31
+ }>();
32
+
33
+ const allEntriesAreOlderThanPeriod = computed(() => {
34
+ if (entriesStore.loading) {
35
+ return false;
36
+ }
37
+
38
+ if (properties.entries.length == 0) {
39
+ return false;
40
+ }
41
+
42
+ return properties.entries.every((entryId) => {
43
+ const entry = entriesStore.entries[entryId];
44
+ return entry.publishedAt.getTime() < Date.now() - properties.period.seconds * 1000;
45
+ });
46
+ });
47
+ </script>
@@ -4,7 +4,7 @@
4
4
  href="/api/docs"
5
5
  target="_blank"
6
6
  class="ffun-page-header-link"
7
- @click="events.socialLinkClicked({linkType: 'api'})"
7
+ @click="events.socialLinkClicked({linkType: 'api', view: eventsView})"
8
8
  >API</a
9
9
  >
10
10
 
@@ -13,7 +13,7 @@
13
13
  :href="settings.blog"
14
14
  target="_blank"
15
15
  class="ffun-page-header-link"
16
- @click="events.socialLinkClicked({linkType: 'blog'})"
16
+ @click="events.socialLinkClicked({linkType: 'blog', view: eventsView})"
17
17
  >Blog</a
18
18
  >
19
19
 
@@ -23,7 +23,7 @@
23
23
  target="_blank"
24
24
  class="ffun-page-header-link text-xl align-middle"
25
25
  title="Reddit"
26
- @click="events.socialLinkClicked({linkType: 'reddit'})"
26
+ @click="events.socialLinkClicked({linkType: 'reddit', view: eventsView})"
27
27
  ><i class="ti ti-brand-reddit"></i
28
28
  ></a>
29
29
 
@@ -33,7 +33,7 @@
33
33
  target="_blank"
34
34
  class="ffun-page-header-link text-xl align-middle"
35
35
  title="Discord"
36
- @click="events.socialLinkClicked({linkType: 'discord'})"
36
+ @click="events.socialLinkClicked({linkType: 'discord', view: eventsView})"
37
37
  ><i class="ti ti-brand-discord"></i
38
38
  ></a>
39
39
 
@@ -43,16 +43,21 @@
43
43
  target="_blank"
44
44
  class="ffun-page-header-link text-xl align-middle"
45
45
  title="GitHub"
46
- @click="events.socialLinkClicked({linkType: 'github'})">
46
+ @click="events.socialLinkClicked({linkType: 'github', view: eventsView})">
47
47
  <i class="ti ti-brand-github"></i
48
48
  ></a>
49
49
  </template>
50
50
 
51
51
  <script lang="ts" setup>
52
- import {ref, computed, useSlots, onMounted, watch, watchEffect} from "vue";
52
+ import {inject} from "vue";
53
53
 
54
54
  import * as events from "@/logic/events";
55
55
  import * as settings from "@/logic/settings";
56
+ import * as asserts from "@/logic/asserts";
56
57
 
57
58
  const properties = defineProps<{showApi: boolean}>();
59
+
60
+ const eventsView = inject<events.EventsViewName>("eventsViewName");
61
+
62
+ asserts.defined(eventsView);
58
63
  </script>
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <a
3
+ href="#"
4
+ class="ffun-page-header-link text-2xl align-middle flex-none pb-0 relative"
5
+ :title="title"
6
+ @click.prevent="onClick">
7
+ <i
8
+ v-if="globalSettings.showSidebar"
9
+ class="ti ti-layout-sidebar-left-collapse"></i>
10
+ <i
11
+ v-else
12
+ class="ti ti-layout-sidebar-left-expand"></i>
13
+
14
+ <span
15
+ v-if="showPoint"
16
+ class="absolute top-0 right-0 h-2 w-2 rounded-full bg-red-500 border border-white"></span>
17
+ </a>
18
+ </template>
19
+
20
+ <script lang="ts" setup>
21
+ import {ref, computed, useSlots, onMounted, watch, watchEffect, inject} from "vue";
22
+ import {useRouter, RouterLink, RouterView} from "vue-router";
23
+ import {useGlobalSettingsStore} from "@/stores/globalSettings";
24
+ import {useGlobalState} from "@/stores/globalState";
25
+ import {useSupertokens} from "@/stores/supertokens";
26
+ import * as asserts from "@/logic/asserts";
27
+ import * as events from "@/logic/events";
28
+ import * as e from "@/logic/enums";
29
+ import * as settings from "@/logic/settings";
30
+
31
+ const globalSettings = useGlobalSettingsStore();
32
+
33
+ const eventsView = inject<events.EventsViewName>("eventsViewName");
34
+
35
+ asserts.defined(eventsView);
36
+
37
+ const title = computed(() => {
38
+ return globalSettings.showSidebar ? "Hide sidebar" : "Show sidebar";
39
+ });
40
+
41
+ const showPoint = computed(() => {
42
+ return !globalSettings.showSidebar && globalSettings.showSidebarPoint;
43
+ });
44
+
45
+ function onClick() {
46
+ globalSettings.showSidebar = !globalSettings.showSidebar;
47
+
48
+ asserts.defined(eventsView);
49
+
50
+ events.sidebarStateChanged({
51
+ view: eventsView,
52
+ subEvent: globalSettings.showSidebar ? "show" : "hide",
53
+ source: "top_sidebar_button"
54
+ });
55
+ }
56
+ </script>
@@ -19,8 +19,10 @@
19
19
  const tagsStore = useTagsStore();
20
20
 
21
21
  const tagsStates = inject<Ref<tagsFilterState.Storage>>("tagsStates");
22
+ const eventsView = inject<events.EventsViewName>("eventsViewName");
22
23
 
23
24
  asserts.defined(tagsStates);
25
+ asserts.defined(eventsView);
24
26
 
25
27
  const properties = defineProps<{
26
28
  uid: string;
@@ -57,14 +59,13 @@
57
59
  return result;
58
60
  });
59
61
 
60
- const changeSource = "entry_record";
61
-
62
62
  async function onClick() {
63
63
  asserts.defined(tagsStates);
64
+ asserts.defined(eventsView);
64
65
 
65
66
  let changeInfo = tagsStates.value.onTagClicked({tag: properties.uid});
66
67
 
67
- await events.tagStateChanged({tag: properties.uid, source: changeSource, ...changeInfo});
68
+ await events.tagStateChanged({tag: properties.uid, view: eventsView, source: "entry_record", ...changeInfo});
68
69
  }
69
70
 
70
71
  const tooltip = computed(() => {
@@ -35,15 +35,16 @@
35
35
  const tagsStore = useTagsStore();
36
36
 
37
37
  const tagsStates = inject<Ref<tagsFilterState.Storage>>("tagsStates");
38
+ const eventsView = inject<events.EventsViewName>("eventsViewName");
38
39
 
39
40
  asserts.defined(tagsStates);
41
+ asserts.defined(eventsView);
40
42
 
41
43
  const properties = defineProps<{
42
44
  uid: string;
43
45
  count?: number | null;
44
46
  showCount: boolean;
45
47
  showSwitch: boolean;
46
- changeSource: "news_tags_filter" | "rules_tags_filter";
47
48
  }>();
48
49
 
49
50
  const tagInfo = computed(() => {
@@ -78,18 +79,20 @@
78
79
 
79
80
  async function onClick() {
80
81
  asserts.defined(tagsStates);
82
+ asserts.defined(eventsView);
81
83
 
82
84
  let changeInfo = tagsStates.value.onTagClicked({tag: properties.uid});
83
85
 
84
- await events.tagStateChanged({tag: properties.uid, source: properties.changeSource, ...changeInfo});
86
+ await events.tagStateChanged({tag: properties.uid, view: eventsView, source: "tags_filter", ...changeInfo});
85
87
  }
86
88
 
87
89
  async function onRevers() {
88
90
  asserts.defined(tagsStates);
91
+ asserts.defined(eventsView);
89
92
 
90
93
  let changeInfo = tagsStates.value.onTagReversed({tag: properties.uid});
91
94
 
92
- await events.tagStateChanged({tag: properties.uid, source: properties.changeSource, ...changeInfo});
95
+ await events.tagStateChanged({tag: properties.uid, view: eventsView, source: "tags_filter", ...changeInfo});
93
96
  }
94
97
 
95
98
  const switchTooltip = computed(() => {
@@ -18,8 +18,10 @@
18
18
  const tagsStore = useTagsStore();
19
19
 
20
20
  const tagsStates = inject<Ref<tagsFilterState.Storage>>("tagsStates");
21
+ const eventsView = inject<events.EventsViewName>("eventsViewName");
21
22
 
22
23
  asserts.defined(tagsStates);
24
+ asserts.defined(eventsView);
23
25
 
24
26
  const properties = defineProps<{
25
27
  uid: string;
@@ -55,13 +57,12 @@
55
57
  return result;
56
58
  });
57
59
 
58
- const changeSource = "rule_record";
59
-
60
60
  async function onClick() {
61
61
  asserts.defined(tagsStates);
62
+ asserts.defined(eventsView);
62
63
 
63
64
  let changeInfo = tagsStates.value.onTagClicked({tag: properties.uid});
64
65
 
65
- await events.tagStateChanged({tag: properties.uid, source: changeSource, ...changeInfo});
66
+ await events.tagStateChanged({tag: properties.uid, view: eventsView, source: "rule_record", ...changeInfo});
66
67
  }
67
68
  </script>
@@ -11,13 +11,23 @@
11
11
  :uid="tag"
12
12
  :count="tags[tag] ?? 0"
13
13
  :show-switch="true"
14
- :show-count="false"
15
- :change-source="changeSource" />
14
+ :show-count="false" />
16
15
  </li>
17
16
  </ul>
18
17
 
19
18
  <rule-constructor v-if="showCreateRule" />
20
19
 
20
+ <p
21
+ v-if="showRegistrationInvitation"
22
+ class="ffun-info-common">
23
+ <a
24
+ href="#"
25
+ @click.prevent="router.push({name: 'main'})"
26
+ >Register</a
27
+ >
28
+ to score news by tags!
29
+ </p>
30
+
21
31
  <input
22
32
  class="ffun-input w-full"
23
33
  type="text"
@@ -35,8 +45,7 @@
35
45
  :uid="tag"
36
46
  :count="tags[tag]"
37
47
  :show-switch="false"
38
- :show-count="true"
39
- :change-source="changeSource" />
48
+ :show-count="true" />
40
49
  </li>
41
50
  </ul>
42
51
 
@@ -53,6 +62,7 @@
53
62
 
54
63
  <script lang="ts" setup>
55
64
  import {computed, ref, inject} from "vue";
65
+ import {useRoute, useRouter} from "vue-router";
56
66
  import type {Ref} from "vue";
57
67
  import {useTagsStore} from "@/stores/tags";
58
68
  import type * as tagsFilterState from "@/logic/tagsFilterState";
@@ -60,6 +70,8 @@
60
70
  import * as api from "@/logic/api";
61
71
  import {useGlobalSettingsStore} from "@/stores/globalSettings";
62
72
 
73
+ const router = useRouter();
74
+
63
75
  const tagsStore = useTagsStore();
64
76
 
65
77
  const globalSettings = useGlobalSettingsStore();
@@ -72,7 +84,7 @@
72
84
  const properties = defineProps<{
73
85
  tags: {[key: string]: number};
74
86
  showCreateRule?: boolean;
75
- changeSource: "news_tags_filter" | "rules_tags_filter";
87
+ showRegistrationInvitation?: boolean;
76
88
  }>();
77
89
 
78
90
  const showFromStart = ref(25);