Update bookmark editing flow

This commit is contained in:
rijkvanzanten
2020-09-04 16:56:57 -04:00
parent a570d75d53
commit 15e86a4efb
6 changed files with 104 additions and 48 deletions

View File

@@ -9,26 +9,40 @@ export function usePreset(collection: Ref<string>, bookmark: Ref<number | null>
const presetsStore = usePresetsStore();
const userStore = useUserStore();
const saving = ref(false);
const { info: collectionInfo } = useCollection(collection);
const bookmarkExists = computed(() => {
if (!bookmark.value) return false;
return !!presetsStore.state.collectionPresets.find((preset) => preset.id === bookmark.value);
});
const localPreset = ref<Partial<Preset>>({});
initLocalPreset();
const bookmarkSaved = computed(() => localPreset.value.$saved !== false);
const bookmarkIsMine = computed(() => localPreset.value.user === userStore.state.currentUser!.id);
const savePreset = async (preset?: Partial<Preset>) => {
saving.value = true;
const updatedValues = await presetsStore.savePreset(preset ? preset : localPreset.value);
initLocalPreset();
localPreset.value.id = updatedValues.id;
saving.value = false;
return updatedValues;
};
const saveLocal = async () => {
presetsStore.saveLocal(localPreset.value);
initLocalPreset();
};
const autoSave = debounce(async () => {
if (!bookmark || bookmark.value === null) {
savePreset();
} else {
saveLocal();
}
}, 450);
@@ -143,6 +157,9 @@ export function usePreset(collection: Ref<string>, bookmark: Ref<number | null>
saveCurrentAsBookmark,
title,
resetPreset,
bookmarkSaved,
bookmarkIsMine,
saving,
};
async function resetPreset() {

View File

@@ -1,15 +1,13 @@
import { computed, Ref } from '@vue/composition-api';
import { clone } from 'lodash';
export default function useSync<T, K extends keyof T>(
props: T,
key: K,
emit: (event: string, ...args: any[]) => void
): Ref<Readonly<T[K]>> {
return computed<T[K]>({
get() {
return clone(props[key]);
return props[key];
},
set(newVal) {
emit(`update:${key}`, newVal);

View File

@@ -143,7 +143,7 @@
<script lang="ts">
import Vue from 'vue';
import { defineComponent, PropType, ref, computed, inject, toRefs, Ref } from '@vue/composition-api';
import { defineComponent, PropType, ref, computed, inject, toRefs, Ref, watch } from '@vue/composition-api';
import { HeaderRaw, Item } from '@/components/v-table/types';
import { Field, Filter } from '@/types';
@@ -389,6 +389,13 @@ export default defineComponent({
const localWidths = ref<{ [field: string]: number }>({});
watch(
() => _viewOptions.value,
() => {
localWidths.value = {};
}
);
const saveWidthsToViewOptions = debounce(() => {
_viewOptions.value = {
...(_viewOptions.value || {}),

View File

@@ -13,30 +13,38 @@
</template>
<template #title-outer:append>
<bookmark-add
v-if="!bookmark"
class="bookmark-add"
v-model="bookmarkDialogActive"
@save="createBookmark"
:saving="creatingBookmark"
>
<template #activator="{ on }">
<v-icon class="toggle" name="bookmark_outline" @click="on" />
</template>
</bookmark-add>
<div class="bookmark-controls">
<bookmark-add
v-if="!bookmark"
class="add"
v-model="bookmarkDialogActive"
@save="createBookmark"
:saving="creatingBookmark"
>
<template #activator="{ on }">
<v-icon class="toggle" name="bookmark_outline" @click="on" />
</template>
</bookmark-add>
<bookmark-edit
v-else
class="bookmark-edit"
v-model="bookmarkDialogActive"
:saving="editingBookmark"
:name="bookmarkName"
@save="editBookmark"
>
<template #activator="{ on }">
<v-icon class="toggle" name="bookmark" @click="on" />
<v-icon class="saved" name="bookmark" v-else-if="bookmarkSaved" />
<template v-else-if="bookmarkIsMine">
<v-progress-circular indeterminate small v-if="bookmarkSaving" />
<v-icon class="save" v-else @click="savePreset()" name="save" />
</template>
</bookmark-edit>
<bookmark-add
v-else
class="add"
v-model="bookmarkDialogActive"
@save="createBookmark"
:saving="creatingBookmark"
>
<template #activator="{ on }">
<v-icon class="toggle" name="bookmark_outline" @click="on" />
</template>
</bookmark-add>
</div>
</template>
<template #actions:prepend>
@@ -277,6 +285,9 @@ export default defineComponent({
saveCurrentAsBookmark,
title: bookmarkName,
resetPreset,
bookmarkSaved,
bookmarkIsMine,
saving: bookmarkSaving,
} = usePreset(collection, bookmarkID);
const {
@@ -345,6 +356,9 @@ export default defineComponent({
deleteError,
createAllowed,
resetPreset,
bookmarkSaved,
bookmarkIsMine,
bookmarkSaving,
};
function useBreadcrumb() {
@@ -559,25 +573,31 @@ export default defineComponent({
--layout-offset-top: 64px;
}
.bookmark-add .toggle,
.bookmark-edit .toggle {
margin-left: 8px;
transition: color var(--fast) var(--transition);
}
.bookmark-add {
color: var(--foreground-subdued);
&:hover {
color: var(--foreground-normal);
}
}
.bookmark-edit {
color: var(--primary);
}
.header-icon {
--v-button-color-disabled: var(--foreground-normal);
}
.bookmark-controls {
.add,
.save,
.saved,
.v-progress-circular {
display: inline-block;
margin-left: 8px;
}
.add,
.save {
color: var(--foreground-subdued);
transition: color var(--fast) var(--transition);
&:hover {
color: var(--foreground-normal);
}
}
.saved {
color: var(--primary);
}
}
</style>

View File

@@ -22,7 +22,6 @@ export const usePresetsStore = createStore({
actions: {
async hydrate() {
// Hydrate is only called for logged in users, therefore, currentUser exists
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const { id, role } = useUserStore().state.currentUser!;
const values = await Promise.all([
@@ -65,6 +64,7 @@ export const usePresetsStore = createStore({
this.state.collectionPresets = this.state.collectionPresets.map((preset) => {
const updatedPreset = response.data.data;
if (preset.id === updatedPreset.id) {
return updatedPreset;
}
@@ -167,5 +167,18 @@ export const usePresetsStore = createStore({
return await this.update(id, preset);
}
},
async saveLocal(updatedPreset: Preset) {
this.state.collectionPresets = this.state.collectionPresets.map((preset) => {
if (preset.id === updatedPreset.id) {
return {
...updatedPreset,
$saved: false,
};
}
return preset;
});
},
},
});

View File

@@ -37,8 +37,9 @@ export type Preset = {
search_query: string | null;
filters: readonly Filter[] | null;
view_type: string | null;
view_query: { [view_type: string]: any } | null;
view_options: { [view_type: string]: any } | null;
// App flag to indicate that the local copy hasn't been saved to the API yet
$saved?: false;
};