Fix revisions drawer detail when number of revisions > 100

Fixes #4187
This commit is contained in:
rijkvanzanten
2021-02-23 14:38:38 -05:00
parent a7ba05b6f8
commit fab082b63f
3 changed files with 110 additions and 28 deletions

View File

@@ -437,6 +437,7 @@ system_collections: System Collections
placeholder: Placeholder
icon_left: Icon Left
icon_right: Icon Right
count_other_revisions: '{count} Other Revisions'
font: Font
sans_serif: Sans Serif
serif: Serif

View File

@@ -0,0 +1,23 @@
export function abbreviateNumber(value: number) {
if (value >= 1000) {
const suffixes = ['', 'K', 'M', 'B', 'T'];
const suffixNum = Math.floor(('' + value).length / 3);
let shortValue: number = value;
for (let precision = 2; precision >= 1; precision--) {
shortValue = parseFloat((suffixNum != 0 ? value / Math.pow(1000, suffixNum) : value).toPrecision(precision));
const dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g, '');
if (dotLessShortValue.length <= 2) break;
}
let valueAsString: string = String(shortValue);
if (shortValue % 1 != 0) {
valueAsString = shortValue.toFixed(1);
}
return shortValue + suffixes[suffixNum];
}
return value;
}

View File

@@ -2,28 +2,39 @@
<sidebar-detail
:title="$t('revisions')"
icon="change_history"
:badge="!loading && revisions ? revisions.length : null"
:badge="!loading && revisions ? abbreviateNumber(revisionsCount) : null"
>
<v-progress-linear indeterminate v-if="loading" />
<template v-else v-for="group in revisionsByDate">
<v-divider :key="group.date.toString()">{{ group.dateFormatted }}</v-divider>
<template v-else>
<template v-for="group in revisionsByDate">
<v-divider :key="group.date.toString()">{{ group.dateFormatted }}</v-divider>
<template v-for="(item, index) in group.revisions">
<revision-item
:key="item.id"
:revision="item"
:last="index === group.revisions.length - 1"
@click="openModal(item.id)"
/>
<template v-for="(item, index) in group.revisions">
<revision-item
:key="item.id"
:revision="item"
:last="index === group.revisions.length - 1"
@click="openModal(item.id)"
/>
</template>
</template>
</template>
<template v-if="loading === false && hasCreate === false">
<v-divider v-if="revisionsByDate.length > 0" />
<div class="external">
{{ $t('revision_delta_created_externally') }}
</div>
<v-divider class="other" v-if="revisionsCount > 100">
{{ $tc('count_other_revisions', revisionsCount - 101) }}
</v-divider>
<template v-if="created">
<revision-item :revision="created" last @click="openModal(created.id)" />
</template>
<template v-else>
<v-divider v-if="revisionsByDate.length > 0" />
<div class="external">
{{ $t('revision_delta_created_externally') }}
</div>
</template>
</template>
<revisions-drawer
@@ -49,6 +60,7 @@ import formatLocalized from '@/utils/localized-format';
import RevisionItem from './revision-item.vue';
import RevisionsDrawer from './revisions-drawer.vue';
import { unexpectedError } from '@/utils/unexpected-error';
import { abbreviateNumber } from '@/utils/abbreviate-number';
export default defineComponent({
components: { RevisionItem, RevisionsDrawer },
@@ -63,16 +75,10 @@ export default defineComponent({
},
},
setup(props, { emit }) {
const { revisions, revisionsByDate, loading, refresh } = useRevisions(props.collection, props.primaryKey);
const hasCreate = computed(() => {
// We expect the very first revision record to be a creation
return (
revisions.value &&
revisions.value.length > 0 &&
revisions.value[revisions.value.length - 1].activity.action === 'create'
);
});
const { revisions, revisionsByDate, loading, refresh, revisionsCount, created } = useRevisions(
props.collection,
props.primaryKey
);
const modalActive = ref(false);
const modalCurrentRevision = ref<number | null>(null);
@@ -82,11 +88,13 @@ export default defineComponent({
revisionsByDate,
loading,
refresh,
hasCreate,
modalActive,
modalCurrentRevision,
openModal,
onRevert,
revisionsCount,
created,
abbreviateNumber,
};
function openModal(id: number) {
@@ -98,10 +106,12 @@ export default defineComponent({
const revisions = ref<Revision[] | null>(null);
const revisionsByDate = ref<RevisionsByDate[] | null>(null);
const loading = ref(false);
const revisionsCount = ref(0);
const created = ref<Revision>();
getRevisions();
return { revisions, revisionsByDate, loading, refresh };
return { created, revisions, revisionsByDate, loading, refresh, revisionsCount };
async function getRevisions() {
loading.value = true;
@@ -117,6 +127,8 @@ export default defineComponent({
_eq: primaryKey,
},
},
sort: '-id',
limit: 100,
fields: [
'id',
'data',
@@ -132,9 +144,48 @@ export default defineComponent({
'activity.ip',
'activity.user_agent',
],
meta: ['filter_count'],
},
});
const createdResponse = await api.get(`/revisions`, {
params: {
filter: {
collection: {
_eq: collection,
},
item: {
_eq: primaryKey,
},
activity: {
action: {
_eq: 'create',
},
},
},
sort: '-id',
limit: 1,
fields: [
'id',
'data',
'delta',
'collection',
'item',
'activity.action',
'activity.timestamp',
'activity.user.id',
'activity.user.email',
'activity.user.first_name',
'activity.user.last_name',
'activity.ip',
'activity.user_agent',
],
meta: ['filter_count'],
},
});
created.value = createdResponse.data.data?.[0];
const revisionsGroupedByDate = groupBy(response.data.data, (revision: Revision) => {
// revision's timestamp date is in iso-8601
const date = new Date(new Date(revision.activity.timestamp).toDateString());
@@ -166,6 +217,7 @@ export default defineComponent({
revisionsByDate.value = orderBy(revisionsGrouped, ['date'], ['desc']);
revisions.value = orderBy(response.data.data, ['activity.timestamp'], ['desc']);
revisionsCount.value = response.data.meta.filter_count;
} catch (err) {
unexpectedError(err);
} finally {
@@ -219,4 +271,10 @@ export default defineComponent({
color: var(--foreground-subdued);
font-style: italic;
}
.other {
--v-divider-label-color: var(--foreground-subdued);
font-style: italic;
}
</style>