layer/layerRec/layerInterface.js

  1. 'use strict';
  2. // Controls Interface class is used to provide something to the UI that it can bind to.
  3. // It helps the UI keep in line with the layer state.
  4. // Due to bindings, we cannot destroy & recreate an interface when a legend item
  5. // goes from 'Unknown Placeholder' to 'Specific Layer Type'. This means we cannot
  6. // do object heirarchies, as to go from PlaceholderInterface to FeatureLayerInterface
  7. // would require a new object. Instead, we have a class that exposes all possible
  8. // methods and properties as error throwing stubs. Then we replace those functions
  9. // with real ones once we know the flavour of interface we want.
  10. class LayerInterface {
  11. /**
  12. * @param {Object} source object that provides info to the interface. usually a LayerRecord or FeatureClass
  13. */
  14. constructor (source) {
  15. this._source = source;
  16. // TODO revisit isPlaceholder after grand refactor
  17. this._isPlaceholder = true;
  18. }
  19. get isPlaceholder () { return this._isPlaceholder; } // returns Boolean
  20. // these expose ui controls available on the interface and indicate which ones are disabled
  21. get symbology () { return undefined; } // returns Array
  22. // can be group or node name
  23. get name () { return undefined; } // returns String
  24. // these are needed for the type flag
  25. get layerType () { return undefined; } // returns String
  26. get geometryType () { return undefined; } // returns String
  27. get featureCount () { return undefined; } // returns Integer
  28. get extent () { return undefined; } // returns Object (Esri Extent)
  29. // layer states
  30. get state () { return undefined; } // returns String
  31. // these return the current values of the corresponding controls
  32. get visibility () { return undefined; } // returns Boolean
  33. get opacity () { return undefined; } // returns Decimal
  34. get query () { return undefined; } // returns Boolean
  35. get snapshot () { return undefined; } // returns Boolean
  36. // fetches attributes for use in the datatable
  37. get formattedAttributes () { return undefined; } // returns Promise of Object
  38. // these set values to the corresponding controls
  39. setVisibility () { return undefined; }
  40. setOpacity () { return undefined; }
  41. setQuery () { return undefined; }
  42. setSnapshot () { return undefined; }
  43. zoomToBoundary () { return undefined; } // returns promise that resolves after zoom completes
  44. // updates what this interface is pointing to, in terms of layer data source.
  45. // often, the interface starts with a placeholder to avoid errors and return
  46. // defaults. This update happens after a layer has loaded, and new now want
  47. // the interface reading off the real FC.
  48. // TODO docs
  49. updateSource (newSource) {
  50. this._source = newSource;
  51. }
  52. convertToSingleLayer (layerRecord) {
  53. this._source = layerRecord;
  54. this._isPlaceholder = false;
  55. newProp(this, 'symbology', standardGetSymbology);
  56. newProp(this, 'state', standardGetState);
  57. newProp(this, 'visibility', standardGetVisibility);
  58. newProp(this, 'opacity', standardGetOpacity);
  59. newProp(this, 'query', standardGetQuery);
  60. newProp(this, 'name', standardGetName);
  61. newProp(this, 'geometryType', standardGetGeometryType);
  62. newProp(this, 'layerType', standardGetLayerType);
  63. newProp(this, 'featureCount', standardGetFeatureCount);
  64. newProp(this, 'extent', standardGetExtent);
  65. this.setVisibility = standardSetVisibility;
  66. this.setOpacity = standardSetOpacity;
  67. this.setQuery = standardSetQuery;
  68. this.zoomToBoundary = standardZoomToBoundary;
  69. }
  70. convertToFeatureLayer (layerRecord) {
  71. this.convertToSingleLayer(layerRecord);
  72. newProp(this, 'snapshot', featureGetSnapshot);
  73. newProp(this, 'formattedAttributes', standardGetFormattedAttributes);
  74. newProp(this, 'geometryType', featureGetGeometryType);
  75. newProp(this, 'featureCount', featureGetFeatureCount);
  76. this.setSnapshot = featureSetSnapshot;
  77. }
  78. convertToDynamicLeaf (dynamicFC) {
  79. this._source = dynamicFC;
  80. this._isPlaceholder = false;
  81. newProp(this, 'symbology', dynamicLeafGetSymbology);
  82. newProp(this, 'state', dynamicLeafGetState);
  83. newProp(this, 'name', dynamicLeafGetName);
  84. newProp(this, 'visibility', dynamicLeafGetVisibility);
  85. newProp(this, 'opacity', dynamicLeafGetOpacity);
  86. newProp(this, 'query', dynamicLeafGetQuery);
  87. newProp(this, 'formattedAttributes', dynamicLeafGetFormattedAttributes);
  88. newProp(this, 'geometryType', dynamicLeafGetGeometryType);
  89. newProp(this, 'layerType', dynamicLeafGetLayerType);
  90. newProp(this, 'featureCount', dynamicLeafGetFeatureCount);
  91. newProp(this, 'extent', dynamicLeafGetExtent);
  92. this.setVisibility = dynamicLeafSetVisibility;
  93. this.setOpacity = dynamicLeafSetOpacity;
  94. this.setQuery = dynamicLeafSetQuery;
  95. this.zoomToBoundary = dynamicLeafZoomToBoundary;
  96. }
  97. convertToPlaceholder (placeholderFC) {
  98. this._source = placeholderFC;
  99. this._isPlaceholder = true;
  100. newProp(this, 'symbology', standardGetSymbology);
  101. newProp(this, 'name', standardGetName);
  102. newProp(this, 'state', standardGetState);
  103. newProp(this, 'layerType', standardGetLayerType);
  104. }
  105. }
  106. /**
  107. * Worker function to add or override a get property on an object
  108. *
  109. * @function newProp
  110. * @private
  111. * @param {Object} target the object that will receive the new property
  112. * @param {String} propName name of the get property
  113. * @param {Function} getter the function defining the guts of the get property.
  114. */
  115. function newProp(target, propName, getter) {
  116. Object.defineProperty(target, propName, {
  117. get: getter,
  118. enumerable: true,
  119. configurable: true
  120. });
  121. }
  122. // these functions are upgrades to the duds above.
  123. // we don't use arrow notation, as we want the `this` to point at the object
  124. // that these functions get smashed into.
  125. function standardGetState() {
  126. /* jshint validthis: true */
  127. return this._source.state;
  128. }
  129. function dynamicLeafGetState() {
  130. /* jshint validthis: true */
  131. return this._source.state;
  132. }
  133. function standardGetVisibility() {
  134. /* jshint validthis: true */
  135. return this._source.visibility;
  136. }
  137. function dynamicLeafGetVisibility() {
  138. /* jshint validthis: true */
  139. return this._source.getVisibility();
  140. }
  141. function standardGetName() {
  142. /* jshint validthis: true */
  143. return this._source.name;
  144. }
  145. function dynamicLeafGetName() {
  146. /* jshint validthis: true */
  147. return this._source.name;
  148. }
  149. function standardGetOpacity() {
  150. /* jshint validthis: true */
  151. return this._source.opacity;
  152. }
  153. function dynamicLeafGetOpacity() {
  154. /* jshint validthis: true */
  155. return this._source.opacity;
  156. }
  157. function standardGetLayerType() {
  158. /* jshint validthis: true */
  159. return this._source.layerType;
  160. }
  161. function dynamicLeafGetLayerType() {
  162. /* jshint validthis: true */
  163. return this._source.layerType;
  164. }
  165. function standardGetExtent() {
  166. /* jshint validthis: true */
  167. return this._source.extent;
  168. }
  169. function dynamicLeafGetExtent() {
  170. /* jshint validthis: true */
  171. return this._source.extent;
  172. }
  173. function standardGetQuery() {
  174. /* jshint validthis: true */
  175. return this._source.isQueryable();
  176. }
  177. function dynamicLeafGetQuery() {
  178. /* jshint validthis: true */
  179. return this._source.queryable;
  180. }
  181. function standardGetFormattedAttributes() {
  182. /* jshint validthis: true */
  183. return this._source.getFormattedAttributes();
  184. }
  185. function dynamicLeafGetFormattedAttributes() {
  186. /* jshint validthis: true */
  187. // TODO code-wise this looks identical to standardGetFormattedAttributes.
  188. // however in this case, ._source is a DynamicFC, not a LayerRecord.
  189. // This is safer. Deleting this would avoid the duplication. Decide.
  190. return this._source.getFormattedAttributes();
  191. }
  192. function standardGetSymbology() {
  193. /* jshint validthis: true */
  194. return this._source.symbology;
  195. }
  196. function dynamicLeafGetSymbology() {
  197. /* jshint validthis: true */
  198. // TODO code-wise this looks identical to standardGetSymbology.
  199. // however in this case, ._source is a DynamicFC, not a LayerRecord.
  200. // This is safer. Deleting this would avoid the duplication. Decide.
  201. return this._source.symbology;
  202. }
  203. function standardGetGeometryType() {
  204. /* jshint validthis: true */
  205. return undefined;
  206. }
  207. function featureGetGeometryType() {
  208. /* jshint validthis: true */
  209. return this._source.getGeomType();
  210. }
  211. function dynamicLeafGetGeometryType() {
  212. /* jshint validthis: true */
  213. // TEST STATUS none
  214. return this._source.geomType;
  215. }
  216. function standardGetFeatureCount() {
  217. /* jshint validthis: true */
  218. return undefined;
  219. }
  220. function featureGetFeatureCount() {
  221. /* jshint validthis: true */
  222. return this._source.featureCount;
  223. }
  224. function dynamicLeafGetFeatureCount() {
  225. /* jshint validthis: true */
  226. return this._source.featureCount;
  227. }
  228. function standardSetVisibility(value) {
  229. /* jshint validthis: true */
  230. this._source.visibility = value;
  231. }
  232. function dynamicLeafSetVisibility(value) {
  233. /* jshint validthis: true */
  234. this._source.setVisibility(value);
  235. }
  236. function standardSetOpacity(value) {
  237. /* jshint validthis: true */
  238. this._source.opacity = value;
  239. }
  240. function dynamicLeafSetOpacity(value) {
  241. /* jshint validthis: true */
  242. this._source.opacity = value;
  243. }
  244. function standardSetQuery(value) {
  245. /* jshint validthis: true */
  246. this._source.setQueryable(value);
  247. }
  248. function dynamicLeafSetQuery(value) {
  249. /* jshint validthis: true */
  250. this._source.queryable = value;
  251. }
  252. function featureGetSnapshot() {
  253. /* jshint validthis: true */
  254. return this._source.isSnapshot;
  255. }
  256. function featureSetSnapshot() {
  257. // TODO trigger the snapshot process. need the big picture on how this orchestrates.
  258. // it involves a layer reload so possible this function is irrelevant, as the record
  259. // will likely get nuked
  260. console.log('MOCKING THE SNAPSHOT PROCESS');
  261. }
  262. function standardZoomToBoundary(map) {
  263. /* jshint validthis: true */
  264. this._source.zoomToBoundary(map);
  265. }
  266. function dynamicLeafZoomToBoundary(map) {
  267. /* jshint validthis: true */
  268. this._source.zoomToBoundary(map);
  269. }
  270. module.exports = () => ({
  271. LayerInterface
  272. });