feat(link shares): allows switching the initial view by passing a query parameter #2335

Merged
konrad merged 11 commits from feature/redirect-to-specific-view into main 2022-09-14 16:37:56 +00:00
3 changed files with 20 additions and 13 deletions
Showing only changes of commit 23598dd2ee - Show all commits

View File

@ -201,13 +201,16 @@ import {useStore} from '@/store'
import {useI18n} from 'vue-i18n'
import {RIGHTS} from '@/constants/rights'
import LinkShareModel, {type ILinkShare} from '@/models/linkShare'
import LinkShareModel from '@/models/linkShare'
import type {ILinkShare} from '@/modelTypes/ILinkShare'
import LinkShareService from '@/services/linkShare'
import {useCopyToClipboard} from '@/composables/useCopyToClipboard'
import {success} from '@/message'
import type {IList} from '@/models/list'
import type {IList} from '@/modelTypes/IList'
import type {ListView} from '@/types/ListView'
import {LIST_VIEWS} from '@/types/ListView'
const props = defineProps({
listId: {
@ -227,9 +230,7 @@ const showDeleteModal = ref(false)
const linkIdToDelete = ref(0)
konrad marked this conversation as resolved Outdated

Use Record with IList['id'].

I think in the future even if our ids are defined as numbers in the api it might make sense to cast them as strings in the frontend.

I got the idea while reading the zod documentation.
See: https://github.com/colinhacks/zod#record-key-type under A note on numerical keys.

We should define the types of possible views only once.
Something like:

// define outside of this file e.g. somewhere in types
export const TASK_VIEWS = {
  LIST: 'list',
  GANTT: 'gantt',
  TABLE: 'table',
  KANBAN: 'kanban',
} as const

export type TaskView = typeof TASK_VIEWS[keyof typeof TASK_VIEWS]

I'm not so good in the use of TS enums yet but I have heard quite often hat using objects / arrays with as const and then getting the types from them can have advantages. E.g. if I remember corretly iteration is easier.

So as a result:

type SelectedViewMapper = Record<IList['id'], TaskView>

We can then also define the options like this:

export const TASK_VIEW_OPTION_MAP : Record<TaskView, string> = {
  list: t('list.list.title'),
  gantt: t('list.gantt.title'),
  table: t('list.table.title'),
  kanban: t('list.kanban.title'),
}
Use `Record` with `IList['id']`. I think in the future even if our ids are defined as numbers in the api it might make sense to cast them as strings in the frontend. I got the idea while reading the zod documentation. See: https://github.com/colinhacks/zod#record-key-type under **A note on numerical keys**. We should define the types of possible views only once. Something like: ```ts // define outside of this file e.g. somewhere in types export const TASK_VIEWS = { LIST: 'list', GANTT: 'gantt', TABLE: 'table', KANBAN: 'kanban', } as const export type TaskView = typeof TASK_VIEWS[keyof typeof TASK_VIEWS] ``` I'm not so good in the use of TS enums yet but I have heard quite often hat using objects / arrays with `as const` and then getting the types from them can have advantages. E.g. if I remember corretly iteration is easier. So as a result: ```ts type SelectedViewMapper = Record<IList['id'], TaskView> ``` We can then also define the options like this: ```ts export const TASK_VIEW_OPTION_MAP : Record<TaskView, string> = { list: t('list.list.title'), gantt: t('list.gantt.title'), table: t('list.table.title'), kanban: t('list.kanban.title'), } ```

Makes a lot of sense. I knew there had to be a way to do this properly :)

Makes a lot of sense. I knew there had to be a way to do this properly :)

I've called it ListView though because this is about lists and not directly about tasks.

I've called it `ListView` though because this is about lists and not directly about tasks.
const showNewForm = ref(false)
interface SelectedViewMapper {
[listId: number]: string,
}
type SelectedViewMapper = Record<IList['id'], ListView>
const selectedView = ref<SelectedViewMapper>({})
@ -285,7 +286,7 @@ async function remove(listId: IList['id']) {
}
}
konrad marked this conversation as resolved Outdated

Use then the TaskView type here.

Use then the `TaskView` type here.

Done.

Done.
function getShareLink(hash: string, view: string = 'list') {
function getShareLink(hash: string, view: ListView = LIST_VIEWS.LIST) {
return frontendUrl.value + 'share/' + hash + '/auth?view=' + view
}
</script>

8
src/types/ListView.ts Normal file
View File

@ -0,0 +1,8 @@
export const LIST_VIEWS = {
LIST: 'list',
GANTT: 'gantt',
TABLE: 'table',
KANBAN: 'kanban',
} as const
export type ListView = typeof LIST_VIEWS[keyof typeof LIST_VIEWS]

View File

@ -41,6 +41,7 @@ import {useTitle} from '@vueuse/core'
import Message from '@/components/misc/message.vue'
import {LOGO_VISIBLE} from '@/store/mutation-types'
import {LIST_VIEWS, type ListView} from '@/types/ListView'
const {t} = useI18n({useScope: 'global'})
useTitle(t('sharing.authenticating'))
@ -80,13 +81,10 @@ function useAuth() {
: true
store.commit(LOGO_VISIBLE, logoVisible)
let view = 'list'
if (route.query.view &&
(route.query.view === 'gantt' ||
route.query.view === 'kanban' ||
route.query.view === 'table')) {
view = route.query.view
}
const view = route.query.view && Object.values(LIST_VIEWS).includes(route.query.view as ListView)
? route.query.view
: 'list'
router.push({name: `list.${view}`, params: {listId}})
} catch (e: any) {
if (e.response?.data?.code === 13001) {