diff --git a/.babelrc b/.babelrc index 0073bc468..607d0d1ba 100644 --- a/.babelrc +++ b/.babelrc @@ -1,8 +1,15 @@ { "presets": [ - "env" + "@babel/preset-env" ], + env: { + test: { + plugins: [ + '@babel/plugin-proposal-class-properties', + ] + } + }, "plugins": [ - "transform-regenerator" + "transform-regenerator", ] } diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..17cbd4a67 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,52 @@ +## Description + +A meaningful description of proposed change in your own words. + +## Related Issue + + +## How to test it locally + + +## Screenshots + + +## Changelog + +### Added + +### Updated + +### Removed + + +## Checklist + +- [ ] 🚀 is the code ready to be merged and go live? +- [ ] 🛠 does it work (build) locally + +### Pull Request + +- [ ] 📰 good title +- [ ] 📝good description +- [ ] 🔖 issue linked +- [ ] 📖 changelog filled out + +### Commits + +- [ ] commits are clean +- [ ] commit messages are clean + +### Code Quality + +- [ ] 🚧 no commented out code +- [ ] 🖨 no unnecessary logging +- [ ] 🎱 no magic numbers +- [ ] ⚙️ ran jslint +- [ ] 🧰 ran codeclimate locally + +### Testing + +- [ ] ✅ added (appropriate) unit tests +- [ ] 💢 edge cases in tests were considered +- [ ] ✅ ran tests locally & are passing diff --git a/.travis.yml b/.travis.yml index f13a8a34d..f9d48662f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,12 @@ os: linux -language: python -python: - - "3.7" -addons: - chrome: stable +language: node_js +node_js: + - "14" cache: - - pip - yarn: true - directories: - node_modules install: - - pip install -r requirements.txt -services: - - docker -before_script: - - docker-compose up -d + - npm install script: - - ./run_test.sh -after_script: - - docker-compose down + - npm test diff --git a/README.md b/README.md index 00c20e047..945da85a6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,43 @@ -# Installation +# Introduction +Wazimap-NG is the next version of [Wazimap](http://www.wazimap.co.za). It provides a platform for users to bind tabular data to spatial boundaries in order create curated views of datasets. Yes - that's probably too vague a description to understand what it is. Hopefully the images below provide a better description: + +Screen-Shot-2020-09-27-at-09-50-00 Screen-Shot-2020-09-27-at-09-50-33

+Screen-Shot-2020-09-27-at-09-50-50 Screen-Shot-2020-09-27-at-09-51-30

