From 1f43df999a22630afceb81aa4b6c1c15b1d31ed3 Mon Sep 17 00:00:00 2001 From: Matteo V Date: Fri, 18 May 2018 10:49:59 +0200 Subject: [PATCH] Align master on c125_annotations branch (#2923) * Fix #2602 loader spinner on file import * Fixes #2741: set openlayers single tile wms layers default ratio to 1 (#2742) * Fixed #2626 fixed leaflet measure tool (#2730) * Fixed #2626 fixed leaflet measure tool * added some comments to document changes * improved implementation * added more tests * Fix #2746 leaflet drawing of linestring (#2747) * fix leaflet override * fixed with retrocompatibility * Fixed binding of overridden functions * Croatian language translation (#2755) * Fixes #2748: leaflet draw issues (#2752) * Fixes #2748: leaflet draw issues * Additional fix for measures * Removed bootstrap overlay trigger (#2734) * Fix #2661 First implementation of map widget (#2721) * Fixes #2021: limit list of srs saved in layers from catalog to the ones supported by the current mapstore2 instance (#2756) * Update README.md Add instructions to test MapStore2 using Docker containers * Fixes #2760: integrated printing service (#2761) * Added missing files for printing (#2762) * Removed duplicated and mismatching in version libraries from geostore and mapfish-print (#2763) * Fixes #2631: usage of mapping libraries (#2739) * Fixes #2631: usage of mapping libraries * Fixed switching to 3d mode * Improved sidecard/sidegrid styles and structures (#2764) * Quick fix to embedded map style (#2766) * Fix #2754 Add map widget layer's editing (#2767) * Croatian language translation - update (#2776) * Fix #2778 Embedded doesn't work (#2779) * Added embedded mode in standard app * Removed map layout reducers/epics * Fixed leaflet-draw inclusion in share api template (#2782) * Connect to #2662 Geodashboard single connection support (#2780) * Improved widgets dependencies system * Support for single map connection * removed test for old map sync switches * Add support for map sync (#2783) * Fix #2775 Styles misalignment in BorderLayout component (#2785) * Multiple map connection support (#2791) * Fixes #1506 OpenLayers and Leaflet vector different default styles (#2771) * Fix #2662. Add widget connections and colors (#2793) * Improved suggestion when the user can not create a widget (#2795) * Charts builder improvements (#2796) * Fixed color style in pdf print (#2792) * Fixed color style in pdf print * Tinycolor version * Fix #2798 search clickable (#2800) * fix #2798 make clickable search in home * remove unneeded configuration * update spinner style dinamically and fix example icon * Add back buttons to dashboard and map widgets (#2801) * Add empty state to featuregrid widget (#2802) * Fix #2787 Panels hide the feature info marker (#2788) * Merge pull request #1 from geosolutions-it/master (#2805) * translation data.zh-ZH * Modify spelling mistakes * Fixed #2809. Moved utility function in the proper place (#2810) * Fixed layout of counter widget (#2804) * Add empty map to map selector (#2813) * Fix #2794 Force update of map widget position on save (#2814) * Fix #2807 and add a tool to create chart from feature grid (#2808) * Fix #2807 and add a tool to create chart from feature grid * add a flag for disabling chart creation from feature grid * fix feature grid toolbar test * update flag used to show char in feature grid * Exclude google background from widgets (#2817) * Fix #2812 parseInitialState function (#2818) * fix #2812 update parsing of initialState in localConfig.json * update parsing method * add documentation and test * update documentation * add default in toChangesMap and add a test for empty arrays * Fix #2790 improved wizard messages (#2819) * Fixes #2815: elevation support in MousePosition, through elevation layers (#2816) * fix #2807 back interaction from widget to feature grid (#2821) * Fix #2803 add popover overlay to the sync tool in feature grid (#2829) * Fix #2696 map rotation style for openlayers (#2820) * fix #2696 aligned style of map rotation tool for ol * disable map rotation on openlayers * fix require of maplayout selector (#2834) * Fix #2798 change configuration and make search icon clickable and configurable (#2831) * Fix #2825. Improved messages in case of no attributes layer (#2833) * Fixes #2827 Add featured maps plugin (#2828) * #2827 Minor fixes (#2836) * Fix #2660 implemented first version of save functionalities for dashboard (#2832) * Fix #2773. First rules-editor implementation (#2845) * Fixes #2824: enable elevation layer only for cesium or when mouseposition is enabled (#2841) * fix #2803 synch popover defaults (#2847) * fix #2825 interactions between featuregrid anche chart wizard (#2846) * Removed github link from navbar (#2839) * fix #2852 dev build fails (#2853) * Fix #2610 clipped long descriptions of catalog cards (#2830) * Fix #2664 Implemented browsing functionality for dashboards (#2854) * First version of GeoDashboard browsing - Has a first abstraction of resources browser. can be reused in maps - Still to implement delete and effective link to dashboard * WIP for dashboard browsing Still missing: - i18n and tests - link to the contents - titles of tabs with parenthesis - tests - fix issues with geostore * Finalized code for dashboard browser - Missing translations and tests * Add sample category for dashboards * Fixed groups retrival by admin user * add some tests * Add unit tests * Add i18n * Fixed confirm dialog test * Improved empty view style * Fixed test's context not restored properly * add tests for geostore observables * Fix #2825. Fixed error message for layers with no attributes (#2855) * Fix #2563: Fixed unnecessary details request on Map open (#2849) * Update data.it-IT * Fixes #2700 Toolbar icon for 3D map (#2850) * Minor fixes to localized strings (#2869) * Changed create map/dashboard buttons (#2871) * Fix #2843 and Fix #2659. Fixed resize issues on dashboard and map widgets (#2868) * Added GeoFence admin icon (#2873) * Fix #2856 Legend action plugin (#2857) * Added details editor styles filters and attributes (#2867) * Fix #2876 Cross layer filter doesn't work if layer has localized title (#2877) * Changed MapStore 2 strings to Mapstore (#2882) - All translation files, html - Readme.md Doc pages, pom.xml and package.json still have MapStore 2 * Connected to #2885. Temporary disabled video from detail sheet (#2886) * Fix #2842. Add legend widget (#2884) * Fix #2859 Escape special XML chars for title and description (#2887) * fix #2888 switch to correct 2d mode (#2889) * Added area editor (#2891) * Fix #2892. Remove authkey from dashboard layers (#2894) * Fixed home button position (#2895) * Fix #2862. Add geofence icon to the manager menu (#2899) * Fix #2663. Add edit and view mode to the dashboard (#2901) * Fix #2903. Add support to hide spatial and cross layer filter (#2904) * fix #2696 map rotation disables correctly (#2905) * fix #2861 layer metadata layout (#2863) * fix #2864 properties row viewer (#2865) * Fix #2898 TOC moves down if Measure tool and print are opened (#2900) * fix #2711 remove arc layer when toggling length measure tool (#2902) * RuleEditor Layers filter always enabled (#2907) * Showing spatial filter selection area when FeatureGrid is open (#2906) * Moved icons for firefox/ie support (#2912) * Modify SaveLayer in order to take the custom origin of a wms layer (#2917) * Modify SaveLayer in order to take the custom origin of a wms layer in account (tilegrid config) * update maputils tests --- README.md | 19 + TableWidget.jsx | 74 - buildConfig.js | 8 + docma-config.json | 19 +- docs/developer-guide/maps-configuration.md | 60 +- package.json | 5 +- project/standard/templates/web/pom.xml | 86 + .../translations/findMissingTranslations.js | 2 +- .../actions/__tests__/dashboard-test.js | 96 +- .../actions/__tests__/dashboards-test.js | 74 + .../actions/__tests__/featuregrid-test.js | 23 +- .../actions/__tests__/floatinglegend-test.js | 32 + web/client/actions/__tests__/mapInfo-test.js | 10 +- .../actions/__tests__/rulesmanager-test.js | 39 +- web/client/actions/__tests__/search-test.js | 16 +- web/client/actions/__tests__/widgets-test.js | 28 +- web/client/actions/dashboard.js | 40 +- web/client/actions/dashboards.js | 40 + web/client/actions/featuregrid.js | 22 + web/client/actions/floatinglegend.js | 44 + web/client/actions/mapInfo.js | 16 +- web/client/actions/maps.js | 11 + web/client/actions/rulesmanager.js | 69 +- web/client/actions/search.js | 24 +- web/client/actions/widgets.js | 103 +- web/client/api.html | 6 +- web/client/api/GeoStoreDAO.js | 83 +- web/client/api/WMS.js | 4 +- web/client/api/__tests__/GeoStoreDAO-test.jsx | 4 + web/client/api/geoserver/GeoFence.js | 137 +- web/client/apiTemplate.html | 6 +- web/client/components/I18N/FlagButton.jsx | 22 +- web/client/components/I18N/LangBar.jsx | 79 +- .../I18N/__tests__/LangBar-test.jsx | 2 +- .../I18N/__tests__/LangSelector-test.jsx | 2 +- .../components/I18N/images/flags/hr-HR.png | Bin 0 -> 393 bytes web/client/components/TOC/DefaultLayer.jsx | 97 +- web/client/components/TOC/FloatingLegend.jsx | 229 +++ web/client/components/TOC/Toolbar.jsx | 3 +- .../TOC/__tests__/DefaultLayer-test.jsx | 35 +- .../TOC/__tests__/FloatingLegend-test.jsx | 226 +++ .../TOC/enhancers/tocItemsSettings.js | 57 +- .../components/TOC/fragments/StatusIcon.jsx | 3 +- .../settings/__tests__/General-test.jsx | 4 +- web/client/components/app/StandardApp.jsx | 25 +- .../app/__tests__/StandardApp-test.jsx | 61 + .../buttons/GlobeViewSwitcherButton.jsx | 2 +- web/client/components/catalog/CatalogForm.jsx | 3 +- .../components/catalog/CompactCatalog.jsx | 4 +- web/client/components/catalog/RecordItem.jsx | 8 +- web/client/components/charts/Pie.jsx | 5 +- web/client/components/charts/SimpleChart.jsx | 2 +- web/client/components/dashboard/Dashboard.jsx | 20 +- .../data/download/DownloadOptions.jsx | 2 +- .../data/featuregrid/enhancers/withHint.js | 16 + .../data/featuregrid/enhancers/withPopover.js | 29 + .../data/featuregrid/enhancers/withTooltip.js | 8 + .../filterRenderers/AttributeFilter.jsx | 3 +- .../data/featuregrid/toolbars/TButton.jsx | 19 +- .../data/featuregrid/toolbars/Toolbar.jsx | 92 +- .../toolbars/__tests__/Toolbar-test.jsx | 12 + web/client/components/data/grid/DataGrid.jsx | 1 + .../data/identify/enhancers/identify.js | 8 +- .../identify/viewers/row/PropertiesViewer.jsx | 9 +- .../row/__tests__/PropertiesViewer-test.jsx | 18 + .../components/data/query/QueryBuilder.jsx | 14 +- .../query/__tests__/QueryBuilder-test.jsx | 45 + web/client/components/layout/BorderLayout.jsx | 2 +- .../enhancers/__tests__/gridLayout-test.js | 47 + .../layout/enhancers/gridLayout.jsx | 39 + .../rulesmanager/AttributeAccessSelect.jsx | 24 + .../manager/rulesmanager/AvailableStyles.jsx | 49 + .../manager/rulesmanager/DefaultStyle.jsx | 36 + .../manager/rulesmanager/MapModal.jsx | 41 + .../manager/rulesmanager/RoiCql.jsx | 63 + .../rulesmanager/SimpleSpatialFilter.jsx | 212 +++ .../manager/rulesmanager/StylesList.jsx | 32 + .../manager/rulesmanager/enhancers/Map.js | 74 + .../enhancers/__tests__/autoComplete-test.js | 197 +++ .../enhancers/__tests__/fixedOptions-test.js | 142 ++ .../rulesmanager/enhancers/autoComplete.js | 179 +++ .../rulesmanager/enhancers/filterstyles.js | 24 + .../rulesmanager/enhancers/fixedOptions.js | 83 + .../ruleseditor/AttributesEditor.jsx | 62 + .../rulesmanager/ruleseditor/EditMain.jsx | 28 + .../ruleseditor/FiltersEditor.jsx | 79 + .../rulesmanager/ruleseditor/Header.jsx | 41 + .../rulesmanager/ruleseditor/StylesEditor.jsx | 63 + .../__tests__/AttributesEditor-test.jsx | 54 + .../ruleseditor/__tests__/EditMain-test.jsx | 82 + .../ruleseditor/__tests__/Header-test.jsx | 54 + .../__tests__/StylesEditor-test.jsx | 78 + .../ruleseditor/attributeselectors/Access.jsx | 47 + .../attributeselectors/IpAddress.jsx | 63 + .../ruleseditor/attributeselectors/Layer.jsx | 57 + .../attributeselectors/Priority.jsx | 64 + .../attributeselectors/Request.jsx | 74 + .../ruleseditor/attributeselectors/Role.jsx | 52 + .../attributeselectors/Service.jsx | 56 + .../ruleseditor/attributeselectors/User.jsx | 52 + .../attributeselectors/Workspace.jsx | 52 + .../ruleseditor/attributeselectors/index.js | 12 + .../ruleseditor/enhancers/filters.js | 66 + .../ruleseditor/enhancers/style.js | 19 + .../ruleseditor/enhancers/switch.js | 26 + .../rulesmanager/rulesgrid/RulesGrid.jsx | 123 ++ .../rulesgrid/__tests__/RuleGrid-test.jsx | 32 + .../enhancers/__tests__/filtersStream-test.js | 23 + .../enhancers/__tests__/scrollStream-test.js | 27 + .../enhancers/__tests__/triggerFetch-test.js | 38 + .../__tests__/virtualScrollFetch-test.js | 48 + .../rulesgrid/enhancers/filtersStream.js | 19 + .../rulesgrid/enhancers/reorderRules.js | 33 + .../rulesgrid/enhancers/rulesgrid.js | 110 ++ .../rulesgrid/enhancers/scrollStream.js | 35 + .../rulesgrid/enhancers/triggerFetch.js | 35 + .../rulesgrid/enhancers/virtualScrollFetch.js | 53 + .../filterRenderers/LayersFilter.jsx | 48 + .../filterRenderers/RequestsFilter.jsx | 68 + .../rulesgrid/filterRenderers/RolesFilter.jsx | 43 + .../filterRenderers/ServicesFilter.jsx | 45 + .../rulesgrid/filterRenderers/UsersFilter.jsx | 43 + .../filterRenderers/WorkspacesFilter.jsx | 46 + .../__tests__/WorkspacesFilter-test.jsx | 44 + .../rulesgrid/filterRenderers/index.js | 8 + .../rulesgrid/formatters/AccessFormatter.jsx | 24 + .../__tests__/AccessFormatter-test.jsx | 35 + .../renderers/PriorityActionCell.jsx | 65 + .../rulesgrid/renderers/RuleRenderer.jsx | 47 + .../components/manager/users/GroupGrid.jsx | 4 +- .../components/manager/users/UserGrid.jsx | 4 +- .../users/__tests__/GroupGrid-test.jsx | 8 +- web/client/components/map/BaseMap.jsx | 146 ++ .../map/__tests__/BaseMap-test-chrome.jsx | 146 ++ .../components/map/__tests__/BaseMap-test.jsx | 152 ++ web/client/components/map/cesium/Layer.jsx | 12 +- web/client/components/map/cesium/Map.jsx | 2 + .../map/cesium/__tests__/Map-test-chrome.jsx | 15 + .../components/map/cesium/plugins/WMSLayer.js | 22 +- .../enhancers/__tests__/autoResize-test.js | 48 + .../__tests__/onMapViewChanges-test.js | 46 + .../components/map/enhancers/autoMapType.js | 4 + .../components/map/enhancers/autoResize.js | 38 + .../components/map/enhancers/mapType.js | 17 + .../map/enhancers/onMapViewChanges.js | 41 + .../components/map/enhancers/withDraw.js | 37 + .../components/map/leaflet/DrawSupport.jsx | 66 +- web/client/components/map/leaflet/Map.jsx | 7 +- .../map/leaflet/MeasurementSupport.jsx | 363 ++++- .../components/map/leaflet/SingleClick.js | 43 +- .../map/leaflet/__tests__/Feature-test.jsx | 265 +++ .../map/leaflet/__tests__/Layer-test.jsx | 25 + .../map/leaflet/__tests__/Map-test.jsx | 152 ++ .../__tests__/MeasurementSupport-test.jsx | 235 ++- .../map/leaflet/plugins/BingLayer.js | 4 +- .../map/leaflet/plugins/WMSLayer.js | 50 +- .../components/map/openlayers/Layer.jsx | 3 + web/client/components/map/openlayers/Map.jsx | 5 +- .../map/openlayers/MeasurementSupport.jsx | 6 +- .../components/map/openlayers/VectorStyle.js | 121 +- .../map/openlayers/__tests__/Layer-test.jsx | 83 + .../map/openlayers/__tests__/Map-test.jsx | 125 ++ .../openlayers/__tests__/VectorStyle-test.js | 246 ++- .../map/openlayers/plugins/WMSLayer.js | 97 +- web/client/components/map/plugins/cesium.js | 16 + web/client/components/map/plugins/leaflet.js | 21 + .../components/map/plugins/openlayers.js | 22 + web/client/components/map/plugins/sink.js | 18 + .../mapcontrols/measure/MeasureComponent.jsx | 8 +- .../mouseposition/MousePosition.jsx | 23 +- .../__tests__/MousePosition-test.js | 30 + .../mapcontrols/search/SearchBar.jsx | 58 +- .../mapcontrols/search/SearchResultList.jsx | 8 +- .../search/__tests__/SearchBar-test.jsx | 35 + .../__tests__/SearchResultList-test.jsx | 5 +- web/client/components/maps/MapCard.jsx | 110 +- web/client/components/maps/MapCatalog.jsx | 51 + web/client/components/maps/MapCatalogForm.jsx | 18 + web/client/components/maps/MapGrid.jsx | 36 +- .../maps/__tests__/MapCatalog-test.jsx | 78 + .../enhancers/__tests__/featuredMaps-test.jsx | 112 ++ .../components/maps/enhancers/enhancers.js | 123 ++ .../components/maps/enhancers/featuredMaps.js | 134 ++ .../components/maps/enhancers/mapCatalog.js | 8 + .../maps/enhancers/mapCatalogWithEmptyMap.js | 8 + .../components/maps/modals/MetadataModal.jsx | 2 +- web/client/components/maps/style/mapcard.css | 30 - web/client/components/misc/GridCard.jsx | 35 +- web/client/components/misc/Loader.jsx | 2 +- web/client/components/misc/Overlay.jsx | 11 + .../components/misc/PaginationToolbar.jsx | 48 +- web/client/components/misc/ResizableModal.jsx | 9 + web/client/components/misc/ShowMore.jsx | 46 + web/client/components/misc/Slider.jsx | 24 + .../misc/__tests__/PaginationToolbar-test.jsx | 2 +- .../misc/__tests__/ResizableModal-test.jsx | 12 +- .../misc/__tests__/ShowMore-test.jsx | 57 + .../components/misc/cardgrids/SideCard.jsx | 63 +- .../components/misc/cardgrids/SideGrid.jsx | 65 +- .../cardgrids/__tests__/SideCard-test.jsx | 53 + .../cardgrids/__tests__/SideGrid-test.jsx | 30 + .../misc/combobox/PagedCombobox.jsx | 44 +- .../__tests__/gridPagination-test.jsx | 61 + .../enhancers/__tests__/withMask-test.jsx | 60 + .../misc/enhancers/gridPagination.jsx | 50 + .../misc/enhancers/infiniteScroll/loadMore.js | 2 +- .../infiniteScroll/withInfiniteScroll.js | 12 +- .../enhancers/infiniteScroll/withScrollSpy.js | 15 +- .../misc/enhancers/localizeStringMap.js | 45 + .../misc/enhancers/localizedProps.js | 2 +- .../components/misc/enhancers/tooltip.jsx | 10 +- .../components/misc/enhancers/withMask.js | 46 + .../misc/enhancers/withPropsStream.js | 31 + .../misc/enhancers/withResizeSpy.js | 86 + web/client/components/misc/style/gridcard.css | 3 - .../misc/style/pagination-toolbar.css | 3 - .../components/misc/toolbar/ToolbarButton.jsx | 7 +- .../components/resources/ResourceCard.jsx | 175 ++ .../components/resources/ResourceGrid.jsx | 76 + .../resources/__tests__/ResourceCard-test.jsx | 88 + .../resources/__tests__/ResourceGrid-test.jsx | 43 + .../resources/enhancers/resourceGrid.js | 89 ++ .../components/resources/forms/Metadata.jsx | 85 + .../components/resources/forms/Thumbnail.jsx | 136 ++ .../forms/__tests__/Metadata-test.jsx | 56 + .../forms/__tests__/Thumbnail-test.jsx | 79 + .../resources/modals/ConfirmModal.jsx | 47 + .../resources/modals/DetailSheet.jsx | 84 + .../components/resources/modals/Save.jsx | 122 ++ .../modals/__tests__/Confirm-test.jsx | 33 + .../resources/modals/__tests__/Save-test.jsx | 80 + .../__tests__/handlePermission-test.jsx | 71 + .../__tests__/handleResourceData-test.jsx | 82 + .../modals/enhancers/handleErrors.jsx | 21 + .../modals/enhancers/handlePermission.jsx | 76 + .../modals/enhancers/handleResourceData.jsx | 86 + .../enhancers/handleResourceDownload.js | 34 + .../modals/enhancers/handleSaveModal.js | 20 + .../resources/modals/enhancers/ruleEditor.js | 15 + .../resources/modals/fragments/DetailsRow.jsx | 87 + .../resources/modals/fragments/ErrorBox.jsx | 33 + .../resources/modals/fragments/MainForm.jsx | 55 + .../modals/fragments/PermissionEditor.jsx | 238 +++ .../components/shapefile/SelectShape.jsx | 2 +- .../shapefile/__tests__/SelectShape-test.jsx | 8 + web/client/components/share/api-template.raw | 6 +- .../widgets/builder/WidgetTypeSelector.jsx | 10 + .../widgets/builder/wizard/ChartWizard.jsx | 64 +- .../widgets/builder/wizard/CounterWizard.jsx | 19 +- .../widgets/builder/wizard/LegendWizard.jsx | 66 + .../widgets/builder/wizard/MapWizard.jsx | 51 + .../wizard/__tests__/CounterWizard-test.jsx | 15 +- .../wizard/__tests__/LegendWizard-test.jsx | 59 + .../wizard/__tests__/MapWizard-test.jsx | 50 + .../builder/wizard/chart/ChartType.jsx | 12 +- .../widgets/builder/wizard/chart/Toolbar.jsx | 10 +- .../wizard/chart/__tests__/Toolbar-test.jsx | 68 + .../wizard/common/WPSWidgetOptions.jsx | 16 - .../builder/wizard/common/WidgetOptions.jsx | 1 - .../__tests__/WPSWidgetOptions-test.jsx | 10 +- .../wizard/common/layerselector/Toolbar.jsx | 14 +- .../wizard/common/noAttributesEmptyView.js | 25 + .../builder/wizard/common/wfsChartOptions.js | 1 + .../builder/wizard/counter/Toolbar.jsx | 11 +- .../wizard/counter/__tests__/Toolbar-test.jsx | 18 + .../widgets/builder/wizard/legend/Toolbar.jsx | 55 + .../widgets/builder/wizard/map/MapOptions.jsx | 60 + .../builder/wizard/map/MapSelector.jsx | 79 + .../widgets/builder/wizard/map/NodeEditor.jsx | 48 + .../widgets/builder/wizard/map/PreviewMap.jsx | 10 + .../widgets/builder/wizard/map/TOC.jsx | 54 + .../widgets/builder/wizard/map/Toolbar.jsx | 44 + .../wizard/map/__tests__/MapOptions-test.jsx | 60 + .../wizard/map/__tests__/NodeEditor-test.jsx | 37 + .../builder/wizard/map/__tests__/TOC-test.jsx | 50 + .../__tests__/handleNodeFiltering-test.js | 34 + .../handleNodePropertyChanges-test.jsx | 65 + .../__tests__/handleNodeSelection-test.js | 40 + .../enhancers/__tests__/mapToNodes-test.jsx | 45 + .../enhancers/__tests__/nodeEditor-test.jsx | 55 + .../enhancers/__tests__/previewMap-test.js | 42 + .../enhancers/__tests__/withSortable-test.jsx | 37 + .../map/enhancers/handleNodeFiltering.js | 52 + .../enhancers/handleNodePropertyChanges.js | 58 + .../map/enhancers/handleNodeSelection.js | 60 + .../wizard/map/enhancers/mapToNodes.js | 21 + .../wizard/map/enhancers/nodeEditor.js | 99 ++ .../wizard/map/enhancers/previewMap.js | 10 + .../enhancers/withCapabilitiesRetrieval.js | 39 + .../wizard/map/enhancers/withSelectedNode.js | 32 + .../wizard/map/enhancers/withSortable.js | 42 + .../builder/wizard/table/TableOptions.jsx | 48 +- .../widgets/builder/wizard/table/Toolbar.jsx | 13 +- .../table/__tests__/TableOptions-test.jsx | 12 +- .../widgets/builder/wizard/text/Toolbar.jsx | 4 +- .../__tests__/dependenciesToMapProp-test.jsx | 40 + .../__tests__/dependenciesToWidget-test.jsx | 32 + .../widgets/enhancers/dependenciesToFilter.js | 3 + .../enhancers/dependenciesToMapProp.js | 24 + .../widgets/enhancers/dependenciesToWidget.js | 35 + .../widgets/enhancers/emptyLegendState.js | 18 + .../widgets/enhancers/legendWidget.js | 28 + .../widgets/enhancers/withGroupColor.jsx | 18 + .../components/widgets/view/WidgetsView.jsx | 89 +- .../__tests__/withSelection-test.jsx | 47 + .../widgets/view/enhancers/withSelection.js | 32 + .../components/widgets/widget/ChartWidget.jsx | 10 +- .../components/widgets/widget/CounterView.jsx | 27 +- .../widgets/widget/CounterWidget.jsx | 15 +- .../widgets/widget/DefaultWidget.jsx | 48 +- .../components/widgets/widget/InfoPopover.jsx | 43 +- .../components/widgets/widget/LegendView.jsx | 60 + .../widgets/widget/LegendWidget.jsx | 50 + .../components/widgets/widget/MapView.jsx | 20 + .../components/widgets/widget/MapWidget.jsx | 52 + .../components/widgets/widget/TableWidget.jsx | 9 +- .../components/widgets/widget/TextWidget.jsx | 8 +- .../widgets/widget/WidgetContainer.jsx | 4 +- .../widget/__tests__/ChartWidget-test.jsx | 8 + .../widget/__tests__/CounterView-test.jsx | 15 + .../widget/__tests__/CounterWidget-test.jsx | 8 + .../widget/__tests__/LegendView-test.jsx | 48 + .../widget/__tests__/LegendWidget-test.jsx | 70 + .../widget/__tests__/MapWidget-test.jsx | 35 + .../widget/__tests__/TableWidget-test.jsx | 24 +- .../widget/__tests__/TextWidget-test.jsx | 57 + web/client/embedded.html | 6 +- web/client/embeddedTemplate.html | 6 +- web/client/epics/__tests__/dashboard-test.js | 2 +- web/client/epics/__tests__/dashboards-test.js | 99 ++ .../epics/__tests__/globeswitcher-test.js | 75 +- web/client/epics/__tests__/identify-test.js | 134 ++ .../epics/__tests__/localconfig-test.js | 2 +- web/client/epics/__tests__/maplayout-test.js | 10 +- web/client/epics/__tests__/maps-test.js | 29 +- web/client/epics/__tests__/search-test.js | 13 +- web/client/epics/__tests__/widgets-test.js | 150 +- .../epics/__tests__/widgetsbuilder-test.js | 35 +- web/client/epics/dashboard.js | 111 +- web/client/epics/dashboards.js | 80 + web/client/epics/globeswitcher.js | 26 +- web/client/epics/identify.js | 48 +- web/client/epics/maplayout.js | 33 +- web/client/epics/maps.js | 12 +- web/client/epics/rulesmanager.js | 37 + web/client/epics/search.js | 2 + web/client/epics/widgets.js | 92 +- web/client/epics/widgetsbuilder.js | 17 +- .../examples/3dviewer/containers/Viewer.jsx | 2 +- web/client/examples/3dviewer/localConfig.json | 2 +- web/client/examples/api/index.html | 8 +- web/client/examples/layertree/index.html | 2 +- web/client/examples/mouseposition/index.html | 7 +- web/client/examples/plugins/app.jsx | 7 +- web/client/examples/plugins/index.html | 8 +- .../print/components/PrintPreview.jsx | 15 +- web/client/examples/print/index.html | 5 +- web/client/examples/print/localConfig.json | 7 +- web/client/examples/scalebar/index.html | 7 +- web/client/index.html | 2 +- web/client/indexTemplate.html | 2 +- web/client/libs/__tests__/ajax-test.js | 3 +- web/client/libs/ajax.js | 2 + web/client/localConfig.json | 60 +- .../observables/__tests__/geostore-test.js | 68 + web/client/observables/epics.js | 38 + web/client/observables/geostore.js | 284 ++++ web/client/observables/rulesmanager.js | 145 ++ web/client/observables/wfs.js | 14 +- web/client/observables/wms.js | 9 +- web/client/plugins/ContentTabs.jsx | 81 + web/client/plugins/CreateNewMap.jsx | 32 +- web/client/plugins/Dashboard.jsx | 55 +- web/client/plugins/DashboardEditor.jsx | 174 +- web/client/plugins/Dashboards.jsx | 128 ++ web/client/plugins/DrawerMenu.jsx | 61 +- web/client/plugins/FeatureEditor.jsx | 13 +- web/client/plugins/FeaturedMaps.jsx | 163 ++ web/client/plugins/FloatingLegend.jsx | 129 ++ web/client/plugins/Identify.jsx | 6 +- web/client/plugins/Map.jsx | 58 +- web/client/plugins/MapSearch.jsx | 26 +- web/client/plugins/Maps.jsx | 130 +- web/client/plugins/MousePosition.jsx | 12 + web/client/plugins/QueryPanel.jsx | 18 +- web/client/plugins/RulesDataGrid.jsx | 77 + web/client/plugins/RulesEditor.jsx | 80 + web/client/plugins/RulesManagerFooter.jsx | 47 + web/client/plugins/ScrollTop.jsx | 11 +- web/client/plugins/Search.jsx | 44 +- web/client/plugins/Settings.jsx | 2 +- web/client/plugins/TOC.jsx | 11 +- web/client/plugins/Widgets.jsx | 26 +- web/client/plugins/WidgetsBuilder.jsx | 17 +- .../plugins/dashboard/DashboardsGrid.jsx | 29 + .../plugins/dashboard/EmptyDashboardsView.jsx | 38 + .../plugins/dashboard/PaginationToolbar.jsx | 50 + web/client/plugins/dashboard/SaveDialog.jsx | 36 + web/client/plugins/featuregrid/gridTools.jsx | 4 +- .../plugins/featuregrid/panels/index.jsx | 10 +- .../plugins/featuregrid/toolbarEvents.js | 10 +- web/client/plugins/manager/EditorEnhancer.js | 86 + web/client/plugins/manager/GroupManager.jsx | 9 +- web/client/plugins/manager/ManagerMenu.jsx | 13 +- web/client/plugins/manager/ModalDialog.jsx | 31 + web/client/plugins/manager/RulesEditor.jsx | 147 ++ web/client/plugins/manager/RulesToolbar.jsx | 144 ++ web/client/plugins/manager/UserManager.jsx | 9 +- web/client/plugins/map/index.js | 1 + web/client/plugins/maps/MapsGrid.jsx | 57 + web/client/plugins/maps/MetadataModal.jsx | 29 + web/client/plugins/widgetbuilder/Catalog.jsx | 9 +- .../plugins/widgetbuilder/ChartBuilder.jsx | 48 +- .../plugins/widgetbuilder/CounterBuilder.jsx | 41 +- .../plugins/widgetbuilder/LayerSelector.jsx | 41 +- .../plugins/widgetbuilder/LegendBuilder.jsx | 119 ++ .../plugins/widgetbuilder/MapBuilder.jsx | 111 ++ .../widgetbuilder/MapLayerSelector.jsx | 56 + .../plugins/widgetbuilder/MapSelector.jsx | 32 + .../plugins/widgetbuilder/TableBuilder.jsx | 45 +- .../plugins/widgetbuilder/TextBuilder.jsx | 25 +- .../widgetbuilder/WidgetTypeBuilder.jsx | 9 +- .../widgetbuilder/WidgetTypeSelector.jsx | 6 +- web/client/plugins/widgetbuilder/commons.js | 16 +- .../enhancers/chartLayerSelector.js | 35 + .../connection/legendBuilderConnect.js | 22 + .../enhancers/connection/mapBuilderConnect.js | 24 + .../connection/mapBuilderConnectMask.jsx | 22 + .../connection/viewportBuilderConnect.js | 20 + .../connection/viewportBuilderConnectMask.jsx | 22 + .../enhancers/connection/withConnectButton.js | 37 + .../enhancers/connection/withMapConnect.js | 21 + .../enhancers/handleNodeEditing.js | 20 + .../widgetbuilder/enhancers/layerSelector.js | 40 + .../widgetbuilder/enhancers/manageLayers.js | 28 + .../widgetbuilder/enhancers/mapToolbar.js | 63 + .../enhancers/withDashboardExitButton.js | 26 + .../widgetbuilder/enhancers/withExitButton.js | 15 + .../enhancers/withMapExitButton.js | 52 + web/client/product/appConfig.js | 12 + web/client/product/assets/css/maps.css | 68 +- web/client/product/assets/img/groups_logo.png | Bin 0 -> 5966 bytes .../product/components/home/MailingLists.jsx | 105 +- .../components/viewer/about/AboutContent.jsx | 2 +- web/client/product/embedded.jsx | 8 +- web/client/product/pages/Dashboard.jsx | 50 +- web/client/product/pages/RulesManager.jsx | 128 ++ web/client/product/plugins.js | 11 +- web/client/product/plugins/Attribution.jsx | 24 +- web/client/product/plugins/Footer.jsx | 26 +- web/client/product/plugins/Fork.jsx | 4 +- .../product/plugins/HomeDescription.jsx | 31 +- web/client/product/plugins/MailingLists.jsx | 27 + web/client/product/plugins/MapType.jsx | 2 +- web/client/product/plugins/NavMenu.jsx | 102 ++ .../attribution/geosolutions-brand-sm.png | Bin 0 -> 3107 bytes .../reducers/__tests__/dashboard-test.js | 71 + .../reducers/__tests__/dashboards-test.js | 49 + .../reducers/__tests__/featuredmaps-test.js | 72 + .../reducers/__tests__/featuregrid-test.js | 18 +- .../reducers/__tests__/floatinglegend.js | 33 + web/client/reducers/__tests__/mapInfo-test.js | 10 + .../reducers/__tests__/maplayout-test.js | 11 + web/client/reducers/__tests__/search-test.js | 10 +- web/client/reducers/__tests__/widgets-test.js | 46 +- web/client/reducers/config.js | 2 +- web/client/reducers/dashboard.js | 25 +- web/client/reducers/dashboards.js | 59 + web/client/reducers/featuredmaps.js | 52 + web/client/reducers/featuregrid.js | 18 +- web/client/reducers/floatinglegend.js | 34 + web/client/reducers/mapInfo.js | 8 +- web/client/reducers/maplayout.js | 5 +- web/client/reducers/rulesmanager.js | 105 +- web/client/reducers/search.js | 4 +- web/client/reducers/widgets.js | 34 +- .../selectors/__tests__/controls-test.js | 31 +- .../selectors/__tests__/dashboard-test.js | 43 +- .../selectors/__tests__/featuredmaps-test.js | 41 + .../selectors/__tests__/featuregrid-test.js | 19 + .../__tests__/floatinglegend-test.js | 38 + .../selectors/__tests__/highlight-test.js | 83 +- web/client/selectors/__tests__/layers-test.js | 71 +- .../selectors/__tests__/maplayout-test.js | 20 +- .../selectors/__tests__/widgets-test.js | 68 +- web/client/selectors/dashboard.js | 14 +- web/client/selectors/dashboards.js | 17 + web/client/selectors/featuredmaps.js | 41 + web/client/selectors/featuregrid.js | 4 + web/client/selectors/floatinglegend.js | 33 + web/client/selectors/highlight.js | 50 +- web/client/selectors/layers.js | 32 +- web/client/selectors/map.js | 2 +- web/client/selectors/maplayout.js | 12 +- web/client/selectors/maps.js | 2 + web/client/selectors/queryform.js | 6 +- web/client/selectors/rulesmanager.js | 38 +- web/client/selectors/security.js | 1 + web/client/selectors/widgets.js | 67 +- web/client/simple.html | 2 +- web/client/test-resources/data.en-US | 6 +- web/client/test-resources/data.es-ES | 8 +- web/client/test-resources/data.fr-FR | 6 +- web/client/test-resources/data.hr-HR | 19 + web/client/test-resources/data.it-IT | 6 +- web/client/test-resources/data.it-IT-broken | 4 +- web/client/test-resources/data.nl-NL-broken | 6 +- web/client/test-resources/elevation.bin | 1 + .../test-resources/geofence/rest/rules/count | 1 + .../geofence/rest/rules/rules.xml | 62 + .../geostore/extjs/search/category/MAP/1.json | 19 + .../test-resources/geostore/extjs/search/list | 32 + .../geostore/extjs/search/search_1.json | 15 + .../geostore/resources/resource/2/attributes | 21 + web/client/test-resources/img/blank.jpg | Bin 0 -> 631 bytes web/client/test-resources/localConfig.json | 1 + .../test-resources/widgets/complex_graph.json | 546 +++++++ .../test-resources/widgets/widgets1.json | 590 +++++++ web/client/themes/default/icons.less | 125 +- web/client/themes/default/icons/icons.eot | Bin 75808 -> 76600 bytes web/client/themes/default/icons/icons.svg | 1040 ++++++------ web/client/themes/default/icons/icons.ttf | Bin 75644 -> 76436 bytes web/client/themes/default/icons/icons.woff | Bin 43980 -> 45068 bytes web/client/themes/default/less/common.less | 54 +- web/client/themes/default/less/dashboard.less | 3 + web/client/themes/default/less/embedded.less | 1 + web/client/themes/default/less/home.less | 112 +- .../themes/default/less/map-search-bar.less | 10 +- .../themes/default/less/maps-properties.less | 90 +- web/client/themes/default/less/modal.less | 17 +- .../themes/default/less/mouse-position.less | 21 + web/client/themes/default/less/ol.less | 24 + .../themes/default/less/rulesmanager.less | 496 ++++++ web/client/themes/default/less/select.less | 28 +- web/client/themes/default/less/sidegrid.less | 393 ++--- .../themes/default/less/square-button.less | 51 +- web/client/themes/default/less/toc.less | 198 ++- web/client/themes/default/less/widget.less | 73 +- web/client/themes/default/less/wizard.less | 3 + web/client/themes/default/ms2-theme.less | 1 + web/client/themes/default/variables.less | 1 + web/client/translations/data.de-DE | 205 ++- web/client/translations/data.en-US | 208 ++- web/client/translations/data.es-ES | 211 ++- web/client/translations/data.fr-FR | 209 ++- web/client/translations/data.hr-HR | 1414 +++++++++++++++++ web/client/translations/data.it-IT | 267 +++- web/client/translations/data.nl-NL | 50 +- web/client/translations/data.zh-ZH | 399 ++--- .../fragments/cookie/cookieDetails-hr-HR.html | 61 + web/client/utils/CatalogUtils.js | 2 +- web/client/utils/ColorUtils.js | 11 +- web/client/utils/CoordinatesUtils.js | 122 +- web/client/utils/ElevationUtils.js | 113 ++ web/client/utils/FeatureGridUtils.js | 6 +- web/client/utils/FilterUtils.jsx | 11 + web/client/utils/GraphUtils.js | 74 + web/client/utils/LayersUtils.js | 68 +- web/client/utils/LocaleUtils.js | 24 +- web/client/utils/MapUtils.js | 22 +- web/client/utils/MeasureUtils.js | 175 +- web/client/utils/RulesEditor.js | 32 + web/client/utils/RulesGridUtils.js | 75 + web/client/utils/SecurityUtils.js | 24 +- web/client/utils/StringUtils.js | 27 + web/client/utils/WidgetsUtils.js | 61 + .../utils/__tests__/CatalogUtils-test.js | 13 + web/client/utils/__tests__/ColorUtils-test.js | 6 +- .../utils/__tests__/CoordinatesUtils-test.js | 191 ++- .../utils/__tests__/ElevationUtils-test.js | 49 + .../utils/__tests__/LayersUtils-test.js | 38 + .../utils/__tests__/LocaleUtils-test.js | 8 + web/client/utils/__tests__/MapUtils-test.js | 117 +- .../utils/__tests__/MeasureUtils-test.js | 80 +- .../utils/__tests__/SecurityUtils-test.js | 7 + .../utils/__tests__/StringUtils-test.js | 20 + .../utils/__tests__/WidgetsUtils-test.js | 49 + web/client/utils/cesium/BILTerrainProvider.js | 1108 +++++++++++++ web/client/utils/cesium/ClickUtils.js | 7 +- web/pom.xml | 91 ++ web/src/main/resources/applicationContext.xml | 104 ++ web/src/main/resources/sample_categories.xml | 3 + web/src/main/webapp/WEB-INF/web.xml | 14 + 583 files changed, 28921 insertions(+), 3002 deletions(-) delete mode 100644 TableWidget.jsx create mode 100644 web/client/actions/__tests__/dashboards-test.js create mode 100644 web/client/actions/__tests__/floatinglegend-test.js create mode 100644 web/client/actions/dashboards.js create mode 100644 web/client/actions/floatinglegend.js create mode 100644 web/client/components/I18N/images/flags/hr-HR.png create mode 100644 web/client/components/TOC/FloatingLegend.jsx create mode 100644 web/client/components/TOC/__tests__/FloatingLegend-test.jsx create mode 100644 web/client/components/data/featuregrid/enhancers/withHint.js create mode 100644 web/client/components/data/featuregrid/enhancers/withPopover.js create mode 100644 web/client/components/data/featuregrid/enhancers/withTooltip.js create mode 100644 web/client/components/layout/enhancers/__tests__/gridLayout-test.js create mode 100644 web/client/components/layout/enhancers/gridLayout.jsx create mode 100644 web/client/components/manager/rulesmanager/AttributeAccessSelect.jsx create mode 100644 web/client/components/manager/rulesmanager/AvailableStyles.jsx create mode 100644 web/client/components/manager/rulesmanager/DefaultStyle.jsx create mode 100644 web/client/components/manager/rulesmanager/MapModal.jsx create mode 100644 web/client/components/manager/rulesmanager/RoiCql.jsx create mode 100644 web/client/components/manager/rulesmanager/SimpleSpatialFilter.jsx create mode 100644 web/client/components/manager/rulesmanager/StylesList.jsx create mode 100644 web/client/components/manager/rulesmanager/enhancers/Map.js create mode 100644 web/client/components/manager/rulesmanager/enhancers/__tests__/autoComplete-test.js create mode 100644 web/client/components/manager/rulesmanager/enhancers/__tests__/fixedOptions-test.js create mode 100644 web/client/components/manager/rulesmanager/enhancers/autoComplete.js create mode 100644 web/client/components/manager/rulesmanager/enhancers/filterstyles.js create mode 100644 web/client/components/manager/rulesmanager/enhancers/fixedOptions.js create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/AttributesEditor.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/EditMain.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/FiltersEditor.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/Header.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/StylesEditor.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/__tests__/AttributesEditor-test.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/__tests__/EditMain-test.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/__tests__/Header-test.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/__tests__/StylesEditor-test.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/attributeselectors/Access.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/attributeselectors/IpAddress.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/attributeselectors/Layer.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/attributeselectors/Priority.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/attributeselectors/Request.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/attributeselectors/Role.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/attributeselectors/Service.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/attributeselectors/User.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/attributeselectors/Workspace.jsx create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/attributeselectors/index.js create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/enhancers/filters.js create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/enhancers/style.js create mode 100644 web/client/components/manager/rulesmanager/ruleseditor/enhancers/switch.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/RulesGrid.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/__tests__/RuleGrid-test.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/enhancers/__tests__/filtersStream-test.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/enhancers/__tests__/scrollStream-test.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/enhancers/__tests__/triggerFetch-test.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/enhancers/__tests__/virtualScrollFetch-test.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/enhancers/filtersStream.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/enhancers/reorderRules.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/enhancers/rulesgrid.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/enhancers/scrollStream.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/enhancers/triggerFetch.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/enhancers/virtualScrollFetch.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/filterRenderers/LayersFilter.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/filterRenderers/RequestsFilter.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/filterRenderers/RolesFilter.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/filterRenderers/ServicesFilter.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/filterRenderers/UsersFilter.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/filterRenderers/WorkspacesFilter.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/filterRenderers/__tests__/WorkspacesFilter-test.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/filterRenderers/index.js create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/formatters/AccessFormatter.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/formatters/__tests__/AccessFormatter-test.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/renderers/PriorityActionCell.jsx create mode 100644 web/client/components/manager/rulesmanager/rulesgrid/renderers/RuleRenderer.jsx create mode 100644 web/client/components/map/BaseMap.jsx create mode 100644 web/client/components/map/__tests__/BaseMap-test-chrome.jsx create mode 100644 web/client/components/map/__tests__/BaseMap-test.jsx create mode 100644 web/client/components/map/enhancers/__tests__/autoResize-test.js create mode 100644 web/client/components/map/enhancers/__tests__/onMapViewChanges-test.js create mode 100644 web/client/components/map/enhancers/autoMapType.js create mode 100644 web/client/components/map/enhancers/autoResize.js create mode 100644 web/client/components/map/enhancers/mapType.js create mode 100644 web/client/components/map/enhancers/onMapViewChanges.js create mode 100644 web/client/components/map/enhancers/withDraw.js create mode 100644 web/client/components/map/leaflet/__tests__/Feature-test.jsx create mode 100644 web/client/components/map/plugins/cesium.js create mode 100644 web/client/components/map/plugins/leaflet.js create mode 100644 web/client/components/map/plugins/openlayers.js create mode 100644 web/client/components/map/plugins/sink.js create mode 100644 web/client/components/maps/MapCatalog.jsx create mode 100644 web/client/components/maps/MapCatalogForm.jsx create mode 100644 web/client/components/maps/__tests__/MapCatalog-test.jsx create mode 100644 web/client/components/maps/enhancers/__tests__/featuredMaps-test.jsx create mode 100644 web/client/components/maps/enhancers/enhancers.js create mode 100644 web/client/components/maps/enhancers/featuredMaps.js create mode 100644 web/client/components/maps/enhancers/mapCatalog.js create mode 100644 web/client/components/maps/enhancers/mapCatalogWithEmptyMap.js delete mode 100644 web/client/components/maps/style/mapcard.css create mode 100644 web/client/components/misc/Overlay.jsx create mode 100644 web/client/components/misc/ShowMore.jsx create mode 100644 web/client/components/misc/Slider.jsx create mode 100644 web/client/components/misc/__tests__/ShowMore-test.jsx create mode 100644 web/client/components/misc/enhancers/__tests__/gridPagination-test.jsx create mode 100644 web/client/components/misc/enhancers/__tests__/withMask-test.jsx create mode 100644 web/client/components/misc/enhancers/gridPagination.jsx create mode 100644 web/client/components/misc/enhancers/localizeStringMap.js create mode 100644 web/client/components/misc/enhancers/withMask.js create mode 100644 web/client/components/misc/enhancers/withPropsStream.js create mode 100644 web/client/components/misc/enhancers/withResizeSpy.js delete mode 100644 web/client/components/misc/style/pagination-toolbar.css create mode 100644 web/client/components/resources/ResourceCard.jsx create mode 100644 web/client/components/resources/ResourceGrid.jsx create mode 100644 web/client/components/resources/__tests__/ResourceCard-test.jsx create mode 100644 web/client/components/resources/__tests__/ResourceGrid-test.jsx create mode 100644 web/client/components/resources/enhancers/resourceGrid.js create mode 100644 web/client/components/resources/forms/Metadata.jsx create mode 100644 web/client/components/resources/forms/Thumbnail.jsx create mode 100644 web/client/components/resources/forms/__tests__/Metadata-test.jsx create mode 100644 web/client/components/resources/forms/__tests__/Thumbnail-test.jsx create mode 100644 web/client/components/resources/modals/ConfirmModal.jsx create mode 100644 web/client/components/resources/modals/DetailSheet.jsx create mode 100644 web/client/components/resources/modals/Save.jsx create mode 100644 web/client/components/resources/modals/__tests__/Confirm-test.jsx create mode 100644 web/client/components/resources/modals/__tests__/Save-test.jsx create mode 100644 web/client/components/resources/modals/enhancers/__tests__/handlePermission-test.jsx create mode 100644 web/client/components/resources/modals/enhancers/__tests__/handleResourceData-test.jsx create mode 100644 web/client/components/resources/modals/enhancers/handleErrors.jsx create mode 100644 web/client/components/resources/modals/enhancers/handlePermission.jsx create mode 100644 web/client/components/resources/modals/enhancers/handleResourceData.jsx create mode 100644 web/client/components/resources/modals/enhancers/handleResourceDownload.js create mode 100644 web/client/components/resources/modals/enhancers/handleSaveModal.js create mode 100644 web/client/components/resources/modals/enhancers/ruleEditor.js create mode 100644 web/client/components/resources/modals/fragments/DetailsRow.jsx create mode 100644 web/client/components/resources/modals/fragments/ErrorBox.jsx create mode 100644 web/client/components/resources/modals/fragments/MainForm.jsx create mode 100644 web/client/components/resources/modals/fragments/PermissionEditor.jsx create mode 100644 web/client/components/widgets/builder/wizard/LegendWizard.jsx create mode 100644 web/client/components/widgets/builder/wizard/MapWizard.jsx create mode 100644 web/client/components/widgets/builder/wizard/__tests__/LegendWizard-test.jsx create mode 100644 web/client/components/widgets/builder/wizard/__tests__/MapWizard-test.jsx create mode 100644 web/client/components/widgets/builder/wizard/chart/__tests__/Toolbar-test.jsx create mode 100644 web/client/components/widgets/builder/wizard/common/noAttributesEmptyView.js create mode 100644 web/client/components/widgets/builder/wizard/legend/Toolbar.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/MapOptions.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/MapSelector.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/NodeEditor.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/PreviewMap.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/TOC.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/Toolbar.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/__tests__/MapOptions-test.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/__tests__/NodeEditor-test.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/__tests__/TOC-test.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/__tests__/handleNodeFiltering-test.js create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/__tests__/handleNodePropertyChanges-test.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/__tests__/handleNodeSelection-test.js create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/__tests__/mapToNodes-test.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/__tests__/nodeEditor-test.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/__tests__/previewMap-test.js create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/__tests__/withSortable-test.jsx create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/handleNodeFiltering.js create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/handleNodePropertyChanges.js create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/handleNodeSelection.js create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/mapToNodes.js create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/nodeEditor.js create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/previewMap.js create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/withCapabilitiesRetrieval.js create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/withSelectedNode.js create mode 100644 web/client/components/widgets/builder/wizard/map/enhancers/withSortable.js create mode 100644 web/client/components/widgets/enhancers/__tests__/dependenciesToMapProp-test.jsx create mode 100644 web/client/components/widgets/enhancers/__tests__/dependenciesToWidget-test.jsx create mode 100644 web/client/components/widgets/enhancers/dependenciesToMapProp.js create mode 100644 web/client/components/widgets/enhancers/dependenciesToWidget.js create mode 100644 web/client/components/widgets/enhancers/emptyLegendState.js create mode 100644 web/client/components/widgets/enhancers/legendWidget.js create mode 100644 web/client/components/widgets/enhancers/withGroupColor.jsx create mode 100644 web/client/components/widgets/view/enhancers/__tests__/withSelection-test.jsx create mode 100644 web/client/components/widgets/view/enhancers/withSelection.js create mode 100644 web/client/components/widgets/widget/LegendView.jsx create mode 100644 web/client/components/widgets/widget/LegendWidget.jsx create mode 100644 web/client/components/widgets/widget/MapView.jsx create mode 100644 web/client/components/widgets/widget/MapWidget.jsx create mode 100644 web/client/components/widgets/widget/__tests__/LegendView-test.jsx create mode 100644 web/client/components/widgets/widget/__tests__/LegendWidget-test.jsx create mode 100644 web/client/components/widgets/widget/__tests__/MapWidget-test.jsx create mode 100644 web/client/components/widgets/widget/__tests__/TextWidget-test.jsx create mode 100644 web/client/epics/__tests__/dashboards-test.js create mode 100644 web/client/epics/__tests__/identify-test.js create mode 100644 web/client/epics/dashboards.js create mode 100644 web/client/epics/rulesmanager.js create mode 100644 web/client/observables/__tests__/geostore-test.js create mode 100644 web/client/observables/epics.js create mode 100644 web/client/observables/geostore.js create mode 100644 web/client/observables/rulesmanager.js create mode 100644 web/client/plugins/ContentTabs.jsx create mode 100644 web/client/plugins/Dashboards.jsx create mode 100644 web/client/plugins/FeaturedMaps.jsx create mode 100644 web/client/plugins/FloatingLegend.jsx create mode 100644 web/client/plugins/RulesDataGrid.jsx create mode 100644 web/client/plugins/RulesEditor.jsx create mode 100644 web/client/plugins/RulesManagerFooter.jsx create mode 100644 web/client/plugins/dashboard/DashboardsGrid.jsx create mode 100644 web/client/plugins/dashboard/EmptyDashboardsView.jsx create mode 100644 web/client/plugins/dashboard/PaginationToolbar.jsx create mode 100644 web/client/plugins/dashboard/SaveDialog.jsx create mode 100644 web/client/plugins/manager/EditorEnhancer.js create mode 100644 web/client/plugins/manager/ModalDialog.jsx create mode 100644 web/client/plugins/manager/RulesEditor.jsx create mode 100644 web/client/plugins/manager/RulesToolbar.jsx create mode 100644 web/client/plugins/maps/MapsGrid.jsx create mode 100644 web/client/plugins/maps/MetadataModal.jsx create mode 100644 web/client/plugins/widgetbuilder/LegendBuilder.jsx create mode 100644 web/client/plugins/widgetbuilder/MapBuilder.jsx create mode 100644 web/client/plugins/widgetbuilder/MapLayerSelector.jsx create mode 100644 web/client/plugins/widgetbuilder/MapSelector.jsx create mode 100644 web/client/plugins/widgetbuilder/enhancers/chartLayerSelector.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/connection/legendBuilderConnect.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/connection/mapBuilderConnect.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/connection/mapBuilderConnectMask.jsx create mode 100644 web/client/plugins/widgetbuilder/enhancers/connection/viewportBuilderConnect.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/connection/viewportBuilderConnectMask.jsx create mode 100644 web/client/plugins/widgetbuilder/enhancers/connection/withConnectButton.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/connection/withMapConnect.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/handleNodeEditing.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/layerSelector.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/manageLayers.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/mapToolbar.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/withDashboardExitButton.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/withExitButton.js create mode 100644 web/client/plugins/widgetbuilder/enhancers/withMapExitButton.js create mode 100644 web/client/product/assets/img/groups_logo.png create mode 100644 web/client/product/pages/RulesManager.jsx create mode 100644 web/client/product/plugins/MailingLists.jsx create mode 100644 web/client/product/plugins/NavMenu.jsx create mode 100644 web/client/product/plugins/attribution/geosolutions-brand-sm.png create mode 100644 web/client/reducers/__tests__/dashboard-test.js create mode 100644 web/client/reducers/__tests__/dashboards-test.js create mode 100644 web/client/reducers/__tests__/featuredmaps-test.js create mode 100644 web/client/reducers/__tests__/floatinglegend.js create mode 100644 web/client/reducers/dashboards.js create mode 100644 web/client/reducers/featuredmaps.js create mode 100644 web/client/reducers/floatinglegend.js create mode 100644 web/client/selectors/__tests__/featuredmaps-test.js create mode 100644 web/client/selectors/__tests__/floatinglegend-test.js create mode 100644 web/client/selectors/dashboards.js create mode 100644 web/client/selectors/featuredmaps.js create mode 100644 web/client/selectors/floatinglegend.js create mode 100644 web/client/test-resources/data.hr-HR create mode 100644 web/client/test-resources/elevation.bin create mode 100644 web/client/test-resources/geofence/rest/rules/count create mode 100644 web/client/test-resources/geofence/rest/rules/rules.xml create mode 100644 web/client/test-resources/geostore/extjs/search/category/MAP/1.json create mode 100644 web/client/test-resources/geostore/extjs/search/list create mode 100644 web/client/test-resources/geostore/extjs/search/search_1.json create mode 100644 web/client/test-resources/geostore/resources/resource/2/attributes create mode 100644 web/client/test-resources/img/blank.jpg create mode 100644 web/client/test-resources/widgets/complex_graph.json create mode 100644 web/client/test-resources/widgets/widgets1.json create mode 100644 web/client/themes/default/less/rulesmanager.less create mode 100644 web/client/translations/data.hr-HR create mode 100644 web/client/translations/fragments/cookie/cookieDetails-hr-HR.html create mode 100644 web/client/utils/ElevationUtils.js create mode 100644 web/client/utils/GraphUtils.js create mode 100644 web/client/utils/RulesEditor.js create mode 100644 web/client/utils/RulesGridUtils.js create mode 100644 web/client/utils/StringUtils.js create mode 100644 web/client/utils/WidgetsUtils.js create mode 100644 web/client/utils/__tests__/ElevationUtils-test.js create mode 100644 web/client/utils/__tests__/StringUtils-test.js create mode 100644 web/client/utils/__tests__/WidgetsUtils-test.js create mode 100644 web/client/utils/cesium/BILTerrainProvider.js create mode 100644 web/src/main/resources/applicationContext.xml diff --git a/README.md b/README.md index 03d0c3785e..83df091507 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,25 @@ You can download the WAR file from the latest release [here](https://github.com/ Quick Start ------------ + +There are two quick ways to test out MapStore2. Either using [Docker](https://www.docker.com/) or a local java web container like [Apache Tomcat](http://tomcat.apache.org/) + +### Using Docker + +Pull the latest image from Docker Hub: + +`docker pull geosolutionsit/mapstore2` + +`docker run --name mapstore -p8080:8080 geosolutionsit/mapstore2` + +Then you can access MapStore2 using the following URL: + +[http://localhost:8080/mapstore](http://localhost:8080/mapstore) + +Use the default credentials (admin / admin) to login and start creating your maps! + +### Using the Web Archive (WAR file) + After downloading the MapStore2 war file, install it in your java web container (e.g. Tomcat), with usual procedures for the container (normally you only need to copy the war file in the webapps subfolder). If you don't have a java web container you can download Apache Tomcat from [here](https://tomcat.apache.org/download-70.cgi) and install it. You will also need a Java7 [JRE](http://www.oracle.com/technetwork/java/javase/downloads/jre7-downloads-1880261.html) diff --git a/TableWidget.jsx b/TableWidget.jsx deleted file mode 100644 index 5a74058ff0..0000000000 --- a/TableWidget.jsx +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2018, GeoSolutions Sas. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. - */ -const React = require('react'); -const Message = require('../../I18N/Message'); -const loadingState = require('../../misc/enhancers/loadingState'); -const FeatureGrid = loadingState(({ describeFeatureType }) => !describeFeatureType)(require('../../data/featuregrid/FeatureGrid')); -const InfoPopover = require('./InfoPopover'); - -const WidgetContainer = require('./WidgetContainer'); -const { - Glyphicon, - ButtonToolbar, - DropdownButton, - MenuItem -} = require('react-bootstrap'); - -const renderHeaderLeftTopItem = ({ title, description }) => { - return title || description ? : null; -}; - - -module.exports = ({ - id, - title, - description, - loading, - confirmDelete = false, - toggleTableView = () => { }, - toggleDeleteConfirm = () => { }, - exportCSV = () => { }, - onEdit = () => { }, - onDelete = () => { }, - pageEvents = { - moreFeatures: () => {} - }, - describeFeatureType, - features, - size, - pages, - pagination = {}, - virtualScroll = true -}) => - ( - } noCaret id="dropdown-no-caret"> - toggleTableView()} eventKey="1">  - onEdit()} eventKey="3">  - toggleDeleteConfirm(true)} eventKey="2">  - exportCSV({ title })} eventKey="4">  - - }> - - - - ); diff --git a/buildConfig.js b/buildConfig.js index 41d8acba91..5cb6926102 100644 --- a/buildConfig.js +++ b/buildConfig.js @@ -161,6 +161,14 @@ module.exports = (bundles, themeEntries, paths, extractThemesPlugin, prod, publi target: "https://dev.mapstore2.geo-solutions.it/mapstore", secure: false }, + '/pdf': { + target: "https://dev.mapstore2.geo-solutions.it/mapstore", + secure: false + }, + '/mapstore/pdf': { + target: "https://dev.mapstore2.geo-solutions.it", + secure: false + }, '/proxy': { target: "https://dev.mapstore2.geo-solutions.it/mapstore", secure: false diff --git a/docma-config.json b/docma-config.json index 8938fd8a11..96ddbb85cb 100644 --- a/docma-config.json +++ b/docma-config.json @@ -28,7 +28,7 @@ "emoji": true }, "app": { - "title": "MapStore 2 documentation", + "title": "MapStore documentation", "base": "/mapstore/docs", "entrance": "content:site", "routing": { "method": "path", "caseSensitive": true } @@ -36,7 +36,7 @@ "template": { "path": "./docma-template", "options": { - "title": "MapStore 2", + "title": "MapStore", "sidebar": true, "collapsed": false, "outline": "tree", @@ -75,17 +75,17 @@ "href": "index.html", "items": [ { - "label": "MapStore 2 Releases", + "label": "MapStore Releases", "href": "https://github.com/geosolutions-it/MapStore2/releases", "target": "_blank" }, { - "label": "MapStore 2 tar.gz", + "label": "MapStore tar.gz", "href": "https://github.com/geosolutions-it/MapStore2/tarball/master", "target": "_blank" }, { - "label": "MapStore 2 .zip", + "label": "MapStore .zip", "href": "https://github.com/geosolutions-it/MapStore2/zipball/master", "target": "_blank" } @@ -120,6 +120,8 @@ "web/client/components/mapcontrols/annotations/Annotations.jsx", "web/client/components/mapcontrols/annotations/AnnotationsEditor.jsx", "web/client/components/mapcontrols/annotations/AnnotationsConfig.js", + "web/client/components/misc/cardgrids/SideCard.jsx", + "web/client/components/misc/cardgrids/SideGrid.jsx", "web/client/components/misc/enhancers/emptyState.jsx", "web/client/components/misc/enhancers/tooltip.jsx", "web/client/components/misc/panels/Accordion.jsx", @@ -130,6 +132,8 @@ "web/client/components/misc/toolbar/Toolbar.jsx", "web/client/components/misc/EmptyView.jsx", "web/client/components/misc/ResizableModal.jsx", + "web/client/components/misc/Slider.jsx", + "web/client/components/TOC/FloatingLegend.jsx", "web/client/components/TOC/TOCItemsSettings.jsx", "web/client/components/TOC/fragments/settings/FeatureInfo.jsx", "web/client/components/TOC/fragments/settings/FeatureInfoEditor.jsx", @@ -138,6 +142,7 @@ "web/client/actions/controls.js", "web/client/actions/fullscreen.js", "web/client/actions/globeswitcher.js", + "web/client/actions/floatinglegend.js", "web/client/actions/maplayout.js", "web/client/actions/maps.js", "web/client/actions/maptype.js", @@ -146,6 +151,7 @@ "web/client/selectors/index.jsdoc", "web/client/selectors/featuregrid.js", + "web/client/selectors/floatinglegend.js", "web/client/selectors/map.js", "web/client/selectors/mapinfo.js", "web/client/selectors/maplayout.js", @@ -156,6 +162,7 @@ "web/client/reducers/controls.js", "web/client/reducers/featuregrid.js", "web/client/reducers/globeswitcher.js", + "web/client/reducers/floatinglegend.js", "web/client/reducers/maps.js", "web/client/reducers/maptype.js", "web/client/reducers/notifications.js", @@ -197,11 +204,13 @@ "web/client/plugins/GlobeViewSwitcher.jsx", "web/client/plugins/GoFull.jsx", "web/client/plugins/Map.jsx", + "web/client/plugins/MapSearch.jsx", "web/client/plugins/Measure.jsx", "web/client/plugins/MeasurePanel.jsx", "web/client/plugins/MeasureResults.jsx", "web/client/plugins/FullScreen.jsx", "web/client/plugins/Identify.jsx", + "web/client/plugins/FloatingLegend.jsx", "web/client/plugins/Locate.jsx", "web/client/plugins/Login.jsx", "web/client/plugins/MousePosition.jsx", diff --git a/docs/developer-guide/maps-configuration.md b/docs/developer-guide/maps-configuration.md index 597c1c6b01..4468455ae7 100644 --- a/docs/developer-guide/maps-configuration.md +++ b/docs/developer-guide/maps-configuration.md @@ -8,7 +8,8 @@ maxExtent: {number[]} max bbox of the map expressed [minx, miny, maxx, maxy] layers: {object[]} list of layers to be loaded on the map i.e. -> ``{ "projection": "EPSG:900913", +``` javascript +{ "projection": "EPSG:900913", "units": "m", "center": {"x": 1000000.000000, "y": 5528000.000000, "crs": "EPSG:900913"}, "zoom": 15, @@ -17,18 +18,22 @@ i.e. 20037508.34, 20037508.34 ], "layers": [{...},{...}] -}`` +} +``` # Layers option i.e. -> ``{ + ``` javascript +{ "url": "http..." "format": "image/png8" "title": "Open Street Map", "name": "mapnik", "group": "background", - "visibility": false -}`` + "visibility": false, + "hidden": true +} +``` ## Layer types @@ -41,6 +46,45 @@ i.e. ### WMS +#### Elevation layer +WMS layers can be configured to be used as a source for elevation related functions. +This requires: + * a GeoServer WMS service with the DDS/BIL plugin + * A WMS layer configured with BIL 16 bit output in big endian mode and -9999 nodata value + * a static layer in the Map plugin configuration (use the additionalLayers configuration option): + +**in localConfig.json** + ``` javascript + { + "name": "Map", + "cfg": { + "additionalLayers": [{ + "url": "http..." + "format": "application/bil16", + ... + "name": "elevation", + "visibility": true, + "useForElevation": true + }] + } + } + ``` + + The layer will be used for: + * showing elevation in the MousePosition plugin (requires showElevation: true in the plugin configuration) + * as a TerrainProvider if the maptype is Cesium + +**in localConfig.json** + ``` javascript + { + "name": "MousePosition", + "cfg": { + "showElevation": true, + ... + } + } + ``` + ### Bing ### Google @@ -54,14 +98,16 @@ It's enough to add provider property and 'tileprovider' as type property to the List of available layer [here](https://github.com/geosolutions-it/MapStore2/blob/master/web/client/utils/ConfigProvider.js) i.e. -> ``{ +``` javascript +{ "type": "tileprovider", "title": "Title", "provider": "Stamen.Toner", "name": "Name", "group": "GroupName", "visibility": false -}`` +} +``` Options passed in configuration object, if already configured by TileProvider, will be overridden. diff --git a/package.json b/package.json index 20db588a22..8f5dc13068 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "istanbul-instrumenter-loader": "2.0.0", "jsdoc": "https://github.com/geosolutions-it/jsdoc/tarball/fix_acorn_jsx", "jsdoc-jsx": "0.1.0", - "json-loader": "0.5.4", "karma": "1.5.0", "karma-chrome-launcher": "2.0.0", "karma-cli": "1.0.1", @@ -123,6 +122,7 @@ "leaflet.locatecontrol": "0.62.0", "leaflet.nontiledlayer": "1.0.7", "lodash": "4.16.6", + "lru-cache": "4.1.2", "moment": "2.21.0", "node-geo-distance": "1.2.0", "object-assign": "4.1.1", @@ -142,6 +142,7 @@ "react-container-dimensions": "1.3.2", "react-copy-to-clipboard": "5.0.0", "react-data-grid": "2.0.59", + "react-data-grid-addons": "3.0.11", "react-dnd": "2.4.0", "react-dnd-html5-backend": "2.4.1", "react-dock": "0.2.4", @@ -182,6 +183,7 @@ "redux-thunk": "0.1.0", "redux-undo": "0.5.0", "reselect": "2.5.1", + "resize-observer-polyfill": "1.5.0", "rxjs": "5.1.1", "screenfull": "3.1.0", "shpjs": "3.4.2", @@ -195,6 +197,7 @@ "url": "0.10.3", "uuid": "3.0.1", "w3c-schemas": "1.3.1", + "wellknown": "0.5.0", "wkt-parser": "https://github.com/geosolutions-it/wkt-parser/tarball/mapstore2_fixes", "xml2js": "0.4.17" }, diff --git a/project/standard/templates/web/pom.xml b/project/standard/templates/web/pom.xml index c371f48f72..738a7465ed 100644 --- a/project/standard/templates/web/pom.xml +++ b/project/standard/templates/web/pom.xml @@ -33,6 +33,73 @@ war runtime + + + org.mapfish.print + print-lib + geosolutions-2.0-SNAPSHOT + + + + org.geotools + gt-epsg-hsql + 8.6 + + + org.jyaml + jyaml + 1.3 + + + com.vividsolutions + jts + 1.8 + + + org.mapfish.geo + mapfish-geo-lib + 1.2.0 + + + javax.media + jai_codec + 1.1.3 + + + org.apache.pdfbox + pdfbox + 1.6.0 + + + javax.media + jai_imageio + 1.1 + + + commons-httpclient + commons-httpclient + 3.1 + + + org.apache.xmlgraphics + batik-transcoder + 1.7 + + + com.lowagie + itext + 2.1.5 + + + org.json + json + 20080701 + + + javax.media + jai_core + 1.1.3 + junit @@ -168,6 +235,25 @@ + + + printing + process-classes + + copy-resources + + + ${basedir}/target/__PROJECTNAME__/printing + UTF-8 + + + ${basedir}/../MapStore2/resources/geoserver/print + + * + + + + translations-ms2 diff --git a/utility/translations/findMissingTranslations.js b/utility/translations/findMissingTranslations.js index 71815a05d8..41fa8f8420 100644 --- a/utility/translations/findMissingTranslations.js +++ b/utility/translations/findMissingTranslations.js @@ -101,6 +101,6 @@ files.forEach(file => { if (fail) { throw Error("i18n files failed"); } -log('## mandatory translations checks passed!! ##'); +log('## mandatory translations checks passed!! ##\n'); diff --git a/web/client/actions/__tests__/dashboard-test.js b/web/client/actions/__tests__/dashboard-test.js index 7fc11224ee..a5a62dba46 100644 --- a/web/client/actions/__tests__/dashboard-test.js +++ b/web/client/actions/__tests__/dashboard-test.js @@ -9,16 +9,92 @@ var expect = require('expect'); const { setEditing, SET_EDITING, - setEditorAvailable, SET_EDITOR_AVAILABLE + setEditorAvailable, SET_EDITOR_AVAILABLE, + triggerShowConnections, SHOW_CONNECTIONS, + triggerSave, TRIGGER_SAVE_MODAL, + saveDashboard, SAVE_DASHBOARD, + dashboardSaveError, SAVE_ERROR, + dashboardSaved, DASHBOARD_SAVED, + loadDashboard, LOAD_DASHBOARD, + resetDashboard, DASHBOARD_RESET, + dashboardLoaded, DASHBOARD_LOADED, + dashboardLoading, DASHBOARD_LOADING } = require('../dashboard'); -it('setEditing', () => { - const retval = setEditing(); - expect(retval).toExist(); - expect(retval.type).toBe(SET_EDITING); -}); -it('setEditorAvailable', () => { - const retval = setEditorAvailable(); - expect(retval).toExist(); - expect(retval.type).toBe(SET_EDITOR_AVAILABLE); +describe('Test correctness of the dashboard actions', () => { + it('setEditing', () => { + const retval = setEditing(); + expect(retval).toExist(); + expect(retval.type).toBe(SET_EDITING); + }); + it('setEditorAvailable', () => { + const retval = setEditorAvailable(); + expect(retval).toExist(); + expect(retval.type).toBe(SET_EDITOR_AVAILABLE); + }); + it('triggerShowConnections', () => { + const retval = triggerShowConnections(true); + expect(retval).toExist(); + expect(retval.type).toBe(SHOW_CONNECTIONS); + expect(retval.show).toBe(true); + }); + it('triggerShowConnections', () => { + const retval = triggerShowConnections(); + expect(retval).toExist(); + expect(retval.type).toBe(SHOW_CONNECTIONS); + }); + it('triggerSave', () => { + const retval = triggerSave(); + expect(retval).toExist(); + expect(retval.type).toBe(TRIGGER_SAVE_MODAL); + }); + it('saveDashboard', () => { + const retval = saveDashboard({TEST: "TEST"}); + expect(retval).toExist(); + expect(retval.type).toBe(SAVE_DASHBOARD); + expect(retval.resource.TEST).toBe("TEST"); + }); + it('dashboardSaveError', () => { + const retval = dashboardSaveError("ERROR"); + expect(retval).toExist(); + expect(retval.type).toBe(SAVE_ERROR); + expect(retval.error).toBe("ERROR"); + }); + it('dashboardSaved', () => { + const retval = dashboardSaved(); + expect(retval).toExist(); + expect(retval.type).toBe(DASHBOARD_SAVED); + }); + it('loadDashboard', () => { + const retval = loadDashboard(1); + expect(retval).toExist(); + expect(retval.type).toBe(LOAD_DASHBOARD); + expect(retval.id).toBe(1); + }); + it('resetDashboard', () => { + const retval = resetDashboard(); + expect(retval).toExist(); + expect(retval.type).toBe(DASHBOARD_RESET); + }); + it('dashboardLoaded', () => { + const retval = dashboardLoaded("RES", "DATA"); + expect(retval).toExist(); + expect(retval.type).toBe(DASHBOARD_LOADED); + expect(retval.resource).toBe("RES"); + expect(retval.data).toBe("DATA"); + }); + it('dashboardLoading default', () => { + const retval = dashboardLoading(false); + expect(retval).toExist(); + expect(retval.type).toBe(DASHBOARD_LOADING); + expect(retval.name).toBe("loading"); + expect(retval.value).toBe(false); + }); + it('dashboardLoading', () => { + const retval = dashboardLoading(true, "saving"); + expect(retval).toExist(); + expect(retval.type).toBe(DASHBOARD_LOADING); + expect(retval.name).toBe("saving"); + expect(retval.value).toBe(true); + }); }); diff --git a/web/client/actions/__tests__/dashboards-test.js b/web/client/actions/__tests__/dashboards-test.js new file mode 100644 index 0000000000..a777dc56f8 --- /dev/null +++ b/web/client/actions/__tests__/dashboards-test.js @@ -0,0 +1,74 @@ +/* + * Copyright 2018, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ +var expect = require('expect'); +const { + setDashboardsAvailable, SET_DASHBOARDS_AVAILABLE, + searchDashboards, SEARCH_DASHBOARDS, + dashboardsLoading, LOADING, + dashboardListLoaded, DASHBOARDS_LIST_LOADED, + deleteDashboard, DELETE_DASHBOARD, + dashboardDeleted, DASHBOARD_DELETED, + reloadDashboards, RELOAD + + +} = require('../dashboards'); +describe('dashboards (browse) actions', () => { + it('setDashboardsAvailable', () => { + const retval = setDashboardsAvailable(true); + expect(retval).toExist(); + expect(retval.type).toBe(SET_DASHBOARDS_AVAILABLE); + expect(retval.available).toBe(true); + + }); + it('searchDashboards', () => { + const retval = searchDashboards(); + expect(retval).toExist(); + expect(retval.type).toBe(SEARCH_DASHBOARDS); + }); + it('dashboardLoading', () => { + const retval = dashboardsLoading(true, "test"); + expect(retval).toExist(); + expect(retval.type).toBe(LOADING); + expect(retval.value).toBe(true); + expect(retval.name).toBe("test"); + }); + it('dashboardListLoaded', () => { + const retval = dashboardListLoaded({ + results: [{id: 1}], + success: true, + totalCount: 1 + }, { + searchText: "test", + options: "someOptions" + }); + expect(retval).toExist(); + expect(retval.type).toBe(DASHBOARDS_LIST_LOADED); + expect(retval.results[0].id).toBe(1); + expect(retval.totalCount).toBe(1); + expect(retval.success).toBe(true); + expect(retval.searchText).toBe("test"); + expect(retval.options).toBe("someOptions"); + }); + it('deleteDashboard', () => { + const retval = deleteDashboard(1); + expect(retval).toExist(); + expect(retval.type).toBe(DELETE_DASHBOARD); + expect(retval.id).toBe(1); + }); + it('dashboardDeleted', () => { + const retval = dashboardDeleted(); + expect(retval).toExist(); + expect(retval.type).toBe(DASHBOARD_DELETED); + }); + it('reloadDashboards', () => { + const retval = reloadDashboards(); + expect(retval).toExist(); + expect(retval.type).toBe(RELOAD); + }); + +}); diff --git a/web/client/actions/__tests__/featuregrid-test.js b/web/client/actions/__tests__/featuregrid-test.js index 5980eef5f0..cb9d730da1 100644 --- a/web/client/actions/__tests__/featuregrid-test.js +++ b/web/client/actions/__tests__/featuregrid-test.js @@ -40,8 +40,11 @@ const { sizeChange, SIZE_CHANGE, START_SYNC_WMS, startSyncWMS, storeAdvancedSearchFilter, STORE_ADVANCED_SEARCH_FILTER, + setShowCurrentFilter, SET_SHOW_CURRENT_FILTER, fatureGridQueryResult, GRID_QUERY_RESULT, - moreFeatures, LOAD_MORE_FEATURES + moreFeatures, LOAD_MORE_FEATURES, + hideSyncPopover, HIDE_SYNC_POPOVER, + toggleShowAgain, TOGGLE_SHOW_AGAIN_FLAG } = require('../featuregrid'); const idFeature = "2135"; @@ -96,6 +99,16 @@ describe('Test correctness of featurgrid actions', () => { expect(retval).toExist(); expect(retval.type).toBe(CLEAR_CHANGES_CONFIRMED); }); + it('Test hideSyncPopover action creator', () => { + const retval = hideSyncPopover(); + expect(retval).toExist(); + expect(retval.type).toBe(HIDE_SYNC_POPOVER); + }); + it('Test toggleShowAgain action creator', () => { + const retval = toggleShowAgain(); + expect(retval).toExist(); + expect(retval.type).toBe(TOGGLE_SHOW_AGAIN_FLAG); + }); it('Test startDrawingFeature action creator', () => { const retval = startDrawingFeature(); expect(retval).toExist(); @@ -282,4 +295,12 @@ describe('Test correctness of featurgrid actions', () => { expect(retval.type).toBe(LOAD_MORE_FEATURES); expect(retval.pages).toBe(pages); }); + + it('Test setShowCurrentFilter', () => { + const showFilteredObject = true; + const retval = setShowCurrentFilter(showFilteredObject); + expect(retval).toExist(); + expect(retval.type).toBe(SET_SHOW_CURRENT_FILTER); + expect(retval.showFilteredObject).toBe(showFilteredObject); + }); }); diff --git a/web/client/actions/__tests__/floatinglegend-test.js b/web/client/actions/__tests__/floatinglegend-test.js new file mode 100644 index 0000000000..a4de85b2c4 --- /dev/null +++ b/web/client/actions/__tests__/floatinglegend-test.js @@ -0,0 +1,32 @@ +/* + * Copyright 2018, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +const expect = require('expect'); +const { + RESIZE_LEGEND, + EXPAND_LEGEND, + resizeLegend, + expandLegend +} = require('../floatinglegend'); + +describe('Test floatinglegend actions', () => { + it('resizeLegend', () => { + const size = {height: 100}; + const retval = resizeLegend(size); + expect(retval).toExist(); + expect(retval.type).toBe(RESIZE_LEGEND); + expect(retval.size).toBe(size); + }); + it('expandLegend', () => { + const expanded = true; + const retval = expandLegend(expanded); + expect(retval).toExist(); + expect(retval.type).toEqual(EXPAND_LEGEND); + expect(retval.expanded).toEqual(expanded); + }); +}); diff --git a/web/client/actions/__tests__/mapInfo-test.js b/web/client/actions/__tests__/mapInfo-test.js index f73e3b78cb..33cfe5f078 100644 --- a/web/client/actions/__tests__/mapInfo-test.js +++ b/web/client/actions/__tests__/mapInfo-test.js @@ -19,6 +19,7 @@ var { HIDE_REVERSE_GEOCODE, GET_VECTOR_INFO, TOGGLE_MAPINFO_STATE, + UPDATE_CENTER_TO_MARKER, getFeatureInfo, changeMapInfoState, newMapInfoRequest, @@ -27,7 +28,8 @@ var { showMapinfoRevGeocode, hideMapinfoRevGeocode, getVectorInfo, - toggleMapInfoState + toggleMapInfoState, + updateCenterToMarker } = require('../mapInfo'); describe('Test correctness of the map actions', () => { @@ -198,4 +200,10 @@ describe('Test correctness of the map actions', () => { const retval = toggleMapInfoState(); expect(retval.type).toBe(TOGGLE_MAPINFO_STATE); }); + + it('update center to marker', () => { + const retval = updateCenterToMarker('enabled'); + expect(retval.type).toBe(UPDATE_CENTER_TO_MARKER); + expect(retval.status).toBe('enabled'); + }); }); diff --git a/web/client/actions/__tests__/rulesmanager-test.js b/web/client/actions/__tests__/rulesmanager-test.js index c3e3b7c12c..3fba228be8 100644 --- a/web/client/actions/__tests__/rulesmanager-test.js +++ b/web/client/actions/__tests__/rulesmanager-test.js @@ -10,11 +10,44 @@ const expect = require('expect'); const { RULES_SELECTED, RULES_LOADED, UPDATE_ACTIVE_RULE, ACTION_ERROR, OPTIONS_LOADED, UPDATE_FILTERS_VALUES, rulesSelected, rulesLoaded, updateActiveRule, - actionError, optionsLoaded, updateFiltersValues} = require('../rulesmanager'); + actionError, optionsLoaded, updateFiltersValues, + SET_FILTER, setFilter, + SAVE_RULE, saveRule, cleanEditing, CLEAN_EDITING, + onEditRule, EDIT_RULE, delRules, DELETE_RULES} = require('../rulesmanager'); describe('test rules manager actions', () => { - - it('rules slected', () => { + it('save rule', () => { + const rule = {}; + const action = saveRule(rule); + expect(action).toExist(); + expect(action.type).toBe(SAVE_RULE); + expect(action.rule).toBe(rule); + }); + it('clean editing', () => { + const action = cleanEditing(); + expect(action).toExist(); + expect(action.type).toBe(CLEAN_EDITING); + }); + it('on edit rule', () => { + const action = onEditRule(); + expect(action).toExist(); + expect(action.type).toBe(EDIT_RULE); + expect(action.createNew).toBe(false); + expect(action.targetPriority).toBe(0); + }); + it('delete rules', () => { + const action = delRules(); + expect(action).toExist(); + expect(action.type).toBe(DELETE_RULES); + }); + it('set Filter', () => { + const action = setFilter("key", "value"); + expect(action).toExist(); + expect(action.type).toBe(SET_FILTER); + expect(action.key).toBe("key"); + expect(action.value).toBe("value"); + }); + it('rules selected', () => { const rules = [ { id: "rules1" }, { id: "rules2" } diff --git a/web/client/actions/__tests__/search-test.js b/web/client/actions/__tests__/search-test.js index b76b3a100e..cae2339bdc 100644 --- a/web/client/actions/__tests__/search-test.js +++ b/web/client/actions/__tests__/search-test.js @@ -15,13 +15,15 @@ var { TEXT_SEARCH_ITEM_SELECTED, TEXT_SEARCH_NESTED_SERVICES_SELECTED, TEXT_SEARCH_CANCEL_ITEM, + UPDATE_RESULTS_STYLE, searchResultLoaded, searchTextLoading, searchResultError, textSearch, selectSearchItem, selectNestedService, - cancelSelectedItem + cancelSelectedItem, + updateResultsStyle } = require('../search'); describe('Test correctness of the search actions', () => { @@ -56,11 +58,12 @@ describe('Test correctness of the search actions', () => { expect(retval2.append).toBe(true); }); it('serch item selected', () => { - const retval = selectSearchItem("A", "B"); + const retval = selectSearchItem("A", "B", {color: '#ff0000'}); expect(retval).toExist(); expect(retval.type).toBe(TEXT_SEARCH_ITEM_SELECTED); expect(retval.item).toEqual("A"); expect(retval.mapConfig).toBe("B"); + expect(retval.resultsStyle).toEqual({color: '#ff0000'}); }); it('serch item cancelled', () => { const retval = cancelSelectedItem("ITEM"); @@ -77,6 +80,11 @@ describe('Test correctness of the search actions', () => { expect(retval.items).toEqual(items); expect(retval.services).toEqual(services); }); - - + it('update results style', () => { + const style = {color: '#ff0000'}; + const retval = updateResultsStyle(style); + expect(retval).toExist(); + expect(retval.type).toBe(UPDATE_RESULTS_STYLE); + expect(retval.style).toEqual({color: '#ff0000'}); + }); }); diff --git a/web/client/actions/__tests__/widgets-test.js b/web/client/actions/__tests__/widgets-test.js index bf3eaac557..421b906235 100644 --- a/web/client/actions/__tests__/widgets-test.js +++ b/web/client/actions/__tests__/widgets-test.js @@ -22,6 +22,8 @@ const { OPEN_FILTER_EDITOR, EXPORT_CSV, EXPORT_IMAGE, + DEPENDENCY_SELECTOR_KEY, + createChart, NEW_CHART, exportCSV, exportImage, openFilterEditor, @@ -35,7 +37,9 @@ const { editNewWidget, onEditorChange, changeEditorSetting, - setPage + setPage, + setupDependencySelector, + toggleDependencySelector } = require('../widgets'); describe('Test correctness of the widgets actions', () => { @@ -156,5 +160,27 @@ describe('Test correctness of the widgets actions', () => { expect(retval.key).toBe("step"); expect(retval.value).toBe(1); }); + it('setupDependencySelector', () => { + const value = { active: true, setup: "setup" }; + const retval = setupDependencySelector(value); + expect(retval).toExist(); + expect(retval.type).toBe(EDITOR_SETTING_CHANGE); + expect(retval.key).toBe(`${DEPENDENCY_SELECTOR_KEY}`); + expect(retval.value).toBe(value); + }); + it('toggleDependencySelector', () => { + const value = { setup: "setup" }; + const retval = toggleDependencySelector(true, value); + expect(retval).toExist(); + expect(retval.type).toBe(EDITOR_SETTING_CHANGE); + expect(retval.key).toBe(`${DEPENDENCY_SELECTOR_KEY}`); + expect(retval.value.setup).toBe("setup"); + expect(retval.value.active).toBe(true); + }); + it('createChart', () => { + const retval = createChart(true); + expect(retval).toExist(); + expect(retval.type).toBe(NEW_CHART); + }); }); diff --git a/web/client/actions/dashboard.js b/web/client/actions/dashboard.js index b8eb3a3e07..53dd44d5a6 100644 --- a/web/client/actions/dashboard.js +++ b/web/client/actions/dashboard.js @@ -1,8 +1,46 @@ const SET_EDITOR_AVAILABLE = "DASHBOARD:SET_AVAILABLE"; const SET_EDITING = "DASHBOARD:SET_EDITING"; +const SHOW_CONNECTIONS = "DASHBOARD:SHOW_CONNECTIONS"; +const TRIGGER_SAVE_MODAL = "DASHBOARD:TRIGGER_SAVE_MODAL"; + +const SAVE_DASHBOARD = "DASHBOARD:SAVE_DASHBOARD"; +const SAVE_ERROR = "DASHBOARD:SAVE_ERROR"; +const DASHBOARD_SAVED = "DASHBOARD:DASHBOARD_SAVED"; + +const LOAD_DASHBOARD = "DASHBOARD:LOAD_DASHBOARD"; +const DASHBOARD_RESET = "DASHBOARD:DASHBOARD_RESET"; +const DASHBOARD_LOADED = "DASHBOARD:DASHBOARD_LOADED"; +const DASHBOARD_LOADING = "DASHBOARD:DASHBOARD_LOADING"; + module.exports = { SET_EDITING, setEditing: (editing) => ({type: SET_EDITING, editing }), SET_EDITOR_AVAILABLE, - setEditorAvailable: available => ({type: SET_EDITOR_AVAILABLE, available}) + setEditorAvailable: available => ({type: SET_EDITOR_AVAILABLE, available}), + SHOW_CONNECTIONS, + triggerShowConnections: show => ({ type: SHOW_CONNECTIONS, show}), + TRIGGER_SAVE_MODAL, + triggerSave: show => ({ type: TRIGGER_SAVE_MODAL, show}), + SAVE_DASHBOARD, + saveDashboard: resource => ({ type: SAVE_DASHBOARD, resource}), + SAVE_ERROR, + dashboardSaveError: error => ({type: SAVE_ERROR, error}), + DASHBOARD_SAVED, + dashboardSaved: id => ({type: DASHBOARD_SAVED, id}), + LOAD_DASHBOARD, + loadDashboard: id => ({ type: LOAD_DASHBOARD, id}), + DASHBOARD_LOADED, + DASHBOARD_RESET, + resetDashboard: () => ({ type: DASHBOARD_RESET}), + dashboardLoaded: (resource, data) => ({ type: DASHBOARD_LOADED, resource, data}), + DASHBOARD_LOADING, + /** + * @param {boolean} value the value of the flag + * @param {string} [name] the name of the flag to set. loading is anyway always triggered + */ + dashboardLoading: (value, name = "loading") => ({ + type: DASHBOARD_LOADING, + name, + value + }) }; diff --git a/web/client/actions/dashboards.js b/web/client/actions/dashboards.js new file mode 100644 index 0000000000..f894680d4d --- /dev/null +++ b/web/client/actions/dashboards.js @@ -0,0 +1,40 @@ +/* + * Copyright 2018, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +const SET_DASHBOARDS_AVAILABLE = "DASHBOARDS:SET_DASHBOARDS_AVAILABLE"; +const SEARCH_DASHBOARDS = "DASHBOARDS:SEARCH_DASHBOARDS"; +const DASHBOARDS_LIST_LOADED = "DASHBOARDS:DASHBOARDS_LIST_LOADED"; +const DELETE_DASHBOARD = "DASHBOARDS:DELETE_DASHBOARD"; +const DASHBOARD_DELETED = "DASHBOARDS:DASHBOARD_DELETED"; +const RELOAD = "DASHBOARDS:RELOAD_DASHBOARDS"; +const LOADING = "DASHBOARDS:LOADING"; + +module.exports = { + SET_DASHBOARDS_AVAILABLE, + setDashboardsAvailable: (available) => ({ type: SET_DASHBOARDS_AVAILABLE, available }), + SEARCH_DASHBOARDS, + searchDashboards: (searchText, params) => ({ type: SEARCH_DASHBOARDS, searchText, params }), + LOADING, + /** + * @param {boolean} value the value of the flag + * @param {string} [name] the name of the flag to set. loading is anyway always triggered + */ + dashboardsLoading: (value, name = "loading") => ({ + type: LOADING, + name, + value + }), + DASHBOARDS_LIST_LOADED, + dashboardListLoaded: ({ results, success, totalCount }, { searchText, options } = {}) => ({ type: DASHBOARDS_LIST_LOADED, results, success, totalCount, searchText, options }), + DELETE_DASHBOARD, + deleteDashboard: id => ({type: DELETE_DASHBOARD, id}), + DASHBOARD_DELETED, + RELOAD, + reloadDashboards: () => ({ type: RELOAD}), + dashboardDeleted: id => ({type: DASHBOARD_DELETED, id}) +}; diff --git a/web/client/actions/featuregrid.js b/web/client/actions/featuregrid.js index 90c661c6fd..db93df7077 100644 --- a/web/client/actions/featuregrid.js +++ b/web/client/actions/featuregrid.js @@ -6,6 +6,7 @@ * LICENSE file in the root directory of this source tree. */ +const SET_SHOW_CURRENT_FILTER = 'SET_SHOW_CURRENT_FILTER'; const SELECT_FEATURES = 'FEATUREGRID:SELECT_FEATURES'; const DESELECT_FEATURES = 'FEATUREGRID:DESELECT_FEATURES'; const CLEAR_SELECTION = 'FEATUREGRID:CLEAR_SELECTION'; @@ -45,6 +46,8 @@ const OPEN_ADVANCED_SEARCH = 'FEATUREGRID:ADVANCED_SEARCH'; const ZOOM_ALL = 'FEATUREGRID:ZOOM_ALL'; const INIT_PLUGIN = 'FEATUREGRID:INIT_PLUGIN'; const SIZE_CHANGE = 'FEATUREGRID:SIZE_CHANGE'; +const TOGGLE_SHOW_AGAIN_FLAG = 'FEATUREGRID:TOGGLE_SHOW_AGAIN_FLAG'; +const HIDE_SYNC_POPOVER = 'FEATUREGRID:HIDE_SYNC_POPOVER'; const MODES = { EDIT: "EDIT", @@ -56,6 +59,16 @@ const STORE_ADVANCED_SEARCH_FILTER = 'STORE_ADVANCED_SEARCH_FILTER'; const LOAD_MORE_FEATURES = "LOAD_MORE_FEATURES"; const GRID_QUERY_RESULT = 'FEATUREGRID:QUERY_RESULT'; +function toggleShowAgain() { + return { + type: TOGGLE_SHOW_AGAIN_FLAG + }; +} +function hideSyncPopover() { + return { + type: HIDE_SYNC_POPOVER + }; +} function fatureGridQueryResult(features, pages) { return { type: GRID_QUERY_RESULT, @@ -94,6 +107,12 @@ function selectFeatures(features, append) { append }; } +function setShowCurrentFilter(showFilteredObject) { + return { + type: SET_SHOW_CURRENT_FILTER, + showFilteredObject + }; +} function geometryChanged(features) { return { type: GEOMETRY_CHANGED, @@ -352,6 +371,7 @@ module.exports = { OPEN_FEATURE_GRID, openFeatureGrid, CLOSE_FEATURE_GRID_CONFIRM, closeFeatureGridConfirm, FEATURE_GRID_CLOSE_CONFIRMED, closeFeatureGridConfirmed, + SET_SHOW_CURRENT_FILTER, setShowCurrentFilter, DISABLE_TOOLBAR, disableToolbar, OPEN_ADVANCED_SEARCH, openAdvancedSearch, ZOOM_ALL, zoomAll, @@ -381,6 +401,8 @@ module.exports = { toggleEditMode, toggleViewMode, initPlugin, INIT_PLUGIN, + hideSyncPopover, HIDE_SYNC_POPOVER, + toggleShowAgain, TOGGLE_SHOW_AGAIN_FLAG, START_SYNC_WMS, startSyncWMS, STOP_SYNC_WMS, storeAdvancedSearchFilter, STORE_ADVANCED_SEARCH_FILTER, diff --git a/web/client/actions/floatinglegend.js b/web/client/actions/floatinglegend.js new file mode 100644 index 0000000000..61bff25549 --- /dev/null +++ b/web/client/actions/floatinglegend.js @@ -0,0 +1,44 @@ +/* + * Copyright 2018, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +const RESIZE_LEGEND = 'FLOATINGLEGEND:RESIZE_LEGEND'; +const EXPAND_LEGEND = 'FLOATINGLEGEND:EXPAND_LEGEND'; +/** + * resizeLegend action, type `RESIZE_LEGEND` + * @memberof actions.floatinglegend + * @param {object} size size of legend {width: 0, height: 0} + * @return {action} type `RESIZE_LEGEND` with size + */ +function resizeLegend(size) { + return { + type: RESIZE_LEGEND, + size + }; +} +/** + * expandLegend action, type `EXPAND_LEGEND` + * @memberof actions.floatinglegend + * @param {boolean} expanded expanded state of legend action + * @return {action} type `EXPAND_LEGEND` with expanded + */ +function expandLegend(expanded) { + return { + type: EXPAND_LEGEND, + expanded + }; +} +/** + * Actions for floatinglegend. + * @name actions.floatinglegend + */ +module.exports = { + RESIZE_LEGEND, + EXPAND_LEGEND, + resizeLegend, + expandLegend +}; diff --git a/web/client/actions/mapInfo.js b/web/client/actions/mapInfo.js index 11731f7de4..8630a1b902 100644 --- a/web/client/actions/mapInfo.js +++ b/web/client/actions/mapInfo.js @@ -27,6 +27,7 @@ const NO_QUERYABLE_LAYERS = 'NO_QUERYABLE_LAYERS'; const CLEAR_WARNING = 'CLEAR_WARNING'; const FEATURE_INFO_CLICK = 'FEATURE_INFO_CLICK'; const TOGGLE_MAPINFO_STATE = 'TOGGLE_MAPINFO_STATE'; +const UPDATE_CENTER_TO_MARKER = 'UPDATE_CENTER_TO_MARKER'; /** * Private @@ -196,6 +197,17 @@ function toggleMapInfoState() { }; } +/** + * Update center to marker if it's not in visible extent + */ + +function updateCenterToMarker(status) { + return { + type: UPDATE_CENTER_TO_MARKER, + status + }; +} + module.exports = { ERROR_FEATURE_INFO, EXCEPTIONS_FEATURE_INFO, @@ -213,6 +225,7 @@ module.exports = { CLEAR_WARNING, FEATURE_INFO_CLICK, TOGGLE_MAPINFO_STATE, + UPDATE_CENTER_TO_MARKER, getFeatureInfo, changeMapInfoState, newMapInfoRequest, @@ -228,5 +241,6 @@ module.exports = { clearWarning, errorFeatureInfo, loadFeatureInfo, - toggleMapInfoState + toggleMapInfoState, + updateCenterToMarker }; diff --git a/web/client/actions/maps.js b/web/client/actions/maps.js index ab50963de5..344ab4d04c 100644 --- a/web/client/actions/maps.js +++ b/web/client/actions/maps.js @@ -60,6 +60,7 @@ const TOGGLE_DETAILS_EDITABILITY = 'DETAILS:TOGGLE_DETAILS_EDITABILITY'; const DETAILS_LOADED = 'DETAILS:DETAILS_LOADED'; const DETAILS_SAVING = 'DETAILS:DETAILS_SAVING'; const NO_DETAILS_AVAILABLE = "NO_DETAILS_AVAILABLE"; +const FEATURED_MAPS_SET_ENABLED = "FEATURED_MAPS:SET_ENABLED"; /** @@ -893,6 +894,15 @@ function doNothing() { }; } +/** + * enable/disabled the "featured maps" functionality + * @memberof actions.maps + * @param {boolean} enabled the `enabled` flag + */ +const setFeaturedMapsEnabled = (enabled) => ({ + type: FEATURED_MAPS_SET_ENABLED, + enabled +}); /** * Actions for maps @@ -941,6 +951,7 @@ module.exports = { detailsLoaded, DETAILS_LOADED, detailsSaving, DETAILS_SAVING, toggleDetailsEditability, TOGGLE_DETAILS_EDITABILITY, + setFeaturedMapsEnabled, FEATURED_MAPS_SET_ENABLED, metadataChanged, loadMaps, mapsLoading, diff --git a/web/client/actions/rulesmanager.js b/web/client/actions/rulesmanager.js index 2c2e975675..2ea4acf47e 100644 --- a/web/client/actions/rulesmanager.js +++ b/web/client/actions/rulesmanager.js @@ -18,13 +18,63 @@ const UPDATE_ACTIVE_RULE = 'UPDATE_ACTIVE_RULE'; const UPDATE_FILTERS_VALUES = 'UPDATE_FILTERS_VALUES'; const ACTION_ERROR = 'ACTION_ERROR'; const OPTIONS_LOADED = 'OPTIONS_LOADED'; +const LOADING = 'RULES_MANAGER:LOADING'; +const SET_FILTER = "RULES_MANAGER:SET_FILTER"; +const EDIT_RULE = "RULES_MANAGER:EDIT_RULE"; +const CLEAN_EDITING = "RULES_MANAGER:CLEAN_EDITING"; +const SAVE_RULE = "RULES_MANAGER:SAVE_RULE"; +const RULE_SAVED = "RULES_MANAGER:RULE_SAVED"; +const DELETE_RULES = "RULES_MANAGER:DELETE_RULES"; +const CACHE_CLEAN = "RULES_MANAGER:CACHE_CLEAN"; -function rulesSelected(rules, merge, unselect) { +function onCacheClean() { + return { + type: CACHE_CLEAN + }; +} +function delRules(ids) { + return { + type: DELETE_RULES, + ids + }; +} + +function setFilter(key, value) { + return { + type: SET_FILTER, + key, + value + }; +} + +function onEditRule(targetPriority = 0, createNew = false) { + return { + type: EDIT_RULE, + createNew, + targetPriority + }; +} + +function cleanEditing() { + return { + type: CLEAN_EDITING + }; +} + +function setLoading(loading) { + return { + type: LOADING, + loading + }; +} + +function rulesSelected(rules, merge, unselect, targetPosition) { return { type: RULES_SELECTED, - rules: rules, - merge: merge, - unselect: unselect + rules, + merge, + unselect, + targetPosition }; } @@ -203,6 +253,8 @@ function updateRule() { }; } +const saveRule = (rule) => ({type: SAVE_RULE, rule}); + module.exports = { RULES_SELECTED, RULES_LOADED, @@ -225,5 +277,12 @@ module.exports = { loadWorkspaces, loadLayers, actionError, - optionsLoaded + optionsLoaded, + LOADING, setLoading, + SET_FILTER, setFilter, + EDIT_RULE, onEditRule, + CLEAN_EDITING, cleanEditing, + SAVE_RULE, saveRule, RULE_SAVED, + DELETE_RULES, delRules, + CACHE_CLEAN, onCacheClean }; diff --git a/web/client/actions/search.js b/web/client/actions/search.js index 88a6f46ecb..45102f50b8 100644 --- a/web/client/actions/search.js +++ b/web/client/actions/search.js @@ -18,6 +18,8 @@ const TEXT_SEARCH_ERROR = 'TEXT_SEARCH_ERROR'; const TEXT_SEARCH_CANCEL_ITEM = 'TEXT_SEARCH_CANCEL_ITEM'; const TEXT_SEARCH_ITEM_SELECTED = 'TEXT_SEARCH_ITEM_SELECTED'; const TEXT_SEARCH_SET_HIGHLIGHTED_FEATURE = 'TEXT_SEARCH_SET_HIGHLIGHTED_FEATURE'; +const UPDATE_RESULTS_STYLE = 'UPDATE_RESULTS_STYLE'; + /** * updates the results of the search result loaded * @memberof actions.search @@ -120,12 +122,14 @@ function textSearch(searchText, {services = null} = {}) { * @memberof actions.search * @param {object} item the selected item * @param {object} mapConfig the current map configuration (with size, projection...) + * @param {object} resultsStyle style to apply to results geometries */ -function selectSearchItem(item, mapConfig) { +function selectSearchItem(item, mapConfig, resultsStyle) { return { type: TEXT_SEARCH_ITEM_SELECTED, item, - mapConfig + mapConfig, + resultsStyle }; } @@ -171,6 +175,18 @@ function setHighlightedFeature(feature) { }; } +/** + * Change default style of results geometries + * @memberof actions.search + * @param {object} style style of results geometries + */ +function updateResultsStyle(style) { + return { + type: UPDATE_RESULTS_STYLE, + style + }; +} + /** * Actions for search * @name actions.search @@ -189,6 +205,7 @@ module.exports = { TEXT_SEARCH_NESTED_SERVICES_SELECTED, TEXT_SEARCH_CANCEL_ITEM, TEXT_SEARCH_SET_HIGHLIGHTED_FEATURE, + UPDATE_RESULTS_STYLE, searchTextLoading, searchResultError, searchResultLoaded, @@ -200,5 +217,6 @@ module.exports = { selectNestedService, selectSearchItem, cancelSelectedItem, - setHighlightedFeature + setHighlightedFeature, + updateResultsStyle }; diff --git a/web/client/actions/widgets.js b/web/client/actions/widgets.js index 1f0c7ee626..6f06d87f0b 100644 --- a/web/client/actions/widgets.js +++ b/web/client/actions/widgets.js @@ -17,10 +17,20 @@ const UPDATE_PROPERTY = "WIDGETS:UPDATE_PROPERTY"; const CHANGE_LAYOUT = "WIDGETS:CHANGE_LAYOUT"; const DELETE = "WIDGETS:DELETE"; const CLEAR_WIDGETS = "WIDGETS:CLEAR_WIDGETS"; +const ADD_DEPENDENCY = "WIDGETS:ADD_DEPENDENCY"; +const REMOVE_DEPENDENCY = "WIDGETS:REMOVE_DEPENDENCY"; +const LOAD_DEPENDENCIES = "WIDGETS:LOAD_DEPENDENCIES"; +const RESET_DEPENDENCIES = "WIDGETS:RESET_DEPENDENCIES"; +const TOGGLE_CONNECTION = "WIDGETS:TOGGLE_CONNECTION"; + const OPEN_FILTER_EDITOR = "WIDGETS:OPEN_FILTER_EDITOR"; const EXPORT_CSV = "WIDGETS:EXPORT_CSV"; const EXPORT_IMAGE = "WIDGETS:EXPORT_IMAGE"; +const WIDGET_SELECTED = "WIDGETS:WIDGET_SELECTED"; +const NEW_CHART = "WIDGETS:NEW_CHART"; const DEFAULT_TARGET = "floating"; +const DEPENDENCY_SELECTOR_KEY = "dependencySelector"; +const WIDGETS_REGEX = /^widgets\["?([^"\]]*)"?\]\.?(.*)$/; /** @@ -33,6 +43,14 @@ const createWidget = (widget) => ({ widget }); +/** + * Intent to create a new chart Widget + * @return {object} action with type `WIDGETS:NEW_CHART` + */ +const createChart = () => ({ + type: NEW_CHART +}); + /** * Add a new widget to the target * @param {object} widget The widget template to start with @@ -146,6 +164,40 @@ const changeEditorSetting = (key, value) => ({ key, value }); + +const addDependency = (key, value) => ({ + type: ADD_DEPENDENCY, + key, + value +}); + +const removeDependency = (key) => ({ + type: REMOVE_DEPENDENCY, + key +}); + +const resetDependencies = () => ({ + type: RESET_DEPENDENCIES +}); +const loadDependencies = (dependencies) => ({ + type: LOAD_DEPENDENCIES, + dependencies +}); + +/** + * Action triggered to start the connection flow. Typically starts the connection flow + * @param {array} availableDependencies Array of available dependency keys + * @param {object} the map of available dependencies where to choose. + * @param {object} options a map of connections to apply when the dependencies has been resolved. E.g. mappings for dependenciesMap + * @param {string} target target of the connection. If not present we assume is the current editing widget (not yet supported) + */ +const toggleConnection = (active, availableDependencies, options, target) => ({ + type: TOGGLE_CONNECTION, + active, + availableDependencies, + options, + target +}); /** * Change the page setting of the editor * @param {number} step the page number @@ -163,11 +215,40 @@ const exportCSV = ({data= [], title = "export"}) => ({ title }); +const selectWidget = (widget, opts) => ({ + type: WIDGET_SELECTED, + widget, + opts +}); const exportImage = ({widgetDivId}) => ({ type: EXPORT_IMAGE, widgetDivId }); +/** + * Triggers the filter editor opening + */ const openFilterEditor = () => ({type: OPEN_FILTER_EDITOR}); +/** + * Changes the setup of the dependency selector, that allow to select a dependent widget + * @param {object} setup the initial setup of the dependency selector + */ +const setupDependencySelector = (setup) => changeEditorSetting(`${DEPENDENCY_SELECTOR_KEY}`, setup); +/** + * Sets a value in the configuration of the dependency selector + * @param {string} key the configuration of the dependency selector to change + * @param {any} value the value to assign to the key + */ +const changeDependencySelector = (key, value) => changeEditorSetting(`${DEPENDENCY_SELECTOR_KEY}[${key}]`, value); +/** + * Activate/deactivate the dependency selector with an initial setup + * @param {boolean} active active flag of the dependency selector + * @param {object} settings initial setup + */ +const toggleDependencySelector = (active, settings) => setupDependencySelector({ + active, + ...settings +}); + module.exports = { NEW, INSERT, @@ -180,10 +261,16 @@ module.exports = { EDIT_NEW, EDITOR_CHANGE, EDITOR_SETTING_CHANGE, - DEFAULT_TARGET, + ADD_DEPENDENCY, + REMOVE_DEPENDENCY, + LOAD_DEPENDENCIES, + RESET_DEPENDENCIES, OPEN_FILTER_EDITOR, EXPORT_CSV, EXPORT_IMAGE, + TOGGLE_CONNECTION, + WIDGET_SELECTED, + createChart, NEW_CHART, exportCSV, exportImage, openFilterEditor, @@ -198,5 +285,17 @@ module.exports = { editNewWidget, onEditorChange, changeEditorSetting, - setPage + toggleConnection, + selectWidget, + addDependency, + removeDependency, + loadDependencies, + resetDependencies, + setPage, + changeDependencySelector, + setupDependencySelector, + toggleDependencySelector, + DEPENDENCY_SELECTOR_KEY, + DEFAULT_TARGET, + WIDGETS_REGEX }; diff --git a/web/client/api.html b/web/client/api.html index a87f1b093c..838974e615 100644 --- a/web/client/api.html +++ b/web/client/api.html @@ -4,15 +4,15 @@ - Page with MapStore 2 API + Page with MapStore API - + - + - + - +
diff --git a/web/client/embeddedTemplate.html b/web/client/embeddedTemplate.html index f6c40c5b0c..f9f7eb256e 100644 --- a/web/client/embeddedTemplate.html +++ b/web/client/embeddedTemplate.html @@ -4,7 +4,7 @@ - MapStore 2 HomePage + MapStore HomePage - + - +
diff --git a/web/client/epics/__tests__/dashboard-test.js b/web/client/epics/__tests__/dashboard-test.js index 72615f3ac5..e652228b1b 100644 --- a/web/client/epics/__tests__/dashboard-test.js +++ b/web/client/epics/__tests__/dashboard-test.js @@ -147,7 +147,7 @@ describe('openDashboardWidgetEditor epic', () => { case EDIT_NEW: expect(action.widget).toExist(); // verify default mapSync - expect(action.widget.mapSync).toBe(true); + expect(action.widget.mapSync).toBe(false); break; default: done(new Error("Action not recognized")); diff --git a/web/client/epics/__tests__/dashboards-test.js b/web/client/epics/__tests__/dashboards-test.js new file mode 100644 index 0000000000..0a82cbea50 --- /dev/null +++ b/web/client/epics/__tests__/dashboards-test.js @@ -0,0 +1,99 @@ +/* + * Copyright 2018, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +var expect = require('expect'); +const { testEpic } = require('./epicTestUtils'); +const ConfigUtils = require('../../utils/ConfigUtils'); + +const { + searchDashboardsOnMapSearch, + searchDashboards: searchDashboardsEpic +} = require('../dashboards'); + +const { + SEARCH_DASHBOARDS, + searchDashboards, + LOADING, + DASHBOARDS_LIST_LOADED +} = require('../../actions/dashboards'); + +const { + SHOW_NOTIFICATION +} = require('../../actions/notifications'); + +const { + mapsLoading +} = require('../../actions/maps'); +let getDefaults = ConfigUtils.getDefaults; +describe('dashboards epics', () => { + beforeEach( () => { + getDefaults = ConfigUtils.getDefaults; + }); + afterEach(() => { + ConfigUtils.getDefaults = getDefaults; + }); + it('searchDashboardsOnMapSearch', (done) => { + const startActions = [mapsLoading("Search Text")]; + testEpic(searchDashboardsOnMapSearch, 1, startActions, actions => { + expect(actions.length).toBe(1); + actions.map((action) => { + switch (action.type) { + case LOADING: + + break; + case SEARCH_DASHBOARDS: + expect(action.searchText).toBe("Search Text"); + done(); + break; + default: + done(new Error("Action not recognized")); + } + }); + done(); + }, {}); + }); + it('searchDashboards', (done) => { + const baseUrl = "base/web/client/test-resources/geostore/extjs/search/search_1.json#"; + ConfigUtils.getDefaults = () => ({ + geoStoreUrl: baseUrl + }); + + const startActions = [searchDashboards("Search Text")]; + testEpic(searchDashboardsEpic, 3, startActions, actions => { + expect(actions.length).toBe(3); + expect(actions[0].type).toBe(LOADING); + expect(actions[0].name).toBe("loading"); + expect(actions[0].value).toBe(true); + expect(actions[1].type).toBe(DASHBOARDS_LIST_LOADED); + expect(actions[1].totalCount).toBe(1); + expect(actions[2].type).toBe(LOADING); + expect(actions[2].name).toBe("loading"); + expect(actions[2].value).toBe(false); + done(); + }, {}); + }); + it('searchDashboards error', (done) => { + const baseUrl = "base/web/client/test-resources/geostore/extjs/search/NODATA#"; + ConfigUtils.getDefaults = () => ({ + geoStoreUrl: baseUrl + }); + + const startActions = [searchDashboards("Search Text")]; + testEpic(searchDashboardsEpic, 3, startActions, actions => { + expect(actions.length).toBe(3); + expect(actions[0].type).toBe(LOADING); + expect(actions[0].name).toBe("loading"); + expect(actions[0].value).toBe(true); + expect(actions[1].type).toBe(SHOW_NOTIFICATION); + expect(actions[2].type).toBe(LOADING); + expect(actions[2].name).toBe("loading"); + expect(actions[2].value).toBe(false); + done(); + }, {}); + }); +}); diff --git a/web/client/epics/__tests__/globeswitcher-test.js b/web/client/epics/__tests__/globeswitcher-test.js index e42ec788ec..6d718a77cf 100644 --- a/web/client/epics/__tests__/globeswitcher-test.js +++ b/web/client/epics/__tests__/globeswitcher-test.js @@ -9,23 +9,24 @@ var expect = require('expect'); const {toggle3d, UPDATE_LAST_2D_MAPTYPE} = require('../../actions/globeswitcher'); +const { localConfigLoaded } = require('../../actions/localConfig'); + const assign = require('object-assign'); -const {updateRouteOn3dSwitch} = require('../globeswitcher'); + +const { updateRouteOn3dSwitch, updateLast2dMapTypeOnChangeEvents} = require('../globeswitcher'); + const {testEpic} = require('./epicTestUtils'); describe('globeswitcher Epics', () => { - it('updates maptype', (done) => { - testEpic(updateRouteOn3dSwitch, 2, assign({hash: "/viewer/leaflet/2"}, toggle3d(true, "leaflet")), actions => { - expect(actions.length).toBe(2); + it('updates maptype toggling to 3D', (done) => { + testEpic(updateRouteOn3dSwitch, 1, assign({hash: "/viewer/leaflet/2"}, toggle3d(true, "leaflet")), actions => { + expect(actions.length).toBe(1); actions.map((action) => { switch (action.type) { case "@@router/CALL_HISTORY_METHOD": expect(action.payload.method).toBe('push'); expect(action.payload.args.length).toBe(1); break; - case UPDATE_LAST_2D_MAPTYPE: - expect(action.mapType).toBe("leaflet"); - break; default: expect(true).toBe(false); @@ -34,19 +35,68 @@ describe('globeswitcher Epics', () => { done(); }); + }); + it('updates maptype toggling from 3D', (done) => { + testEpic(updateRouteOn3dSwitch, 1, assign({ hash: "/viewer/cesium/2" }, toggle3d(true, "leaflet")), actions => { + expect(actions.length).toBe(1); + actions.map((action) => { + switch (action.type) { + case "@@router/CALL_HISTORY_METHOD": + expect(action.payload.method).toBe('push'); + expect(action.payload.args.length).toBe(1); + break; + default: + expect(true).toBe(false); + + } + }); + done(); + }); + }); it('updates maptype on newmap', (done) => { - testEpic(updateRouteOn3dSwitch, 2, assign({hash: "/viewer/leaflet/new"}, toggle3d(true, "leaflet")), actions => { - expect(actions.length).toBe(2); + testEpic(updateRouteOn3dSwitch, 1, assign({hash: "/viewer/leaflet/new"}, toggle3d(true, "leaflet")), actions => { + expect(actions.length).toBe(1); actions.map((action) => { switch (action.type) { case "@@router/CALL_HISTORY_METHOD": expect(action.payload.method).toBe('push'); expect(action.payload.args.length).toBe(1); break; + default: + expect(true).toBe(false); + + } + }); + done(); + }); + + }); + it('updateLast2dMapTypeOnChangeEvents', (done) => { + testEpic(updateLast2dMapTypeOnChangeEvents, 1, [localConfigLoaded(), assign({ hash: "/viewer/leaflet/new" }, toggle3d(true))], actions => { + expect(actions.length).toBe(1); + actions.map((action) => { + switch (action.type) { + case UPDATE_LAST_2D_MAPTYPE: + expect(action.mapType).toBe('leaflet'); + break; + default: + expect(true).toBe(false); + + } + }); + done(); + }); + + }); + it('updateLast2dMapTypeOnChangeEvents with custom mapType', (done) => { + testEpic(updateLast2dMapTypeOnChangeEvents, 1, [localConfigLoaded(), assign({ hash: "/viewer/leaflet/new" }, toggle3d(true))], actions => { + expect(actions.length).toBe(1); + actions.map((action) => { + switch (action.type) { case UPDATE_LAST_2D_MAPTYPE: - expect(action.mapType).toBe("leaflet"); + expect(action.mapType).toBe('openlayers'); break; default: expect(true).toBe(false); @@ -54,7 +104,12 @@ describe('globeswitcher Epics', () => { } }); done(); + }, { + maptype: { + mapType: 'openlayers' + } }); }); + }); diff --git a/web/client/epics/__tests__/identify-test.js b/web/client/epics/__tests__/identify-test.js new file mode 100644 index 0000000000..f5916e27cf --- /dev/null +++ b/web/client/epics/__tests__/identify-test.js @@ -0,0 +1,134 @@ +/* + * Copyright 2018, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +const expect = require('expect'); + +const {ZOOM_TO_POINT} = require('../../actions/map'); +const {FEATURE_INFO_CLICK, UPDATE_CENTER_TO_MARKER, loadFeatureInfo} = require('../../actions/mapInfo'); +const {zoomToVisibleAreaEpic} = require('../identify'); +const {testEpic} = require('./epicTestUtils'); +const {registerHook} = require('../../utils/MapUtils'); + +describe('identify Epics', () => { + + it('test center to visible area', (done) => { + + // remove previous hook + registerHook('RESOLUTION_HOOK', undefined); + + const state = { + mapInfo: { + centerToMarker: true + }, + map: { + present: { + size: { + width: 1581, + height: 946 + }, + zoom: 4, + projection: 'EPSG:3857', + bbox: { + bounds: { + maxx: -5732165, + maxy: 5722381, + minx: -9599267, + miny: 3408479 + }, + crs: 'EPSG:3857' + } + } + }, + maplayout: { + boundingMapRect: { + left: 500, + bottom: 250 + } + } + }; + + const sentActions = [{type: FEATURE_INFO_CLICK, point: {latlng: {lat: 36.95, lng: -79.84}}}, loadFeatureInfo()]; + + const expectedAction = actions => { + expect(actions.length).toBe(2); + actions.map((action) => { + switch (action.type) { + case ZOOM_TO_POINT: + expect(action.zoom).toBe(4); + expect({x: parseFloat(action.pos.x.toFixed(2)), y: parseFloat(action.pos.y.toFixed(2))}).toEqual({x: -101.81, y: 27.68}); + expect(action.crs).toBe('EPSG:4326'); + break; + case UPDATE_CENTER_TO_MARKER: + expect(action.status).toBe('enabled'); + break; + default: + expect(true).toBe(false); + } + }); + done(); + }; + + testEpic(zoomToVisibleAreaEpic, 2, sentActions, expectedAction, state); + }); + + it('test no center to visible area', (done) => { + + // remove previous hook + registerHook('RESOLUTION_HOOK', undefined); + + const state = { + mapInfo: { + centerToMarker: true + }, + map: { + present: { + size: { + width: 1581, + height: 946 + }, + zoom: 4, + projection: 'EPSG:3857', + bbox: { + bounds: { + maxx: -5732165, + maxy: 5722381, + minx: -9599267, + miny: 3408479 + }, + crs: 'EPSG:3857' + } + } + }, + maplayout: { + boundingMapRect: { + left: 0, + bottom: 0 + } + } + }; + + const sentActions = [{type: FEATURE_INFO_CLICK, point: {latlng: {lat: 36.95, lng: -79.84}}}, loadFeatureInfo()]; + + const expectedAction = actions => { + expect(actions.length).toBe(1); + actions.map((action) => { + switch (action.type) { + case UPDATE_CENTER_TO_MARKER: + expect(action.status).toBe('disabled'); + break; + default: + expect(true).toBe(false); + } + }); + done(); + }; + + testEpic(zoomToVisibleAreaEpic, 1, sentActions, expectedAction, state); + }); + +}); diff --git a/web/client/epics/__tests__/localconfig-test.js b/web/client/epics/__tests__/localconfig-test.js index 65232789c6..509e74297d 100644 --- a/web/client/epics/__tests__/localconfig-test.js +++ b/web/client/epics/__tests__/localconfig-test.js @@ -27,7 +27,7 @@ describe('localconfig Epics', () => { switch (action.type) { case SUPPORTED_LOCALES_REGISTERED: // 7 is the actual default number of locales - expect(Object.keys(suppLocales).length).toBe(7); + expect(Object.keys(suppLocales).length).toBe(8); break; default: expect(true).toBe(false); diff --git a/web/client/epics/__tests__/maplayout-test.js b/web/client/epics/__tests__/maplayout-test.js index 25a43badca..2ea611c020 100644 --- a/web/client/epics/__tests__/maplayout-test.js +++ b/web/client/epics/__tests__/maplayout-test.js @@ -20,7 +20,11 @@ describe('map layout epics', () => { expect(actions.length).toBe(1); actions.map((action) => { expect(action.type).toBe(UPDATE_MAP_LAYOUT); - expect(action.layout).toEqual({ left: 600, right: 658, bottom: 30, transform: 'none', height: 'calc(100% - 30px)' } ); + expect(action.layout).toEqual({ left: 600, right: 658, bottom: 30, transform: 'none', height: 'calc(100% - 30px)', boundingMapRect: { + left: 600, + right: 658, + bottom: 30 + }}); }); } catch(e) { done(e); @@ -37,7 +41,9 @@ describe('map layout epics', () => { expect(actions.length).toBe(1); actions.map((action) => { expect(action.type).toBe(UPDATE_MAP_LAYOUT); - expect(action.layout).toEqual({ height: 'calc(100% - 30px)' } ); + expect(action.layout).toEqual({ height: 'calc(100% - 30px)', boundingMapRect: { + bottom: undefined + }} ); }); } catch(e) { done(e); diff --git a/web/client/epics/__tests__/maps-test.js b/web/client/epics/__tests__/maps-test.js index 8effdc41a3..736dbde657 100644 --- a/web/client/epics/__tests__/maps-test.js +++ b/web/client/epics/__tests__/maps-test.js @@ -13,9 +13,10 @@ const {createEpicMiddleware, combineEpics } = require('redux-observable'); const { saveDetails, SET_DETAILS_CHANGED, CLOSE_DETAILS_PANEL, closeDetailsPanel, - openDetailsPanel, UPDATE_DETAILS, + openDetailsPanel, UPDATE_DETAILS, DETAILS_LOADED, MAP_DELETING, MAP_DELETED, deleteMap, TOGGLE_DETAILS_SHEET } = require('../../actions/maps'); +const { mapInfoLoaded } = require('../../actions/config'); const {SHOW_NOTIFICATION} = require('../../actions/notifications'); const {TOGGLE_CONTROL} = require('../../actions/controls'); const {RESET_CURRENT_MAP, editMap} = require('../../actions/currentMap'); @@ -24,7 +25,7 @@ const {CLOSE_FEATURE_GRID} = require('../../actions/featuregrid'); const { setDetailsChangedEpic, closeDetailsPanelEpic, fetchDataForDetailsPanel, - fetchDetailsFromResourceEpic, deleteMapAndAssociatedResourcesEpic} = require('../maps'); + fetchDetailsFromResourceEpic, deleteMapAndAssociatedResourcesEpic, storeDetailsInfoEpic} = require('../maps'); const rootEpic = combineEpics(setDetailsChangedEpic, closeDetailsPanelEpic); const epicMiddleware = createEpicMiddleware(rootEpic); const mockStore = configureMockStore([epicMiddleware]); @@ -49,6 +50,7 @@ const locale = { } }; const mapId = 1; +const mapId2 = 2; const mapId8 = 8; const detailsText = "

details of this map

"; const detailsUri = "data/2"; @@ -56,6 +58,10 @@ let map1 = { id: mapId, name: "name" }; +let map2 = { + id: mapId2, + name: "name2" +}; let map8 = { id: mapId8, name: "name" @@ -433,5 +439,24 @@ describe('maps Epics', () => { } }); }); + it('test storeDetailsInfoEpic', (done) => { + testEpic(addTimeoutEpic(storeDetailsInfoEpic), 1, mapInfoLoaded(map2, mapId2), actions => { + expect(actions.length).toBe(1); + actions.map((action) => { + switch (action.type) { + case DETAILS_LOADED: + expect(action.mapId).toBe(mapId2); + expect(action.detailsUri).toBe("rest%2Fgeostore%2Fdata%2F3983%2Fraw%3Fdecode%3Ddatauri"); + break; + default: + expect(true).toBe(false); + } + }); + done(); + }, {mapInitialConfig: { + "mapId": mapId2 + }}); + }); + }); diff --git a/web/client/epics/__tests__/search-test.js b/web/client/epics/__tests__/search-test.js index 874d7ecfab..b3d2f48fd0 100644 --- a/web/client/epics/__tests__/search-test.js +++ b/web/client/epics/__tests__/search-test.js @@ -11,7 +11,7 @@ var expect = require('expect'); const configureMockStore = require('redux-mock-store').default; const { createEpicMiddleware, combineEpics } = require('redux-observable'); -const { textSearch, selectSearchItem, TEXT_SEARCH_RESULTS_LOADED, TEXT_SEARCH_LOADING, TEXT_SEARCH_ADD_MARKER, TEXT_SEARCH_RESULTS_PURGE, TEXT_SEARCH_NESTED_SERVICES_SELECTED, TEXT_SEARCH_TEXT_CHANGE } = require('../../actions/search'); +const { textSearch, selectSearchItem, TEXT_SEARCH_RESULTS_LOADED, TEXT_SEARCH_LOADING, TEXT_SEARCH_ADD_MARKER, TEXT_SEARCH_RESULTS_PURGE, TEXT_SEARCH_NESTED_SERVICES_SELECTED, TEXT_SEARCH_TEXT_CHANGE, UPDATE_RESULTS_STYLE } = require('../../actions/search'); const {CHANGE_MAP_VIEW} = require('../../actions/map'); const {searchEpic, searchItemSelected } = require('../search'); const rootEpic = combineEpics(searchEpic, searchItemSelected); @@ -106,10 +106,11 @@ describe('search Epics', () => { store.dispatch( action ); let actions = store.getActions(); - expect(actions.length).toBe(4); + expect(actions.length).toBe(5); expect(actions[1].type).toBe(TEXT_SEARCH_RESULTS_PURGE); - expect(actions[2].type).toBe(CHANGE_MAP_VIEW); - expect(actions[3].type).toBe(TEXT_SEARCH_ADD_MARKER); + expect(actions[2].type).toBe(UPDATE_RESULTS_STYLE); + expect(actions[3].type).toBe(CHANGE_MAP_VIEW); + expect(actions[4].type).toBe(TEXT_SEARCH_ADD_MARKER); }); it('searchItemSelected epic with nested services', () => { @@ -124,8 +125,8 @@ describe('search Epics', () => { store.dispatch( action ); let actions = store.getActions(); - expect(actions.length).toBe(6); - let expectedActions = [CHANGE_MAP_VIEW, TEXT_SEARCH_ADD_MARKER, TEXT_SEARCH_RESULTS_PURGE, TEXT_SEARCH_NESTED_SERVICES_SELECTED, TEXT_SEARCH_TEXT_CHANGE ]; + expect(actions.length).toBe(7); + let expectedActions = [CHANGE_MAP_VIEW, TEXT_SEARCH_ADD_MARKER, TEXT_SEARCH_RESULTS_PURGE, UPDATE_RESULTS_STYLE, TEXT_SEARCH_NESTED_SERVICES_SELECTED, TEXT_SEARCH_TEXT_CHANGE ]; let actionsType = actions.map(a => a.type); expectedActions.forEach((a) => { diff --git a/web/client/epics/__tests__/widgets-test.js b/web/client/epics/__tests__/widgets-test.js index 00cdb9d81d..3199b8d80c 100644 --- a/web/client/epics/__tests__/widgets-test.js +++ b/web/client/epics/__tests__/widgets-test.js @@ -9,10 +9,19 @@ var expect = require('expect'); const { testEpic, addTimeoutEpic, TEST_TIMEOUT } = require('./epicTestUtils'); const { - clearWidgetsOnLocationChange + clearWidgetsOnLocationChange, + alignDependenciesToWidgets, + toggleWidgetConnectFlow } = require('../widgets'); const { - CLEAR_WIDGETS + CLEAR_WIDGETS, + insertWidget, + toggleConnection, + selectWidget, + EDITOR_CHANGE, + EDITOR_SETTING_CHANGE, + LOAD_DEPENDENCIES, + DEPENDENCY_SELECTOR_KEY } = require('../../actions/widgets'); const { savingMap, @@ -126,4 +135,141 @@ describe('widgets Epics', () => { }; }); }); + it('alignDependenciesToWidgets triggered on insertWidget', (done) => { + const checkActions = actions => { + expect(actions.length).toBe(1); + const action = actions[0]; + expect(action.type).toBe(LOAD_DEPENDENCIES); + expect(action.dependencies).toExist(); + expect(action.dependencies.center).toBe("map.center"); + expect(action.dependencies.viewport).toBe("map.bbox"); + expect(action.dependencies.zoom).toBe("map.zoom"); + done(); + }; + testEpic(alignDependenciesToWidgets, + 1, + [insertWidget({id: 'test'})], + checkActions, + {}); + }); + + it('toggleWidgetConnectFlow with only map', (done) => { + const checkActions = actions => { + expect(actions.length).toBe(2); + expect(actions[0].type).toBe(EDITOR_CHANGE); + expect(actions[0].key).toBe("mapSync"); + expect(actions[0].value).toBe(true); + const action = actions[1]; + expect(action.type).toBe(EDITOR_CHANGE); + expect(action.key).toExist(); + expect(action.key).toBe("dependenciesMap"); + expect(action.value.center).toBe("center"); + expect(action.value.zoom).toBe("zoom"); + done(); + }; + testEpic(toggleWidgetConnectFlow, + 2, + [toggleConnection( + true, + ["map"], + { mappings: { zoom: "zoom", center: "center" } } + )], + checkActions, + {}); + }); + it('toggleWidgetConnectFlow for widgets', (done) => { + const checkActions = actions => { + expect(actions.length).toBe(2); + expect(actions[0].type).toBe(EDITOR_CHANGE); + expect(actions[0].key).toBe("mapSync"); + expect(actions[0].value).toBe(true); + const action = actions[1]; + expect(action.type).toBe(EDITOR_CHANGE); + expect(action.key).toExist(); + expect(action.key).toBe("dependenciesMap"); + expect(action.value.center).toBe("widgets[a].map.center"); + expect(action.value.zoom).toBe("widgets[a].map.zoom"); + done(); + }; + testEpic(toggleWidgetConnectFlow, + 2, + [toggleConnection( + true, + ["widgets[a].map"], + { mappings: { "center": "center", "zoom": "zoom" } } + )], + checkActions, + {}); + }); + it('toggleWidgetConnectFlow for multiple widgets', (done) => { + const checkActions = actions => { + expect(actions.length).toBe(4); + expect(actions[0].type).toBe(EDITOR_SETTING_CHANGE); + expect(actions[0].key).toBe(DEPENDENCY_SELECTOR_KEY); + expect(actions[0].value.active).toBe(true); + expect(actions[0].value.availableDependencies.length).toBe(2); + expect(actions[1].type).toBe(EDITOR_CHANGE); + expect(actions[1].key).toBe("mapSync"); + expect(actions[1].value).toBe(true); + const action = actions[2]; + expect(action.type).toBe(EDITOR_CHANGE); + expect(action.key).toExist(); + expect(action.key).toBe("dependenciesMap"); + expect(action.value.center).toBe("widgets[w1].map.center"); + expect(action.value.zoom).toBe("widgets[w1].map.zoom"); + expect(actions[3].type).toBe(EDITOR_SETTING_CHANGE); + expect(actions[3].key).toBe(DEPENDENCY_SELECTOR_KEY); + expect(actions[3].value.active).toBe(false); + done(); + }; + testEpic(toggleWidgetConnectFlow, + 4, + [toggleConnection( + true, + ["w1", "w2"], + { mappings: { "center": "center", "zoom": "zoom" } } + ), selectWidget({ + id: "w1", + widgetType: "map" + })], + checkActions, + { + widgets: { + builder: { + settings: { + [DEPENDENCY_SELECTOR_KEY]: { active: true, + availableDependencies: [ + "map.zoom", + "widgets[w1].map", + "widgets[w2].map" + ] } + } + } + } + }); + }); + it('toggleWidgetConnectFlow deactivate widgets', (done) => { + const checkActions = actions => { + expect(actions.length).toBe(2); + expect(actions[0].type).toBe(EDITOR_CHANGE); + expect(actions[0].key).toBe("mapSync"); + expect(actions[0].value).toBe(false); + const action = actions[1]; + expect(action.type).toBe(EDITOR_CHANGE); + expect(action.key).toExist(); + expect(action.key).toBe("dependenciesMap"); + expect(action.value.center).toNotExist(); + expect(action.value.zoom).toNotExist(); + done(); + }; + testEpic(toggleWidgetConnectFlow, + 2, + [toggleConnection( + false, + ["map"], + { mappings: { "center": "widgets[a].map.center", "zoom": "widgets[a].map.zoom" } } + )], + checkActions, + {}); + }); }); diff --git a/web/client/epics/__tests__/widgetsbuilder-test.js b/web/client/epics/__tests__/widgetsbuilder-test.js index 0e7c508915..50d9725219 100644 --- a/web/client/epics/__tests__/widgetsbuilder-test.js +++ b/web/client/epics/__tests__/widgetsbuilder-test.js @@ -11,14 +11,18 @@ const { openWidgetEditor, initEditorOnNew, closeWidgetEditorOnFinish, - handleWidgetsFilterPanel + handleWidgetsFilterPanel, + initEditorOnNewChart } = require('../widgetsbuilder'); const { createWidget, editWidget, insertWidget, - openFilterEditor, + openFilterEditor, createChart, EDIT_NEW, EDITOR_CHANGE } = require('../../actions/widgets'); +const { + CLOSE_FEATURE_GRID +} = require('../../actions/featuregrid'); const {FEATURE_TYPE_SELECTED} = require('../../actions/wfsquery'); const {LOAD_FILTER, search} = require('../../actions/queryform'); @@ -170,6 +174,33 @@ describe('widgetsbuilder epic', () => { } }); }); + it('initEditorOnNewChart', (done) => { + const startActions = [createChart()]; + testEpic(initEditorOnNewChart, 2, startActions, actions => { + expect(actions.length).toBe(2); + actions.map((action) => { + switch (action.type) { + case EDIT_NEW: + expect(action.widget).toExist(); + // verify default mapSync + expect(action.widget.mapSync).toBe(true); + break; + case CLOSE_FEATURE_GRID: + expect(action.type).toBe(CLOSE_FEATURE_GRID); + break; + default: + done(new Error("Action not recognized")); + } + }, ); + done(); + }, { + controls: { + widgetBuilder: { + available: true + } + } + }); + }); it('handleWidgetsFilterPanel', (done) => { const startActions = [openFilterEditor()]; testEpic(handleWidgetsFilterPanel, 4, startActions, actions => { diff --git a/web/client/epics/dashboard.js b/web/client/epics/dashboard.js index 30e3dc841c..e49ad82372 100644 --- a/web/client/epics/dashboard.js +++ b/web/client/epics/dashboard.js @@ -11,7 +11,15 @@ const { editNewWidget, onEditorChange } = require('../actions/widgets'); const { - setEditing + setEditing, + dashboardSaved, + dashboardLoaded, + dashboardLoading, + triggerSave, + loadDashboard, + dashboardSaveError, + SAVE_DASHBOARD, + LOAD_DASHBOARD } = require('../actions/dashboard'); const { setControlProperty, @@ -20,20 +28,40 @@ const { const { featureTypeSelected } = require('../actions/wfsquery'); +const { + show, + error +} = require('../actions/notifications'); const { loadFilter, QUERY_FORM_SEARCH } = require('../actions/queryform'); +const { + LOGIN_SUCCESS, + LOGOUT +} = require('../actions/security'); const { isDashboardEditing, isDashboardAvailable = () => true } = require('../selectors/dashboard'); + +const { + isLoggedIn +} = require('../selectors/security'); const { getEditingWidgetLayer, getEditingWidgetFilter } = require('../selectors/widgets'); -const {LOCATION_CHANGE} = require('react-router-redux'); +const { + createResource, + updateResource, + getResource +} = require('../observables/geostore'); +const { + wrapStartStop +} = require('../observables/epics'); +const { LOCATION_CHANGE, push} = require('react-router-redux'); const getFTSelectedArgs = (state) => { let layer = getEditingWidgetLayer(state); let url = layer.search && layer.search.url; @@ -42,23 +70,29 @@ const getFTSelectedArgs = (state) => { }; module.exports = { + + // Basic interactions with dashboard editor openDashboardWidgetEditor: (action$, {getState = () => {}} = {}) => action$.ofType(NEW, EDIT) .filter( () => isDashboardAvailable(getState())) .switchMap(() => Rx.Observable.of( setEditing(true) )), + // Basic interactions with dashboard editor closeDashboardWidgetEditorOnFinish: (action$, {getState = () => {}} = {}) => action$.ofType(INSERT) .filter( () => isDashboardAvailable(getState())) .switchMap(() => Rx.Observable.of(setEditing(false))), + + // Basic interactions with dashboard editor initDashboardEditorOnNew: (action$, {getState = () => {}} = {}) => action$.ofType(NEW) .filter( () => isDashboardAvailable(getState())) .switchMap((w) => Rx.Observable.of(editNewWidget({ legend: false, - mapSync: true, + mapSync: false, ...w, // override action's type type: undefined }, {step: 0}))), + // Basic interactions with dashboard editor closeDashboardEditorOnExit: (action$, {getState = () => {}} = {}) => action$.ofType(LOCATION_CHANGE) .filter( () => isDashboardAvailable(getState())) .filter( () => isDashboardEditing(getState()) ) @@ -99,6 +133,73 @@ module.exports = { setControlProperty('queryPanel', "enabled", false) ) ) - ) - + ), + // dashboard loading from resource ID. + loadDashboardStream: (action$, {getState = () => {}}) => action$ + .ofType(LOAD_DASHBOARD) + .switchMap( ({id}) => + getResource(id) + .map(({ data, ...resource }) => dashboardLoaded(resource, data)) + .let(wrapStartStop( + dashboardLoading(true, "loading"), + dashboardLoading(false, "loading"), + e => { + if (e.status === 403 ) { + if ( isLoggedIn(getState())) { + return Rx.Observable.of(error({ + title: "dashboard.errors.loading.title", + message: "dashboard.errors.loading.dashboardNotAccessible" + })); + } + return Rx.Observable.of(error({ + title: "dashboard.errors.loading.title", + message: "dashboard.errors.loading.pleaseLogin" + })); + } if (e.status === 404) { + return Rx.Observable.of(error({ + title: "dashboard.errors.loading.title", + message: "dashboard.errors.loading.dashboardDoesNotExist" + })); + } + return Rx.Observable.of(error({ + title: "dashboard.errors.loading.title", + message: "dashboard.errors.loading.unknownError" + })); + } + )) + ), + reloadDashboardOnLoginLogout: (action$) => + action$.ofType(LOAD_DASHBOARD).switchMap( + ({ id }) => action$ + .ofType(LOGIN_SUCCESS, LOGOUT) + .switchMap(() => Rx.Observable.of(loadDashboard(id)).delay(1000)) + .takeUntil(action$.ofType(LOCATION_CHANGE)) + ), + // saving dashboard flow (both creation and update) + saveDashboard: action$ => action$ + .ofType(SAVE_DASHBOARD) + .exhaustMap(({resource} = {}) => + (!resource.id ? createResource(resource) : updateResource(resource)) + .switchMap(rid => Rx.Observable.of( + dashboardSaved(rid), + triggerSave(false), + !resource.id + ? push(`/dashboard/${rid}`) + : loadDashboard(rid), + ).merge( + Rx.Observable.of(show({ + id: "DASHBOARD_SAVE_SUCCESS", + title: "dashboard.saveDialog.saveSuccessTitle", + message: "dashboard.saveDialog.saveSuccessMessage" + })).delay(!resource.id ? 1000 : 0) // delay to allow loading + ) + ) + .let(wrapStartStop( + dashboardLoading(true, "saving"), + dashboardLoading(false, "saving") + )) + .catch( + ({ status, statusText, data, message, ...other } = {}) => Rx.Observable.of(dashboardSaveError(status ? { status, statusText, data } : message || other), dashboardLoading(false, "saving")) + ) + ) }; diff --git a/web/client/epics/dashboards.js b/web/client/epics/dashboards.js new file mode 100644 index 0000000000..2509d93330 --- /dev/null +++ b/web/client/epics/dashboards.js @@ -0,0 +1,80 @@ +/* + * Copyright 2018, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ +const Rx = require('rxjs'); +const { MAPS_LIST_LOADING, ATTRIBUTE_UPDATED} = require('../actions/maps'); +const { SEARCH_DASHBOARDS, DELETE_DASHBOARD, DASHBOARD_DELETED, RELOAD, searchDashboards, dashboardListLoaded, dashboardDeleted, dashboardsLoading } = require('../actions/dashboards'); +const { searchParamsSelector, searchTextSelector, totalCountSelector} = require('../selectors/dashboards'); +const GeoStoreApi = require('../api/GeoStoreDAO'); +const { wrapStartStop } = require('../observables/epics'); +const {error} = require('../actions/notifications'); + +const {deleteResource} = require('../observables/geostore'); + +const calculateNewParams = state => { + const totalCount = totalCountSelector(state); + const {start, limit, ...params} = searchParamsSelector(state); + if (start === totalCount - 1) { + return { + start: Math.max(0, start - limit), + limit + }; + } + return { + start, limit, ...params + }; +}; + +module.exports = { + searchDashboardsOnMapSearch: action$ => + action$.ofType(MAPS_LIST_LOADING) + .switchMap(({ searchText }) => Rx.Observable.of(searchDashboards(searchText))), + searchDashboards: (action$, { getState = () => { } }) => + action$.ofType(SEARCH_DASHBOARDS) + .map( ({params, searchText, geoStoreUrl}) => ({ + searchText, + options: { + params: params || searchParamsSelector(getState()) || {start: 0, limit: 12}, + ...(geoStoreUrl ? { baseURL: geoStoreUrl } : {}) + } + })) + .switchMap( + ({ searchText, options }) => + Rx.Observable.defer(() => GeoStoreApi.getResourcesByCategory("DASHBOARD", searchText, options)) + .map(results => dashboardListLoaded(results, {searchText, options})) + .let(wrapStartStop( + dashboardsLoading(true, "loading"), + dashboardsLoading(false, "loading"), + () => Rx.Observable.of(error({ + title: "notification.error", + message: "resources.dashboards.errorLoadingDashboards", + autoDismiss: 6, + position: "tc" + })) + )) + ), + deleteDashboard: action$ => action$ + .ofType(DELETE_DASHBOARD) + .switchMap(id => deleteResource(id).map(() => dashboardDeleted(id))) + .let(wrapStartStop( + dashboardsLoading(true, "loading"), + dashboardsLoading(false, "loading"), + () => Rx.Observable.of(error({ + title: "notification.error", + message: "resources.dashboards.deleteError", + autoDismiss: 6, + position: "tc" + })) + )), + reloadOnDashboards: (action$, { getState = () => { } }) => + action$.ofType(DASHBOARD_DELETED, RELOAD, ATTRIBUTE_UPDATED) + .delay(1000) // delay as a workaround for geostore issue #178 + .switchMap( () => Rx.Observable.of(searchDashboards( + searchTextSelector(getState()), + calculateNewParams(getState()) + ))) + }; diff --git a/web/client/epics/globeswitcher.js b/web/client/epics/globeswitcher.js index 492a2308fc..a32ef6e79f 100644 --- a/web/client/epics/globeswitcher.js +++ b/web/client/epics/globeswitcher.js @@ -6,17 +6,22 @@ * LICENSE file in the root directory of this source tree. */ const {TOGGLE_3D, updateLast2dMapType} = require('../actions/globeswitcher'); +const {MAP_TYPE_CHANGED} = require('../actions/maptype'); +const { mapTypeSelector } = require('../selectors/maptype'); +const {LOCAL_CONFIG_LOADED} = require('../actions/localConfig'); const Rx = require('rxjs'); const {get} = require('lodash'); -const defaultRegex = /\/(viewer)\/(\w+)\/(\w+)/; +const defaultRegexes = [/\/viewer\/\w+\/(\w+)/, /\/viewer\/(\w+)/]; const { push } = require('react-router-redux'); const replaceMapType = (path, newMapType) => { - let match = path.match(defaultRegex); + const match = defaultRegexes.reduce((previous, regex) => { + return previous || path.match(regex); + }, null); if (match) { - return `/viewer/${newMapType}/${match[3]}`; + return `/viewer/${newMapType}/${match[1]}`; } }; /** @@ -27,18 +32,23 @@ const replaceMapType = (path, newMapType) => { */ const updateRouteOn3dSwitch = (action$, store) => action$.ofType(TOGGLE_3D) - .switchMap( action => { - const newPath = replaceMapType(action.hash || location.hash, action.enable ? "cesium" : get(store.getState(), "globeswitcher.last2dMapType") || "leaflet"); + .switchMap( (action) => { + const newPath = replaceMapType(action.hash || location.hash, action.enable ? "cesium" : get(store.getState(), "globeswitcher.last2dMapType") || 'leaflet'); if (newPath) { - return Rx.Observable.from([push(newPath), updateLast2dMapType(action.originalMapType)]); + return Rx.Observable.from([push(newPath)]); } - Rx.Observable.of(updateLast2dMapType(action.mapType)); + Rx.Observable.empty(); }); +const updateLast2dMapTypeOnChangeEvents = (action$, store) => action$ + .ofType(LOCAL_CONFIG_LOADED).map(() => mapTypeSelector(store.getState())) + .merge(action$.ofType(MAP_TYPE_CHANGED, TOGGLE_3D).pluck('mapType').filter((mapType) => mapType && mapType !== "cesium")) + .switchMap(type => Rx.Observable.of(updateLast2dMapType(type))); /** * Epics for 3d switcher functionality * @name epics.globeswitcher * @type {Object} */ module.exports = { - updateRouteOn3dSwitch + updateRouteOn3dSwitch, + updateLast2dMapTypeOnChangeEvents }; diff --git a/web/client/epics/identify.js b/web/client/epics/identify.js index c6568c1004..6aca270c26 100644 --- a/web/client/epics/identify.js +++ b/web/client/epics/identify.js @@ -7,11 +7,22 @@ */ const Rx = require('rxjs'); -const {LOAD_FEATURE_INFO, GET_VECTOR_INFO, FEATURE_INFO_CLICK} = require('../actions/mapInfo'); +const {LOAD_FEATURE_INFO, ERROR_FEATURE_INFO, GET_VECTOR_INFO, FEATURE_INFO_CLICK, updateCenterToMarker} = require('../actions/mapInfo'); const {closeFeatureGrid} = require('../actions/featuregrid'); -const {CHANGE_MOUSE_POINTER, CLICK_ON_MAP} = require('../actions/map'); +const {CHANGE_MOUSE_POINTER, CLICK_ON_MAP, zoomToPoint} = require('../actions/map'); const {MAP_CONFIG_LOADED} = require('../actions/config'); const {stopGetFeatureInfoSelector} = require('../selectors/mapinfo'); +const {centerToMarkerSelector} = require('../selectors/layers'); +const {mapSelector} = require('../selectors/map'); +const {boundingMapRectSelector} = require('../selectors/maplayout'); +const {centerToVisibleArea, isInsideVisibleArea} = require('../utils/CoordinatesUtils'); +const {getCurrentResolution, parseLayoutValue} = require('../utils/MapUtils'); + +/** + * Epics for Identify and map info + * @name epics.identify + * @type {Object} + */ module.exports = { closeFeatureGridFromIdentifyEpic: (action$) => @@ -28,5 +39,36 @@ module.exports = { const {disableAlwaysOn = false} = (store.getState()).mapInfo; return disableAlwaysOn || !stopGetFeatureInfoSelector(store.getState() || {}); }) - .map(({point, layer}) => ({type: FEATURE_INFO_CLICK, point, layer})) + .map(({point, layer}) => ({type: FEATURE_INFO_CLICK, point, layer})), + /** + * Centers marker on visible map if it's hidden by layout + * @param {external:Observable} action$ manages `FEATURE_INFO_CLICK` and `LOAD_FEATURE_INFO`. + * @memberof epics.identify + * @return {external:Observable} + */ + zoomToVisibleAreaEpic: (action$, store) => + action$.ofType(FEATURE_INFO_CLICK) + .filter(() => centerToMarkerSelector(store.getState())) + .switchMap((action) => + action$.ofType(LOAD_FEATURE_INFO, ERROR_FEATURE_INFO) + .switchMap(() => { + const state = store.getState(); + const map = mapSelector(state); + const boundingMapRect = boundingMapRectSelector(state); + const coords = action.point && action.point && action.point.latlng; + const resolution = getCurrentResolution(Math.round(map.zoom), 0, 21, 96); + const layoutBounds = boundingMapRect && map && map.size && { + left: parseLayoutValue(boundingMapRect.left, map.size.width), + bottom: parseLayoutValue(boundingMapRect.bottom, map.size.height), + right: parseLayoutValue(boundingMapRect.right, map.size.width), + top: parseLayoutValue(boundingMapRect.top, map.size.height) + }; + // exclude cesium with cartographic options + if (!map || !layoutBounds || !coords || action.point.cartographic || isInsideVisibleArea(coords, map, layoutBounds, resolution)) { + return Rx.Observable.of(updateCenterToMarker('disabled')); + } + const center = centerToVisibleArea(coords, map, layoutBounds, resolution); + return Rx.Observable.of(updateCenterToMarker('enabled'), zoomToPoint(center.pos, center.zoom, center.crs)); + }) + ) }; diff --git a/web/client/epics/maplayout.js b/web/client/epics/maplayout.js index 41346ef78c..d51f4c4df5 100644 --- a/web/client/epics/maplayout.js +++ b/web/client/epics/maplayout.js @@ -10,7 +10,7 @@ const {updateMapLayout} = require('../actions/maplayout'); const {TOGGLE_CONTROL, SET_CONTROL_PROPERTY} = require('../actions/controls'); const {MAP_CONFIG_LOADED} = require('../actions/config'); const {SIZE_CHANGE, CLOSE_FEATURE_GRID, OPEN_FEATURE_GRID} = require('../actions/featuregrid'); -const {PURGE_MAPINFO_RESULTS} = require('../actions/mapInfo'); +const {PURGE_MAPINFO_RESULTS, ERROR_FEATURE_INFO} = require('../actions/mapInfo'); const {SHOW_SETTINGS, HIDE_SETTINGS} = require('../actions/layers'); const {mapInfoRequestsSelector} = require('../selectors/mapinfo'); @@ -32,19 +32,30 @@ const {isFeatureGridOpen, getDockSize} = require('../selectors/featuregrid'); */ const updateMapLayoutEpic = (action$, store) => - action$.ofType(MAP_CONFIG_LOADED, SIZE_CHANGE, CLOSE_FEATURE_GRID, OPEN_FEATURE_GRID, PURGE_MAPINFO_RESULTS, TOGGLE_CONTROL, SET_CONTROL_PROPERTY, SHOW_SETTINGS, HIDE_SETTINGS) + action$.ofType(MAP_CONFIG_LOADED, SIZE_CHANGE, CLOSE_FEATURE_GRID, OPEN_FEATURE_GRID, PURGE_MAPINFO_RESULTS, TOGGLE_CONTROL, SET_CONTROL_PROPERTY, SHOW_SETTINGS, HIDE_SETTINGS, ERROR_FEATURE_INFO) .switchMap(() => { if (get(store.getState(), "browser.mobile")) { - return Rx.Observable.empty(); + const bottom = mapInfoRequestsSelector(store.getState()).length > 0 ? {bottom: '50%'} : {bottom: undefined}; + const boundingMapRect = { + ...bottom + }; + return Rx.Observable.of(updateMapLayout({ + boundingMapRect + })); } const mapLayout = {left: {sm: 300, md: 500, lg: 600}, right: {md: 658}, bottom: {sm: 30}}; if (get(store.getState(), "mode") === 'embedded') { const height = {height: 'calc(100% - ' + mapLayout.bottom.sm + 'px)'}; + const bottom = mapInfoRequestsSelector(store.getState()).length > 0 ? {bottom: '50%'} : {bottom: undefined}; + const boundingMapRect = { + ...bottom + }; return Rx.Observable.of(updateMapLayout({ - ...height + ...height, + boundingMapRect })); } @@ -62,17 +73,25 @@ const updateMapLayoutEpic = (action$, store) => mapInfoRequestsSelector(store.getState()).length > 0 && {right: mapLayout.right.md} || null ].filter(panel => panel)) || {right: 0}; - const footer = isFeatureGridOpen(store.getState()) && {bottom: getDockSize(store.getState()) * 100 + '%'} || {bottom: mapLayout.bottom.sm}; + const dockSize = getDockSize(store.getState()) * 100; + const bottom = isFeatureGridOpen(store.getState()) && {bottom: dockSize + '%', dockSize} || {bottom: mapLayout.bottom.sm}; const transform = isFeatureGridOpen(store.getState()) && {transform: 'translate(0, -' + mapLayout.bottom.sm + 'px)'} || {transform: 'none'}; const height = {height: 'calc(100% - ' + mapLayout.bottom.sm + 'px)'}; + const boundingMapRect = { + ...bottom, + ...leftPanels, + ...rightPanels + }; + return Rx.Observable.of(updateMapLayout({ ...leftPanels, ...rightPanels, - ...footer, + ...bottom, ...transform, - ...height + ...height, + boundingMapRect })); }); diff --git a/web/client/epics/maps.js b/web/client/epics/maps.js index 85c1010e03..a76d4ea46d 100644 --- a/web/client/epics/maps.js +++ b/web/client/epics/maps.js @@ -11,7 +11,7 @@ const uuidv1 = require('uuid/v1'); const {basicError, basicSuccess} = require('../utils/NotificationUtils'); const GeoStoreApi = require('../api/GeoStoreDAO'); const { MAP_INFO_LOADED } = require('../actions/config'); -const {isNil} = require('lodash'); +const {isNil, find} = require('lodash'); const { SAVE_DETAILS, SAVE_RESOURCE_DETAILS, DELETE_MAP, OPEN_DETAILS_PANEL, @@ -255,17 +255,15 @@ const storeDetailsInfoEpic = (action$, store) => return !mapId ? Rx.Observable.empty() : Rx.Observable.fromPromise( - GeoStoreApi.getResourceAttribute(mapId, "details") - .then(res => res.data).catch(() => { - return null; - }) + GeoStoreApi.getResourceAttributes(mapId) ) - .switchMap((details) => { + .switchMap((attributes) => { + let details = find(attributes, {name: 'details'}); if (!details) { return Rx.Observable.empty(); } return Rx.Observable.of( - detailsLoaded(mapId, details) + detailsLoaded(mapId, details.value) ); }); }); diff --git a/web/client/epics/rulesmanager.js b/web/client/epics/rulesmanager.js new file mode 100644 index 0000000000..60a2d48aa2 --- /dev/null +++ b/web/client/epics/rulesmanager.js @@ -0,0 +1,37 @@ +const Rx = require("rxjs"); + +const {SAVE_RULE, setLoading, RULE_SAVED, DELETE_RULES, CACHE_CLEAN} = require("../actions/rulesmanager"); +const {error, success} = require("../actions/notifications"); +const {drawSupportReset} = require("../actions/draw"); +const {updateRule, createRule, deleteRule, cleanCache } = require("../observables/rulesmanager"); +// To do add Error management +const {get} = require("lodash"); +const saveRule = stream$ => stream$ + .mapTo({type: RULE_SAVED}) + .concat(Rx.Observable.of(drawSupportReset())) + .catch(({data}) => { + const isDuplicate = data.indexOf("Duplicat") === 0; + return Rx.Observable.of(error({title: "rulesmanager.errorTitle", message: isDuplicate ? "rulesmanager.errorDuplicateRule" : "rulesmanager.errorUpdatingRule"})); + }) + .startWith(setLoading(true)) + .concat(Rx.Observable.of(setLoading(false))); +module.exports = { + onSave: (action$, {getState}) => action$.ofType(SAVE_RULE) + .exhaustMap(({rule}) => + rule.id ? updateRule(rule, get(getState(), "rulesmanager.activeRule", {})).let(saveRule) : createRule(rule).let(saveRule) + ), + onDelete: (action$, {getState}) => action$.ofType(DELETE_RULES) + .switchMap(({ids = get(getState(), "rulesmanager.selectedRules", []).map(row => row.id)}) => { + return Rx.Observable.combineLatest(ids.map(id => deleteRule(id))).let(saveRule); + }), + onCacheClean: action$ => action$.ofType(CACHE_CLEAN) + .exhaustMap( () => + cleanCache() + .mapTo(success({title: "rulesmanager.errorTitle", message: "rulesmanager.cacheCleaned"})) + .startWith(setLoading(true)) + .catch(() => { + return Rx.Observable.of(error({title: "rulesmanager.errorTitle", message: "rulesmanager.errorCleaningCache"})); + }) + .concat(Rx.Observable.of(setLoading(false)))) +}; + diff --git a/web/client/epics/search.js b/web/client/epics/search.js index 62d20d7ec9..a5ba77d9cd 100644 --- a/web/client/epics/search.js +++ b/web/client/epics/search.js @@ -27,6 +27,7 @@ const {changeMapView} = require('../actions/map'); const toBbox = require('turf-bbox'); const {generateTemplateString} = require('../utils/TemplateUtils'); const assign = require('object-assign'); +const {updateResultsStyle} = require('../actions/search'); const {get} = require('lodash'); @@ -107,6 +108,7 @@ const searchItemSelected = action$ => // center by the max. extent defined in the map's config let newCenter = mapUtils.getCenterForExtent(bbox, "EPSG:4326"); let actions = [ + updateResultsStyle(action.resultsStyle || null), changeMapView(newCenter, newZoom, { bounds: { minx: bbox[0], diff --git a/web/client/epics/widgets.js b/web/client/epics/widgets.js index 767bf6e1e9..21d143e874 100644 --- a/web/client/epics/widgets.js +++ b/web/client/epics/widgets.js @@ -1,15 +1,27 @@ const Rx = require('rxjs'); -const {get} = require('lodash'); -const {EXPORT_CSV, EXPORT_IMAGE, clearWidgets} = require('../actions/widgets'); +const { get, isEqual, omit } = require('lodash'); +const { EXPORT_CSV, EXPORT_IMAGE, INSERT, TOGGLE_CONNECTION, WIDGET_SELECTED, EDITOR_SETTING_CHANGE, + onEditorChange, clearWidgets, loadDependencies, toggleDependencySelector, DEPENDENCY_SELECTOR_KEY, WIDGETS_REGEX} = require('../actions/widgets'); const { MAP_CONFIG_LOADED } = require('../actions/config'); +const { availableDependenciesSelector, isWidgetSelectionActive, getDependencySelectorConfig } = require('../selectors/widgets'); const { MAP_CREATED, SAVING_MAP, MAP_ERROR } = require('../actions/maps'); +const { DASHBOARD_LOADED } = require('../actions/dashboard'); const {LOCATION_CHANGE} = require('react-router-redux'); const {saveAs} = require('file-saver'); const FileUtils = require('../utils/FileUtils'); const converter = require('json-2-csv'); const canvg = require('canvg-browser'); +const updateDependencyMap = (active, id, { dependenciesMap, mappings}) => { + const overrides = Object.keys(mappings).filter(k => mappings[k] !== undefined).reduce( (ov, k) => ({ + ...ov, + [k]: id === "map" ? mappings[k] : `${id}.${mappings[k]}` + }), {}); + return active + ? { ...dependenciesMap, ...overrides} + : omit(dependenciesMap, [Object.keys(mappings)]); +}; const outerHTML = (node) => { const parent = document.createElement('div'); @@ -25,7 +37,28 @@ const getValidLocationChange = action$ => .startWith({type: MAP_CONFIG_LOADED}) // just dummy action to trigger the first switchMap .switchMap(action => action.type === SAVING_MAP ? Rx.Observable.never() : action$) .filter(({type} = {}) => type === LOCATION_CHANGE); - +/** + * Action flow to add/Removes dependencies for a widgets. + * Trigger `mapSync` property of a widget and sets `dependenciesMap` object to map `dependency` prop onto widget props. + * For instance if + * - `active = true` + * - `mappings` option is `{a: "b"} + * - `dependency = "x"` + * then you will have dependencyMap set to : {a: "x.b"}. + * It manages also special dependency "map" where mappings are applied directly (center...) . + * If active = false the dependencies will be removed from dependencyMap. + * + * @param {boolean} active true if the connection must be activated + * @param {string} dependency the dependency element id to add + * @param {object} options dependency mapping options. Must contain `mappings` object + */ +const configureDependency = (active, dependency, options) => + Rx.Observable.of( + onEditorChange("mapSync", active), + onEditorChange('dependenciesMap', + updateDependencyMap(active, dependency, options) + ) + ); module.exports = { exportWidgetData: action$ => action$.ofType(EXPORT_CSV) @@ -34,6 +67,59 @@ module.exports = { csv ], {type: "text/csv"}), title + ".csv"))) .filter( () => false), + /** + * Intercepts changes to widgets to catch widgets that can share some dependencies. + * Then re-configures the dependencies to it. + */ + alignDependenciesToWidgets: (action$, { getState = () => { } } = {}) => + action$.ofType(MAP_CONFIG_LOADED, DASHBOARD_LOADED, INSERT) + .map(() => availableDependenciesSelector(getState())) + .pluck('availableDependencies') + .distinctUntilChanged( (oldMaps = [], newMaps = []) => isEqual([...oldMaps], [...newMaps])) + // add dependencies for all map widgets (for the moment the only ones that shares dependencies) + // and for main "map" dependency, the "viewport" and "center" + .map((maps=[]) => loadDependencies(maps.reduce( (deps, m) => ({ + ...deps, + [m === "map" ? "viewport" : `${m}.viewport`]: `${m}.bbox`, // {viewport: "map.bbox"} or {"widgets[ID_W].viewport": "widgets[ID_W].bbox"} + [m === "map" ? "center" : `${m}.center`]: `${m}.center`, // {center: "map.center"} or {"widgets[ID_W].center": "widgets[ID_W].center"} + [m === "map" ? "zoom" : `${m}.zoom`]: `${m}.zoom`, + [m === "map" ? "layers" : `${m}.layers`]: `${m}.layers` + }), {})) + ), + /** + * Toggles the dependencies setup and widget selection for dependencies + * (if more than one widget is available for connection) + */ + toggleWidgetConnectFlow: (action$, {getState = () => {}} = {}) => + action$.ofType(TOGGLE_CONNECTION).switchMap(({ active, availableDependencies = [], options}) => + (active && availableDependencies.length > 0) + // activate flow + ? availableDependencies.length === 1 + // case singleMap + // In future may be necessary to pass active prop, if different from mapSync, in options object + // also if connection is triggered for a different target (widget not in editing) we should change actions to trigger (onChange instead of onEditorChange) + ? configureDependency(active, availableDependencies[0], options) + // case of multiple map + : Rx.Observable.of(toggleDependencySelector(active, { + availableDependencies + }) + ).merge( + action$.ofType(WIDGET_SELECTED) + .filter(() => isWidgetSelectionActive(getState())) + .switchMap(({ widget }) => { + const ad = get(getDependencySelectorConfig(getState()), 'availableDependencies'); + const deps = ad.filter(d => (WIDGETS_REGEX.exec(d) || [])[1] === widget.id); + return configureDependency(active, deps[0], options).concat(Rx.Observable.of(toggleDependencySelector(false, {}))); + }).takeUntil( + action$.ofType(LOCATION_CHANGE) + .merge(action$.filter(({ type, key } = {}) => type === EDITOR_SETTING_CHANGE && key === DEPENDENCY_SELECTOR_KEY)) + ) + ) + + // deactivate flow + : configureDependency(active, availableDependencies[0], options) + ), + clearWidgetsOnLocationChange: (action$, {getState = () => {}} = {}) => action$.ofType(MAP_CONFIG_LOADED).switchMap( () => { const location = get(getState(), "routing.location"); diff --git a/web/client/epics/widgetsbuilder.js b/web/client/epics/widgetsbuilder.js index 6919a39322..a2aae98e25 100644 --- a/web/client/epics/widgetsbuilder.js +++ b/web/client/epics/widgetsbuilder.js @@ -7,10 +7,11 @@ */ const Rx = require('rxjs'); const { - NEW, INSERT, EDIT, OPEN_FILTER_EDITOR, + NEW, INSERT, EDIT, OPEN_FILTER_EDITOR, NEW_CHART, editNewWidget, onEditorChange } = require('../actions/widgets'); +const {closeFeatureGrid} = require('../actions/featuregrid'); const { drawSupportReset @@ -22,6 +23,7 @@ const {LOCATION_CHANGE} = require('react-router-redux'); const {featureTypeSelected} = require('../actions/wfsquery'); const {getWidgetLayer, getEditingWidgetFilter} = require('../selectors/widgets'); +const {wfsFilter} = require('../selectors/query'); const {widgetBuilderAvailable} = require('../selectors/controls'); const getFTSelectedArgs = (state) => { let layer = getWidgetLayer(state); @@ -30,7 +32,7 @@ const getFTSelectedArgs = (state) => { return [url, typeName]; }; module.exports = { - openWidgetEditor: (action$, {getState = () => {}} = {}) => action$.ofType(NEW, EDIT) + openWidgetEditor: (action$, {getState = () => {}} = {}) => action$.ofType(NEW, EDIT, NEW_CHART) .filter(() => widgetBuilderAvailable(getState())) .switchMap(() => Rx.Observable.of( setControlProperty("widgetBuilder", "enabled", true), @@ -48,6 +50,17 @@ module.exports = { // override action's type type: undefined }, {step: 0}))), + initEditorOnNewChart: (action$, {getState = () => {}} = {}) => action$.ofType(NEW_CHART) + .filter(() => widgetBuilderAvailable(getState())) + .switchMap((w) => Rx.Observable.of(closeFeatureGrid(), editNewWidget({ + legend: false, + mapSync: true, + widgetType: "chart", + filter: wfsFilter(getState()), + ...w, + // override action's type + type: undefined + }, {step: 0}), onEditorChange("returnToFeatureGrid", true))), /** * Manages interaction with QueryPanel and widgetBuilder */ diff --git a/web/client/examples/3dviewer/containers/Viewer.jsx b/web/client/examples/3dviewer/containers/Viewer.jsx index 5460735277..befd2ff970 100644 --- a/web/client/examples/3dviewer/containers/Viewer.jsx +++ b/web/client/examples/3dviewer/containers/Viewer.jsx @@ -111,7 +111,7 @@ class Viewer extends React.Component { }}>
- + - - + + @@ -16,8 +16,8 @@ - - + + diff --git a/web/client/examples/layertree/index.html b/web/client/examples/layertree/index.html index f4afb4c862..4517572132 100644 --- a/web/client/examples/layertree/index.html +++ b/web/client/examples/layertree/index.html @@ -4,7 +4,7 @@ - MapStore 2 Example: LayerTree + MapStore Example: LayerTree diff --git a/web/client/examples/mouseposition/index.html b/web/client/examples/mouseposition/index.html index bf2d87786d..7e4cd7dd8b 100644 --- a/web/client/examples/mouseposition/index.html +++ b/web/client/examples/mouseposition/index.html @@ -4,13 +4,13 @@ - MapStore 2 Example: Mouse Position + MapStore Example: Mouse Position - + - +