Skip to content

Commit

Permalink
feature: import layer button (#1685)
Browse files Browse the repository at this point in the history
* feature: import layer button

Fixes #1678
Adds a button in the legend for import of layer as file. Defaults to false.
    {
      "name": "draganddrop",
      "options": {
        "showLegendButton": true
      }
    },

* Fix for readding layers

* Changed icon

* Added popup menu for add layer

* Update legend.js

* Some css

* Added some styling
  • Loading branch information
jokd authored Feb 22, 2023
1 parent a7ce1ce commit e3e5290
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 33 deletions.
1 change: 1 addition & 0 deletions css/svg/material-icons.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 1 addition & 9 deletions scss/externs/_awesomplete.base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@
width: 100%;
}

.awesomplete.black {
display: flex;
flex-direction: row;
flex-grow: 1;
position: fixed;
min-width: 100%;
}

.awesomplete > input {
display: block;
}
Expand All @@ -48,7 +40,7 @@
list-style: none;
margin: 0;
min-width: 180px;
max-width: 220px;
max-width: 100%;
overflow-wrap: break-word;
padding: 0;
position: absolute;
Expand Down
8 changes: 8 additions & 0 deletions scss/ui/_popup-menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@ $popup-border-color: $grey-light;
margin-top: -30px;
width: max-content;
}

.popup-menu.button-popup {
position: absolute;
text-align: left;
width: max-content;
bottom: 5px;
left: 0;
}
51 changes: 50 additions & 1 deletion src/controls/draganddrop.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,67 @@ import TopoJSONFormat from 'ol/format/TopoJSON';
import VectorSource from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';
import Style from '../style';
import { Component } from '../ui';
import { Component, InputFile, Button, Element as El } from '../ui';

