diff --git a/src/css/map-view.css b/src/css/map-view.css index ce9bddef6..d3c9439e8 100644 --- a/src/css/map-view.css +++ b/src/css/map-view.css @@ -120,6 +120,10 @@ font-size: 1rem; } +.map-view__button--active { + background-color: var(--map-col-highlight); +} + /* ---- BADGE ---- */ .map-view__badge{ @@ -953,4 +957,18 @@ other class: .ui-slider-range */ box-shadow: var(--map-shadow-md); /* imagery appears lighter on the map */ filter: brightness(1.75); -} \ No newline at end of file +} + +/***************************************************************************************** + * + * Draw Tool + * + * Panel for drawing polygons in the map + * + */ + +.draw-tool { + display: grid; + grid-auto-rows: min-content; + grid-gap: 1rem; +} diff --git a/src/js/models/maps/assets/CesiumVectorData.js b/src/js/models/maps/assets/CesiumVectorData.js index 2efc337db..69591079a 100644 --- a/src/js/models/maps/assets/CesiumVectorData.js +++ b/src/js/models/maps/assets/CesiumVectorData.js @@ -519,7 +519,7 @@ define([ */ removeEntity: function (entity) { try { - const entities = this.getEntities(); + const entities = this.getEntityCollection(); if (!entities) return false; let removed = false; // if entity is a string, remove by ID diff --git a/src/js/models/maps/assets/MapAsset.js b/src/js/models/maps/assets/MapAsset.js index e84fd5320..e02f5391c 100644 --- a/src/js/models/maps/assets/MapAsset.js +++ b/src/js/models/maps/assets/MapAsset.js @@ -84,6 +84,8 @@ define([ * the asset is not supported, or there was a problem requesting the resource. * @property {string} [statusDetails = null] Any further details about the status, * especially when there was an error. + * @property {Boolean} [hideInLayerList = false] Set to true to hide this asset + * from the layer list. */ defaults: function () { return { @@ -105,6 +107,7 @@ define([ notification: {}, status: null, statusDetails: null, + hideInLayerList: false, }; }, @@ -171,6 +174,8 @@ define([ * @property {MapConfig#Notification} [notification] A custom badge and message to * display about the layer in the Layer list. For example, this could highlight * the layer if it is new, give a warning if they layer is under development, etc. + * @property {boolean} [hideInLayerList] - Set to true to hide this asset from the + * layer list. */ /** @@ -280,24 +285,25 @@ define([ */ /** - * A notification displays a badge in the {@link LayerListView} and a message in - * the {@link LayerDetailsView}. This is useful for indicating some special status - * of the layer: "new", "under development", etc. - * @typedef {Object} Notification - * @name MapConfig#Notification - * @since 2.22.0 - * @property {'yellow'|'green'|'blue'|'contrast'} [style] - The badge and message - * color. If none is set, then notification elements will be similar to the - * background colour (subtle). - * @property {string} badge - The text to display in the badge element next to the - * layer label in the list. This badge should be as few characters as possible. - * @property {string} message - A longer message to display explaining the status. - - /** - * Executed when a new MapAsset model is created. - * @param {MapConfig#MapAssetConfig} [assetConfig] The initial values of the - * attributes, which will be set on the model. - */ + * A notification displays a badge in the {@link LayerListView} and a message in + * the {@link LayerDetailsView}. This is useful for indicating some special status + * of the layer: "new", "under development", etc. + * @typedef {Object} Notification + * @name MapConfig#Notification + * @since 2.22.0 + * @property {'yellow'|'green'|'blue'|'contrast'} [style] - The badge and message + * color. If none is set, then notification elements will be similar to the + * background colour (subtle). + * @property {string} badge - The text to display in the badge element next to the + * layer label in the list. This badge should be as few characters as possible. + * @property {string} message - A longer message to display explaining the status. + */ + + /** + * Executed when a new MapAsset model is created. + * @param {MapConfig#MapAssetConfig} [assetConfig] The initial values of the + * attributes, which will be set on the model. + */ initialize: function (assetConfig) { try { const model = this; diff --git a/src/js/views/maps/DrawToolView.js b/src/js/views/maps/DrawToolView.js index 768f4499c..9a93bbda8 100644 --- a/src/js/views/maps/DrawToolView.js +++ b/src/js/views/maps/DrawToolView.js @@ -38,9 +38,28 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect */ buttonClass: "map-view__button", + /** + * Class to use for the active button + * @type {string} + */ + buttonClassActive: "map-view__button--active", + + /** + * @typedef {Object} DrawToolButtonOptions + * @property {string} name - The name of the button. This should be the + * same as the mode that the button will activate (if the button is + * supposed to activate a mode). + * @property {string} label - The label to display on the button. + * @property {string} icon - The name of the icon to display on the + * button. + * @property {string} [method] - The name of the method to call when the + * button is clicked. If this is not provided, the button will toggle the + * mode of the draw tool. + */ + /** * The buttons to display in the toolbar and their corresponding actions. - * TODO: Finish documenting this when more finalized. + * @type {DrawToolButtonOptions[]} */ buttons: [ { @@ -48,21 +67,21 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect label: "Draw Polygon", icon: "pencil", }, - { - name: "move", - label: "Move Point", - icon: "move", - }, - { - name: "remove", - label: "Remove Point", - icon: "eraser", - }, + // { + // name: "move", + // label: "Move Point", + // icon: "move", + // }, + // { + // name: "remove", + // label: "Remove Point", + // icon: "eraser", + // }, { name: "clear", label: "Clear Polygon", icon: "trash", - method: "clearPoints", + method: "reset", }, { name: "save", @@ -72,6 +91,12 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect }, ], + /** + * The buttons that have been rendered in the toolbar. Formatted as an + * object with the button name as the key and the button element as the + * value. + * @type {Object} + */ buttonEls: {}, /** @@ -120,7 +145,7 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect * between 0 and 1. * @type {number} */ - opacity: 0.8, + opacity: 0.5, /** * Initializes the DrawTool @@ -134,7 +159,7 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect initialize: function (options) { this.mapModel = options.model; if (!this.mapModel) { - this.handleNoMapModel(); + console.warn("No map model was provided."); return; } // Add models & collections and add interactions, layer, connector, @@ -166,7 +191,7 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect type: "CustomDataSource", label: "Your Polygon", description: "The polygon that you are drawing on the map", - hideInLayerList: true, // TODO: Hide in LayerList, doc in mapConfig + hideInLayerList: true, outlineColor: this.color, opacity: this.opacity, colorPalette: { @@ -217,15 +242,24 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect this.points?.reset(null); }, + /** + * Resets the draw tool to its initial state. + */ + reset: function () { + this.setMode(false); + this.clearPoints(); + this.removeClickListeners(); + }, + /** * Removes the polygon object from the map - * TODO: Test this */ removeLayer: function () { if (!this.mapModel || !this.layer) return; - // TODO - this.connector.disconnect(); - this.connector.set("vectorLayer", null); + this.polygonConnector.disconnect(); + this.polygonConnector.set("vectorLayer", null); + this.pointsConnector.disconnect(); + this.pointsConnector.set("vectorLayer", null); this.mapModel.removeAsset(this.layer); }, @@ -234,17 +268,23 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect * @returns {DrawTool} Returns the view */ render: function () { + if(!this.mapModel) { + this.showError("No map model was provided."); + return this; + } this.renderToolbar(); return this; }, /** - * What to do when this view doesn't have a map view to draw on + * Show an error message to the user if the map model is not available + * or any other error occurs. + * @param {string} [message] - The error message to show to the user. */ - handleNoMapModel: function () { - console.warn("No map model provided to DrawTool"); - // TODO: Add a message to the view to let the user know that the draw - // tool is not available + showError: function (message) { + const str = `` + + ` The draw tool is not available. ${message}`; + this.el.innerHTML = str; }, /** @@ -274,13 +314,14 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect /** * Sends the polygon coordinates to a callback function to do something * with them. - * TODO: This is a WIP. + * @param {Function} callback - The callback function to send the polygon + * coordinates to. */ - save: function () { + save: function (callback) { this.setMode(false); - this.removeClickListeners(); - console.log(this.points.toJSON()); - // TODO: Call a callback function to save the polygon + if(callback && typeof callback === "function") { + callback(this.points.toJSON()); + } }, /** @@ -321,7 +362,7 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect const buttonEl = this.buttonEls[buttonName + "Button"]; if(!buttonEl) return; this.resetButtonStyles(); - buttonEl.style.backgroundColor = "blue"; // TODO - create active style + buttonEl.classList.add(this.buttonClassActive); }, /** @@ -331,7 +372,10 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect resetButtonStyles: function () { // Iterate through the buttonEls object and reset the styles for (const button in this.buttonEls) { - this.buttonEls[button].style.backgroundColor = "grey"; // TODO - create default style + if (this.buttonEls.hasOwnProperty(button)) { + const buttonEl = this.buttonEls[button]; + buttonEl.classList.remove(this.buttonClassActive); + } } }, @@ -396,10 +440,10 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect */ handleClick: function (throttle = 50) { // Prevent double clicks - if (this.blockClick) return; - this.blockClick = true; + if (this.clickActionBlocked) return; + this.clickActionBlocked = true; setTimeout(() => { - this.blockClick = false; + this.clickActionBlocked = false; }, throttle); // Add the point to the polygon if (this.mode === "draw") { diff --git a/src/js/views/maps/LayerListView.js b/src/js/views/maps/LayerListView.js index f53e300c4..3cca479b7 100644 --- a/src/js/views/maps/LayerListView.js +++ b/src/js/views/maps/LayerListView.js @@ -107,8 +107,7 @@ define( setListeners: function () { try { if (this.collection) { - this.listenTo(this.collection, 'add', this.render); - this.listenTo(this.collection, 'remove', this.render); + this.listenTo(this.collection, 'add remove reset', this.render); } } catch (e) { console.log('Failed to set listeners:', e); @@ -138,6 +137,10 @@ define( // Render a layer item for each layer in the collection this.collection.forEach(function (layerModel) { + if(layerModel.get('hideInLayerList') === true){ + // skip this layer + return + } var layerItem = new LayerItemView({ model: layerModel })