diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9eaa3f2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +### Change Log + +Log of changes since the 1.1.0 version + +# 1.2.0 + +* Link the id of the old version changeset to OSMCha +* Add section 'Tags added, updated, deleted' diff --git a/lib/sidebar.js b/lib/sidebar.js index 6b6e794..058f6d9 100644 --- a/lib/sidebar.js +++ b/lib/sidebar.js @@ -1,6 +1,111 @@ import React from 'react'; import moment from 'moment'; import { getBounds } from './helpers'; +import { cmap } from './render'; + +export function getFeatures(features) { + var keys = Object.keys(features); + return keys.map(item => features[item]); +} + +export function processFeatures(features) { + const finalReport = new Map(); + const analyzedFeatures = features.map(feature => + analyzeFeature(feature[0], feature[1]) + ); + const keys = ['addedTags', 'changedValues', 'deletedTags']; + analyzedFeatures.map(item => + keys.map(key => + item.get(key).forEach(tag => { + if (finalReport.get(tag)) { + finalReport.set(tag, finalReport.get(tag).concat([item.get('id')])); + } else { + finalReport.set(tag, [item.get('id')]); + } + }) + ) + ); + return finalReport; +} + +export function analyzeFeature(newVersion, oldVersion) { + var oldVersionKeys = Object.keys(oldVersion.properties.tags); + var newVersionKeys = Object.keys(newVersion.properties.tags); + var addedTags = newVersionKeys.filter( + tag => oldVersionKeys.indexOf(tag) === -1 + ); + var deletedTags = oldVersionKeys.filter( + tag => newVersionKeys.indexOf(tag) === -1 + ); + var changedValues = newVersionKeys + .filter( + tag => addedTags.indexOf(tag) === -1 && deletedTags.indexOf(tag) === -1 + ) + .filter( + tag => newVersion.properties.tags[tag] !== oldVersion.properties.tags[tag] + ); + var result = new Map(); + result + .set('id', newVersion.properties.id) + .set('addedTags', addedTags.map(tag => `Added tag ${tag}`)) + .set('deletedTags', deletedTags.map(tag => `Deleted tag ${tag}`)) + .set( + 'changedValues', + changedValues.map(tag => `Changed value of tag ${tag}`) + ); + return result; +} + +export function selectFeature(id: number) { + if (!id || !cmap) return; + cmap.emit('selectFeature', 'node|way', id); +} + +function FeatureListItem(props) { + return ( +
  • + selectFeature(props.id)}> + {props.id} + +
  • + ); +} + +export class ChangeItem extends React.PureComponent { + constructor(props) { + super(props); + this.state = { + opened: false + }; + this.tag = props.change[0]; + this.value = props.change[1]; + this.handleChange = this.handleChange.bind(this); + } + handleChange() { + this.setState({ opened: !this.state.opened }); + } + render() { + return ( +
    + + {this.state.opened ? '▼' : '▶'} + {this.tag} + + +
    + ); + } +} export class Sidebar extends React.PureComponent { constructor(props) { @@ -8,12 +113,21 @@ export class Sidebar extends React.PureComponent { this.state = { actions: true, type: false, + changes: false, mapStyle: false, user: false }; + this.changeReport = []; + this.changedFeatures = processFeatures( + getFeatures(this.props.result.featureMap).filter( + item => item.length === 2 && item[0].properties.action === 'modify' + ) + ).forEach((featureIDs, tag) => this.changeReport.push([tag, featureIDs])); + this.toggleUser = this.toggleUser.bind(this); this.toggleActions = this.toggleActions.bind(this); this.toggleType = this.toggleType.bind(this); + this.toggleChanges = this.toggleChanges.bind(this); this.toggleMapStyle = this.toggleMapStyle.bind(this); } toggleUser() { @@ -31,6 +145,11 @@ export class Sidebar extends React.PureComponent { type: !this.state.type }); } + toggleChanges() { + this.setState({ + changes: !this.state.changes + }); + } toggleMapStyle() { this.setState({ mapStyle: !this.state.mapStyle @@ -95,7 +214,7 @@ export class Sidebar extends React.PureComponent { className="cmap-hlist-item cmap-noselect cmap-pointer cmap-c-link-osmhv" href={ 'http://osmhv.openstreetmap.de/changeset.jsp?id=' + - changesetId + changesetId } > OSM HV @@ -107,8 +226,8 @@ export class Sidebar extends React.PureComponent { className="cmap-hlist-item cmap-noselect cmap-pointer cmap-c-link-josm" href={ 'http://127.0.0.1:8111/import?url=http://www.openstreetmap.org/api/0.6/changeset/' + - changesetId + - '/download' + changesetId + + '/download' } > JOSM @@ -120,9 +239,9 @@ export class Sidebar extends React.PureComponent { className="cmap-hlist-item cmap-noselect cmap-pointer cmap-c-link-id" href={ 'http://preview.ideditor.com/release#map=15/' + - center.lat + - '/' + - center.lng + center.lat + + '/' + + center.lng } > iD @@ -166,7 +285,7 @@ export class Sidebar extends React.PureComponent { className="cmap-hlist-item cmap-noselect cmap-pointer cmap-u-link-disc" href={ 'http://resultmaps.neis-one.org/osm-discussion-comments?uid=' + - userId + userId } > Discussions @@ -178,8 +297,8 @@ export class Sidebar extends React.PureComponent { className="cmap-hlist-item cmap-noselect cmap-pointer cmap-u-link-comm" href={ 'http://resultmaps.neis-one.org/osm-discussion-comments?uid=115894' + - userId + - '&commented' + userId + + '&commented' } > Comments @@ -258,7 +377,7 @@ export class Sidebar extends React.PureComponent { value="nodes" defaultChecked="true" id="cmap-type-selector-nodes" - onChange={filterLayers} + onClick={filterLayers} /> Nodes @@ -289,6 +408,19 @@ export class Sidebar extends React.PureComponent { +
    +
    + {this.state.changes ? '▼' : '▶'}Tags added / updated / deleted +
    + +
    {this.state.mapStyle ? '▼' : '▶'}Map style diff --git a/package.json b/package.json index d6502e8..001bf16 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "changeset-map", - "version": "1.1.0", + "version": "1.2.0", "description": "", "main": "dist/bundle.js", "scripts": { diff --git a/public/css/style.css b/public/css/style.css index bf5a4ca..21b6eca 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -47,11 +47,34 @@ color: #666; } +.cmap-sidebar section .cmap-sub-heading { + font-size: 0.9em; + margin: 3px 0; + color: #666; +} + .cmap-sidebar em { font-style: italic; text-transform: none; } +/* Vertical list +------------------------------------------------------- */ + +.cmap-vlist li { + display: block; +} +.cmap-vlist li:hover { + font-weight: bold; +} + +.cmap-sub-heading { + padding-left: 0.8em; +} +.cmap-vlist { + padding-left: 1.6em !important; +} + /* Horizontal list ------------------------------------------------------- */