mirror of
https://github.com/gotson/komga.git
synced 2025-12-09 18:16:55 +01:00
announcements
This commit is contained in:
parent
021d12b4f0
commit
598db5a814
12 changed files with 192 additions and 20 deletions
16
next-ui/src/colada/mutations/mark-announcements-read.ts
Normal file
16
next-ui/src/colada/mutations/mark-announcements-read.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import {defineMutation, useMutation, useQueryCache} from '@pinia/colada'
|
||||
import {komgaClient} from '@/api/komga-client'
|
||||
|
||||
export const useMarkAnnouncementsRead = defineMutation(() => {
|
||||
const queryCache = useQueryCache()
|
||||
return useMutation({
|
||||
mutation: (announcementIds: string[]) =>
|
||||
komgaClient.PUT('/api/v1/announcements', {body: announcementIds}),
|
||||
onSuccess: () => {
|
||||
queryCache.invalidateQueries({key: ['announcements']})
|
||||
},
|
||||
onError: (error) => {
|
||||
console.log('announcements mark read error', error)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import {useQuery} from '@pinia/colada'
|
||||
import {defineQuery, useQuery} from '@pinia/colada'
|
||||
import {komgaClient} from '@/api/komga-client'
|
||||
import type {ActuatorInfo} from '@/types/Actuator'
|
||||
|
||||
export function useActuatorInfo() {
|
||||
export const useActuatorInfo = defineQuery(() => {
|
||||
return useQuery({
|
||||
key: () => ['actuator-info'],
|
||||
query: () => komgaClient.GET('/actuator/info')
|
||||
|
|
@ -12,4 +12,4 @@ export function useActuatorInfo() {
|
|||
staleTime: 60 * 60 * 1000,
|
||||
gcTime: false,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
|||
21
next-ui/src/colada/queries/announcements.ts
Normal file
21
next-ui/src/colada/queries/announcements.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import {defineQuery, useQuery} from '@pinia/colada'
|
||||
import {komgaClient} from '@/api/komga-client'
|
||||
|
||||
export const useAnnouncements = defineQuery(() => {
|
||||
const {data, ...rest} = useQuery({
|
||||
key: () => ['announcements'],
|
||||
query: () => komgaClient.GET('/api/v1/announcements')
|
||||
// unwrap the openapi-fetch structure on success
|
||||
.then((res) => res.data),
|
||||
// 1 hour
|
||||
staleTime: 60 * 60 * 1000,
|
||||
gcTime: false,
|
||||
})
|
||||
|
||||
const unreadCount = computed(() => data.value?.items
|
||||
?.filter((x) => false == x._komga?.read)
|
||||
?.length || 0
|
||||
)
|
||||
|
||||
return {...rest, data, unreadCount}
|
||||
})
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import {useQuery} from '@pinia/colada'
|
||||
import {defineQuery, useQuery} from '@pinia/colada'
|
||||
import {komgaClient} from '@/api/komga-client'
|
||||
|
||||
export function useAppReleases() {
|
||||
export const useAppReleases = defineQuery(() => {
|
||||
return useQuery({
|
||||
key: () => ['app-releases'],
|
||||
query: () => komgaClient.GET('/api/v1/releases')
|
||||
|
|
@ -11,4 +11,4 @@ export function useAppReleases() {
|
|||
staleTime: 60 * 60 * 1000,
|
||||
gcTime: false,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import {useQuery} from '@pinia/colada'
|
||||
import {defineQuery, useQuery} from '@pinia/colada'
|
||||
import {komgaClient} from '@/api/komga-client'
|
||||
|
||||
export function useCurrentUser() {
|
||||
export const useCurrentUser = defineQuery(() => {
|
||||
return useQuery({
|
||||
key: () => ['current-user'],
|
||||
query: () => komgaClient.GET('/api/v2/users/me')
|
||||
|
|
@ -12,4 +12,4 @@ export function useCurrentUser() {
|
|||
gcTime: false,
|
||||
autoRefetch: true,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
|||
1
next-ui/src/components.d.ts
vendored
1
next-ui/src/components.d.ts
vendored
|
|
@ -21,6 +21,7 @@ declare module 'vue' {
|
|||
AppFooter: typeof import('./components/AppFooter.vue')['default']
|
||||
BuidVersion: typeof import('./components/BuidVersion.vue')['default']
|
||||
BuildCommit: typeof import('./components/BuildCommit.vue')['default']
|
||||
BuildVersion: typeof import('./components/BuildVersion.vue')['default']
|
||||
HelloWorld: typeof import('./components/HelloWorld.vue')['default']
|
||||
LoginForm: typeof import('./components/LoginForm.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<div class="d-flex align-center text-caption text-medium-emphasis pa-2">
|
||||
<div class="d-flex ms-auto">
|
||||
<BuildCommit class="me-2" />
|
||||
<BuidVersion />
|
||||
<BuildVersion />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,25 @@
|
|||
<template>
|
||||
<v-list-group value="Server">
|
||||
<v-list-group
|
||||
ref="group"
|
||||
value="Server"
|
||||
>
|
||||
<template #activator="{ props }">
|
||||
<v-list-item
|
||||
v-bind="props"
|
||||
title="Server"
|
||||
prepend-icon="mdi-cog"
|
||||
/>
|
||||
>
|
||||
<template #prepend>
|
||||
<v-badge
|
||||
:model-value="unreadCount > 0 && !$refs.group.isOpen"
|
||||
dot
|
||||
floating
|
||||
color="info"
|
||||
>
|
||||
<v-icon>mdi-cog</v-icon>
|
||||
</v-badge>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</template>
|
||||
|
||||
<v-list-item
|
||||
|
|
@ -24,13 +38,30 @@
|
|||
to="/server/metrics"
|
||||
title="Metrics"
|
||||
/>
|
||||
|
||||
<v-list-item
|
||||
to="/server/announcements"
|
||||
title="Announcements"
|
||||
/>
|
||||
>
|
||||
<template #append>
|
||||
<v-badge
|
||||
:model-value="unreadCount > 0"
|
||||
:content="unreadCount"
|
||||
inline
|
||||
color="info"
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item
|
||||
to="/server/updates"
|
||||
title="Updates"
|
||||
/>
|
||||
</v-list-group>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {useAnnouncements} from '@/colada/queries/announcements.ts'
|
||||
|
||||
const {unreadCount} = useAnnouncements()
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import {useAppReleases} from '@/colada/queries/app-releases.ts'
|
|||
import {useBuildVersion} from '@/composables/buid-version.ts'
|
||||
|
||||
export function useLatestVersion() {
|
||||
const {data, } = useAppReleases()
|
||||
const {data } = useAppReleases()
|
||||
|
||||
const {buildVersion} = useBuildVersion()
|
||||
const latestRelease = computed(() => data.value?.find(x => x.latest))
|
||||
|
|
|
|||
|
|
@ -1,11 +1,114 @@
|
|||
<template>
|
||||
<h1>Announcements</h1>
|
||||
<v-alert
|
||||
v-if="error"
|
||||
type="error"
|
||||
variant="tonal"
|
||||
>
|
||||
Error loading data
|
||||
</v-alert>
|
||||
|
||||
<template v-if="data">
|
||||
<div
|
||||
v-for="(item, index) in data.items"
|
||||
:key="index"
|
||||
>
|
||||
<v-row
|
||||
justify="space-between"
|
||||
align="center"
|
||||
>
|
||||
<v-col cols="auto">
|
||||
<div class="ml-n2">
|
||||
<a
|
||||
:href="item.url"
|
||||
target="_blank"
|
||||
class="text-h3 font-weight-medium link-underline"
|
||||
>{{ item.title }}</a>
|
||||
</div>
|
||||
<div class="mt-2 subtitle-1">
|
||||
{{ item.date_modified }}
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col cols="auto">
|
||||
<v-tooltip
|
||||
text="Mark as read"
|
||||
:disabled="item._komga.read"
|
||||
>
|
||||
<template #activator="{ props }">
|
||||
<v-fab
|
||||
v-bind="props"
|
||||
icon="mdi-check"
|
||||
elevation="3"
|
||||
color="success"
|
||||
variant="tonal"
|
||||
size="small"
|
||||
:disabled="item._komga.read"
|
||||
@click="markRead(item.id)"
|
||||
/>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div
|
||||
class="announcement"
|
||||
v-html="item.content_html"
|
||||
/>
|
||||
<!-- eslint-enable vue/no-v-html -->
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-divider
|
||||
v-if="index != data.items.length - 1"
|
||||
class="my-8"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<v-fab
|
||||
:active="unreadCount > 0"
|
||||
color="success"
|
||||
location="bottom right"
|
||||
app
|
||||
icon="mdi-check-all"
|
||||
size="x-large"
|
||||
class="ms-n5"
|
||||
@click="markAllRead()"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//
|
||||
import {useAnnouncements} from '@/colada/queries/announcements.ts'
|
||||
import {useMarkAnnouncementsRead} from '@/colada/mutations/mark-announcements-read.ts'
|
||||
|
||||
const {data, error, unreadCount} = useAnnouncements()
|
||||
|
||||
const {mutate} = useMarkAnnouncementsRead()
|
||||
|
||||
function markAllRead() {
|
||||
mutate(data.value.items.map(x => x.id))
|
||||
}
|
||||
|
||||
function markRead(id: string) {
|
||||
mutate([id])
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.announcement p {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.announcement ul {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
.announcement a {
|
||||
color: var(--v-anchor-base);
|
||||
}
|
||||
</style>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
requiresRole: ADMIN
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
<v-col cols="12">
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div
|
||||
class="releases"
|
||||
class="release"
|
||||
v-html="marked(release.description)"
|
||||
/>
|
||||
<!-- eslint-enable vue/no-v-html -->
|
||||
|
|
@ -103,15 +103,15 @@ const {isLatestVersion, latestRelease: latest} = useLatestVersion()
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.releases p {
|
||||
.release p {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.releases ul {
|
||||
.release ul {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
.releases a {
|
||||
.release a {
|
||||
color: var(--v-anchor-base);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in a new issue