Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WMS layer support for the disclaimer service #4946

Merged
merged 1 commit into from
Jun 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 79 additions & 36 deletions contribs/gmf/src/disclaimer/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,6 @@ const module = angular.module('gmfDisclaimer', [
]);


/**
*
* @param {import("ol/layer/Base.js").default} layer Layer
* @param {function(string):void} func Function
*/
function forEachDisclaimer(layer, func) {
const disclaimers = layer.get('disclaimers');
if (disclaimers && Array.isArray(disclaimers)) {
disclaimers.forEach(func);
}
}


/**
* Used metadata:
*
Expand Down Expand Up @@ -219,30 +206,23 @@ DisclaimerController.prototype.registerLayer_ = function(layer) {

if (this.layerVisibility) {
// Show disclaimer messages for this layer
forEachDisclaimer(layer, (disclaimer) => {
if (layer.getVisible()) {
this.showDisclaimerMessage_(disclaimer);
}
});
if (layer.getVisible()) {
this.update_(layer);
} else {
this.closeAll_(layer);
}

const listenerKey = olEvents.listen(layer, 'change:visible', (event) => {
const layer = event.target;
const listenerKey = olEvents.listen(layer, 'change', (event) => {
if (layer.getVisible()) {
forEachDisclaimer(layer, (disclaimer) => {
this.showDisclaimerMessage_(disclaimer);
});
this.update_(layer);
} else {
forEachDisclaimer(layer, (disclaimer) => {
this.closeDisclaimerMessage_(disclaimer);
});
this.closeAll_(layer);
}
});
this.eventHelper_.addListenerKey(layerUid, listenerKey);
} else {
// Show disclaimer messages for this layer
forEachDisclaimer(layer, (disclaimer) => {
this.showDisclaimerMessage_(disclaimer);
});
this.showAll_(layer);
}
}
};
Expand All @@ -265,11 +245,8 @@ DisclaimerController.prototype.unregisterLayer_ = function(layer) {
layer.getLayers().forEach(layer => this.unregisterLayer_(layer));

} else {

// Close disclaimer messages for this layer
forEachDisclaimer(layer, (disclaimer) => {
this.closeDisclaimerMessage_(disclaimer);
});
// Close all disclaimer messages for this layer
this.closeAll_(layer);
}

};
Expand All @@ -281,10 +258,11 @@ DisclaimerController.prototype.$onDestroy = function() {


/**
* @param {string} layerUid Layer identifier.
* @param {string} msg Disclaimer message.
* @private
*/
DisclaimerController.prototype.showDisclaimerMessage_ = function(msg) {
DisclaimerController.prototype.showDisclaimerMessage_ = function(layerUid, msg) {
msg = this.gettextCatalog_.getString(msg);
if (this.external) {
if (this.msgs_.indexOf(msg) < 0) {
Expand All @@ -296,6 +274,7 @@ DisclaimerController.prototype.showDisclaimerMessage_ = function(msg) {
this.disclaimer_.alert({
popup: this.popup,
msg: msg,
layerUid: layerUid,
target: this.element_,
type: MessageType.WARNING
});
Expand All @@ -304,10 +283,73 @@ DisclaimerController.prototype.showDisclaimerMessage_ = function(msg) {


/**
* @param {import("ol/layer/Base.js").default} layer Layer
* @private
*/
DisclaimerController.prototype.closeAll_ = function(layer) {
const disclaimers = layer.get('disclaimers');
if (disclaimers) {
const layerUid = olUtilGetUid(layer);
for (const key in disclaimers) {
const uid = `${layerUid}-${key}`;
this.closeDisclaimerMessage_(uid, disclaimers[key]);
}
}
};


/**
* @param {import("ol/layer/Base.js").default} layer Layer
* @private
*/
DisclaimerController.prototype.showAll_ = function(layer) {
const disclaimers = layer.get('disclaimers');
if (disclaimers) {
const layerUid = olUtilGetUid(layer);
for (const key in disclaimers) {
const uid = `${layerUid}-${key}`;
this.showDisclaimerMessage_(uid, disclaimers[key]);
}
}
};


/**
* @param {import("ol/layer/Base.js").default} layer Layer
* @private
*/
DisclaimerController.prototype.update_ = function(layer) {
const disclaimers = layer.get('disclaimers');
if (disclaimers) {
if ('all' in disclaimers) {
// the disclaimer is for all the layers, WMS or WMTS.
console.assert(Object.keys(disclaimers).length === 1);
this.showAll_(layer);
} else {
const layerWMS = /** @type {import("ol/layer/Layer.js").default} */ (layer);
const sourceWMS = /** @type {import("ol/source/ImageWMS.js").default} */ (layerWMS.getSource());
if (sourceWMS.getParams) {
const layers = sourceWMS.getParams()['LAYERS'];
const layerUid = olUtilGetUid(layer);
for (const key in disclaimers) {
const uid = `${layerUid}-${key}`;
if (layers.indexOf(key) !== -1) {
this.showDisclaimerMessage_(uid, disclaimers[key]);
} else {
this.closeDisclaimerMessage_(uid, disclaimers[key]);
}
}
}
}
}
};

/**
* @param {string} layerUid Layer identifier.
* @param {string} msg Disclaimer message.
* @private
*/
DisclaimerController.prototype.closeDisclaimerMessage_ = function(msg) {
DisclaimerController.prototype.closeDisclaimerMessage_ = function(layerUid, msg) {
msg = this.gettextCatalog_.getString(msg);
if (this.external) {
this.visibility = false;
Expand All @@ -317,6 +359,7 @@ DisclaimerController.prototype.closeDisclaimerMessage_ = function(msg) {
this.disclaimer_.close({
popup: this.popup,
msg: msg,
layerUid: layerUid,
target: this.element_,
type: MessageType.WARNING
});
Expand Down
12 changes: 9 additions & 3 deletions contribs/gmf/src/layertree/SyncLayertreeMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ SyncLayertreeMap.prototype.createWMTSLayer_ = function(gmfLayerWMTS) {

/**
* Update properties of a layer with the node of a given leafNode.
* @param {import('gmf/themes.js').GmfLayer} leafNode a leaf node.
* @param {import('gmf/themes.js').GmfLayer|import('gmf/themes.js').GmfLayerWMS} leafNode a leaf node.
* @param {import("ol/layer/Base.js").default} layer A layer.
* @private
*/
Expand All @@ -356,8 +356,14 @@ SyncLayertreeMap.prototype.updateLayerReferences_ = function(leafNode, layer) {

const disclaimer = leafNode.metadata.disclaimer;
if (disclaimer) {
const disclaimers = layer.get('disclaimers') || [];
disclaimers.push(leafNode.metadata.disclaimer);
const disclaimers = layer.get('disclaimers') || {};

// 'all' means that the disclaimer is for all the layer.
let layers = 'all';
if ('layers' in leafNode) {
layers = /** @type {import('gmf/themes.js').GmfLayerWMS} */ (leafNode).layers;
}
disclaimers[layers] = leafNode.metadata.disclaimer;
layer.set('disclaimers', disclaimers);
}
};
Expand Down
93 changes: 75 additions & 18 deletions src/message/Disclaimer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ import ngeoMessageMessage, {MessageType} from 'ngeo/message/Message.js';
import 'ngeo/sass/font.scss';


/**
* A message to display by the disclaimer service.
*
* @typedef {Object} Message
* @property {number} [delay=7000] The delay in milliseconds the message is shown
* @property {boolean} [popup=false] Whether the message should be displayed inside a popup window or not.
* @property {string} msg The message text to display.
* @property {string} [layerUid] The OpenLayers layer identifier.
* @property {JQuery|Element|string} [target] The target element (or selector to get the element) in which
* to display the message. If not defined, then the default target of the notification service is used.
* @property {string} [type='info'] The type of message.
*/


/**
* Provides methods to display any sort of messages, disclaimers, errors,
* etc. Requires Bootstrap library (both CSS and JS) to display the alerts
Expand Down Expand Up @@ -55,12 +69,24 @@ export class MessageDisclaimerService extends ngeoMessageMessage {
* @private
*/
this.messages_ = {};

/**
* @type {Object<string, number>}
* @private
*/
this.messagesConsumerCount_ = {};

/**
* @type {Object<string, boolean>}
* @private
*/
this.uids_ = {};
}

/**
* Show disclaimer message string or object or list of disclaimer message
* strings or objects.
* @param {string|import('ngeo/message/Message.js').Message|Array.<string|import('ngeo/message/Message.js').Message>}
* @param {string|Message|Array.<string|Message>}
* object A message or list of messages as text or configuration objects.
*/
alert(object) {
Expand All @@ -70,17 +96,17 @@ export class MessageDisclaimerService extends ngeoMessageMessage {
/**
* Close disclaimer message string or object or list of disclaimer message
* strings or objects.
* @param {string|import('ngeo/message/Message.js').Message|Array.<string|import('ngeo/message/Message.js').Message>}
* @param {string|Message|Array.<string|Message>}
* object A message or list of messages as text or configuration objects.
*/
close(object) {
const msgObjects = this.getMessageObjects(object);
msgObjects.forEach(this.closeMessage_, this);
msgObjects.forEach((message) => this.closeMessage_(message));
}

/**
* Show the message.
* @param {import('ngeo/message/Message.js').Message} message Message.
* @param {Message} message Message.
* @protected
* @override
*/
Expand All @@ -89,15 +115,15 @@ export class MessageDisclaimerService extends ngeoMessageMessage {
const type = message.type;
console.assert(typeof type == 'string', 'Type should be set.');

// No need to do anything if message already exist.
// No need to do anything if message already displayed.
const uid = this.getMessageUid_(message);
if (this.messages_[uid] !== undefined) {
if (this.uids_[uid]) {
return;
}

const showInPopup = message.popup === true;
this.uids_[uid] = true;

if (showInPopup) {
if (message.popup === true) {
// display the message in a popup, i.e. using the ngeo create popup
const popup = this.createPopup_();
const content = this.sce_.trustAsHtml(message.msg);
Expand All @@ -108,7 +134,7 @@ export class MessageDisclaimerService extends ngeoMessageMessage {
});

// Watch the open property
popup.scope.$watch('open', (newVal, oldVal) => {
popup.scope.$watch('open', newVal => {
if (!newVal) {
this.closeMessage_(message);
}
Expand All @@ -117,6 +143,14 @@ export class MessageDisclaimerService extends ngeoMessageMessage {
this.messages_[uid] = popup;

} else {
// get an already displayed compatible message.
const compatibleMessageUid = this.getCompatibleMessageUid_(message);
if (this.messages_[compatibleMessageUid]) {
// we already have a message
this.messagesConsumerCount_[compatibleMessageUid]++;
return;
}

// display the message using a bootstrap dismissible alert
const classNames = ['alert', 'fade', 'alert-dismissible', 'show'];
switch (type) {
Expand Down Expand Up @@ -158,36 +192,58 @@ export class MessageDisclaimerService extends ngeoMessageMessage {

// Listen when the message gets closed to cleanup the cache of messages
el.on('closed.bs.alert', () => {
this.closeMessage_(message);
this.closeMessage_(message, true);
});

this.messages_[uid] = el;
this.messages_[compatibleMessageUid] = el;
this.messagesConsumerCount_[compatibleMessageUid] = 1;
}
}

/**
* @param {import('ngeo/message/Message.js').Message} message Message.
* @param {Message} message Message.
* @return {string} The uid.
* @private
*/
getMessageUid_(message) {
return `${message.msg}-${message.type}-${message.layerUid}`;
}

/**
* @param {Message} message Message.
* @return {string} The uid.
* @private
*/
getCompatibleMessageUid_(message) {
return `${message.msg}-${message.type}`;
}

/**
* Close the message.
* @param {import('ngeo/message/Message.js').Message} message Message.
* @param {Message} message Message.
* @param {boolean} force Force close the message.
* @protected
*/
closeMessage_(message) {
closeMessage_(message, force = false) {
const uid = this.getMessageUid_(message);
const obj = this.messages_[uid];

// (1) No need to do anything if message doesn't exist
if (obj === undefined) {
if (!this.uids_[uid]) {
return;
}
delete this.uids_[uid];
const compatibleMessageUid = this.getCompatibleMessageUid_(message);
if (force) {
this.messagesConsumerCount_[compatibleMessageUid] = 0;
} else {
this.messagesConsumerCount_[compatibleMessageUid]--;
}
if (this.messagesConsumerCount_[compatibleMessageUid] > 0) {
// the message is still used
return;
}

const obj = this.messages_[compatibleMessageUid];

// (2) Close message (popup or alert)
if (obj instanceof MessagePopup) {
// (2.1) Close popup, if not already closed
Expand All @@ -205,7 +261,8 @@ export class MessageDisclaimerService extends ngeoMessageMessage {
}

// (3) Remove message from cache since it's closed now.
delete this.messages_[uid];
delete this.messages_[compatibleMessageUid];
delete this.messagesConsumerCount_[compatibleMessageUid];
}
}

Expand Down
Loading