+ +See a link to the beta site here: [https://beta.youthexplorer.org.za](https://beta.youthexplorer.org.za). + +You can find the frontend code in this repository. The backend is available here: [https://github.com/openupsa/wazimap-ng](https://github.com/openupsa/wazimap-ng). + +# New features + +The main new features are: + +* Admins now have more flexibility when it comes to loading data. This includes uploading massive datasets and then slicing and dicing in the backend rather than pre-preparing datasets beforehand. +* Point data is now fully integrated as a first-class spatial object. +* Choropleths built into the main view. These were hidden behind multiple clicks in the previous version. +* One platform can host multiple profiles off the same database. +* The Rich data view allows richer disaggregation of indicators. +* The administrator can configure the view to use custom basemaps, colours, and other UI settings. +* Arbitrary spatial boundaries and hierarchies can be loaded onto the same server. +* Toggling of overlapping boundary layers such as switching between wards and mainplaces which typically cover the same areas. +* Integration into third-party data sources for realtime data feeds. + +# Related software +There is no shortage of mapping software available, both commerical and open-source. Wazimap focuses on providing a platform for data custodians to showcase their datasets and mashing them up with public data. The most similar tool that we have found is the excellent [GeoNode](https://geonode.org/). We feel that approach to publishing data is significantly different enough to warrant a separate project. + +# Roadmap +Version 0.8 is due soon and will fix bugs that currently don't have workarounds. We'll publish the 1.0 roadmap soon. +# Future features +* WFS endpoint for publishing data to other GIS software +* Pluggable data visualisations +* Better handling of geography hierarchies. +* Improved handling of temporal and other types of non-census-like data. +* Speed improvements +* A large standard database of public datasets. + + +# Installation ```bash @@ -14,3 +52,16 @@ yarn push-gh-pages # pushes to github for hosting ``` +# Documentation +These are works in progress: + +* [Technical manual](https://openup.gitbook.io/wazi-ng-technical/) +* [Administrator manual](https://openup.gitbook.io/wazimap-ng/) + +# Contributions +Contributions are welcome - we are working towards making this process easier. + +# Shoulders of giants +This project is the next iteration of a number of excellent projects starting with [CensusReporter](https://censusreporter.org/) and [Wazimap](http://www.wazimap.co.za) that followed it. Special thanks to William Bird from [Media Monitoring Africa](https://mediamonitoringafrica.org) whose initial idea (and funding) it was to build a tool to help journalists better understand areas they were reporting on. Also thanks to Chris Berens from [VPUU](vpuu.org.za) who directed funding to help kickstart this new build. Finally, all of the amazing spatial software and tools developed by one of the most dedicated open source communities out there. + + diff --git a/__tests__/controller.test.js b/__tests__/controller.test.js new file mode 100644 index 000000000..2e22f0f40 --- /dev/null +++ b/__tests__/controller.test.js @@ -0,0 +1,22 @@ +import Controller from '../src/js/controller'; + +describe('Controller', () => { + + it('initialize successully', () => { + let controller = new Controller({}); + }); + describe('Event loop', () => { + it('adds the state to payload', () => { + let controller = new Controller({}); + let result = null; + let payload = "expected" + controller.on('eventname', (e) => result = e) + + controller.triggerEvent('eventname', payload); + + expect(result).toHaveProperty('state') + expect(result).toHaveProperty('payload') + }); + }); +}); + diff --git a/__tests__/utils.test.js b/__tests__/utils.test.js new file mode 100644 index 000000000..1dc2f6ac8 --- /dev/null +++ b/__tests__/utils.test.js @@ -0,0 +1,47 @@ +import {validation, defaultIfMissing} from '../src/js/utils'; + +describe('Testing validation functions', () => { + + + test.each([ + [null, true], [undefined, false], [{}, false], + ['', false], [NaN, false]])('.isNull(%s)', (value, expected) => { + expect(validation.isNull(value)).toBe(expected); + }); + + test.each([ + [null, false], [undefined, true], [{}, false], + ['', false], [NaN, false]])('.isUndefined(%s)', (value, expected) => { + expect(validation.isUndefined(value)).toBe(expected); + }); + + test.each([ + [null, false], [undefined, false], [{}, false], + ['', true], [NaN, false]])('.isEmptyString(%s)', (value, expected) => { + expect(validation.isEmptyString(value)).toBe(expected); + }); + + test.each([ + [null, false], [undefined, false], [{}, true], + ['', false], [NaN, false]])('.isEmptyObject(%s)', (value, expected) => { + expect(validation.isEmptyObject(value)).toBe(expected); + }); + + test.each([ + [null, true], [undefined, true], [{}, true], + ['', true], [5, false]])('.isMissingData(%s)', (value, expected) => { + expect(validation.isMissingData(value)).toBe(expected); + }); +}); + +describe('Testing defaults', () => { + test('checkAny function works correctly', () => { + expect(defaultIfMissing(5, 5)).toBe(5); + expect(defaultIfMissing('XXX', 5)).toBe('XXX'); + expect(defaultIfMissing(undefined, 5)).toBe(5); + expect(defaultIfMissing(null, 5)).toBe(5); + expect(defaultIfMissing({}, 5)).toBe(5); + expect(defaultIfMissing('', 5)).toBe(5); + }) +}) + diff --git a/package.json b/package.json index 6105bab7d..572c119c1 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "d3-selection": "^1.4.1", "data-visualisations": "https://github.com/vulekamali/data-visualisations.git#reusable", "html2canvas": "^1.0.0-rc.5", + "jquery": "^3.5.1", "js": "^0.1.0", "leaflet": "~1.3.1", "leaflet-event-forwarder": "^0.0.3", @@ -29,20 +30,23 @@ }, "devDependencies": { "@babel/cli": "^7.8.3", - "@babel/core": "^7.0.0-0", + "@babel/core": "^7.11.6", "@babel/plugin-proposal-class-properties": "^7.10.1", - "@babel/preset-env": "^7.9.6", + "@babel/preset-env": "^7.11.5", "babel-core": "^6.26.3", + "babel-jest": "^26.3.0", "babel-loader": "^8.0.6", "babel-plugin-transform-regenerator": "^6.26.0", "babel-preset-env": "^1.7.0", "cssnano": "^4.1.10", + "jest": "^26.4.2", "parcel": "^1.12.4", "parcel-bundler": "^1.12.4" }, "scripts": { "start": "parcel ./src/index.html", - "test": "./run_test.sh", + "test": "jest", + "test:watch": "jest --watch", "prebuild-dev": "shx rm -rf dist/*", "build-dev": "parcel build ./src/index.html --no-minify --public-url ./", "prebuild": "shx rm -rf dist/*", @@ -51,5 +55,10 @@ "push-staging": "push-dir --remote=staging --dir=dist --branch=gh-pages --cleanup --verbose", "clean-files": "cp dist/js*.js dist/wazimap-ng.js; cp dist/js*.js.map dist/wazimap-ng.js.map; cp dist/js*.css dist/wazimap-ng.css" }, - "browserslist": "> 0.25%, not dead" + "browserslist": "> 0.25%, not dead", + "jest": { + "setupFiles": [ + "./setup-jest.js" + ] + } } diff --git a/setup-jest.js b/setup-jest.js new file mode 100644 index 000000000..b8b3275d7 --- /dev/null +++ b/setup-jest.js @@ -0,0 +1,2 @@ +import $ from 'jquery'; +global.$ = global.jQuery = $; diff --git a/src/401.html b/src/401.html index 235ef015a..6ab28ecb3 100644 --- a/src/401.html +++ b/src/401.html @@ -1,6 +1,6 @@ - + @@ -32,6 +32,7 @@ }); window.gtag = gtag; +
@@ -52,7 +53,7 @@

Protected Page

- + diff --git a/src/about.html b/src/about.html index ff0cd3ca3..9406003a8 100644 --- a/src/about.html +++ b/src/about.html @@ -1,6 +1,6 @@ - + diff --git a/src/css/wazimap-ng-v1.webflow.css b/src/css/wazimap-ng-v1.webflow.css old mode 100644 new mode 100755 index 27bc27d45..726287fb2 --- a/src/css/wazimap-ng-v1.webflow.css +++ b/src/css/wazimap-ng-v1.webflow.css @@ -3462,7 +3462,6 @@ label { font-size: 0.85em; font-weight: 500; text-decoration: none; - text-transform: capitalize; cursor: pointer; } @@ -6373,13 +6372,13 @@ label { top: auto; right: 0%; bottom: 0%; + z-index: 999; min-height: 44px; margin-right: 50px; margin-bottom: 10px; border-radius: 4px; background-color: #fff; box-shadow: 0 0 0 -1px rgba(0, 0, 0, 0.2), 0 1px 6px -2px rgba(0, 0, 0, 0.3); - z-index: 999; } .mag-geo__dropdown_wrap { @@ -6406,7 +6405,10 @@ label { right: 0%; bottom: 0%; z-index: 3; - display: none; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; width: 100vw; height: 100vh; -webkit-box-pack: center; @@ -6420,6 +6422,10 @@ label { background-color: rgba(0, 0, 0, 0.5); } +.warning-modal.hidden { + display: none; +} + .warning { position: absolute; display: -webkit-box; diff --git a/src/demo.html b/src/demo.html index 5ecb27cb6..8222f799b 100644 --- a/src/demo.html +++ b/src/demo.html @@ -1,6 +1,6 @@ - + @@ -31,6 +31,7 @@ }); window.gtag = gtag; +