mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-22 16:19:48 +02:00
Merge branch 'master' into new-note
This commit is contained in:
@@ -410,6 +410,13 @@ export default {
|
||||
// load mapillary signs sprite
|
||||
var defs = context.container().select('defs');
|
||||
defs.call(svgDefs(context).addSprites, ['mapillary-sprite']);
|
||||
|
||||
// Register viewer resize handler
|
||||
context.ui().on('photoviewerResize', function() {
|
||||
if (_mlyViewer) {
|
||||
_mlyViewer.resize();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -34,17 +34,17 @@ import {
|
||||
} from '../util';
|
||||
|
||||
|
||||
var apibase = 'https://openstreetcam.org',
|
||||
maxResults = 1000,
|
||||
tileZoom = 14,
|
||||
dispatch = d3_dispatch('loadedImages'),
|
||||
imgZoom = d3_zoom()
|
||||
.extent([[0, 0], [320, 240]])
|
||||
.translateExtent([[0, 0], [320, 240]])
|
||||
.scaleExtent([1, 15])
|
||||
.on('zoom', zoomPan),
|
||||
_oscCache,
|
||||
_oscSelectedImage;
|
||||
var apibase = 'https://openstreetcam.org';
|
||||
var maxResults = 1000;
|
||||
var tileZoom = 14;
|
||||
var dispatch = d3_dispatch('loadedImages');
|
||||
var imgZoom = d3_zoom()
|
||||
.extent([[0, 0], [320, 240]])
|
||||
.translateExtent([[0, 0], [320, 240]])
|
||||
.scaleExtent([1, 15])
|
||||
.on('zoom', zoomPan);
|
||||
var _oscCache;
|
||||
var _oscSelectedImage;
|
||||
|
||||
|
||||
function abortRequest(i) {
|
||||
@@ -129,12 +129,12 @@ function loadNextTilePage(which, currZoom, url, tile) {
|
||||
var maxPages = maxPageAtZoom(currZoom);
|
||||
var nextPage = cache.nextPage[tile.id] || 1;
|
||||
var params = utilQsString({
|
||||
ipp: maxResults,
|
||||
page: nextPage,
|
||||
// client_id: clientId,
|
||||
bbTopLeft: [bbox.maxY, bbox.minX].join(','),
|
||||
bbBottomRight: [bbox.minY, bbox.maxX].join(',')
|
||||
}, true);
|
||||
ipp: maxResults,
|
||||
page: nextPage,
|
||||
// client_id: clientId,
|
||||
bbTopLeft: [bbox.maxY, bbox.minX].join(','),
|
||||
bbBottomRight: [bbox.minY, bbox.maxX].join(',')
|
||||
}, true);
|
||||
|
||||
if (nextPage > maxPages) return;
|
||||
|
||||
@@ -367,6 +367,16 @@ export default {
|
||||
.attr('class', 'osc-image-wrap');
|
||||
|
||||
|
||||
// Register viewer resize handler
|
||||
context.ui().on('photoviewerResize', function(dimensions) {
|
||||
imgZoom = d3_zoom()
|
||||
.extent([[0, 0], dimensions])
|
||||
.translateExtent([[0, 0], dimensions])
|
||||
.scaleExtent([1, 15])
|
||||
.on('zoom', zoomPan);
|
||||
});
|
||||
|
||||
|
||||
function rotate(deg) {
|
||||
return function() {
|
||||
if (!_oscSelectedImage) return;
|
||||
|
||||
@@ -669,6 +669,14 @@ export default {
|
||||
.attr('src', context.asset(pannellumViewerJS));
|
||||
|
||||
|
||||
// Register viewer resize handler
|
||||
context.ui().on('photoviewerResize', function() {
|
||||
if (_pannellumViewer) {
|
||||
_pannellumViewer.resize();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function step(stepBy) {
|
||||
return function() {
|
||||
var viewer = d3_select('#photoviewer');
|
||||
|
||||
@@ -167,7 +167,7 @@ export function uiCommit(context) {
|
||||
|
||||
userLink
|
||||
.append('a')
|
||||
.attr('class','user-info')
|
||||
.attr('class', 'user-info')
|
||||
.text(user.display_name)
|
||||
.attr('href', osm.userURL(user.display_name))
|
||||
.attr('tabindex', -1)
|
||||
|
||||
+112
-21
@@ -2,6 +2,7 @@ import {
|
||||
event as d3_event,
|
||||
select as d3_select
|
||||
} from 'd3-selection';
|
||||
import { dispatch as d3_dispatch } from 'd3-dispatch';
|
||||
|
||||
import { d3keybinding as d3_keybinding } from '../lib/d3.keybinding.js';
|
||||
|
||||
@@ -13,6 +14,7 @@ import { modeBrowse } from '../modes';
|
||||
import { services } from '../services';
|
||||
import { svgDefs, svgIcon } from '../svg';
|
||||
import { utilGetDimensions } from '../util/dimensions';
|
||||
import { utilRebind } from '../util';
|
||||
|
||||
import { uiAccount } from './account';
|
||||
import { uiAttribution } from './attribution';
|
||||
@@ -45,6 +47,7 @@ import { uiCmd } from './cmd';
|
||||
|
||||
export function uiInit(context) {
|
||||
var uiInitCounter = 0;
|
||||
var dispatch = d3_dispatch('photoviewerResize');
|
||||
|
||||
|
||||
function render(container) {
|
||||
@@ -256,7 +259,33 @@ export function uiInit(context) {
|
||||
.append('div')
|
||||
.call(svgIcon('#iD-icon-close'));
|
||||
|
||||
photoviewer
|
||||
.append('button')
|
||||
.attr('class', 'resize-handle-xy')
|
||||
.on(
|
||||
'mousedown',
|
||||
buildResizeListener(photoviewer, 'photoviewerResize', dispatch, { resizeOnX: true, resizeOnY: true })
|
||||
);
|
||||
|
||||
photoviewer
|
||||
.append('button')
|
||||
.attr('class', 'resize-handle-x')
|
||||
.on(
|
||||
'mousedown',
|
||||
buildResizeListener(photoviewer, 'photoviewerResize', dispatch, { resizeOnX: true })
|
||||
);
|
||||
|
||||
photoviewer
|
||||
.append('button')
|
||||
.attr('class', 'resize-handle-y')
|
||||
.on(
|
||||
'mousedown',
|
||||
buildResizeListener(photoviewer, 'photoviewerResize', dispatch, { resizeOnY: true })
|
||||
);
|
||||
|
||||
var mapDimensions = map.dimensions();
|
||||
|
||||
// bind events
|
||||
window.onbeforeunload = function() {
|
||||
return context.save();
|
||||
};
|
||||
@@ -265,30 +294,13 @@ export function uiInit(context) {
|
||||
context.history().unlock();
|
||||
};
|
||||
|
||||
var mapDimensions = map.dimensions();
|
||||
|
||||
|
||||
function onResize() {
|
||||
mapDimensions = utilGetDimensions(content, true);
|
||||
map.dimensions(mapDimensions);
|
||||
}
|
||||
|
||||
d3_select(window)
|
||||
.on('resize.editor', onResize);
|
||||
|
||||
onResize();
|
||||
|
||||
function pan(d) {
|
||||
return function() {
|
||||
d3_event.preventDefault();
|
||||
context.pan(d, 100);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// pan amount
|
||||
var pa = 80;
|
||||
|
||||
var pa = 80; // pan amount
|
||||
var keybinding = d3_keybinding('main')
|
||||
.on('⌫', function() { d3_event.preventDefault(); })
|
||||
.on('←', pan([pa, 0]))
|
||||
@@ -316,8 +328,8 @@ export function uiInit(context) {
|
||||
.call(uiShortcuts(context));
|
||||
}
|
||||
|
||||
var osm = context.connection(),
|
||||
auth = uiLoading(context).message(t('loading_auth')).blocking(true);
|
||||
var osm = context.connection();
|
||||
var auth = uiLoading(context).message(t('loading_auth')).blocking(true);
|
||||
|
||||
if (osm && auth) {
|
||||
osm
|
||||
@@ -336,6 +348,85 @@ export function uiInit(context) {
|
||||
hash.startWalkthrough = false;
|
||||
context.container().call(uiIntro(context));
|
||||
}
|
||||
|
||||
|
||||
function onResize() {
|
||||
mapDimensions = utilGetDimensions(content, true);
|
||||
map.dimensions(mapDimensions);
|
||||
|
||||
// shrink photo viewer if it is too big
|
||||
// (-90 preserves space at top and bottom of map used by menus)
|
||||
var photoDimensions = utilGetDimensions(photoviewer, true);
|
||||
if (photoDimensions[0] > mapDimensions[0] || photoDimensions[1] > (mapDimensions[1] - 90)) {
|
||||
var setPhotoDimensions = [
|
||||
Math.min(photoDimensions[0], mapDimensions[0]),
|
||||
Math.min(photoDimensions[1], mapDimensions[1] - 90),
|
||||
];
|
||||
|
||||
photoviewer
|
||||
.style('width', setPhotoDimensions[0] + 'px')
|
||||
.style('height', setPhotoDimensions[1] + 'px');
|
||||
|
||||
dispatch.call('photoviewerResize', photoviewer, setPhotoDimensions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function pan(d) {
|
||||
return function() {
|
||||
d3_event.preventDefault();
|
||||
context.pan(d, 100);
|
||||
};
|
||||
}
|
||||
|
||||
function buildResizeListener(target, eventName, dispatch, options) {
|
||||
var resizeOnX = !!options.resizeOnX;
|
||||
var resizeOnY = !!options.resizeOnY;
|
||||
var minHeight = options.minHeight || 240;
|
||||
var minWidth = options.minWidth || 320;
|
||||
var startX;
|
||||
var startY;
|
||||
var startWidth;
|
||||
var startHeight;
|
||||
|
||||
function startResize() {
|
||||
var mapSize = context.map().dimensions();
|
||||
|
||||
if (resizeOnX) {
|
||||
var maxWidth = mapSize[0];
|
||||
var newWidth = clamp((startWidth + d3_event.clientX - startX), minWidth, maxWidth);
|
||||
target.style('width', newWidth + 'px');
|
||||
}
|
||||
|
||||
if (resizeOnY) {
|
||||
var maxHeight = mapSize[1] - 90; // preserve space at top/bottom of map
|
||||
var newHeight = clamp((startHeight + startY - d3_event.clientY), minHeight, maxHeight);
|
||||
target.style('height', newHeight + 'px');
|
||||
}
|
||||
|
||||
dispatch.call(eventName, target, utilGetDimensions(target, true));
|
||||
}
|
||||
|
||||
function clamp(num, min, max) {
|
||||
return Math.max(min, Math.min(num, max));
|
||||
}
|
||||
|
||||
function stopResize() {
|
||||
d3_select(window)
|
||||
.on('.' + eventName, null);
|
||||
}
|
||||
|
||||
return function initResize() {
|
||||
startX = d3_event.clientX;
|
||||
startY = d3_event.clientY;
|
||||
startWidth = target.node().getBoundingClientRect().width;
|
||||
startHeight = target.node().getBoundingClientRect().height;
|
||||
|
||||
d3_select(window)
|
||||
.on('mousemove.' + eventName, startResize, false)
|
||||
.on('mouseup.' + eventName, stopResize, false);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -370,5 +461,5 @@ export function uiInit(context) {
|
||||
|
||||
ui.sidebar = uiSidebar(context);
|
||||
|
||||
return ui;
|
||||
return utilRebind(ui, dispatch, 'on');
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ export function uiNoteComments() {
|
||||
mainEnter
|
||||
.append('div')
|
||||
.attr('class', 'comment-text')
|
||||
.text(function(d) { return d.text; });
|
||||
.html(function(d) { return d.html; });
|
||||
|
||||
comments
|
||||
.call(replaceAvatars);
|
||||
@@ -101,6 +101,7 @@ export function uiNoteComments() {
|
||||
if (!s) return null;
|
||||
var detected = utilDetect();
|
||||
var options = { day: 'numeric', month: 'short', year: 'numeric' };
|
||||
s = s.replace(/-/g, '/'); // fix browser-specific Date() issues
|
||||
var d = new Date(s);
|
||||
if (isNaN(d.getTime())) return null;
|
||||
return d.toLocaleDateString(detected.locale, options);
|
||||
|
||||
+123
-12
@@ -1,5 +1,8 @@
|
||||
import { dispatch as d3_dispatch } from 'd3-dispatch';
|
||||
import { select as d3_select } from 'd3-selection';
|
||||
import {
|
||||
event as d3_event,
|
||||
select as d3_select
|
||||
} from 'd3-selection';
|
||||
|
||||
import { t } from '../util/locale';
|
||||
import { services } from '../services';
|
||||
@@ -53,29 +56,42 @@ export function uiNoteEditor(context) {
|
||||
.attr('class', 'body')
|
||||
.merge(body);
|
||||
|
||||
body.selectAll('.note-editor')
|
||||
.data([0])
|
||||
.enter()
|
||||
var editor = body.selectAll('.note-editor')
|
||||
.data([0]);
|
||||
|
||||
editor = editor.enter()
|
||||
.append('div')
|
||||
.attr('class', 'modal-section note-editor')
|
||||
.merge(editor)
|
||||
.call(noteHeader.note(_note))
|
||||
.call(noteComments.note(_note))
|
||||
.call(noteSave);
|
||||
.call(noteSaveSection);
|
||||
|
||||
|
||||
selection.selectAll('.footer')
|
||||
.data([0])
|
||||
.enter()
|
||||
var footer = selection.selectAll('.footer')
|
||||
.data([0]);
|
||||
|
||||
footer = footer.enter()
|
||||
.append('div')
|
||||
.attr('class', 'footer')
|
||||
.merge(footer)
|
||||
.call(uiViewOnOSM(context).what(_note))
|
||||
.call(uiNoteReport(context).note(_note));
|
||||
|
||||
|
||||
// rerender the note editor on any auth change
|
||||
var osm = services.osm;
|
||||
if (osm) {
|
||||
osm.on('change.note-save', function() {
|
||||
selection.call(noteEditor);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function noteSave(selection) {
|
||||
function noteSaveSection(selection) {
|
||||
var isSelected = (_note && _note.id === context.selectedNoteID());
|
||||
var noteSave = selection.selectAll('.note-save-section')
|
||||
var noteSave = selection.selectAll('.note-save')
|
||||
.data((isSelected ? [_note] : []), function(d) { return d.status + d.id; });
|
||||
|
||||
// exit
|
||||
@@ -85,7 +101,7 @@ export function uiNoteEditor(context) {
|
||||
// enter
|
||||
var noteSaveEnter = noteSave.enter()
|
||||
.append('div')
|
||||
.attr('class', 'note-save-section save-section cf');
|
||||
.attr('class', 'note-save save-section cf');
|
||||
|
||||
noteSaveEnter
|
||||
.append('h4')
|
||||
@@ -107,6 +123,7 @@ export function uiNoteEditor(context) {
|
||||
// update
|
||||
noteSave = noteSaveEnter
|
||||
.merge(noteSave)
|
||||
.call(userDetails)
|
||||
.call(noteSaveButtons);
|
||||
|
||||
|
||||
@@ -128,7 +145,100 @@ export function uiNoteEditor(context) {
|
||||
}
|
||||
|
||||
|
||||
function userDetails(selection) {
|
||||
var detailSection = selection.selectAll('.detail-section')
|
||||
.data([0]);
|
||||
|
||||
detailSection = detailSection.enter()
|
||||
.append('div')
|
||||
.attr('class', 'detail-section')
|
||||
.merge(detailSection);
|
||||
|
||||
var osm = services.osm;
|
||||
if (!osm) return;
|
||||
|
||||
// Add warning if user is not logged in
|
||||
var hasAuth = osm.authenticated();
|
||||
var authWarning = detailSection.selectAll('.auth-warning')
|
||||
.data(hasAuth ? [] : [0]);
|
||||
|
||||
authWarning.exit()
|
||||
.transition()
|
||||
.duration(200)
|
||||
.style('opacity', 0)
|
||||
.remove();
|
||||
|
||||
var authEnter = authWarning.enter()
|
||||
.insert('div', '.tag-reference-body')
|
||||
.attr('class', 'field-warning auth-warning')
|
||||
.style('opacity', 0);
|
||||
|
||||
authEnter
|
||||
.call(svgIcon('#iD-icon-alert', 'inline'));
|
||||
|
||||
authEnter
|
||||
.append('span')
|
||||
.text(t('note.login'));
|
||||
|
||||
authEnter
|
||||
.append('a')
|
||||
.attr('target', '_blank')
|
||||
.call(svgIcon('#iD-icon-out-link', 'inline'))
|
||||
.append('span')
|
||||
.text(t('login'))
|
||||
.on('click.note-login', function() {
|
||||
d3_event.preventDefault();
|
||||
osm.authenticate();
|
||||
});
|
||||
|
||||
authEnter
|
||||
.transition()
|
||||
.duration(200)
|
||||
.style('opacity', 1);
|
||||
|
||||
|
||||
var prose = detailSection.selectAll('.note-save-prose')
|
||||
.data(hasAuth ? [0] : []);
|
||||
|
||||
prose.exit()
|
||||
.remove();
|
||||
|
||||
prose = prose.enter()
|
||||
.append('p')
|
||||
.attr('class', 'note-save-prose')
|
||||
.text(t('note.upload_explanation'))
|
||||
.merge(prose);
|
||||
|
||||
osm.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 pre-text user-icon');
|
||||
}
|
||||
|
||||
userLink
|
||||
.append('a')
|
||||
.attr('class', 'user-info')
|
||||
.text(user.display_name)
|
||||
.attr('href', osm.userURL(user.display_name))
|
||||
.attr('tabindex', -1)
|
||||
.attr('target', '_blank');
|
||||
|
||||
prose
|
||||
.html(t('note.upload_explanation_with_user', { user: userLink.html() }));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function noteSaveButtons(selection) {
|
||||
var osm = services.osm;
|
||||
var hasAuth = osm && osm.authenticated();
|
||||
|
||||
var isSelected = (_note && _note.id === context.selectedNoteID());
|
||||
var buttonSection = selection.selectAll('.buttons')
|
||||
.data((isSelected ? [_note] : []), function(d) { return d.status + d.id; });
|
||||
@@ -168,6 +278,7 @@ export function uiNoteEditor(context) {
|
||||
.merge(buttonEnter);
|
||||
|
||||
buttonSection.select('.status-button') // select and propagate data
|
||||
.attr('disabled', (hasAuth ? null : true))
|
||||
.text(function(d) {
|
||||
var action = (d.status === 'open' ? 'close' : 'open');
|
||||
var andComment = (d.newComment ? '_comment' : '');
|
||||
@@ -186,7 +297,7 @@ export function uiNoteEditor(context) {
|
||||
|
||||
buttonSection.select('.comment-button') // select and propagate data
|
||||
.attr('disabled', function(d) {
|
||||
return (d.status === 'open' && d.newComment) ? null : true;
|
||||
return (hasAuth && d.status === 'open' && d.newComment) ? null : true;
|
||||
})
|
||||
.on('click.save', function(d) {
|
||||
this.blur(); // avoid keeping focus on the button - #4641
|
||||
|
||||
Reference in New Issue
Block a user