const DragAndDrop = function DragAndDrop(options = {}) {
let dragAndDrop;
let viewer;
let map;
let legendButton;

if (options.showLegendButton) {
const fileInput = InputFile({
labelCls: 'hidden',
inputCls: 'hidden',
change(e) {
const filesToDrop = e.target.files;

function fakeIt(file) {
this.dropEffect = 'copy';
this.effectAllowed = 'all';
this.items = [];
this.types = [];
this.getData = function getData() {
return file;
};
this.files = file;
}

const fakeEvent = new DragEvent('drop');
Object.defineProperty(fakeEvent, 'dataTransfer', {
value: new fakeIt(filesToDrop)
});
viewer.getMap().getViewport().dispatchEvent(fakeEvent);
}
});

const openBtn = Button({
cls: 'text-medium padding-0',
click() {
const inputEl = document.getElementById(fileInput.getId());
inputEl.value = null;
inputEl.click();
},
text: 'Lägg till från fil',
ariaLabel: 'Lägg till från fil'
});

legendButton = El({
components: [fileInput, openBtn]
});

legendButton.on('click', () => {
openBtn.dispatch('click');
});
}

return Component({
name: 'draganddrop',
onAdd(evt) {
viewer = evt.target;
map = viewer.getMap();
const legend = viewer.getControlByName('legend');
if (options.showLegendButton) { legend.addButtonToTools(legendButton, 'addLayerButton'); }
const groupName = options.groupName || 'egna-lager';
const groupTitle = options.groupTitle || 'Egna lager';
const featureStyles = options.featureStyles || {
Expand Down
128 changes: 106 additions & 22 deletions src/controls/legend.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import imageSource from './legend/imagesource';
import Overlays from './legend/overlays';
import VisibleOverlays from './legend/visibleOverlays';
import LayerProperties from './legend/overlayproperties';
import PopupMenu from '../ui/popupmenu';

const Legend = function Legend(options = {}) {
const {
Expand Down Expand Up @@ -52,13 +53,17 @@ const Legend = function Legend(options = {}) {
const backgroundLayerButtons = [];
let toggleGroup;
let layerSwitcherEl;
let addLayerButton;
let closeButton;
let layerButton;
let layerButtonEl;
let isExpanded;
let toolsCmp;
const cls = `${clsSettings} control bottom-right box overflow-hidden flex row o-legend`.trim();
const style = dom.createStyle(Object.assign({}, { width: 'auto' }, styleSettings));
const cls = `${clsSettings} control bottom-right box flex row o-legend`.trim();
const style = dom.createStyle(Object.assign({}, { width: 'auto', overflow: 'unset' }, styleSettings));

const popupMenuItems = [];
let popupMenu;

const setTabIndex = function setTabIndex() {
let idx = -1;
Expand Down Expand Up @@ -255,9 +260,83 @@ const Legend = function Legend(options = {}) {
}
});

const addPopupMenuItems = function addPopupMenuItems(button, cmp) {
if (addLayerButton.getState() === 'hidden') {
cmp.addButtonToTools(addLayerButton);
addLayerButton.setState('initial');
}
popupMenuItems.push(button);
};

const popupMenuList = Component({
render() {
this.addComponents(popupMenuItems);
let html = `<ul id="${this.getId()}">`;
popupMenuItems.forEach((item) => {
html += `<li class="padding-x-small">${item.render()}</li>`;
});
html += '</ul>';
return html;
}
});

const createPopupMenu = function createPopupMenu() {
const relDiv = document.createElement('div');
const absDiv = document.createElement('div');
relDiv.classList.add('relative');
relDiv.style.display = 'contents';
absDiv.classList.add('absolute');
const addLayerButtonEl = document.getElementById(addLayerButton.getId());
const onUnfocus = (e) => {
if (!addLayerButtonEl.contains(e.target)) {
popupMenu.setVisibility(false);
}
};
popupMenu = PopupMenu({ onUnfocus, cls: 'button-popup' });
addLayerButtonEl.insertAdjacentElement('beforebegin', relDiv);
relDiv.appendChild(absDiv);
absDiv.appendChild(dom.html(popupMenu.render()));
relDiv.addEventListener('click', () => { popupMenu.setVisibility(false); });
popupMenu.setContent(popupMenuList.render());
popupMenuList.dispatch('render');
if (popupMenuItems.length > 1) {
popupMenu.setVisibility(true);
} else {
popupMenu.setVisibility(false);
popupMenuItems[0].dispatch('click');
}
};

const togglePopupMenu = function togglePopupMenu() {
if (!popupMenu) {
createPopupMenu();
} else if (popupMenuItems.length > 1) {
popupMenu.toggleVisibility();
} else {
popupMenu.setVisibility(false);
popupMenuItems[0].dispatch('click');
}
};

addLayerButton = Button({
cls: 'round compact primary icon-small margin-x-smaller o-tooltip',
click() {
togglePopupMenu();
},
style: {
'align-self': 'center'
},
icon: '#o_add_24px',
ariaLabel: 'Lägg till lager',
title: 'Lägg till lager',
tabIndex: -1,
validStates: ['initial', 'hidden'],
state: 'hidden'
});

const layerSearchInput = Input({
cls: 'o-search-layer-field placeholder-text-smaller smaller',
style: { height: '1.5rem', margin: 0, width: '180px' },
style: { height: '1.5rem', margin: 0, width: '100%' },
placeholderText: searchLayersPlaceholderText,
value: ''
});
Expand Down Expand Up @@ -429,6 +508,7 @@ const Legend = function Legend(options = {}) {
});

input.parentNode.classList.add('black');
input.parentNode.classList.add('grow');
input.addEventListener('keyup', (e) => {
const keyCode = e.keyCode;
if (input.value.length >= searchLayersMinLength) {
Expand Down Expand Up @@ -472,25 +552,29 @@ const Legend = function Legend(options = {}) {
getuseGroupIndication() { return useGroupIndication; },
getOverlaysCollapse() { return overlaysCmp.overlaysCollapse; },
setVisibleLayersViewActive,
addButtonToTools(button) {
const toolsEl = document.getElementById(toolsCmp.getId());
toolsEl.classList.remove('hidden');
if (toolsCmp.getComponents().length > 0) {
toolsEl.style.justifyContent = 'space-between';
toolsEl.insertBefore(dom.html(divider.render()), toolsEl.firstChild);
toolsEl.insertBefore(dom.html(button.render()), toolsEl.firstChild);
addButtonToTools(button, buttonGroup) {
if (buttonGroup === 'addLayerButton') {
addPopupMenuItems(button, this);
} else {
const node = document.createElement('div');
if (typeof button.getValue === 'function') {
node.classList.add('grow');
toolsEl.appendChild(node);
node.appendChild(dom.html(button.render()));
const toolsEl = document.getElementById(toolsCmp.getId());
toolsEl.classList.remove('hidden');
if (toolsCmp.getComponents().length > 0) {
toolsEl.style.justifyContent = 'space-between';
toolsEl.insertBefore(dom.html(divider.render()), toolsEl.firstChild);
toolsEl.insertBefore(dom.html(button.render()), toolsEl.firstChild);
} else {
toolsEl.appendChild(dom.html(button.render()));
const node = document.createElement('div');
if (typeof button.getValue === 'function') {
node.classList.add('grow');
toolsEl.appendChild(node);
node.appendChild(dom.html(button.render()));
} else {
toolsEl.appendChild(dom.html(button.render()));
}
}
toolsCmp.addComponent(button);
button.onRender();
}
toolsCmp.addComponent(button);
button.onRender();
},
onInit() {
this.on('render', this.onRender);
Expand All @@ -511,7 +595,6 @@ const Legend = function Legend(options = {}) {
components: backgroundLayerButtons,
cls: 'spacing-horizontal-small'
});

this.render();
this.dispatch('render');
viewer.getMap().on('click', onMapClick);
Expand All @@ -527,7 +610,7 @@ const Legend = function Legend(options = {}) {
if (turnOnLayersControl) layerControlCmps.push(turnOnLayersButton);
if (turnOffLayersControl) layerControlCmps.push(turnOffLayersButton);
const layerControl = El({
cls: 'grow flex justify-end align-center no-shrink',
cls: 'flex justify-end align-center no-shrink',
components: layerControlCmps
});
mainContainerEl = document.getElementById(mainContainerCmp.getId());
Expand Down Expand Up @@ -609,15 +692,16 @@ const Legend = function Legend(options = {}) {
style: {
'background-color': '#fff',
height: '50px',
'border-top': '1px solid #dbdbdb'
'border-top': '1px solid #dbdbdb',
'border-radius': '0.5rem'
},
components: baselayerCmps
});

const mainContainerComponents = [overlaysCmp, visibleOverlaysCmp, toolsCmp, baselayersCmp];

mainContainerCmp = El({
cls: 'flex column overflow-hidden relative',
cls: 'flex column relative width-100',
components: mainContainerComponents,
style: {
'max-height': `${maxHeight}px`
Expand Down
2 changes: 2 additions & 0 deletions src/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ export { default as Icon } from './ui/icon';
export { default as Element } from './ui/element';
export { default as Input } from './ui/input';
export { default as InputRange } from './ui/input-range';
export { default as InputFile } from './ui/input-file';
export { default as Textarea } from './ui/textarea';
export { default as Modal } from './ui/modal';
export { default as PopupMenu } from './ui/popupmenu';
export { default as Slidenav } from './ui/slidenav';
export { default as ToggleGroup } from './ui/togglegroup';
export { default as Component } from './ui/component';
Expand Down
33 changes: 33 additions & 0 deletions src/ui/input-file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Component from './component';

export default function Input(options = {}) {
const {
labelCls = '',
inputCls = '',
label = '',
change
} = options;

return Component({
onInit() {
if (change) {
this.on('change', change.bind(this));
this.on('clear', () => {
this.un('change', change.bind(this));
});
}
},
onRender() {
const el = document.getElementById(this.getId());
el.addEventListener('change', this.onChange.bind(this));
},
onChange(evt) {
this.dispatch('change', evt);
},
render() {
return `
<label for="${this.getId()}" class="${labelCls}">${label}</label><input id="${this.getId()}" type="file" class="${inputCls}">
`;
}
});
}
1 change: 0 additions & 1 deletion src/ui/popupmenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ export default function popup(options = {}) {
const popupMenuEl = document.getElementById(id);
if (popupMenuEl && !popupMenuEl.contains(e.target)) {
onUnfocus(e);
e.preventDefault();
}
});
},
Expand Down

0 comments on commit e3e5290

Please sign in to comment.