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
2 changed files with 38 additions and 34 deletions
Showing only changes of commit 7a457eb161 - Show all commits

View File

@ -80,9 +80,7 @@
<thead>
<tr>
<th>{{ $t('list.share.attributes.link') }}</th>
<th>{{ $t('list.share.attributes.name') }}</th>
<th>{{ $t('list.share.attributes.sharedBy') }}</th>
<th>{{ $t('list.share.attributes.right') }}</th>
<th>&nbsp;</th>
konrad marked this conversation as resolved Outdated

Why is the &nbsp; necessary?

Why is the `&nbsp;` necessary?

I thought it was necessary, looks like it isn't.

I thought it was necessary, looks like it isn't.
<th>{{ $t('list.share.links.view') }}</th>
<th>{{ $t('list.share.attributes.delete') }}</th>
</tr>
@ -112,34 +110,37 @@
</div>
</div>
</td>
<td>
<template v-if="s.name !== ''">
{{ s.name }}
</template>
<i v-else>{{ $t('list.share.links.noName') }}</i>
</td>
<td>
{{ s.sharedBy.getDisplayName() }}
</td>
<td class="type">
<template v-if="s.right === RIGHTS.ADMIN">
<span class="icon is-small">
<icon icon="lock"/>
</span>&nbsp;
{{ $t('list.share.right.admin') }}
</template>
<template v-else-if="s.right === RIGHTS.READ_WRITE">
<span class="icon is-small">
<icon icon="pen"/>
</span>&nbsp;
{{ $t('list.share.right.readWrite') }}
</template>
<template v-else>
<span class="icon is-small">
<icon icon="users"/>
</span>&nbsp;
{{ $t('list.share.right.read') }}
</template>
<p class="mb-2" v-if="s.name !== ''">
{{ s.name }}
</p>
<p class="mb-2">
<i18n-t keypath="list.share.links.sharedBy">
<strong>{{ s.sharedBy.getDisplayName() }}</strong>
</i18n-t>
</p>
<p class="rights-item">
<template v-if="s.right === RIGHTS.ADMIN">
<span class="icon is-small">
<icon icon="lock"/>
</span>&nbsp;
{{ $t('list.share.right.admin') }}
</template>
<template v-else-if="s.right === RIGHTS.READ_WRITE">
<span class="icon is-small">
<icon icon="pen"/>
</span>&nbsp;
{{ $t('list.share.right.readWrite') }}
</template>
<template v-else>
<span class="icon is-small">
<icon icon="users"/>
</span>&nbsp;
{{ $t('list.share.right.read') }}
</template>
</p>
</td>
<td>
<div class="select">
@ -229,6 +230,7 @@ const showNewForm = ref(false)
interface SelectedViewMapper {
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.
[listId: number]: string,
}
const selectedView = ref<SelectedViewMapper>({})
const copy = useCopyToClipboard()
@ -294,5 +296,9 @@ function getShareLink(hash: string, view: string = 'list') {
overflow-y: auto
}
.rights-item {
white-space: nowrap;
}
@include modal-transition();
</style>

View File

@ -243,7 +243,8 @@
"removeText": "Are you sure you want to remove this link share? It will no longer be possible to access this list with this link share. This cannot be undone!",
"createSuccess": "The link share was successfully created.",
"deleteSuccess": "The link share was successfully deleted",
"view": "View"
"view": "View",
"sharedBy": "Shared by {0}"
},
"userTeam": {
"typeUser": "user | users",
@ -265,9 +266,6 @@
},
"attributes": {
"link": "Link",
"name": "Name",
"sharedBy": "Shared by",
"right": "Right",
"delete": "Delete"
}
},