mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Tweeks to the Labels view in the project history (#16046)
* added lastUpdatedTimestamp in label list item * formatTimeBasedOnYear * removed unused translation * fix typos * translate last_edit * use moment().subtract() * using moment.diff * fix formatting GitOrigin-RevId: 16af3962eaa4c718fcd749caaff05de82a431bcc
This commit is contained in:
parent
8035241cc0
commit
788ebd2bce
9 changed files with 54 additions and 34 deletions
|
@ -603,6 +603,7 @@
|
||||||
"large_or_high-resolution_images_taking_too_long": "",
|
"large_or_high-resolution_images_taking_too_long": "",
|
||||||
"last_active": "",
|
"last_active": "",
|
||||||
"last_active_description": "",
|
"last_active_description": "",
|
||||||
|
"last_edit": "",
|
||||||
"last_logged_in": "",
|
"last_logged_in": "",
|
||||||
"last_modified": "",
|
"last_modified": "",
|
||||||
"last_name": "",
|
"last_name": "",
|
||||||
|
@ -1022,7 +1023,6 @@
|
||||||
"save_or_cancel-or": "",
|
"save_or_cancel-or": "",
|
||||||
"save_or_cancel-save": "",
|
"save_or_cancel-save": "",
|
||||||
"save_x_percent_or_more": "",
|
"save_x_percent_or_more": "",
|
||||||
"saved_by": "",
|
|
||||||
"saving": "",
|
"saving": "",
|
||||||
"search": "",
|
"search": "",
|
||||||
"search_bib_files": "",
|
"search_bib_files": "",
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import { memo, useCallback } from 'react'
|
import { memo, useCallback } from 'react'
|
||||||
import { UpdateRange, Version } from '../../services/types/update'
|
import { UpdateRange, Version } from '../../services/types/update'
|
||||||
import TagTooltip from './tag-tooltip'
|
import TagTooltip from './tag-tooltip'
|
||||||
import { formatTime, isoToUnix } from '../../../utils/format-date'
|
import { formatTimeBasedOnYear, isoToUnix } from '../../../utils/format-date'
|
||||||
import { isPseudoLabel } from '../../utils/label'
|
|
||||||
import UserNameWithColoredBadge from './user-name-with-colored-badge'
|
|
||||||
import HistoryDropdown from './dropdown/history-dropdown'
|
import HistoryDropdown from './dropdown/history-dropdown'
|
||||||
import HistoryVersionDetails from './history-version-details'
|
import HistoryVersionDetails from './history-version-details'
|
||||||
import { LoadedLabel } from '../../services/types/label'
|
import { LoadedLabel } from '../../services/types/label'
|
||||||
|
@ -132,29 +130,18 @@ function LabelListItem({
|
||||||
{labels.map(label => (
|
{labels.map(label => (
|
||||||
<div key={label.id} className="history-version-label">
|
<div key={label.id} className="history-version-label">
|
||||||
<TagTooltip
|
<TagTooltip
|
||||||
showTooltip={false}
|
showTooltip
|
||||||
currentUserId={currentUserId}
|
currentUserId={currentUserId}
|
||||||
label={label}
|
label={label}
|
||||||
/>
|
/>
|
||||||
|
{label.lastUpdatedTimestamp && (
|
||||||
<time
|
<time
|
||||||
className="history-version-metadata-time"
|
className="history-version-metadata-time"
|
||||||
data-testid="history-version-metadata-time"
|
data-testid="history-version-metadata-time"
|
||||||
>
|
>
|
||||||
{formatTime(label.created_at, 'Do MMMM, h:mm a')}
|
{t('last_edit')}{' '}
|
||||||
|
{formatTimeBasedOnYear(label.lastUpdatedTimestamp)}
|
||||||
</time>
|
</time>
|
||||||
{!isPseudoLabel(label) && (
|
|
||||||
<div className="history-version-saved-by">
|
|
||||||
<span className="history-version-saved-by-label">
|
|
||||||
{t('saved_by')}
|
|
||||||
</span>
|
|
||||||
<UserNameWithColoredBadge
|
|
||||||
user={{
|
|
||||||
id: label.user_id,
|
|
||||||
displayName: label.user_display_name,
|
|
||||||
}}
|
|
||||||
currentUserId={currentUserId}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -12,9 +12,9 @@ import useAddOrRemoveLabels from '../../hooks/use-add-or-remove-labels'
|
||||||
import { useHistoryContext } from '../../context/history-context'
|
import { useHistoryContext } from '../../context/history-context'
|
||||||
import { deleteLabel } from '../../services/api'
|
import { deleteLabel } from '../../services/api'
|
||||||
import { isPseudoLabel } from '../../utils/label'
|
import { isPseudoLabel } from '../../utils/label'
|
||||||
import { formatDate } from '../../../../utils/dates'
|
|
||||||
import { LoadedLabel } from '../../services/types/label'
|
import { LoadedLabel } from '../../services/types/label'
|
||||||
import { debugConsole } from '@/utils/debugging'
|
import { debugConsole } from '@/utils/debugging'
|
||||||
|
import { formatTimeBasedOnYear } from '@/features/utils/format-date'
|
||||||
|
|
||||||
type TagProps = {
|
type TagProps = {
|
||||||
label: LoadedLabel
|
label: LoadedLabel
|
||||||
|
@ -152,7 +152,7 @@ function TagTooltip({ label, currentUserId, showTooltip }: LabelBadgesProps) {
|
||||||
{t('history_label_created_by')} {labelOwnerName}
|
{t('history_label_created_by')} {labelOwnerName}
|
||||||
</div>
|
</div>
|
||||||
<div className="history-version-label-tooltip-row">
|
<div className="history-version-label-tooltip-row">
|
||||||
<time>{formatDate(label.created_at)}</time>
|
<time>{formatTimeBasedOnYear(label.created_at)}</time>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,9 +181,12 @@ function useHistory() {
|
||||||
Promise.all([updatesPromise, labelsPromise])
|
Promise.all([updatesPromise, labelsPromise])
|
||||||
.then(([{ updates: updatesData, nextBeforeTimestamp }, labels]) => {
|
.then(([{ updates: updatesData, nextBeforeTimestamp }, labels]) => {
|
||||||
const lastUpdateToV = updatesData.length ? updatesData[0].toV : null
|
const lastUpdateToV = updatesData.length ? updatesData[0].toV : null
|
||||||
|
const lastUpdatedTimestamp = updatesData.length
|
||||||
|
? updatesData[0].meta.end_ts
|
||||||
|
: null
|
||||||
|
|
||||||
if (labels) {
|
if (labels) {
|
||||||
setLabels(loadLabels(labels, lastUpdateToV))
|
setLabels(loadLabels(labels, lastUpdateToV, lastUpdatedTimestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
const { updates, visibleUpdateCount, freeHistoryLimitHit } =
|
const { updates, visibleUpdateCount, freeHistoryLimitHit } =
|
||||||
|
|
|
@ -36,7 +36,11 @@ function useAddOrRemoveLabels() {
|
||||||
if (labels) {
|
if (labels) {
|
||||||
const nonPseudoLabels = labels.filter(isLabel)
|
const nonPseudoLabels = labels.filter(isLabel)
|
||||||
const processedNonPseudoLabels = labelsHandler(nonPseudoLabels)
|
const processedNonPseudoLabels = labelsHandler(nonPseudoLabels)
|
||||||
const newLabels = loadLabels(processedNonPseudoLabels, tempUpdates[0].toV)
|
const newLabels = loadLabels(
|
||||||
|
processedNonPseudoLabels,
|
||||||
|
tempUpdates[0].toV,
|
||||||
|
tempUpdates[0].meta.end_ts
|
||||||
|
)
|
||||||
setLabels(newLabels)
|
setLabels(newLabels)
|
||||||
|
|
||||||
return newLabels
|
return newLabels
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { Nullable } from '../../../../../../types/utils'
|
||||||
interface LabelBase {
|
interface LabelBase {
|
||||||
id: string
|
id: string
|
||||||
created_at: string
|
created_at: string
|
||||||
|
lastUpdatedTimestamp: Nullable<number>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateLabel extends LabelBase {
|
interface UpdateLabel extends LabelBase {
|
||||||
|
|
|
@ -35,7 +35,8 @@ const deletePseudoCurrentStateLabelIfExistent = (labels: LoadedLabel[]) => {
|
||||||
|
|
||||||
const addPseudoCurrentStateLabelIfNeeded = (
|
const addPseudoCurrentStateLabelIfNeeded = (
|
||||||
labels: LoadedLabel[],
|
labels: LoadedLabel[],
|
||||||
mostRecentVersion: Nullable<number>
|
mostRecentVersion: Nullable<number>,
|
||||||
|
lastUpdatedTimestamp: Nullable<number>
|
||||||
) => {
|
) => {
|
||||||
if (!labels.length || labels[0].version !== mostRecentVersion) {
|
if (!labels.length || labels[0].version !== mostRecentVersion) {
|
||||||
const pseudoCurrentStateLabel: PseudoCurrentStateLabel = {
|
const pseudoCurrentStateLabel: PseudoCurrentStateLabel = {
|
||||||
|
@ -43,25 +44,41 @@ const addPseudoCurrentStateLabelIfNeeded = (
|
||||||
isPseudoCurrentStateLabel: true,
|
isPseudoCurrentStateLabel: true,
|
||||||
version: mostRecentVersion,
|
version: mostRecentVersion,
|
||||||
created_at: new Date().toISOString(),
|
created_at: new Date().toISOString(),
|
||||||
|
lastUpdatedTimestamp,
|
||||||
}
|
}
|
||||||
return [pseudoCurrentStateLabel, ...labels]
|
return [pseudoCurrentStateLabel, ...labels]
|
||||||
}
|
}
|
||||||
return labels
|
return labels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const addLastUpdatedTimestamp = (
|
||||||
|
labels: LoadedLabel[],
|
||||||
|
lastUpdatedTimestamp: Nullable<number>
|
||||||
|
) => {
|
||||||
|
return labels.map(label => ({
|
||||||
|
...label,
|
||||||
|
lastUpdatedTimestamp,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
export const loadLabels = (
|
export const loadLabels = (
|
||||||
labels: Label[],
|
labels: Label[],
|
||||||
lastUpdateToV: Nullable<number>
|
lastUpdateToV: Nullable<number>,
|
||||||
|
lastUpdatedTimestamp: Nullable<number>
|
||||||
) => {
|
) => {
|
||||||
const sortedLabels = sortLabelsByVersionAndDate(labels)
|
const sortedLabels = sortLabelsByVersionAndDate(labels)
|
||||||
const labelsWithoutPseudoLabel =
|
const labelsWithoutPseudoLabel =
|
||||||
deletePseudoCurrentStateLabelIfExistent(sortedLabels)
|
deletePseudoCurrentStateLabelIfExistent(sortedLabels)
|
||||||
const labelsWithPseudoLabelIfNeeded = addPseudoCurrentStateLabelIfNeeded(
|
const labelsWithPseudoLabelIfNeeded = addPseudoCurrentStateLabelIfNeeded(
|
||||||
labelsWithoutPseudoLabel,
|
labelsWithoutPseudoLabel,
|
||||||
lastUpdateToV
|
lastUpdateToV,
|
||||||
|
lastUpdatedTimestamp
|
||||||
)
|
)
|
||||||
|
const labelsWithLastUpdatedTimestamp = addLastUpdatedTimestamp(
|
||||||
return labelsWithPseudoLabelIfNeeded
|
labelsWithPseudoLabelIfNeeded,
|
||||||
|
lastUpdatedTimestamp
|
||||||
|
)
|
||||||
|
return labelsWithLastUpdatedTimestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getVersionWithLabels = (labels: Nullable<LoadedLabel[]>) => {
|
export const getVersionWithLabels = (labels: Nullable<LoadedLabel[]>) => {
|
||||||
|
|
|
@ -19,6 +19,14 @@ export function relativeDate(date) {
|
||||||
return moment(date).calendar()
|
return moment(date).calendar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatTimeBasedOnYear(date) {
|
||||||
|
const currentDate = moment()
|
||||||
|
|
||||||
|
return currentDate.diff(date, 'years') > 0
|
||||||
|
? formatTime(date, 'D MMMM YYYY, h:mm a')
|
||||||
|
: formatTime(date, 'D MMMM, h:mm a')
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} isoTimestamp
|
* @param {string} isoTimestamp
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
|
|
|
@ -922,6 +922,7 @@
|
||||||
"large_or_high-resolution_images_taking_too_long": "Large or high-resolution images taking too long to process. You may be able to <0>optimize them</0>.",
|
"large_or_high-resolution_images_taking_too_long": "Large or high-resolution images taking too long to process. You may be able to <0>optimize them</0>.",
|
||||||
"last_active": "Last Active",
|
"last_active": "Last Active",
|
||||||
"last_active_description": "Last time a project was opened.",
|
"last_active_description": "Last time a project was opened.",
|
||||||
|
"last_edit": "Last edit",
|
||||||
"last_logged_in": "Last logged in",
|
"last_logged_in": "Last logged in",
|
||||||
"last_modified": "Last Modified",
|
"last_modified": "Last Modified",
|
||||||
"last_name": "Last Name",
|
"last_name": "Last Name",
|
||||||
|
@ -1547,7 +1548,6 @@
|
||||||
"save_or_cancel-or": "or",
|
"save_or_cancel-or": "or",
|
||||||
"save_or_cancel-save": "Save",
|
"save_or_cancel-save": "Save",
|
||||||
"save_x_percent_or_more": "Save __percent__% or more",
|
"save_x_percent_or_more": "Save __percent__% or more",
|
||||||
"saved_by": "Saved by",
|
|
||||||
"saving": "Saving",
|
"saving": "Saving",
|
||||||
"saving_20_percent": "Saving 20%!",
|
"saving_20_percent": "Saving 20%!",
|
||||||
"saving_notification_with_seconds": "Saving __docname__... (__seconds__ seconds of unsaved changes)",
|
"saving_notification_with_seconds": "Saving __docname__... (__seconds__ seconds of unsaved changes)",
|
||||||
|
|
Loading…
Reference in a new issue