Merge pull request #888 from colouring-cities/edit-history-latest
Add a line of text saying when the building was last edited
This commit is contained in:
commit
4278944a4f
@ -33,7 +33,7 @@
|
||||
|
||||
.section-header .section-header-actions {
|
||||
display: inline-block;
|
||||
flex-basis: 200px;
|
||||
flex-basis: 400px;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: center;
|
||||
|
@ -19,6 +19,8 @@ import { ViewEditControl } from './header-buttons/view-edit-control';
|
||||
import './data-container.css';
|
||||
import { dataFields } from '../config/data-fields-config'
|
||||
|
||||
import { EditHistoryLatest } from './edit-history/edit-history-latest';
|
||||
|
||||
interface DataContainerProps {
|
||||
title: string;
|
||||
cat: string;
|
||||
@ -330,7 +332,7 @@ const withCopyEdit: (wc: React.ComponentType<CategoryViewProps>) => DataContaine
|
||||
<NavLink
|
||||
className="icon-button history"
|
||||
to={`/${this.props.mode}/${this.props.cat}/${this.props.building.building_id}/history`}
|
||||
>History</NavLink>
|
||||
>Edit History</NavLink>
|
||||
<ViewEditControl
|
||||
cat={this.props.cat}
|
||||
mode={this.props.mode}
|
||||
@ -345,6 +347,9 @@ const withCopyEdit: (wc: React.ComponentType<CategoryViewProps>) => DataContaine
|
||||
}
|
||||
</ContainerHeader>
|
||||
<div className="section-body">
|
||||
<EditHistoryLatest
|
||||
building={this.props.building}
|
||||
/>
|
||||
{
|
||||
this.props.inactive ?
|
||||
<Fragment>
|
||||
|
@ -0,0 +1,67 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import './building-edit-summary.css';
|
||||
|
||||
import { Category } from '../../config/categories-config';
|
||||
import { DataFieldDefinition, dataFields } from '../../config/data-fields-config';
|
||||
import { arrayToDictionary, parseDate } from '../../helpers';
|
||||
import { EditHistoryEntry } from '../../models/edit-history-entry';
|
||||
|
||||
import { CategoryEditSummary } from './category-edit-summary';
|
||||
|
||||
interface BuildingEditLatestProps {
|
||||
historyEntry: EditHistoryEntry;
|
||||
showBuildingId?: boolean;
|
||||
hyperlinkCategories?: boolean;
|
||||
}
|
||||
|
||||
function formatDate(dt: Date) {
|
||||
return dt.toLocaleString(undefined, {
|
||||
weekday: 'short',
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
}
|
||||
|
||||
function enrichHistoryEntries(forwardPatch: object, reversePatch: object) {
|
||||
return Object
|
||||
.entries(forwardPatch)
|
||||
.map(([key, value]) => {
|
||||
const {
|
||||
title = `Unknown field (${key})`,
|
||||
category = undefined
|
||||
} = dataFields[key] as DataFieldDefinition ?? {};
|
||||
|
||||
return {
|
||||
title,
|
||||
category,
|
||||
value,
|
||||
oldValue: reversePatch && reversePatch[key]
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const BuildingEditLatest: React.FunctionComponent<BuildingEditLatestProps> = ({
|
||||
historyEntry,
|
||||
showBuildingId = false,
|
||||
hyperlinkCategories = false
|
||||
}) => {
|
||||
const entriesWithMetadata = enrichHistoryEntries(historyEntry.forward_patch, historyEntry.reverse_patch);
|
||||
const entriesByCategory = arrayToDictionary(entriesWithMetadata, x => x.category);
|
||||
|
||||
const categoryHyperlinkTemplate = hyperlinkCategories && historyEntry.building_id != undefined ?
|
||||
`/edit/$category/${historyEntry.building_id}` :
|
||||
undefined;
|
||||
|
||||
return (
|
||||
<h2 className="edit-history-timestamp">Building last edited on {formatDate(parseDate(historyEntry.revision_timestamp))}</h2>
|
||||
);
|
||||
};
|
||||
|
||||
export {
|
||||
BuildingEditLatest
|
||||
};
|
@ -0,0 +1,46 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import './edit-history.css';
|
||||
|
||||
import { apiGet } from '../../apiHelpers';
|
||||
import { Building } from '../../models/building';
|
||||
import { EditHistoryEntry } from '../../models/edit-history-entry';
|
||||
import ContainerHeader from '../container-header';
|
||||
|
||||
import { BuildingEditLatest } from './building-edit-latest';
|
||||
|
||||
interface EditHistoryLatestProps {
|
||||
building: Building;
|
||||
}
|
||||
|
||||
const EditHistoryLatest: React.FunctionComponent<EditHistoryLatestProps> = (props) => {
|
||||
const [history, setHistory] = useState<EditHistoryEntry[]>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const {history} = await apiGet(`/api/buildings/${props.building.building_id}/history.json`);
|
||||
|
||||
setHistory(history);
|
||||
};
|
||||
|
||||
if (props.building != undefined) { // only call fn if there is a building provided
|
||||
fetchData(); // define and call, because effect cannot return anything and an async fn always returns a Promise
|
||||
}
|
||||
}, [props.building]); // only re-run effect on building prop change
|
||||
|
||||
return (
|
||||
<>
|
||||
<ul className="edit-history-first" id="first-only">
|
||||
{history && history.map(entry => (
|
||||
<li key={`${entry.revision_id}`} className="edit-history-list-element">
|
||||
<BuildingEditLatest historyEntry={entry} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export {
|
||||
EditHistoryLatest
|
||||
};
|
@ -6,3 +6,10 @@
|
||||
list-style: none;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
ul[id="first-only"] li{
|
||||
display: none;
|
||||
}
|
||||
ul[id="first-only"] li:first-of-type {
|
||||
display: block;
|
||||
}
|
Loading…
Reference in New Issue
Block a user