├── app ├── js │ ├── polyfills.js │ ├── modals │ │ ├── comments.js │ │ ├── modal.js │ │ ├── share.js │ │ ├── mapillary.js │ │ └── area-selector.js │ ├── ui │ │ ├── list.js │ │ ├── ui.js │ │ └── map.js │ ├── api │ │ └── openstreetmap.js │ ├── theme.js │ ├── comment.js │ ├── request.js │ ├── toast.js │ ├── effects.js │ ├── elements │ │ └── SingleSelectionButtonGroup.js │ ├── preferences.js │ ├── users.js │ ├── linkify.js │ ├── auth.js │ ├── badges.js │ ├── note.js │ └── localizer.js ├── .gitignore ├── templates │ ├── includes │ │ ├── scripts.hbs │ │ ├── structuredData.json │ │ ├── head.hbs │ │ ├── header.hbs │ │ └── nav.hbs │ ├── modal.hbs │ ├── modals │ │ ├── area-selector.hbs │ │ ├── mapillary.hbs │ │ ├── comments.hbs │ │ ├── filter.hbs │ │ ├── share.hbs │ │ ├── settings.hbs │ │ └── help.hbs │ └── dynamic │ │ ├── actions.hbs │ │ ├── note.hbs │ │ ├── comment.hbs │ │ └── mapillary.hbs ├── public │ ├── icons │ │ ├── icon.png │ │ ├── list.png │ │ ├── map.png │ │ ├── any │ │ │ ├── icon-72x72.png │ │ │ ├── icon-96x96.png │ │ │ ├── icon-128x128.png │ │ │ ├── icon-144x144.png │ │ │ ├── icon-152x152.png │ │ │ ├── icon-192x192.png │ │ │ ├── icon-384x384.png │ │ │ └── icon-512x512.png │ │ ├── icon-512x512.png │ │ └── maskable │ │ │ ├── icon-48x48.png │ │ │ ├── icon-72x72.png │ │ │ ├── icon-96x96.png │ │ │ ├── icon-128x128.png │ │ │ ├── icon-192x192.png │ │ │ ├── icon-384x384.png │ │ │ └── icon-512x512.png │ ├── assets │ │ └── logo.jpg │ ├── landing.html │ └── manifest.json ├── css │ ├── colors.scss │ ├── icons.scss │ ├── markers.scss │ ├── dark.scss │ └── main.scss ├── svg │ ├── icon │ │ ├── flash.svg │ │ ├── download.svg │ │ ├── account.svg │ │ ├── close.svg │ │ ├── filter.svg │ │ ├── search.svg │ │ ├── flag.svg │ │ ├── help.svg │ │ ├── refresh.svg │ │ ├── list.svg │ │ ├── trash.svg │ │ ├── map.svg │ │ ├── external.svg │ │ ├── chat.svg │ │ ├── clipboard.svg │ │ ├── share.svg │ │ ├── settings.svg │ │ └── mapillary.svg │ ├── assets │ │ ├── liberapay.svg │ │ ├── mapillary.svg │ │ └── notesreview-small.svg │ ├── marker │ │ └── template.svg │ └── illustration │ │ └── lost.svg ├── index.html └── locales │ ├── ja.json │ ├── fr.json │ ├── zh-TW.json │ ├── nl.json │ ├── pl.json │ ├── pt-BR.json │ ├── it.json │ └── es.json ├── .gitignore ├── .dockerignore ├── assets └── screenshots │ ├── dark │ ├── list.png │ └── map.png │ └── light │ ├── map.png │ ├── images.png │ ├── list.png │ └── comments.png ├── .browserslistrc ├── Dockerfile ├── .editorconfig ├── .github ├── workflows │ ├── lint.yml │ ├── lighthouse.yml │ └── gh-pages.yml ├── actions │ ├── node-and-npm-cache │ │ └── action.yml │ └── build │ │ └── action.yml └── lighthouse │ └── lighthouserc.json ├── package.json ├── vite.config.js ├── README.md ├── CONTRIBUTING.md └── eslint.config.js /app/js/polyfills.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | .env* 3 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | node_modules 3 | 4 | Dockerfile 5 | npm-debug.log 6 | -------------------------------------------------------------------------------- /app/templates/includes/scripts.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/public/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/icon.png -------------------------------------------------------------------------------- /app/public/icons/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/list.png -------------------------------------------------------------------------------- /app/public/icons/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/map.png -------------------------------------------------------------------------------- /app/public/assets/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/assets/logo.jpg -------------------------------------------------------------------------------- /assets/screenshots/dark/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/assets/screenshots/dark/list.png -------------------------------------------------------------------------------- /assets/screenshots/dark/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/assets/screenshots/dark/map.png -------------------------------------------------------------------------------- /assets/screenshots/light/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/assets/screenshots/light/map.png -------------------------------------------------------------------------------- /app/public/icons/any/icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/any/icon-72x72.png -------------------------------------------------------------------------------- /app/public/icons/any/icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/any/icon-96x96.png -------------------------------------------------------------------------------- /app/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /assets/screenshots/light/images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/assets/screenshots/light/images.png -------------------------------------------------------------------------------- /assets/screenshots/light/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/assets/screenshots/light/list.png -------------------------------------------------------------------------------- /app/public/icons/any/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/any/icon-128x128.png -------------------------------------------------------------------------------- /app/public/icons/any/icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/any/icon-144x144.png -------------------------------------------------------------------------------- /app/public/icons/any/icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/any/icon-152x152.png -------------------------------------------------------------------------------- /app/public/icons/any/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/any/icon-192x192.png -------------------------------------------------------------------------------- /app/public/icons/any/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/any/icon-384x384.png -------------------------------------------------------------------------------- /app/public/icons/any/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/any/icon-512x512.png -------------------------------------------------------------------------------- /assets/screenshots/light/comments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/assets/screenshots/light/comments.png -------------------------------------------------------------------------------- /app/public/icons/maskable/icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/maskable/icon-48x48.png -------------------------------------------------------------------------------- /app/public/icons/maskable/icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/maskable/icon-72x72.png -------------------------------------------------------------------------------- /app/public/icons/maskable/icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/maskable/icon-96x96.png -------------------------------------------------------------------------------- /app/public/icons/maskable/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/maskable/icon-128x128.png -------------------------------------------------------------------------------- /app/public/icons/maskable/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/maskable/icon-192x192.png -------------------------------------------------------------------------------- /app/public/icons/maskable/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/maskable/icon-384x384.png -------------------------------------------------------------------------------- /app/public/icons/maskable/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ENT8R/NotesReview/HEAD/app/public/icons/maskable/icon-512x512.png -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | # The list of supported browsers is taken from the Vite Documentation: 2 | # https://vitejs.dev/guide/build.html#browser-compatibility 3 | 4 | defaults 5 | chrome >= 107 6 | firefox >= 104 7 | edge >= 107 8 | safari >= 16 9 | not ie <= 11 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node 2 | 3 | COPY . /app 4 | WORKDIR /app 5 | 6 | RUN npm install 7 | EXPOSE 5173 8 | 9 | ENV NOTESREVIEW_API_URL=https://api.notesreview.org 10 | ENV OPENSTREETMAP_SERVER=https://www.openstreetmap.org 11 | 12 | CMD ["npm", "run", "dev", "--", "--host"] 13 | -------------------------------------------------------------------------------- /app/templates/modal.hbs: -------------------------------------------------------------------------------- 1 |
Select countries by clicking on them or draw a custom shape using the toolbar on the left
3 | 4 |{{localizer 'mapillary.empty.title'}}
24 |{{localizer 'mapillary.empty.subtitle'}}
25 | 31 |7 | 8 |
9 | 10 | 11 |
39 |
40 |
41 |
42 | ## License
43 |
44 | NotesReview is available under the [GNU GPL-3.0 License](https://opensource.org/licenses/GPL-3.0).
45 | See the [LICENSE](LICENSE) file for more details.
46 |
--------------------------------------------------------------------------------
/app/js/modals/share.js:
--------------------------------------------------------------------------------
1 | import * as Localizer from '../localizer.js';
2 | import Modal from './modal.js';
3 | import { AREA } from '../query.js';
4 | import Toast from '../toast.js';
5 |
6 | export default class Share extends Modal {
7 | /**
8 | * Initializes the sharing modal
9 | *
10 | * @constructor
11 | * @param {Query} query
12 | * @returns {void}
13 | */
14 | constructor(query) {
15 | super();
16 |
17 | // Update links if the share modal is opened
18 | document.querySelector('.modal[data-modal="share"]').addEventListener('modal-open', () => {
19 | document.getElementById('permalink').value = query.permalink;
20 |
21 | document.getElementById('download').href = URL.createObjectURL(new Blob([JSON.stringify(query.result, null, 2)], {
22 | type: 'application/json',
23 | }));
24 | document.getElementById('download').download = `NotesReview-${query.history[query.history.length - 1].time.toISOString()}.json`;
25 |
26 | // Only show the checkbox for adding the polygon shape if it would have an effect
27 | // (i.e. a custom area is used, no countries are selected but something was drawn on the map)
28 | document.getElementById('share-polygon-checkbox').style.display =
29 | (query.data.area === AREA.CUSTOM && query.data.countries === null && query.data.polygon !== null) ? 'block' : 'none';
30 | });
31 |
32 | // Update links if a parameter changed
33 | Array.from(document.getElementsByClassName('update-permalink')).forEach(element => {
34 | element.addEventListener('change', () => {
35 | document.getElementById('permalink').value = query.permalink;
36 | });
37 | });
38 |
39 | document.getElementById('permalink').addEventListener('click', document.getElementById('permalink').select);
40 | document.getElementById('permalink').addEventListener('dblclick', () => this.copy());
41 | document.getElementById('permalink-copy').addEventListener('click', () => this.copy());
42 |
43 | // Free memory if the share modal is closed
44 | document.querySelector('.modal[data-modal="share"]').addEventListener('modal-close', () => {
45 | URL.revokeObjectURL(document.getElementById('download').href);
46 | });
47 | }
48 |
49 | /**
50 | * Copy permalink to clipboard
51 | *
52 | * @function
53 | * @returns {void}
54 | */
55 | copy() {
56 | document.getElementById('permalink').select();
57 | document.execCommand('copy');
58 | new Toast(Localizer.message('action.copyLinkSuccess'), 'toast-success').show();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing guidelines
2 | Thank you for your interest in contributing to NotesReview!
3 |
4 | If you want to work on improving the application, the following tips and hints may be useful for you. 😉
5 |
6 | ## Building and running
7 | NotesReview is a web application and is therefore mainly written in Javascript. `npm` is used as the preferred package manager, [`Vite` ⚡](https://github.com/vitejs/vite) is used as a module bundler.
8 |
9 | You may want to take a look at the [`package.json`](https://github.com/ENT8R/NotesReview/blob/main/package.json) file in order to get an overview on which modules are being used and what commands to run.
10 |
11 | Before running the application, make sure the file `app/.env` with the following required environment variables exists:
12 | ```shell
13 | NOTESREVIEW_API_URL=https://api.notesreview.org
14 | OPENSTREETMAP_SERVER=https://www.openstreetmap.org
15 | ```
16 | There are a few more environment variables that are used for additional features, but they are not mandatory to run the application, so in most cases the configuration above should be sufficient.
17 |
18 | To setup, change and run the application locally, simply follow these steps:
19 | ```shell
20 | # 1. Install all necessary dependencies using npm
21 | npm install
22 | # 2. Start the application by running the following command
23 | # and visiting http://localhost:5173 in your browser
24 | npm run dev
25 | # 3. Now it's your turn — change, fix or improve something!
26 | ```
27 | That's it already! Now you can submit your change as a [pull request on Github](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests).
28 |
29 | ### Docker
30 | If you want to run the application in a docker container, you can use the following commands instead:
31 | ```shell
32 | docker build --pull -t notesreview .
33 | docker run -t -i -p 3000:5173 notesreview
34 | ```
35 |
36 | ## Translating
37 | If you want to translate the website into your language or fix a wrong term, you can do so by visiting the project at POEditor.
38 |
39 | Follow [**this link** to improve the translations](https://poeditor.com/join/project/oVilUChBdf):
40 |
41 | [](https://poeditor.com/join/project/oVilUChBdf)
42 |
43 | The use of POEditor is preferred over proposing new translations via pull requests.
44 |
45 | ## Testing and reporting bugs
46 | The easiest way to contribute is of course to use and test the application and report bugs on Github using the [issue tracker](https://github.com/ENT8R/NotesReview/issues/). Just let me know if you spot something that looks suspicious. 🙃
47 |
--------------------------------------------------------------------------------
/app/js/preferences.js:
--------------------------------------------------------------------------------
1 | const JSON_REGEX = /^({|\[)[\s\S]*(}|\])$/m;
2 |
3 | const DEFAULTS = {
4 | view: 'map',
5 | map: {
6 | center: [0, 0],
7 | zoom: 2
8 | },
9 | query: {},
10 | theme: 'system',
11 | tools: {
12 | openstreetmap: true,
13 | mapillary: false,
14 | deepl: false
15 | },
16 | editors: {
17 | id: true,
18 | rapid: false,
19 | josm: false,
20 | level0: true
21 | }
22 | };
23 |
24 | export default class Preferences {
25 | /**
26 | * Get a specific preference by its key and if it's not available, return the default value
27 | *
28 | * @function
29 | * @param {String} key
30 | * @param {Boolean} temporary
31 | * @returns {String|Boolean|Object|Array}
32 | */
33 | static get(key, temporary) {
34 | const storage = temporary ? window.sessionStorage : window.localStorage;
35 |
36 | let value = storage.getItem(key);
37 |
38 | if (JSON_REGEX.test(value)) {
39 | value = JSON.parse(value);
40 | }
41 |
42 | return value || DEFAULTS[key];
43 | }
44 |
45 | /**
46 | * Set or change the value of a preference
47 | *
48 | * @function
49 | * @param {Object} preferences
50 | * @param {boolean} temporary
51 | * @returns {void}
52 | */
53 | static set(preferences, temporary) {
54 | const storage = temporary ? window.sessionStorage : window.localStorage;
55 |
56 | for (const key in preferences) {
57 | if (Object.prototype.hasOwnProperty.call(preferences, key)) {
58 | const preference = preferences[key];
59 |
60 | if (Array.isArray(preference)) {
61 | storage.setItem(key, JSON.stringify(preference));
62 | } else if (typeof preference === 'object') {
63 | let value = storage.getItem(key);
64 |
65 | if (JSON_REGEX.test(value)) {
66 | value = JSON.parse(value);
67 | } else {
68 | value = {};
69 | }
70 |
71 | storage.setItem(key, JSON.stringify(Object.assign(value, preference)));
72 | } else {
73 | storage.setItem(key, preference);
74 | }
75 | }
76 | }
77 | }
78 |
79 | /**
80 | * Remove a specific item from the storage
81 | *
82 | * @function
83 | * @param {String} key
84 | * @param {Boolean} temporary
85 | * @returns {void}
86 | */
87 | static remove(key, temporary) {
88 | const storage = temporary ? window.sessionStorage : window.localStorage;
89 | storage.removeItem(key);
90 | }
91 |
92 | /**
93 | * Set all values to the default values
94 | *
95 | * @function
96 | * @returns {void}
97 | */
98 | static reset() {
99 | window.sessionStorage.clear();
100 | window.localStorage.clear();
101 | Preferences.set(DEFAULTS);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/app/templates/modals/settings.hbs:
--------------------------------------------------------------------------------
1 | Select your favorite tool(s)
20 |Every colors represents the age of the note
5 | 6 |
49 | Yes, by using a comma to separate each user.
50 | When searching for the author of a note, it will try to find notes that were opened by any of the given users.
51 | When searching for the users of a note, it will try to find notes that all of the given users commented on.
52 |
58 | Yes, by writing either NOT or - in front of the user to exclude.
59 | It is also possible to exclude multiple users by separating each user with a comma.
60 |
66 | All notes are synchronized every 5 minutes with the OpenStreetMap API.
67 | It can happen that notes or comments which have been hidden by the moderators still appear in the results.
68 |
69 | This is mainly due to the fact that the underlying API of OpenStreetMap does not directly offer the possibility to know which notes and comments have been hidden by moderators.
70 | As a result, the complete daily notes dump is analyzed from time to time in irregular intervals in order to find and fix these anomalies.
71 |
72 | If you want to know the last time the manual synchronization was performed, take a look at the
73 | status page with regard to the value of last_import (for comments) or last_sync (for notes).
74 |
80 | NotesReview is an open source project. You are currently using version {{version}}. 81 | The source code is available on Github. 82 |
83 |84 | You can support the project by translating 85 | it or by reporting bugs. 86 |
87 |88 | Made with ❤️ by ENT8R 89 |
90 | 98 |
{{{html}}}
12 |