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 {
|
.section-header .section-header-actions {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
flex-basis: 200px;
|
flex-basis: 400px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -19,6 +19,8 @@ import { ViewEditControl } from './header-buttons/view-edit-control';
|
|||||||
import './data-container.css';
|
import './data-container.css';
|
||||||
import { dataFields } from '../config/data-fields-config'
|
import { dataFields } from '../config/data-fields-config'
|
||||||
|
|
||||||
|
import { EditHistoryLatest } from './edit-history/edit-history-latest';
|
||||||
|
|
||||||
interface DataContainerProps {
|
interface DataContainerProps {
|
||||||
title: string;
|
title: string;
|
||||||
cat: string;
|
cat: string;
|
||||||
@ -330,7 +332,7 @@ const withCopyEdit: (wc: React.ComponentType<CategoryViewProps>) => DataContaine
|
|||||||
<NavLink
|
<NavLink
|
||||||
className="icon-button history"
|
className="icon-button history"
|
||||||
to={`/${this.props.mode}/${this.props.cat}/${this.props.building.building_id}/history`}
|
to={`/${this.props.mode}/${this.props.cat}/${this.props.building.building_id}/history`}
|
||||||
>History</NavLink>
|
>Edit History</NavLink>
|
||||||
<ViewEditControl
|
<ViewEditControl
|
||||||
cat={this.props.cat}
|
cat={this.props.cat}
|
||||||
mode={this.props.mode}
|
mode={this.props.mode}
|
||||||
@ -345,6 +347,9 @@ const withCopyEdit: (wc: React.ComponentType<CategoryViewProps>) => DataContaine
|
|||||||
}
|
}
|
||||||
</ContainerHeader>
|
</ContainerHeader>
|
||||||
<div className="section-body">
|
<div className="section-body">
|
||||||
|
<EditHistoryLatest
|
||||||
|
building={this.props.building}
|
||||||
|
/>
|
||||||
{
|
{
|
||||||
this.props.inactive ?
|
this.props.inactive ?
|
||||||
<Fragment>
|
<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;
|
list-style: none;
|
||||||
padding-left: 1rem;
|
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