iD.ui.Commit = function(context) { var event = d3.dispatch('cancel', 'save'); function commit(selection) { var changes = context.history().changes(), summary = context.history().difference().summary(); function zoomToEntity(change) { var entity = change.entity; if (change.changeType !== 'deleted' && context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') { context.map().zoomTo(entity); context.surface().selectAll( iD.util.entityOrMemberSelector([entity.id], context.graph())) .classed('hover', true); } } var header = selection.append('div') .attr('class', 'header fillL'); header.append('button') .attr('class', 'fr') .on('click', event.cancel) .append('span') .attr('class', 'icon close'); header.append('h3') .text(t('commit.title')); var body = selection.append('div') .attr('class', 'body'); // Comment Section var commentSection = body.append('div') .attr('class', 'modal-section form-field commit-form'); commentSection.append('label') .attr('class', 'form-label') .text(t('commit.message_label')); var commentField = commentSection.append('textarea') .attr('placeholder', t('commit.description_placeholder')) .property('value', context.storage('comment') || '') .on('blur.save', function () { context.storage('comment', this.value); }); commentField.node().select(); // Warnings var warnings = body.selectAll('div.warning-section') .data([iD.validate(changes, context.graph())]) .enter() .append('div') .attr('class', 'modal-section warning-section fillL2') .style('display', function(d) { return _.isEmpty(d) ? 'none' : null; }) .style('background', '#ffb'); warnings.append('h3') .text(t('commit.warnings')); var warningLi = warnings.append('ul') .attr('class', 'changeset-list') .selectAll('li') .data(function(d) { return d; }) .enter() .append('li') .style() .on('mouseover', mouseover) .on('mouseout', mouseout) .on('click', warningClick); warningLi.append('span') .attr('class', 'alert icon icon-pre-text'); warningLi.append('strong').text(function(d) { return d.message; }); warningLi.filter(function(d) { return d.tooltip; }) .call(bootstrap.tooltip() .title(function(d) { return d.tooltip; }) .placement('top') ); // Save Section var saveSection = body.append('div') .attr('class','modal-section fillL cf'); var prose = saveSection.append('p') .attr('class', 'commit-info') .html(t('commit.upload_explanation')); context.connection().userDetails(function(err, user) { if (err) return; var userLink = d3.select(document.createElement('div')); if (user.image_url) { userLink.append('img') .attr('src', user.image_url) .attr('class', 'icon icon-pre-text user-icon'); } userLink.append('a') .attr('class','user-info') .text(user.display_name) .attr('href', context.connection().userURL(user.display_name)) .attr('tabindex', -1) .attr('target', '_blank'); prose.html(t('commit.upload_explanation_with_user', {user: userLink.html()})); }); // Confirm Button var saveButton = saveSection.append('button') .attr('class', 'action col4 button') .on('click.save', function() { event.save({ comment: commentField.node().value }); }); saveButton.append('span') .attr('class', 'label') .text(t('commit.save')); var changeSection = body.selectAll('div.commit-section') .data([0]) .enter() .append('div') .attr('class', 'commit-section modal-section fillL2'); changeSection.append('h3') .text(summary.length + ' Changes'); var li = changeSection.append('ul') .attr('class', 'changeset-list') .selectAll('li') .data(summary) .enter() .append('li') .on('mouseover', mouseover) .on('mouseout', mouseout) .on('click', zoomToEntity); li.append('span') .attr('class', function(d) { return d.entity.geometry(d.graph) + ' ' + d.changeType + ' icon icon-pre-text'; }); li.append('span') .attr('class', 'change-type') .text(function(d) { return d.changeType + ' '; }); li.append('strong') .attr('class', 'entity-type') .text(function(d) { return context.presets().match(d.entity, d.graph).name(); }); li.append('span') .attr('class', 'entity-name') .text(function(d) { var name = iD.util.displayName(d.entity) || '', string = ''; if (name !== '') string += ':'; return string += ' ' + name; }); li.style('opacity', 0) .transition() .style('opacity', 1); li.style('opacity', 0) .transition() .style('opacity', 1); function mouseover(d) { if (d.entity) { context.surface().selectAll( iD.util.entityOrMemberSelector([d.entity.id], context.graph()) ).classed('hover', true); } } function mouseout() { context.surface().selectAll('.hover') .classed('hover', false); } function warningClick(d) { if (d.entity) { context.map().zoomTo(d.entity); context.enter(iD.modes.Select(context, [d.entity.id])); } } } return d3.rebind(commit, event, 'on'); };