feat: various formatting and type improvements
This commit is contained in:
parent
f9a825b577
commit
af464668b3
|
@ -21,7 +21,7 @@
|
|||
</BaseButton>
|
||||
|
||||
<list-settings-dropdown
|
||||
v-if="canWriteCurrentList && currentList.id !== -1"
|
||||
v-if="canWriteCurrentList && currentList.id !== LIST_ID.FAVORITES"
|
||||
class="list-title-dropdown"
|
||||
:list="currentList"
|
||||
>
|
||||
|
@ -88,6 +88,7 @@
|
|||
import {computed} from 'vue'
|
||||
|
||||
import {RIGHTS as Rights} from '@/constants/rights'
|
||||
import {LIST_ID} from '@/constants/lists'
|
||||
|
||||
import ListSettingsDropdown from '@/components/list/list-settings-dropdown.vue'
|
||||
import Dropdown from '@/components/misc/dropdown.vue'
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
<div
|
||||
:class="{'is-visible': background}"
|
||||
class="app-container-background background-fade-in d-print-none"
|
||||
:style="{'background-image': background && `url(${background})`}"></div>
|
||||
:style="{'background-image': background && `url(${background})`}">
|
||||
</div>
|
||||
<navigation class="d-print-none"/>
|
||||
<main
|
||||
class="app-content"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export const LIST_ID = {
|
||||
FAVORITES: -1
|
||||
} as const
|
|
@ -0,0 +1,5 @@
|
|||
export const NAMESPACE_ID = {
|
||||
SHARED_LIST: -1,
|
||||
FAVORITES: -2,
|
||||
FILTERS: -3,
|
||||
} as const;
|
|
@ -1,8 +1,10 @@
|
|||
import {i18n} from '@/i18n'
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
|
||||
import {LIST_ID} from '@/constants/lists'
|
||||
|
||||
export function getListTitle(l: IList) {
|
||||
if (l.id === -1) {
|
||||
if (l.id === LIST_ID.FAVORITES) {
|
||||
return i18n.global.t('list.pseudo.favorites.title')
|
||||
}
|
||||
return l.title
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import {i18n} from '@/i18n'
|
||||
import type {INamespace} from '@/modelTypes/INamespace'
|
||||
|
||||
import {NAMESPACE_ID} from "@/constants/namespaces"
|
||||
|
||||
export const getNamespaceTitle = (n: INamespace) => {
|
||||
if (n.id === -1) {
|
||||
if (n.id === NAMESPACE_ID.SHARED_LIST) {
|
||||
return i18n.global.t('namespace.pseudo.sharedLists.title')
|
||||
}
|
||||
if (n.id === -2) {
|
||||
if (n.id === NAMESPACE_ID.FAVORITES) {
|
||||
return i18n.global.t('namespace.pseudo.favorites.title')
|
||||
}
|
||||
if (n.id === -3) {
|
||||
if (n.id === NAMESPACE_ID.FILTERS) {
|
||||
return i18n.global.t('namespace.pseudo.savedFilters.title')
|
||||
}
|
||||
return n.title
|
||||
|
|
|
@ -16,10 +16,10 @@ export interface IList extends IAbstract {
|
|||
hexColor: string
|
||||
identifier: string
|
||||
backgroundInformation: unknown | null // FIXME: improve type
|
||||
backgroundBlurHash: string
|
||||
isFavorite: boolean
|
||||
subscription: ISubscription
|
||||
position: number
|
||||
backgroundBlurHash: string
|
||||
|
||||
created: Date
|
||||
updated: Date
|
||||
|
|
|
@ -300,7 +300,6 @@ const router = createRouter({
|
|||
meta: {
|
||||
showAsModal: true,
|
||||
},
|
||||
props: route => ({ listId: Number(route.params.listId as string) }),
|
||||
},
|
||||
{
|
||||
path: '/lists/:listId/settings/share',
|
||||
|
|
|
@ -2,7 +2,6 @@ import {AuthenticatedHTTPFactory} from '@/helpers/fetcher'
|
|||
import type {Method} from 'axios'
|
||||
|
||||
import {objectToSnakeCase} from '@/helpers/case'
|
||||
import AbstractModel from '@/models/abstractModel'
|
||||
import type {IAbstract} from '@/modelTypes/IAbstract'
|
||||
import type {Right} from '@/constants/rights'
|
||||
|
||||
|
@ -185,14 +184,14 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
|
|||
* The modelFactory returns a model from an object.
|
||||
* This one here is the default one, usually the service definitions for a model will override this.
|
||||
*/
|
||||
modelFactory(data : Partial<Model>) {
|
||||
return data as Model
|
||||
modelFactory(data : Partial<Model> = {}) {
|
||||
return {...data} as Model
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the model factory for get requests.
|
||||
*/
|
||||
modelGetFactory(data : Partial<Model>) {
|
||||
modelGetFactory(data : Partial<Model> = {}) {
|
||||
return this.modelFactory(data)
|
||||
}
|
||||
|
||||
|
@ -270,7 +269,7 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
|
|||
* This is a more abstract implementation which only does a get request.
|
||||
* Services which need more flexibility can use this.
|
||||
*/
|
||||
async getM(url : string, model : Model = new AbstractModel({}), params: Record<string, unknown> = {}) {
|
||||
async getM(url : string, model : Model = this.modelGetFactory(), params: Record<string, unknown> = {}) {
|
||||
const cancel = this.setLoading()
|
||||
|
||||
model = this.beforeGet(model)
|
||||
|
@ -293,7 +292,7 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
|
|||
responseType: 'blob',
|
||||
data,
|
||||
})
|
||||
return window.URL.createObjectURL(new Blob([response.data]))
|
||||
return URL.createObjectURL(new Blob([response.data]))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -303,7 +302,7 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
|
|||
* @param params Optional query parameters
|
||||
* @param page The page to get
|
||||
*/
|
||||
async getAll(model : Model = new AbstractModel({}), params = {}, page = 1) {
|
||||
async getAll(model : Model = this.modelFactory(), params = {}, page = 1) {
|
||||
if (this.paths.getAll === '') {
|
||||
throw new Error('This model is not able to get data.')
|
||||
}
|
||||
|
|
|
@ -25,6 +25,6 @@ export default class BackgroundUnsplashService extends AbstractService<IBackgrou
|
|||
method: 'GET',
|
||||
responseType: 'blob',
|
||||
})
|
||||
return window.URL.createObjectURL(new Blob([response.data]))
|
||||
return URL.createObjectURL(new Blob([response.data]))
|
||||
}
|
||||
}
|
|
@ -3,20 +3,21 @@ import {useRouter} from 'vue-router'
|
|||
import {useI18n} from 'vue-i18n'
|
||||
import type {MaybeRef} from '@vueuse/core'
|
||||
|
||||
import {success} from '@/message'
|
||||
|
||||
import AbstractService from './abstractService'
|
||||
import ListModel from '@/models/list'
|
||||
import TaskService from './task'
|
||||
import {colorFromHex} from '@/helpers/color/colorFromHex'
|
||||
import ListDuplicateModel from '@/models/listDuplicateModel'
|
||||
import ListDuplicateService from './listDuplicateService'
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
import type {INamespace} from '@/modelTypes/INamespace'
|
||||
|
||||
import {useListStore} from '@/stores/lists'
|
||||
import {useNamespaceStore} from '@/stores/namespaces'
|
||||
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
import type {INamespace} from '@/modelTypes/INamespace'
|
||||
import AbstractService from '@/services/abstractService'
|
||||
import TaskService from '@/services/task'
|
||||
import ListDuplicateService from '@/services/listDuplicateService'
|
||||
|
||||
import ListModel from '@/models/list'
|
||||
import ListDuplicateModel from '@/models/listDuplicateModel'
|
||||
|
||||
import {colorFromHex} from '@/helpers/color/colorFromHex'
|
||||
import {success} from '@/message'
|
||||
|
||||
export default class ListService extends AbstractService<IList> {
|
||||
constructor() {
|
||||
|
@ -48,7 +49,7 @@ export default class ListService extends AbstractService<IList> {
|
|||
return model
|
||||
}
|
||||
|
||||
beforeCreate(list) {
|
||||
beforeCreate(list: IList) {
|
||||
list.hexColor = colorFromHex(list.hexColor)
|
||||
return list
|
||||
}
|
||||
|
@ -70,7 +71,7 @@ export default class ListService extends AbstractService<IList> {
|
|||
const cancel = this.setLoading()
|
||||
|
||||
try {
|
||||
const response = await this.http.delete(`/lists/${list.id}/background`, list)
|
||||
const response = await this.http.delete<IList>(`/lists/${list.id}/background`)
|
||||
return response.data
|
||||
} finally {
|
||||
cancel()
|
||||
|
|
|
@ -4,7 +4,7 @@ import {defineStore, acceptHMRUpdate} from 'pinia'
|
|||
import {getBlobFromBlurHash} from '@/helpers/getBlobFromBlurHash'
|
||||
|
||||
import ListModel from '@/models/list'
|
||||
import ListService from '../services/list'
|
||||
import ListService from '@/services/list'
|
||||
import {checkAndSetApiUrl} from '@/helpers/checkAndSetApiUrl'
|
||||
|
||||
import {useMenuActive} from '@/composables/useMenuActive'
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import {watch, reactive, shallowReactive, unref, toRefs, readonly, ref, computed} from 'vue'
|
||||
import type {MaybeRef} from '@vueuse/core'
|
||||
import {acceptHMRUpdate, defineStore} from 'pinia'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
|
||||
import ListService from '@/services/list'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {removeListFromHistory} from '@/modules/listHistory'
|
||||
import {createNewIndexer} from '@/indexes'
|
||||
import {useNamespaceStore} from './namespaces'
|
||||
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
|
||||
import type {MaybeRef} from '@vueuse/core'
|
||||
import {LIST_ID} from '@/constants/lists'
|
||||
import {NAMESPACE_ID} from "@/constants/namespaces"
|
||||
|
||||
import ListModel from '@/models/list'
|
||||
import {success} from '@/message'
|
||||
import {useNamespaceStore} from '@/stores/namespaces'
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
|
||||
const {add, remove, search, update} = createNewIndexer('lists', ['title', 'description'])
|
||||
import ListModel from '@/models/list'
|
||||
import {removeListFromHistory} from '@/modules/listHistory'
|
||||
import ListService from '@/services/list'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {createNewIndexer} from '@/indexes'
|
||||
import {success} from '@/message'
|
||||
|
||||
const FavoriteListsNamespace = -2
|
||||
const {add, remove, search, update} = createNewIndexer('lists', ['title', 'description'])
|
||||
|
||||
export interface ListState {
|
||||
[id: IList['id']]: IList
|
||||
|
@ -35,7 +35,9 @@ export const useListStore = defineStore('list', () => {
|
|||
|
||||
|
||||
const getListById = computed(() => {
|
||||
return (id: IList['id']) => typeof lists.value[id] !== 'undefined' ? lists.value[id] : null
|
||||
return (id: IList['id']) => typeof lists.value[id] !== 'undefined'
|
||||
? lists.value[id]
|
||||
: null
|
||||
})
|
||||
|
||||
const findListByExactname = computed(() => {
|
||||
|
@ -85,7 +87,7 @@ export const useListStore = defineStore('list', () => {
|
|||
function toggleListFavorite(list: IList) {
|
||||
// The favorites pseudo list is always favorite
|
||||
// Archived lists cannot be marked favorite
|
||||
if (list.id === -1 || list.isArchived) {
|
||||
if (list.id === LIST_ID.FAVORITES || list.isArchived) {
|
||||
return
|
||||
}
|
||||
return updateList({
|
||||
|
@ -122,7 +124,7 @@ export const useListStore = defineStore('list', () => {
|
|||
// in order to not create a manipulation in pinia store we have to create a new copy
|
||||
const newList = {
|
||||
...list,
|
||||
namespaceId: FavoriteListsNamespace,
|
||||
namespaceId: NAMESPACE_ID.FAVORITES,
|
||||
}
|
||||
|
||||
namespaceStore.removeListFromNamespaceById(newList)
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import {computed, readonly, ref} from 'vue'
|
||||
import {defineStore, acceptHMRUpdate} from 'pinia'
|
||||
|
||||
import NamespaceService from '../services/namespace'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {createNewIndexer} from '@/indexes'
|
||||
import type {INamespace} from '@/modelTypes/INamespace'
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
|
||||
import {NAMESPACE_ID} from "@/constants/namespaces"
|
||||
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {useListStore} from '@/stores/lists'
|
||||
|
||||
import {createNewIndexer} from '@/indexes'
|
||||
import NamespaceService from '@/services/namespace'
|
||||
|
||||
const {add, remove, search, update} = createNewIndexer('namespaces', ['title', 'description'])
|
||||
|
||||
export const useNamespaceStore = defineStore('namespace', () => {
|
||||
|
@ -169,14 +173,20 @@ export const useNamespaceStore = defineStore('namespace', () => {
|
|||
|
||||
function loadNamespacesIfFavoritesDontExist() {
|
||||
// The first or second namespace should be the one holding all favorites
|
||||
if (namespaces.value[0].id === -2 || namespaces.value[1]?.id === -2) {
|
||||
if (
|
||||
namespaces.value[0].id === NAMESPACE_ID.FAVORITES ||
|
||||
namespaces.value[1]?.id === NAMESPACE_ID.FAVORITES
|
||||
) {
|
||||
return
|
||||
}
|
||||
return loadNamespaces()
|
||||
}
|
||||
|
||||
function removeFavoritesNamespaceIfEmpty() {
|
||||
if (namespaces.value[0].id === -2 && namespaces.value[0].lists.length === 0) {
|
||||
if (
|
||||
namespaces.value[0].id === NAMESPACE_ID.FAVORITES &&
|
||||
namespaces.value[0].lists.length === 0
|
||||
) {
|
||||
namespaces.value.splice(0, 1)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,20 @@
|
|||
@close="$router.back()"
|
||||
@submit="archiveList()"
|
||||
>
|
||||
<template #header><span>{{ list.isArchived ? $t('list.archive.unarchive') : $t('list.archive.archive') }}</span></template>
|
||||
<template #header>
|
||||
<span>{{
|
||||
list.isArchived
|
||||
? $t('list.archive.unarchive')
|
||||
: $t('list.archive.archive')
|
||||
}}</span>
|
||||
</template>
|
||||
|
||||
<template #text>
|
||||
<p>{{ list.isArchived ? $t('list.archive.unarchiveText') : $t('list.archive.archiveText') }}</p>
|
||||
<p>{{
|
||||
list.isArchived
|
||||
? $t('list.archive.unarchiveText')
|
||||
: $t('list.archive.archiveText')
|
||||
}}</p>
|
||||
</template>
|
||||
</modal>
|
||||
</template>
|
||||
|
|
|
@ -183,8 +183,7 @@ async function searchBackgrounds(page = 1) {
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
async function setBackground(backgroundId: string) {
|
||||
async function setBackground(backgroundId: IBackgroundImage['id']) {
|
||||
// Don't set a background if we're in the process of setting one
|
||||
if (backgroundService.loading) {
|
||||
return
|
||||
|
|
|
@ -70,7 +70,7 @@ export default { name: 'list-setting-edit' }
|
|||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {toRefs, type PropType} from 'vue'
|
||||
import type {PropType} from 'vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
|
||||
|
@ -85,21 +85,18 @@ import {useList} from '@/stores/lists'
|
|||
|
||||
import {useTitle} from '@/composables/useTitle'
|
||||
|
||||
const props = defineProps<{
|
||||
listId: IList['id']
|
||||
}>()
|
||||
const {listId} = toRefs(props)
|
||||
|
||||
const router = useRouter()
|
||||
const baseStore = useBaseStore()
|
||||
|
||||
const {t} = useI18n({useScope: 'global'})
|
||||
|
||||
const {list, save: saveList, isLoading} = useList(listId)
|
||||
|
||||
useTitle(() => list?.title ? t('list.edit.title', {list: list.title}) : '')
|
||||
|
||||
async function save() {
|
||||
await saveList()
|
||||
await useBaseStore().handleSetCurrentList({list: list.value})
|
||||
await baseStore.handleSetCurrentList({list})
|
||||
router.back()
|
||||
}
|
||||
</script>
|
||||
|
|
Reference in New Issue