Display relation members and memberships in inspector

* Preset icon of relation/member
* Preset name of relation/member
* Name of relation/member
* Role
* Delete button

All currently unstyled.
This commit is contained in:
John Firebaugh
2013-05-22 17:41:59 -07:00
parent cac654e8ab
commit 9c86e2a86c
7 changed files with 281 additions and 5 deletions
+13
View File
@@ -35,6 +35,8 @@ en:
area: Continued an area.
cancel_draw:
annotation: Canceled drawing.
change_role:
annotation: Changed the role of a relation member.
change_tags:
annotation: Changed tags.
circularize:
@@ -66,6 +68,13 @@ en:
relation: Deleted a relation.
multiple: "Deleted {n} objects."
incomplete_relation: This feature can't be deleted because it hasn't been fully downloaded.
delete_member:
annotation:
point: Removed a point from a relation.
vertex: Removed a node from a relation.
line: Removed a line from a relation.
area: Removed an area from a relation.
relation: Removed a relation from a relation.
connect:
annotation:
point: Connected a way to a point.
@@ -168,12 +177,16 @@ en:
view_on_osm: View on openstreetmap.org
editing_feature: "Editing {feature}"
all_tags: All tags
all_members: All members
all_relations: All relations
role: Role
choose: Select feature type
results: "{n} results for {search}"
reference: View on OpenStreetMap Wiki
back_tooltip: Change feature type
remove: Remove
search: Search
incomplete: <not downloaded>
background:
title: Background
description: Background settings
+17 -1
View File
@@ -48,6 +48,9 @@
"cancel_draw": {
"annotation": "Canceled drawing."
},
"change_role": {
"annotation": "Changed the role of a relation member."
},
"change_tags": {
"annotation": "Changed tags."
},
@@ -87,6 +90,15 @@
},
"incomplete_relation": "This feature can't be deleted because it hasn't been fully downloaded."
},
"delete_member": {
"annotation": {
"point": "Removed a point from a relation.",
"vertex": "Removed a node from a relation.",
"line": "Removed a line from a relation.",
"area": "Removed an area from a relation.",
"relation": "Removed a relation from a relation."
}
},
"connect": {
"annotation": {
"point": "Connected a way to a point.",
@@ -208,12 +220,16 @@
"view_on_osm": "View on openstreetmap.org",
"editing_feature": "Editing {feature}",
"all_tags": "All tags",
"all_members": "All members",
"all_relations": "All relations",
"role": "Role",
"choose": "Select feature type",
"results": "{n} results for {search}",
"reference": "View on OpenStreetMap Wiki",
"back_tooltip": "Change feature type",
"remove": "Remove",
"search": "Search"
"search": "Search",
"incomplete": "<not downloaded>"
},
"background": {
"title": "Background",
+2
View File
@@ -92,6 +92,8 @@
<script src='js/id/ui/undo_redo.js'></script>
<script src='js/id/ui/zoom.js'></script>
<script src='js/id/ui/raw_tag_editor.js'></script>
<script src='js/id/ui/raw_member_editor.js'></script>
<script src='js/id/ui/raw_membership_editor.js'></script>
<script src='js/id/ui/preset_list.js'></script>
<script src='js/id/ui/entity_editor.js'></script>
<script src='js/id/ui/disclosure.js'></script>
+22 -4
View File
@@ -6,7 +6,9 @@ iD.ui.EntityEditor = function(context, entity) {
preset,
selection_,
presetUI,
rawTagEditor;
rawTagEditor,
rawMemberEditor,
rawMembershipEditor;
function update() {
var entity = context.hasEntity(id);
@@ -23,6 +25,8 @@ iD.ui.EntityEditor = function(context, entity) {
presetUI.change(tags);
rawTagEditor.tags(tags);
if (rawMemberEditor) rawMemberEditor.change();
rawMembershipEditor.change();
}
function entityEditor(selection, newpreset) {
@@ -77,17 +81,31 @@ iD.ui.EntityEditor = function(context, entity) {
.on('change', changeTags)
.on('close', event.close);
rawTagEditor = iD.ui.RawTagEditor(context, entity)
.on('change', changeTags);
var tageditorpreset = editorwrap.append('div')
.attr('class', 'inspector-preset cf fillL col12')
.call(presetUI);
rawTagEditor = iD.ui.RawTagEditor(context, entity)
.on('change', changeTags);
editorwrap.append('div')
.attr('class', 'inspector-inner raw-tag-editor col12')
.call(rawTagEditor, preset.id === 'other');
if (entity.type === 'relation') {
rawMemberEditor = iD.ui.RawMemberEditor(context, entity);
editorwrap.append('div')
.attr('class', 'inspector-inner raw-membership-editor col12')
.call(rawMemberEditor);
}
rawMembershipEditor = iD.ui.RawMembershipEditor(context, entity);
editorwrap.append('div')
.attr('class', 'inspector-inner raw-membership-editor col12')
.call(rawMembershipEditor);
if (!entity.isNew()) {
var osmLink = tageditorpreset.append('div')
.attr('class', 'col12 inspector-inner')
+117
View File
@@ -0,0 +1,117 @@
iD.ui.RawMemberEditor = function(context, entity) {
var list, disclosure;
var rawMemberEditor = function(selection) {
function toggled(expanded) {
if (expanded) {
selection.node().parentNode.scrollTop += 200;
}
}
disclosure = iD.ui.Disclosure()
.title(t('inspector.all_members'))
.expanded(true)
.on('toggled', toggled)
.content(content);
selection.call(disclosure);
};
rawMemberEditor.change = function() {
drawMembers();
};
function content(wrap) {
list = wrap.append('ul')
.attr('class', 'member-list');
drawMembers();
}
function selectMember(d) {
context.enter(iD.modes.Select(context, [d.member.id]));
}
function changeRole(d) {
var role = d3.select(this).property('value');
context.perform(
iD.actions.ChangeMember(entity.id, _.extend({}, d.member, {role: role}), d.index),
t('operations.change_role.annotation'));
}
function deleteMember(d) {
context.perform(
iD.actions.DeleteMember(entity.id, d.index),
t('operations.delete_member.annotation.' + context.geometry(d.member.id)));
}
function drawMembers() {
var memberships = [];
entity = context.hasEntity(entity.id);
if (!entity) return;
entity.members.forEach(function(member, index) {
memberships.push({member: member, index: index, entity: context.hasEntity(member.id)});
});
disclosure.title(t('inspector.all_members') + ' (' + memberships.length + ')');
var li = list.selectAll('li')
.data(memberships, function(d) { return iD.Entity.key(entity) + ',' + d.index; });
var row = li.enter().append('li')
.attr('class', 'member-row');
row.each(function(d) {
if (d.entity) {
var member = d3.select(this).append('a')
.attr('href', '#')
.attr('class', 'member-entity')
.on('click', selectMember);
member.append('span')
.attr('class', 'member-entity-icon')
.each(function(d) {
return d3.select(this)
.call(iD.ui.PresetIcon(context.geometry(d.entity.id)));
});
member.append('span')
.attr('class', 'member-entity-name')
.text(function(d) { return iD.util.localeName(d.entity); });
member.append('span')
.attr('class', 'member-entity-type')
.text(function(d) { return context.presets().match(d.entity, context.graph()).name(); });
} else {
d3.select(this).append('span')
.attr('class', 'member-incomplete')
.text(t('inspector.incomplete'));
}
});
row.append('span')
.attr('class', 'member-role')
.append('input')
.property('type', 'text')
.attr('class', 'member-role-input')
.attr('maxlength', 255)
.attr('placeholder', t('inspector.role'))
.property('value', function(d) { return d.member.role; })
.on('change', changeRole);
row.append('button')
.attr('tabindex', -1)
.attr('class', 'member-delete')
.on('click', deleteMember)
.append('span')
.attr('class', 'icon delete');
li.exit()
.remove();
}
return rawMemberEditor;
};
+109
View File
@@ -0,0 +1,109 @@
iD.ui.RawMembershipEditor = function(context, entity) {
var list, disclosure;
var rawMembershipEditor = function(selection) {
function toggled(expanded) {
if (expanded) {
selection.node().parentNode.scrollTop += 200;
}
}
disclosure = iD.ui.Disclosure()
.title(t('inspector.all_relations'))
.expanded(true)
.on('toggled', toggled)
.content(content);
selection.call(disclosure);
};
rawMembershipEditor.change = function() {
drawMemberships();
};
function content(wrap) {
list = wrap.append('ul')
.attr('class', 'member-list');
drawMemberships();
}
function selectRelation(d) {
context.enter(iD.modes.Select(context, [d.relation.id]));
}
function changeRole(d) {
var role = d3.select(this).property('value');
context.perform(
iD.actions.ChangeMember(d.relation.id, _.extend({}, d.member, {role: role}), d.index),
t('operations.change_role.annotation'));
}
function deleteMembership(d) {
context.perform(
iD.actions.DeleteMember(d.relation.id, d.index),
t('operations.delete_member.annotation.' + context.geometry(d.member.id)));
}
function drawMemberships() {
var memberships = [];
context.graph().parentRelations(entity).forEach(function(relation) {
relation.members.forEach(function(member, index) {
if (member.id === entity.id) {
memberships.push({relation: relation, member: member, index: index});
}
})
});
disclosure.title(t('inspector.all_relations') + ' (' + memberships.length + ')');
var li = list.selectAll('li')
.data(memberships, function(d) { return iD.Entity.key(d.relation) + ',' + d.index; });
var row = li.enter().append('li')
.attr('class', 'member-row');
var relation = row.append('a')
.attr('href', '#')
.attr('class', 'member-entity')
.on('click', selectRelation);
relation.append('span')
.attr('class', 'member-entity-icon')
.each(function(d) {
return d3.select(this)
.call(iD.ui.PresetIcon(context.geometry(d.relation.id)));
});
relation.append('span')
.attr('class', 'member-entity-name')
.text(function(d) { return iD.util.localeName(d.relation); });
relation.append('span')
.attr('class', 'member-entity-type')
.text(function(d) { return context.presets().match(d.relation, context.graph()).name(); });
row.append('span')
.attr('class', 'member-role')
.append('input')
.property('type', 'text')
.attr('class', 'member-role-input')
.attr('maxlength', 255)
.attr('placeholder', t('inspector.role'))
.property('value', function(d) { return d.member.role; })
.on('change', changeRole);
row.append('button')
.attr('tabindex', -1)
.attr('class', 'member-delete')
.on('click', deleteMembership)
.append('span')
.attr('class', 'icon delete');
li.exit()
.remove();
}
return rawMembershipEditor;
};
+1
View File
@@ -89,6 +89,7 @@
<script src='../js/id/ui/undo_redo.js'></script>
<script src='../js/id/ui/zoom.js'></script>
<script src='../js/id/ui/raw_tag_editor.js'></script>
<script src='../js/id/ui/raw_membership_editor.js'></script>
<script src='../js/id/ui/preset_list.js'></script>
<script src='../js/id/ui/entity_editor.js'></script>
<script src='../js/id/ui/disclosure.js'></script>