Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navigation buttons on landing page #1172

Merged
merged 8 commits into from
Aug 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions web/src/components/DandisetList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
subheader
>
<v-list-item
v-for="item in dandisets"
v-for="(item, index) in dandisets"
:key="item.dandiset.identifier"
selectable
:to="{
name: 'dandisetLanding',
params: { identifier: item.dandiset.identifier, origin }
params: { identifier: item.dandiset.identifier, origin },
query: { ...$route.query, pos: getPos(index) },
}"
>
<v-list-item-content>
Expand Down Expand Up @@ -82,6 +83,7 @@ import moment from 'moment';
import filesize from 'filesize';

import { Version } from '@/types';
import { DANDISETS_PER_PAGE } from '@/utils/constants';

export default defineComponent({
name: 'DandisetList',
Expand All @@ -100,15 +102,18 @@ export default defineComponent({
const { name, params, query } = route;
return { name, params, query };
});

// current position in search result set = items on prev pages + position on current page
function getPos(index: number) {
return (Number(ctx.root.$route.query.page || 1) - 1) * DANDISETS_PER_PAGE + (index + 1);
}
function formatDate(date: string) {
return moment(date).format('LL');
}

return {
origin,
formatDate,

getPos,
// Returned imports
filesize,
};
Expand Down
24 changes: 3 additions & 21 deletions web/src/components/DandisetsPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -100,27 +100,7 @@ import DandisetList from '@/components/DandisetList.vue';
import DandisetSearchField from '@/components/DandisetSearchField.vue';
import { dandiRest } from '@/rest';
import { Dandiset, Paginated } from '@/types';

const DANDISETS_PER_PAGE = 8;

const sortingOptions = [
{
name: 'Modified',
djangoField: 'modified',
},
{
name: 'Identifier',
djangoField: 'id',
},
{
name: 'Name',
djangoField: 'name',
},
{
name: 'Size',
djangoField: 'size',
},
];
import { sortingOptions, DANDISETS_PER_PAGE } from '@/utils/constants';

export default defineComponent({
name: 'DandisetsPage',
Expand Down Expand Up @@ -192,6 +172,8 @@ export default defineComponent({
page: String(page.value),
sortOption: String(sortOption.value),
sortDir: String(sortDir.value),
showDrafts: String(showDrafts.value),
showEmpty: String(showEmpty.value),
}));
watch(queryParams, (params) => {
ctx.root.$router.replace({
Expand Down
23 changes: 23 additions & 0 deletions web/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,27 @@ const VALIDATION_ICONS = {
DEFAULT: 'mdi-alert',
};

const sortingOptions = [
{
name: 'Modified',
djangoField: 'modified',
},
{
name: 'Identifier',
djangoField: 'id',
},
{
name: 'Name',
djangoField: 'name',
},
{
name: 'Size',
djangoField: 'size',
},
];

const DANDISETS_PER_PAGE = 8;

export {
dandiUrl,
dandiAboutUrl,
Expand All @@ -35,4 +56,6 @@ export {
draftVersion,
dandiHelpUrl,
VALIDATION_ICONS,
sortingOptions,
DANDISETS_PER_PAGE,
};
65 changes: 61 additions & 4 deletions web/src/views/DandisetLandingView/DandisetLandingView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
<Meditor v-if="currentDandiset" />
<v-toolbar class="grey darken-2 white--text">
<DandisetSearchField />
<v-pagination
v-model="page"
:length="pages"
:total-visible="0"
/>
</v-toolbar>
<v-container
v-if="currentDandiset"
Expand Down Expand Up @@ -42,16 +47,17 @@

<script lang="ts">
import {
defineComponent, computed, watchEffect, watch, onMounted,
defineComponent, computed, watch, onMounted, Ref, ref,
} from '@vue/composition-api';
import { NavigationGuardNext, RawLocation, Route } from 'vue-router';

import DandisetSearchField from '@/components/DandisetSearchField.vue';
import Meditor from '@/components/Meditor/Meditor.vue';
import store from '@/store';
import { Version } from '@/types';
import { draftVersion } from '@/utils/constants';
import { draftVersion, sortingOptions } from '@/utils/constants';
import { editorInterface } from '@/components/Meditor/state';
import { dandiRest } from '@/rest';
import DandisetMain from './DandisetMain.vue';
import DandisetSidebar from './DandisetSidebar.vue';

Expand Down Expand Up @@ -118,7 +124,7 @@ export default defineComponent({
}
}, { immediate: true });

watchEffect(async () => {
watch([() => props.identifier, () => props.version], async () => {
const { identifier, version } = props;
if (version) {
// On version change, fetch the new dandiset (not initial)
Expand All @@ -140,7 +146,55 @@ export default defineComponent({
}
});

onMounted(() => {
const page = ref(Number(ctx.root.$route.query.pos) || 1);
const pages = ref(1);
const nextDandiset : Ref<any[]> = ref([]);

async function fetchNextPage() {
const sortOption = Number(ctx.root.$route.query.sortOption) || 0;
const sortDir = Number(ctx.root.$route.query.sortDir || -1);
const sortField = sortingOptions[sortOption].djangoField;
const ordering = ((sortDir === -1) ? '-' : '') + sortField;
const response = await dandiRest.dandisets({
page: page.value,
page_size: 1,
ordering,
search: ctx.root.$route.query.search,
draft: ctx.root.$route.query.showDrafts || true,
empty: ctx.root.$route.query.showEmpty,
});

pages.value = (response.data?.count) ? response.data?.count : 1;
nextDandiset.value = response.data?.results.map((dandiset) => ({
...(dandiset.most_recent_published_version || dandiset.draft_version),
contact_person: dandiset.contact_person,
identifier: dandiset.identifier,
}));
}

function navigateToPage() {
if (nextDandiset.value) {
const { identifier } = nextDandiset.value[0];
if (identifier !== props.identifier) { // to avoid redundant navigation
ctx.root.$router.push({
name: ctx.root.$route.name || undefined,
params: { identifier },
query: {
...ctx.root.$route.query,
},
});
}
}
}

watch(page, async (newValue, oldValue) => {
if (oldValue !== newValue) {
await fetchNextPage();
navigateToPage();
}
});

onMounted(async () => {
// This guards against "hard" page navigations, i.e. refreshing, closing tabs, or
// clicking external links. The `beforeRouteLeave` function above handles "soft"
// page navigations, such as using the back/forward buttons or clicking a link
Expand All @@ -153,6 +207,7 @@ export default defineComponent({
e.returnValue = 'You have unsaved changes, are you sure you want to leave?';
}
});
await fetchNextPage(); // get the current page and total count
});

return {
Expand All @@ -161,6 +216,8 @@ export default defineComponent({
schema,
userCanModifyDandiset,
meta,
pages,
page,
};
},
});
Expand Down