11import React from 'react' ;
22import moment from 'moment' ;
33import { getBounds } from './helpers' ;
4+ import { cmap } from './render' ;
5+
6+ export function getFeatures ( features ) {
7+ var keys = Object . keys ( features ) ;
8+ return keys . map ( item => features [ item ] ) ;
9+ }
10+
11+ export function processFeatures ( features ) {
12+ const finalReport = new Map ( ) ;
13+ const analyzedFeatures = features . map ( feature =>
14+ analyzeFeature ( feature [ 0 ] , feature [ 1 ] )
15+ ) ;
16+ const keys = [ 'addedTags' , 'changedValues' , 'deletedTags' ] ;
17+ analyzedFeatures . map ( item =>
18+ keys . map ( key =>
19+ item . get ( key ) . forEach ( tag => {
20+ if ( finalReport . get ( tag ) ) {
21+ finalReport . set ( tag , finalReport . get ( tag ) . concat ( [ item . get ( 'id' ) ] ) ) ;
22+ } else {
23+ finalReport . set ( tag , [ item . get ( 'id' ) ] ) ;
24+ }
25+ } )
26+ )
27+ ) ;
28+ return finalReport ;
29+ }
30+
31+ export function analyzeFeature ( newVersion , oldVersion ) {
32+ var oldVersionKeys = Object . keys ( oldVersion . properties . tags ) ;
33+ var newVersionKeys = Object . keys ( newVersion . properties . tags ) ;
34+ var addedTags = newVersionKeys . filter (
35+ tag => oldVersionKeys . indexOf ( tag ) === - 1
36+ ) ;
37+ var deletedTags = oldVersionKeys . filter (
38+ tag => newVersionKeys . indexOf ( tag ) === - 1
39+ ) ;
40+ var changedValues = newVersionKeys
41+ . filter (
42+ tag => addedTags . indexOf ( tag ) === - 1 && deletedTags . indexOf ( tag ) === - 1
43+ )
44+ . filter (
45+ tag => newVersion . properties . tags [ tag ] !== oldVersion . properties . tags [ tag ]
46+ ) ;
47+ var result = new Map ( ) ;
48+ result
49+ . set ( 'id' , newVersion . properties . id )
50+ . set ( 'addedTags' , addedTags . map ( tag => `Added tag ${ tag } ` ) )
51+ . set ( 'deletedTags' , deletedTags . map ( tag => `Deleted tag ${ tag } ` ) )
52+ . set (
53+ 'changedValues' ,
54+ changedValues . map ( tag => `Changed value of tag ${ tag } ` )
55+ ) ;
56+ return result ;
57+ }
58+
59+ export function selectFeature ( id : number ) {
60+ if ( ! id || ! cmap ) return ;
61+ cmap . emit ( 'selectFeature' , 'node|way' , id ) ;
62+ }
63+
64+ function FeatureListItem ( props ) {
65+ return (
66+ < li >
67+ < span className = "cmap-pointer " onClick = { ( ) => selectFeature ( props . id ) } >
68+ { props . id }
69+ </ span >
70+ </ li >
71+ ) ;
72+ }
73+
74+ export class ChangeItem extends React . PureComponent {
75+ constructor ( props ) {
76+ super ( props ) ;
77+ this . state = {
78+ opened : false
79+ } ;
80+ this . tag = props . change [ 0 ] ;
81+ this . value = props . change [ 1 ] ;
82+ this . handleChange = this . handleChange . bind ( this ) ;
83+ }
84+ handleChange ( ) {
85+ this . setState ( { opened : ! this . state . opened } ) ;
86+ }
87+ render ( ) {
88+ return (
89+ < div >
90+ < h7
91+ className = "cmap-sub-heading cmap-pointer"
92+ onClick = { this . handleChange }
93+ >
94+ { this . state . opened ? '▼' : '▶' }
95+ { this . tag }
96+ </ h7 >
97+ < ul
98+ className = "cmap-vlist"
99+ style = { {
100+ display : this . state . opened ? 'block' : 'none'
101+ } }
102+ >
103+ { this . value . map ( ( id , k ) => < FeatureListItem id = { id } key = { k } /> ) }
104+ </ ul >
105+ </ div >
106+ ) ;
107+ }
108+ }
4109
5110export class Sidebar extends React . PureComponent {
6111 constructor ( props ) {
7112 super ( props ) ;
8113 this . state = {
9114 actions : true ,
10115 type : false ,
116+ changes : false ,
11117 mapStyle : false ,
12118 user : false
13119 } ;
120+ this . changeReport = [ ] ;
121+ this . changedFeatures = processFeatures (
122+ getFeatures ( this . props . result . featureMap ) . filter (
123+ item => item . length === 2 && item [ 0 ] . properties . action === 'modify'
124+ )
125+ ) . forEach ( ( featureIDs , tag ) => this . changeReport . push ( [ tag , featureIDs ] ) ) ;
126+
14127 this . toggleUser = this . toggleUser . bind ( this ) ;
15128 this . toggleActions = this . toggleActions . bind ( this ) ;
16129 this . toggleType = this . toggleType . bind ( this ) ;
130+ this . toggleChanges = this . toggleChanges . bind ( this ) ;
17131 this . toggleMapStyle = this . toggleMapStyle . bind ( this ) ;
18132 }
19133 toggleUser ( ) {
@@ -31,6 +145,11 @@ export class Sidebar extends React.PureComponent {
31145 type : ! this . state . type
32146 } ) ;
33147 }
148+ toggleChanges ( ) {
149+ this . setState ( {
150+ changes : ! this . state . changes
151+ } ) ;
152+ }
34153 toggleMapStyle ( ) {
35154 this . setState ( {
36155 mapStyle : ! this . state . mapStyle
@@ -95,7 +214,7 @@ export class Sidebar extends React.PureComponent {
95214 className = "cmap-hlist-item cmap-noselect cmap-pointer cmap-c-link-osmhv"
96215 href = {
97216 'http://osmhv.openstreetmap.de/changeset.jsp?id=' +
98- changesetId
217+ changesetId
99218 }
100219 >
101220 OSM HV
@@ -107,8 +226,8 @@ export class Sidebar extends React.PureComponent {
107226 className = "cmap-hlist-item cmap-noselect cmap-pointer cmap-c-link-josm"
108227 href = {
109228 'http://127.0.0.1:8111/import?url=http://www.openstreetmap.org/api/0.6/changeset/' +
110- changesetId +
111- '/download'
229+ changesetId +
230+ '/download'
112231 }
113232 >
114233 JOSM
@@ -120,9 +239,9 @@ export class Sidebar extends React.PureComponent {
120239 className = "cmap-hlist-item cmap-noselect cmap-pointer cmap-c-link-id"
121240 href = {
122241 'http://preview.ideditor.com/release#map=15/' +
123- center . lat +
124- '/' +
125- center . lng
242+ center . lat +
243+ '/' +
244+ center . lng
126245 }
127246 >
128247 iD
@@ -166,7 +285,7 @@ export class Sidebar extends React.PureComponent {
166285 className = "cmap-hlist-item cmap-noselect cmap-pointer cmap-u-link-disc"
167286 href = {
168287 'http://resultmaps.neis-one.org/osm-discussion-comments?uid=' +
169- userId
288+ userId
170289 }
171290 >
172291 Discussions
@@ -178,8 +297,8 @@ export class Sidebar extends React.PureComponent {
178297 className = "cmap-hlist-item cmap-noselect cmap-pointer cmap-u-link-comm"
179298 href = {
180299 'http://resultmaps.neis-one.org/osm-discussion-comments?uid=115894' +
181- userId +
182- '&commented'
300+ userId +
301+ '&commented'
183302 }
184303 >
185304 Comments
@@ -258,7 +377,7 @@ export class Sidebar extends React.PureComponent {
258377 value = "nodes"
259378 defaultChecked = "true"
260379 id = "cmap-type-selector-nodes"
261- onChange = { filterLayers }
380+ onClick = { filterLayers }
262381 />
263382 < span className = "cmap-label-text" > Nodes</ span >
264383 </ label >
@@ -289,6 +408,19 @@ export class Sidebar extends React.PureComponent {
289408 </ li >
290409 </ ul >
291410 </ section >
411+ < section className = "cmap-filter-changes-section cmap-pb3" >
412+ < h6 className = "cmap-heading pointer" onClick = { this . toggleChanges } >
413+ { this . state . changes ? '▼' : '▶' } Tags added / updated / deleted
414+ </ h6 >
415+ < ul
416+ className = "cmap-sub-hlist"
417+ style = { { display : this . state . changes ? 'block' : 'none' } }
418+ >
419+ { this . changeReport
420+ . sort ( )
421+ . map ( ( change , k ) => < ChangeItem key = { k } change = { change } /> ) }
422+ </ ul >
423+ </ section >
292424 < section className = "cmap-map-style-section cmap-pb3" >
293425 < h6 className = "cmap-heading pointer" onClick = { this . toggleMapStyle } >
294426 { this . state . mapStyle ? '▼' : '▶' } Map style
0 commit comments