diff --git a/scss/_logger.scss b/scss/_logger.scss
new file mode 100644
index 000000000..bc2da384a
--- /dev/null
+++ b/scss/_logger.scss
@@ -0,0 +1,57 @@
+.logger-toast {
+ border-radius: 0.5em;
+ box-shadow: 0 0 8px #888;
+ padding: 1em;
+ right: 0;
+ left: 0;
+ margin-right: auto;
+ margin-left: auto;
+ text-align: center;
+ position: fixed;
+ z-index: 999;
+ display: inline-block;
+ max-width: 90%;
+ bottom: 2.5rem;
+}
+
+.logger-primary {
+ fill: #084298;
+ color: #084298;
+ background-color: #cfe2ff;
+ border-color: #b6d4fe;
+}
+
+.logger-success {
+ fill: #0f5132;
+ color: #0f5132;
+ background-color: #d1e7dd;
+ border-color: #badbcc;
+}
+
+.logger-info {
+ fill: #055160;
+ color: #055160;
+ background-color: #cff4fc;
+ border-color: #b6effb;
+}
+
+.logger-warning {
+ fill: #664d03;
+ color: #664d03;
+ background-color: #fff3cd;
+ border-color: #ffecb5;
+}
+
+.logger-danger {
+ fill: #842029;
+ color: #842029;
+ background-color: #f8d7da;
+ border-color: #f5c2c7;
+}
+
+.logger-light {
+ fill: #636464;
+ color: #636464;
+ background-color: #fefefe;
+ border-color: #fdfdfe;
+}
\ No newline at end of file
diff --git a/scss/origo.scss b/scss/origo.scss
index adef8d848..3b2003b57 100644
--- a/scss/origo.scss
+++ b/scss/origo.scss
@@ -49,6 +49,7 @@
@import 'scalepicker';
@import 'embedded-overlay';
@import 'spinner';
+ @import 'logger';
}
html,
diff --git a/src/components/logger.js b/src/components/logger.js
new file mode 100644
index 000000000..4b603de2b
--- /dev/null
+++ b/src/components/logger.js
@@ -0,0 +1,109 @@
+import { Icon, Component, Modal } from '../ui';
+
+let viewer;
+let defaults = {
+ toast: {
+ status: 'light',
+ title: 'Meddelande',
+ duration: 5000
+ },
+ modal: {
+ status: 'light',
+ title: 'Meddelande',
+ duration: 0
+ }
+};
+
+function getClass(status) {
+ let cls;
+ if (status === 'primary') {
+ cls = 'logger-primary';
+ } else if (status === 'success') {
+ cls = 'logger-success';
+ } else if (status === 'info') {
+ cls = 'logger-info';
+ } else if (status === 'warning') {
+ cls = 'logger-warning';
+ } else if (status === 'danger') {
+ cls = 'logger-danger';
+ } else {
+ cls = 'logger-light';
+ }
+ return cls;
+}
+
+const createModal = function createModal(options) {
+ const modalSettings = { ...defaults.modal, ...options };
+ const {
+ title = '',
+ message = '',
+ duration,
+ status
+ } = modalSettings;
+ const contentCls = getClass(status);
+
+ let modal = Modal({
+ title,
+ content: message,
+ target: viewer.getId(),
+ contentCls
+ });
+
+ if (duration && duration > 0) {
+ setTimeout(() => {
+ modal.closeModal();
+ modal = null;
+ }, duration);
+ }
+};
+
+const createToast = function createToast(options = {}) {
+ const toastSettings = { ...defaults.toast, ...options };
+ const {
+ status,
+ duration,
+ icon,
+ title = '',
+ message = ''
+ } = toastSettings;
+
+ const contentCls = getClass(status);
+ const toast = document.createElement('div');
+ const parentElement = document.getElementById(viewer.getId());
+ parentElement.appendChild(toast);
+ toast.classList.add('logger-toast');
+ toast.classList.add(contentCls);
+
+ const content = `
+
+
+ ${icon ? Icon({ icon, cls: `${contentCls} icon-medium`, style: 'vertical-align:bottom' }).render() : ''}
+
+ ${title}
+
+ ${message}
+ `;
+ toast.innerHTML = content;
+
+ setTimeout(() => {
+ toast.parentNode.removeChild(toast);
+ }, duration > 0 ? duration : 5000);
+};
+
+const Logger = function Logger(options = {}) {
+ defaults = { ...defaults, ...options };
+ return Component({
+ name: 'logger',
+ createModal,
+ createToast,
+ onAdd(evt) {
+ viewer = evt.target;
+ this.render();
+ },
+ render() {
+ this.dispatch('render');
+ }
+ });
+};
+
+export default Logger;
diff --git a/src/controls/legend.js b/src/controls/legend.js
index 925e01569..2d0c48732 100644
--- a/src/controls/legend.js
+++ b/src/controls/legend.js
@@ -196,8 +196,7 @@ const Legend = function Legend(options = {}) {
},
style: {
'vertical-align': 'bottom',
- 'margin-bottom': '13px',
- 'padding-right': '6px'
+ margin: '0.45rem 0.5rem'
},
icon: '#ic_close_fullscreen_24px',
iconStyle: {
@@ -213,8 +212,7 @@ const Legend = function Legend(options = {}) {
},
style: {
'vertical-align': 'bottom',
- 'margin-bottom': '13px',
- 'padding-right': '6px'
+ margin: '0.45rem 0.5rem'
},
icon: '#ic_open_in_full_24px',
iconStyle: {
@@ -666,8 +664,7 @@ const Legend = function Legend(options = {}) {
cls: 'icon-smaller small round grey-lightest',
style: {
'vertical-align': 'bottom',
- 'margin-bottom': '8.5px',
- 'margin-top': '-2px'
+ margin: '0.2rem 0'
},
icon: '#ic_close_24px',
state: closeButtonState,
@@ -699,7 +696,7 @@ const Legend = function Legend(options = {}) {
style: {
display: 'inline',
'text-align': 'right',
- 'margin-right': '6px'
+ 'margin-right': '0.1rem'
},
components: legendControlCmps
});
@@ -712,7 +709,7 @@ const Legend = function Legend(options = {}) {
'background-color': '#fff',
'border-top': '1px solid #dbdbdb',
'border-radius': '0.5rem',
- 'padding-bottom': '6px'
+ 'line-height': '0'
},
components: baselayerCmps
});
diff --git a/src/controls/legend/visibleOverlays.js b/src/controls/legend/visibleOverlays.js
index 60bf4a733..15e4b3f50 100644
--- a/src/controls/legend/visibleOverlays.js
+++ b/src/controls/legend/visibleOverlays.js
@@ -50,7 +50,7 @@ const Overlays = function Overlays(options) {
mainComponent: groupContainer,
secondaryComponent: layerProps,
cls: 'right flex width-100',
- style: { width: '100%' },
+ style: { width: '100%', display: 'flex' },
legendSlideNav: false,
viewer
});
diff --git a/src/getfeatureinfo.js b/src/getfeatureinfo.js
index 503d533e1..9d02b00b3 100644
--- a/src/getfeatureinfo.js
+++ b/src/getfeatureinfo.js
@@ -319,23 +319,27 @@ function getFeatureInfoRequests({
return requests;
}
-function getFeaturesFromRemote(requestOptions, viewer, textHtmlHandler) {
+async function getFeaturesFromRemote(requestOptions, viewer, textHtmlHandler) {
const requestResult = [];
- const requestPromises = getFeatureInfoRequests(requestOptions, viewer, textHtmlHandler).map((request) => request.fn.then((features) => {
- const layer = viewer.getLayer(request.layer);
- const groupLayers = viewer.getGroupLayers();
- const map = viewer.getMap();
- if (features) {
- features.forEach((feature) => {
+ const requests = getFeatureInfoRequests(requestOptions, viewer, textHtmlHandler);
+ const featureInfoPromises = requests.map((request) => request.fn);
+ const featureInfoPromisesResults = await Promise.allSettled(featureInfoPromises);
+
+ featureInfoPromisesResults.forEach((result, i) => {
+ const layer = viewer.getLayer(requests[i].layer);
+ if (result.status === 'fulfilled' && result.value) {
+ const groupLayers = viewer.getGroupLayers();
+ const map = viewer.getMap();
+ result.value.forEach((feature) => {
const si = createSelectedItem(feature, layer, map, groupLayers);
requestResult.push(si);
});
- return requestResult;
+ } else {
+ console.warn(`GetFeatureInfo request failed for layer: ${layer.get('name')}`);
}
+ });
- return false;
- }));
- return Promise.all([...requestPromises]).then(() => requestResult).catch(error => console.log(error));
+ return requestResult;
}
function getFeaturesAtPixel({
diff --git a/src/ui/modal.js b/src/ui/modal.js
index 6ab2a3952..54bf41049 100644
--- a/src/ui/modal.js
+++ b/src/ui/modal.js
@@ -25,6 +25,7 @@ export default function Modal(options = {}) {
contentElement,
contentCmp,
cls = '',
+ contentCls = '',
isStatic = options.static,
target,
closeIcon = '#ic_close_24px',
@@ -139,7 +140,7 @@ export default function Modal(options = {}) {
}
return `
${screenEl.render()}
-
+
${headerEl.render()}
${contentEl.render()}
diff --git a/src/viewer.js b/src/viewer.js
index 49b331477..4dc16a4f8 100644
--- a/src/viewer.js
+++ b/src/viewer.js
@@ -18,6 +18,7 @@ import flattenGroups from './utils/flattengroups';
import getcenter from './geometry/getcenter';
import isEmbedded from './utils/isembedded';
import generateUUID from './utils/generateuuid';
+import Logger from './components/logger';
import permalink from './permalink/permalink';
import Stylewindow from './style/stylewindow';
@@ -54,6 +55,7 @@ const Viewer = function Viewer(targetOption, options = {}) {
source = {},
clusterOptions = {},
tileGridOptions = {},
+ loggerOptions = {},
url,
palette
} = options;
@@ -105,6 +107,7 @@ const Viewer = function Viewer(targetOption, options = {}) {
const footer = Footer({
data: footerData
});
+ const logger = Logger(loggerOptions);
const centerMarker = CenterMarker();
let mapSize;
@@ -527,6 +530,10 @@ const Viewer = function Viewer(targetOption, options = {}) {
return urlParams;
};
+ const getLogger = function getLogger() {
+ return logger;
+ };
+
/**
* Internal helper used when urlParams.feature is set and the popup should be displayed.
* @param {any} feature
@@ -588,6 +595,7 @@ const Viewer = function Viewer(targetOption, options = {}) {
this.addComponent(selectionmanager);
this.addComponent(featureinfo);
this.addComponent(centerMarker);
+ this.addComponent(logger);
this.addControls();
@@ -718,7 +726,8 @@ const Viewer = function Viewer(targetOption, options = {}) {
getEmbedded,
permalink,
generateUUID,
- centerMarker
+ centerMarker,
+ getLogger
});
};