diff --git a/app/src/api/api.ts b/app/src/api/api.ts index a829fd4c..fd1c1426 100644 --- a/app/src/api/api.ts +++ b/app/src/api/api.ts @@ -1,12 +1,11 @@ -import express from 'express'; import bodyParser from 'body-parser'; - -import { authUser, getNewUserAPIKey, logout } from './services/user'; -import { queryLocation } from './services/search'; +import express from 'express'; import buildingsRouter from './routes/buildingsRouter'; -import usersRouter from './routes/usersRouter'; import extractsRouter from './routes/extractsRouter'; +import usersRouter from './routes/usersRouter'; +import { queryLocation } from './services/search'; +import { authUser, getNewUserAPIKey, logout } from './services/user'; const server = express.Router(); @@ -29,7 +28,7 @@ server.post('/login', function (req, res) { res.send(user); }).catch(function (error) { res.send(error); - }) + }); }); // POST user logout @@ -46,7 +45,7 @@ server.post('/logout', function (req, res) { server.post('/api/key', function (req, res) { if (!req.session.user_id) { res.send({ error: 'Must be logged in' }); - return + return; } getNewUserAPIKey(req.session.user_id).then(function (apiKey) { @@ -54,7 +53,7 @@ server.post('/api/key', function (req, res) { }).catch(function (error) { res.send(error); }); -}) +}); // GET search server.get('/search', function (req, res) { @@ -62,20 +61,20 @@ server.get('/search', function (req, res) { if (!searchTerm) { res.send({ error: 'Please provide a search term' - }) - return + }); + return; } queryLocation(searchTerm).then((results) => { if (typeof (results) === 'undefined') { res.send({ error: 'Database error' - }) - return + }); + return; } res.send({ results: results.map(item => { // map from DB results to GeoJSON Feature objects - const geom = JSON.parse(item.st_asgeojson) + const geom = JSON.parse(item.st_asgeojson); return { type: 'Feature', attributes: { @@ -83,13 +82,13 @@ server.get('/search', function (req, res) { zoom: item.zoom || 9 }, geometry: geom - } + }; }) - }) + }); }).catch(function (error) { res.send(error); }); -}) +}); server.use((err, req, res, next) => { if (res.headersSent) { @@ -104,7 +103,7 @@ server.use((err, req, res, next) => { server.use((req, res) => { res.status(404).json({ error: 'Resource not found'}); -}) +}); export default server; diff --git a/app/src/api/controllers/buildingController.ts b/app/src/api/controllers/buildingController.ts index 40a94e03..269ea7b1 100644 --- a/app/src/api/controllers/buildingController.ts +++ b/app/src/api/controllers/buildingController.ts @@ -1,7 +1,8 @@ import express from 'express'; + +import asyncController from '../routes/asyncController'; import * as buildingService from '../services/building'; import * as userService from '../services/user'; -import asyncController from '../routes/asyncController'; // GET buildings @@ -106,7 +107,7 @@ const getBuildingLikeById = asyncController(async (req: express.Request, res: ex // any value returned means like res.send({ like: like }); } catch(error) { - res.send({ error: 'Database error' }) + res.send({ error: 'Database error' }); } }); diff --git a/app/src/api/controllers/extractController.ts b/app/src/api/controllers/extractController.ts index 6aed512b..183c23d8 100644 --- a/app/src/api/controllers/extractController.ts +++ b/app/src/api/controllers/extractController.ts @@ -1,6 +1,7 @@ import express from 'express'; -import * as dataExtractService from '../services/dataExtract'; + import asyncController from '../routes/asyncController'; +import * as dataExtractService from '../services/dataExtract'; const getAllDataExtracts = asyncController(async function(req: express.Request, res: express.Response) { diff --git a/app/src/api/controllers/userController.ts b/app/src/api/controllers/userController.ts index b29291a2..43c9e801 100644 --- a/app/src/api/controllers/userController.ts +++ b/app/src/api/controllers/userController.ts @@ -1,11 +1,9 @@ -import { URL } from 'url'; - import express from 'express'; -import * as userService from '../services/user'; +import asyncController from '../routes/asyncController'; import * as passwordResetService from '../services/passwordReset'; import { TokenVerificationError } from '../services/passwordReset'; -import asyncController from '../routes/asyncController'; +import * as userService from '../services/user'; import { ValidationError } from '../validation'; const createUser = asyncController(async (req: express.Request, res: express.Response) => { diff --git a/app/src/api/routes/asyncController.ts b/app/src/api/routes/asyncController.ts index 333f664b..ab809bb8 100644 --- a/app/src/api/routes/asyncController.ts +++ b/app/src/api/routes/asyncController.ts @@ -1,4 +1,4 @@ -import { Request, Response, NextFunction } from 'express'; +import { NextFunction, Request, Response } from 'express'; /** * A wrapper for controller functions that return a Promise, enabling them to be used with Express @@ -14,4 +14,4 @@ function asyncController(fn: (req: Request, res: Response, next: NextFunction) = }; } -export default asyncController; \ No newline at end of file +export default asyncController; diff --git a/app/src/api/routes/usersRouter.ts b/app/src/api/routes/usersRouter.ts index 261e36e3..c8b224bf 100644 --- a/app/src/api/routes/usersRouter.ts +++ b/app/src/api/routes/usersRouter.ts @@ -12,4 +12,4 @@ router.route('/me') router.put('/password', userController.resetPassword); -export default router; \ No newline at end of file +export default router; diff --git a/app/src/api/services/building.ts b/app/src/api/services/building.ts index 85d7df37..9cc611d8 100644 --- a/app/src/api/services/building.ts +++ b/app/src/api/services/building.ts @@ -2,10 +2,11 @@ * Building data access * */ +import { ITask } from 'pg-promise'; + import db from '../../db'; import { tileCache } from '../../tiles/rendererDefinition'; import { BoundingBox } from '../../tiles/types'; -import { ITask } from 'pg-promise'; // data type note: PostgreSQL bigint (64-bit) is handled as string in JavaScript, because of // JavaScript numerics are 64-bit double, giving only partial coverage. @@ -276,7 +277,7 @@ async function updateBuildingData( console.log(update); const patches = compare(oldBuilding, update); - console.log('Patching', buildingId, patches) + console.log('Patching', buildingId, patches); const [forward, reverse] = patches; if (Object.keys(forward).length === 0) { throw 'No change provided'; @@ -336,7 +337,7 @@ function privateQueryBuildingBBOX(buildingId: number){ } async function expireBuildingTileCache(buildingId: number) { - const bbox = await privateQueryBuildingBBOX(buildingId) + const bbox = await privateQueryBuildingBBOX(buildingId); const buildingBbox: BoundingBox = [bbox.xmax, bbox.ymax, bbox.xmin, bbox.ymin]; tileCache.removeAllAtBbox(buildingBbox); } diff --git a/app/src/api/services/dataExtract.ts b/app/src/api/services/dataExtract.ts index 4f43f1cb..063e9a7b 100644 --- a/app/src/api/services/dataExtract.ts +++ b/app/src/api/services/dataExtract.ts @@ -50,12 +50,12 @@ function getDataExtractFromRow(er: DataExtractRow): DataExtract { extract_id: er.extract_id, extracted_on: er.extracted_on, download_path: getDownloadLinkForExtract(er) - } + }; } function getDownloadLinkForExtract(extract: DataExtractRow): string { const file_name = path.basename(extract.extract_path); - return `/downloads/${file_name}` // TODO: potentially move base path to env var + return `/downloads/${file_name}`; // TODO: potentially move base path to env var } export { diff --git a/app/src/api/services/passwordReset.ts b/app/src/api/services/passwordReset.ts index facbc074..2bcb3fdb 100644 --- a/app/src/api/services/passwordReset.ts +++ b/app/src/api/services/passwordReset.ts @@ -1,12 +1,13 @@ -import url, { URL } from 'url'; -import { errors } from 'pg-promise'; import nodemailer from 'nodemailer'; +import { errors } from 'pg-promise'; +import url, { URL } from 'url'; import db from '../../db'; -import * as userService from './user'; -import { transporter } from './email'; import { validatePassword } from '../validation'; +import { transporter } from './email'; +import * as userService from './user'; + /** * Generate a password reset token for the specified account and send the password reset link by email diff --git a/app/src/api/services/user.ts b/app/src/api/services/user.ts index c91c8e60..c6cbc74e 100644 --- a/app/src/api/services/user.ts +++ b/app/src/api/services/user.ts @@ -3,10 +3,10 @@ * */ import { errors } from 'pg-promise'; +import { promisify } from 'util'; import db from '../../db'; -import { validateUsername, ValidationError, validatePassword } from '../validation'; -import { promisify } from 'util'; +import { validatePassword, validateUsername, ValidationError } from '../validation'; async function createUser(user) { @@ -71,9 +71,9 @@ async function authUser(username: string, password: string) { ); if (user && user.auth_ok) { - return { user_id: user.user_id } + return { user_id: user.user_id }; } else { - return { error: 'Username or password not recognised' } + return { error: 'Username or password not recognised' }; } } catch(err) { if (err instanceof errors.QueryResultError) { @@ -99,7 +99,7 @@ async function getUserById(id: string) { ] ); } catch(error) { - console.error('Error:', error) + console.error('Error:', error); return undefined; } } @@ -137,7 +137,7 @@ async function getNewUserAPIKey(id: string) { ] ); } catch(error) { - console.error('Error:', error) + console.error('Error:', error); return { error: 'Failed to generate new API key.' }; } } @@ -156,7 +156,7 @@ async function authAPIUser(key: string) { ] ); } catch(error) { - console.error('Error:', error) + console.error('Error:', error); return undefined; } } diff --git a/app/src/api/validation.ts b/app/src/api/validation.ts index e0e17437..77bae6f7 100644 --- a/app/src/api/validation.ts +++ b/app/src/api/validation.ts @@ -22,4 +22,4 @@ export { ValidationError, validateUsername, validatePassword -}; \ No newline at end of file +}; diff --git a/app/src/client.tsx b/app/src/client.tsx index 3c0d7d83..cc1799de 100644 --- a/app/src/client.tsx +++ b/app/src/client.tsx @@ -2,9 +2,9 @@ * Client-side entry point to shared frontend React App * */ -import { BrowserRouter } from 'react-router-dom'; import React from 'react'; import { hydrate } from 'react-dom'; +import { BrowserRouter } from 'react-router-dom'; import App from './frontend/app'; diff --git a/app/src/frontend/app.tsx b/app/src/frontend/app.tsx index 2d2b357c..64e35c8b 100644 --- a/app/src/frontend/app.tsx +++ b/app/src/frontend/app.tsx @@ -1,29 +1,27 @@ import React, { Fragment } from 'react'; -import { Route, Switch, Link } from 'react-router-dom'; +import { Link, Route, Switch } from 'react-router-dom'; + +import Header from './header'; +import MapApp from './map-app'; +import { Building } from './models/building'; +import { User } from './models/user'; +import AboutPage from './pages/about'; +import ContactPage from './pages/contact'; +import ContributorAgreementPage from './pages/contributor-agreement'; +import DataAccuracyPage from './pages/data-accuracy'; +import DataExtracts from './pages/data-extracts'; +import OrdnanceSurveyLicencePage from './pages/ordnance-survey-licence'; +import OrdnanceSurveyUprnPage from './pages/ordnance-survey-uprn'; +import PrivacyPolicyPage from './pages/privacy-policy'; +import ForgottenPassword from './user/forgotten-password'; +import Login from './user/login'; +import MyAccountPage from './user/my-account'; +import PasswordReset from './user/password-reset'; +import SignUp from './user/signup'; import '../../node_modules/bootstrap/dist/css/bootstrap.min.css'; import './app.css'; -import Header from './header'; -import AboutPage from './pages/about'; -import ContributorAgreementPage from './pages/contributor-agreement'; -import PrivacyPolicyPage from './pages/privacy-policy'; -import DataExtracts from './pages/data-extracts'; - -import Login from './user/login'; -import MyAccountPage from './user/my-account'; -import SignUp from './user/signup'; -import ForgottenPassword from './user/forgotten-password'; -import PasswordReset from './user/password-reset'; - -import MapApp from './map-app'; -import ContactPage from './pages/contact'; -import DataAccuracyPage from './pages/data-accuracy'; -import OrdnanceSurveyLicencePage from './pages/ordnance-survey-licence'; -import OrdnanceSurveyUprnPage from './pages/ordnance-survey-uprn'; -import { Building } from './models/building'; -import { User } from './models/user'; - interface AppProps { user?: User; diff --git a/app/src/frontend/building/building-not-found.tsx b/app/src/frontend/building/building-not-found.tsx index 07c7c2af..35a2f3f1 100644 --- a/app/src/frontend/building/building-not-found.tsx +++ b/app/src/frontend/building/building-not-found.tsx @@ -5,7 +5,7 @@ import InfoBox from '../components/info-box'; interface BuildingNotFoundProps { - mode: string + mode: string; } const BuildingNotFound: React.FunctionComponent = (props) => ( diff --git a/app/src/frontend/building/building-view.tsx b/app/src/frontend/building/building-view.tsx index 25fe53b9..d21f7115 100644 --- a/app/src/frontend/building/building-view.tsx +++ b/app/src/frontend/building/building-view.tsx @@ -1,21 +1,21 @@ import React from 'react'; -import BuildingNotFound from './building-not-found'; - -import LocationContainer from './data-containers/location'; -import UseContainer from './data-containers/use'; -import TypeContainer from './data-containers/type'; -import AgeContainer from './data-containers/age'; -import SizeContainer from './data-containers/size'; -import ConstructionContainer from './data-containers/construction'; -import TeamContainer from './data-containers/team'; -import SustainabilityContainer from './data-containers/sustainability'; -import StreetscapeContainer from './data-containers/streetscape'; -import CommunityContainer from './data-containers/community'; -import PlanningContainer from './data-containers/planning'; -import LikeContainer from './data-containers/like'; import { Building } from '../models/building'; +import BuildingNotFound from './building-not-found'; +import AgeContainer from './data-containers/age'; +import CommunityContainer from './data-containers/community'; +import ConstructionContainer from './data-containers/construction'; +import LikeContainer from './data-containers/like'; +import LocationContainer from './data-containers/location'; +import PlanningContainer from './data-containers/planning'; +import SizeContainer from './data-containers/size'; +import StreetscapeContainer from './data-containers/streetscape'; +import SustainabilityContainer from './data-containers/sustainability'; +import TeamContainer from './data-containers/team'; +import TypeContainer from './data-containers/type'; +import UseContainer from './data-containers/use'; + interface BuildingViewProps { cat: string; @@ -23,7 +23,7 @@ interface BuildingViewProps { building?: Building; building_like?: boolean; user?: any; - selectBuilding: (building: Building) => void + selectBuilding: (building: Building) => void; } /** @@ -39,7 +39,7 @@ const BuildingView: React.FunctionComponent = (props) => { title="Location" help="https://pages.colouring.london/location" intro="Where are the buildings? Address, location and cross-references." - /> + />; case 'use': return = (props) => { title="Land Use" intro="How are buildings used, and how does use change over time? Coming soon…" help="https://pages.colouring.london/use" - /> + />; case 'type': return = (props) => { title="Type" intro="How were buildings previously used?" help="https://www.pages.colouring.london/buildingtypology" - /> + />; case 'age': return + />; case 'size': return + />; case 'construction': return = (props) => { intro="How are buildings built? Coming soon…" help="https://pages.colouring.london/construction" inactive={true} - /> + />; case 'team': return = (props) => { intro="Who built the buildings? Coming soon…" help="https://pages.colouring.london/team" inactive={true} - /> + />; case 'sustainability': return = (props) => { intro="Are buildings energy efficient?" help="https://pages.colouring.london/sustainability" inactive={false} - /> + />; case 'streetscape': return = (props) => { intro="What's the building's context? Coming soon…" help="https://pages.colouring.london/streetscape" inactive={true} - /> + />; case 'community': return = (props) => { intro="How does this building work for the local community?" help="https://pages.colouring.london/community" inactive={true} - /> + />; case 'planning': return + />; case 'like': return + />; default: - return + return ; } -} +}; export default BuildingView; diff --git a/app/src/frontend/building/categories.tsx b/app/src/frontend/building/categories.tsx index 54d07541..f03205c4 100644 --- a/app/src/frontend/building/categories.tsx +++ b/app/src/frontend/building/categories.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { NavLink } from 'react-router-dom'; -import './categories.css' +import './categories.css'; interface CategoriesProps { mode: 'view' | 'edit' | 'multi-edit'; @@ -119,7 +119,7 @@ const Categories: React.FC = (props) => ( building_id={props.building_id} /> -) +); interface CategoryProps { mode: 'view' | 'edit' | 'multi-edit'; @@ -152,6 +152,6 @@ const Category: React.FC = (props) => { ); -} +}; export default Categories; diff --git a/app/src/frontend/building/container-header.tsx b/app/src/frontend/building/container-header.tsx index e40d9e4e..9513a91b 100644 --- a/app/src/frontend/building/container-header.tsx +++ b/app/src/frontend/building/container-header.tsx @@ -19,6 +19,6 @@ const ContainerHeader: React.FunctionComponent = (props) = {props.children} -) +); export default ContainerHeader; diff --git a/app/src/frontend/building/data-components/checkbox-data-entry.tsx b/app/src/frontend/building/data-components/checkbox-data-entry.tsx index 2434136c..37ceddb0 100644 --- a/app/src/frontend/building/data-components/checkbox-data-entry.tsx +++ b/app/src/frontend/building/data-components/checkbox-data-entry.tsx @@ -1,7 +1,7 @@ import React, { Fragment } from 'react'; -import { DataTitleCopyable } from './data-title'; import { BaseDataEntryProps } from './data-entry'; +import { DataTitleCopyable } from './data-title'; interface CheckboxDataEntryProps extends BaseDataEntryProps { value: boolean; @@ -33,6 +33,6 @@ const CheckboxDataEntry: React.FunctionComponent = (prop ); -} +}; export default CheckboxDataEntry; diff --git a/app/src/frontend/building/data-components/data-entry-group.tsx b/app/src/frontend/building/data-components/data-entry-group.tsx index e013365c..de4cd710 100644 --- a/app/src/frontend/building/data-components/data-entry-group.tsx +++ b/app/src/frontend/building/data-components/data-entry-group.tsx @@ -1,7 +1,8 @@ import React, { Fragment, useState } from "react"; +import { DownIcon, RightIcon } from "../../components/icons"; + import './data-entry-group.css'; -import { RightIcon, DownIcon } from "../../components/icons"; interface DataEntryGroupProps { /** Name of the group */ @@ -29,7 +30,7 @@ const DataEntryGroup: React.FunctionComponent = (props) => ); -} +}; const CollapseIcon: React.FunctionComponent<{collapsed: boolean}> = (props) => ( diff --git a/app/src/frontend/building/data-components/data-entry.tsx b/app/src/frontend/building/data-components/data-entry.tsx index a9032885..963173b4 100644 --- a/app/src/frontend/building/data-components/data-entry.tsx +++ b/app/src/frontend/building/data-components/data-entry.tsx @@ -1,8 +1,9 @@ import React, { Fragment } from 'react'; -import { DataTitleCopyable } from './data-title'; import { CopyProps } from '../data-containers/category-view-props'; +import { DataTitleCopyable } from './data-title'; + interface BaseDataEntryProps { slug: string; title: string; @@ -17,7 +18,7 @@ interface DataEntryProps extends BaseDataEntryProps { value?: string; maxLength?: number; placeholder?: string; - valueTransform?: (string) => string + valueTransform?: (string) => string; } const DataEntry: React.FunctionComponent = (props) => { @@ -47,7 +48,7 @@ const DataEntry: React.FunctionComponent = (props) => { /> ); -} +}; export default DataEntry; export { diff --git a/app/src/frontend/building/data-components/data-title.tsx b/app/src/frontend/building/data-components/data-title.tsx index fcffd790..5831048d 100644 --- a/app/src/frontend/building/data-components/data-title.tsx +++ b/app/src/frontend/building/data-components/data-title.tsx @@ -15,8 +15,8 @@ const DataTitle: React.FunctionComponent = (props) => { { props.title } { props.tooltip? : null } - ) -} + ); +}; interface DataTitleCopyableProps { @@ -48,7 +48,7 @@ const DataTitleCopyable: React.FunctionComponent = (prop ); -} +}; export default DataTitle; -export { DataTitleCopyable } +export { DataTitleCopyable }; diff --git a/app/src/frontend/building/data-components/like-data-entry.tsx b/app/src/frontend/building/data-components/like-data-entry.tsx index 086dfb7e..e034f2b3 100644 --- a/app/src/frontend/building/data-components/like-data-entry.tsx +++ b/app/src/frontend/building/data-components/like-data-entry.tsx @@ -46,6 +46,6 @@ const LikeDataEntry: React.FunctionComponent = (props) => { ); -} +}; export default LikeDataEntry; diff --git a/app/src/frontend/building/data-components/multi-data-entry.tsx b/app/src/frontend/building/data-components/multi-data-entry.tsx index 755d0583..5efd1a91 100644 --- a/app/src/frontend/building/data-components/multi-data-entry.tsx +++ b/app/src/frontend/building/data-components/multi-data-entry.tsx @@ -1,8 +1,9 @@ import React, { Component, Fragment } from 'react'; import { sanitiseURL } from '../../helpers'; -import { DataTitleCopyable } from './data-title'; + import { BaseDataEntryProps } from './data-entry'; +import { DataTitleCopyable } from './data-title'; interface MultiDataEntryProps extends BaseDataEntryProps { @@ -68,7 +69,7 @@ class MultiDataEntry extends Component { key={index} className="form-control"> {item} - + ; }) } @@ -97,7 +98,7 @@ class MultiDataEntry extends Component { onClick={this.add} disabled={props.mode === 'view'} className="btn btn-outline-dark">+ - + ; } } diff --git a/app/src/frontend/building/data-components/numeric-data-entry.tsx b/app/src/frontend/building/data-components/numeric-data-entry.tsx index f949cb5c..3c1a21fe 100644 --- a/app/src/frontend/building/data-components/numeric-data-entry.tsx +++ b/app/src/frontend/building/data-components/numeric-data-entry.tsx @@ -1,7 +1,7 @@ import React, { Fragment } from 'react'; -import { DataTitleCopyable } from './data-title'; import { BaseDataEntryProps } from './data-entry'; +import { DataTitleCopyable } from './data-title'; interface NumericDataEntryProps extends BaseDataEntryProps { @@ -42,6 +42,6 @@ const NumericDataEntry: React.FunctionComponent = (props) /> ); -} +}; export default NumericDataEntry; diff --git a/app/src/frontend/building/data-components/select-data-entry.tsx b/app/src/frontend/building/data-components/select-data-entry.tsx index 969b2de2..7ed9a70c 100644 --- a/app/src/frontend/building/data-components/select-data-entry.tsx +++ b/app/src/frontend/building/data-components/select-data-entry.tsx @@ -1,7 +1,7 @@ import React, { Fragment } from 'react'; -import { DataTitleCopyable } from './data-title'; import { BaseDataEntryProps } from './data-entry'; +import { DataTitleCopyable } from './data-title'; interface SelectDataEntryProps extends BaseDataEntryProps { value: string; @@ -41,6 +41,6 @@ const SelectDataEntry: React.FunctionComponent = (props) = ); -} +}; export default SelectDataEntry; diff --git a/app/src/frontend/building/data-components/textbox-data-entry.tsx b/app/src/frontend/building/data-components/textbox-data-entry.tsx index 27f929ed..b1ba958a 100644 --- a/app/src/frontend/building/data-components/textbox-data-entry.tsx +++ b/app/src/frontend/building/data-components/textbox-data-entry.tsx @@ -1,7 +1,7 @@ import React, { Fragment } from 'react'; -import { DataTitleCopyable } from './data-title'; import { BaseDataEntryProps } from './data-entry'; +import { DataTitleCopyable } from './data-title'; interface TextboxDataEntryProps extends BaseDataEntryProps { value: string; @@ -39,6 +39,6 @@ const TextboxDataEntry: React.FunctionComponent = (props) > ); -} +}; export default TextboxDataEntry; diff --git a/app/src/frontend/building/data-components/uprns-data-entry.tsx b/app/src/frontend/building/data-components/uprns-data-entry.tsx index 44c414f9..f15de0d4 100644 --- a/app/src/frontend/building/data-components/uprns-data-entry.tsx +++ b/app/src/frontend/building/data-components/uprns-data-entry.tsx @@ -53,7 +53,7 @@ const UPRNsDataEntry: React.FC = (props) => { } - ) + ); }; export default UPRNsDataEntry; diff --git a/app/src/frontend/building/data-components/year-data-entry.tsx b/app/src/frontend/building/data-components/year-data-entry.tsx index 94fcc2cb..1d35f8ee 100644 --- a/app/src/frontend/building/data-components/year-data-entry.tsx +++ b/app/src/frontend/building/data-components/year-data-entry.tsx @@ -1,9 +1,10 @@ import React, { Component, Fragment } from 'react'; -import NumericDataEntry from './numeric-data-entry'; import { dataFields } from '../../data_fields'; import { CopyProps } from '../data-containers/category-view-props'; +import NumericDataEntry from './numeric-data-entry'; + interface YearDataEntryProps { year: number; upper: number; @@ -22,7 +23,7 @@ class YearDataEntry extends Component { lower: props.lower, decade: Math.floor(props.year / 10) * 10, century: Math.floor(props.year / 100) * 100 - } + }; } // TODO add dropdown for decade, century // TODO roll in first/last year estimate @@ -61,7 +62,7 @@ class YearDataEntry extends Component { tooltip={dataFields.date_lower.tooltip} /> - ) + ); } } diff --git a/app/src/frontend/building/data-container.tsx b/app/src/frontend/building/data-container.tsx index c5685fe6..13b2cc27 100644 --- a/app/src/frontend/building/data-container.tsx +++ b/app/src/frontend/building/data-container.tsx @@ -1,15 +1,16 @@ import React, { Fragment } from 'react'; -import { Redirect, NavLink } from 'react-router-dom'; +import { NavLink, Redirect } from 'react-router-dom'; -import ContainerHeader from './container-header'; import ErrorBox from '../components/error-box'; import InfoBox from '../components/info-box'; -import { CopyControl } from './header-buttons/copy-control'; -import { ViewEditControl } from './header-buttons/view-edit-control'; +import { compareObjects } from '../helpers'; import { Building } from '../models/building'; import { User } from '../models/user'; -import { compareObjects } from '../helpers'; + +import ContainerHeader from './container-header'; import { CategoryViewProps, CopyProps } from './data-containers/category-view-props'; +import { CopyControl } from './header-buttons/copy-control'; +import { ViewEditControl } from './header-buttons/view-edit-control'; interface DataContainerProps { title: string; @@ -22,7 +23,7 @@ interface DataContainerProps { mode: 'view' | 'edit'; building?: Building; building_like?: boolean; - selectBuilding: (building: Building) => void + selectBuilding: (building: Building) => void; } interface DataContainerState { @@ -88,7 +89,7 @@ const withCopyEdit = (WrappedComponent: React.ComponentType) toggleCopying() { this.setState({ copying: !this.state.copying - }) + }); } /** @@ -105,7 +106,7 @@ const withCopyEdit = (WrappedComponent: React.ComponentType) } this.setState({ keys_to_copy: keys - }) + }); } isEdited() { @@ -172,7 +173,7 @@ const withCopyEdit = (WrappedComponent: React.ComponentType) const data = await res.json(); if (data.error) { - this.setState({error: data.error}) + this.setState({error: data.error}); } else { this.props.selectBuilding(data); this.updateBuildingState('likes_total', data.likes_total); @@ -198,7 +199,7 @@ const withCopyEdit = (WrappedComponent: React.ComponentType) const data = await res.json(); if (data.error) { - this.setState({error: data.error}) + this.setState({error: data.error}); } else { this.props.selectBuilding(data); } @@ -209,14 +210,14 @@ const withCopyEdit = (WrappedComponent: React.ComponentType) render() { if (this.props.mode === 'edit' && !this.props.user){ - return + return ; } const currentBuilding = this.getEditedBuilding(); - const values_to_copy = {} + const values_to_copy = {}; for (const key of Object.keys(this.state.keys_to_copy)) { - values_to_copy[key] = currentBuilding[key] + values_to_copy[key] = currentBuilding[key]; } const data_string = JSON.stringify(values_to_copy); const copy: CopyProps = { @@ -224,7 +225,7 @@ const withCopyEdit = (WrappedComponent: React.ComponentType) toggleCopying: this.toggleCopying, toggleCopyAttribute: this.toggleCopyAttribute, copyingKey: (key: string) => this.state.keys_to_copy[key] - } + }; const headerBackLink = `/${this.props.mode}/categories${this.props.building != undefined ? `/${this.props.building.building_id}` : ''}`; const edited = this.isEdited(); @@ -346,7 +347,7 @@ const withCopyEdit = (WrappedComponent: React.ComponentType) ); } - } -} + }; +}; export default withCopyEdit; diff --git a/app/src/frontend/building/data-containers/age.tsx b/app/src/frontend/building/data-containers/age.tsx index 4cb1789c..1f1728b6 100644 --- a/app/src/frontend/building/data-containers/age.tsx +++ b/app/src/frontend/building/data-containers/age.tsx @@ -1,12 +1,13 @@ import React, { Fragment } from 'react'; -import withCopyEdit from '../data-container'; +import { dataFields } from '../../data_fields'; import MultiDataEntry from '../data-components/multi-data-entry'; import NumericDataEntry from '../data-components/numeric-data-entry'; import SelectDataEntry from '../data-components/select-data-entry'; import TextboxDataEntry from '../data-components/textbox-data-entry'; import YearDataEntry from '../data-components/year-data-entry'; -import { dataFields } from '../../data_fields'; +import withCopyEdit from '../data-container'; + import { CategoryViewProps } from './category-view-props'; /** @@ -74,7 +75,7 @@ const AgeView: React.FunctionComponent = (props) => ( placeholder="https://..." /> -) +); const AgeContainer = withCopyEdit(AgeView); export default AgeContainer; diff --git a/app/src/frontend/building/data-containers/community.tsx b/app/src/frontend/building/data-containers/community.tsx index 0446e9f2..ddb6b670 100644 --- a/app/src/frontend/building/data-containers/community.tsx +++ b/app/src/frontend/building/data-containers/community.tsx @@ -1,6 +1,7 @@ import React, { Fragment } from 'react'; import withCopyEdit from '../data-container'; + import { CategoryViewProps } from './category-view-props'; /** @@ -27,7 +28,7 @@ const CommunityView: React.FunctionComponent = (props) => ( } -) +); const CommunityContainer = withCopyEdit(CommunityView); export default CommunityContainer; diff --git a/app/src/frontend/building/data-containers/construction.tsx b/app/src/frontend/building/data-containers/construction.tsx index a2630c4e..d72d0499 100644 --- a/app/src/frontend/building/data-containers/construction.tsx +++ b/app/src/frontend/building/data-containers/construction.tsx @@ -1,7 +1,6 @@ import React, { Fragment } from 'react'; import withCopyEdit from '../data-container'; -import DataEntry from '../data-components/data-entry'; /** * Construction view/edit section @@ -50,7 +49,7 @@ const ConstructionView = (props) => ( } -) +); const ConstructionContainer = withCopyEdit(ConstructionView); export default ConstructionContainer; diff --git a/app/src/frontend/building/data-containers/like.tsx b/app/src/frontend/building/data-containers/like.tsx index 0a366bdb..7ee9de61 100644 --- a/app/src/frontend/building/data-containers/like.tsx +++ b/app/src/frontend/building/data-containers/like.tsx @@ -1,7 +1,8 @@ import React, { Fragment } from 'react'; -import withCopyEdit from '../data-container'; import LikeDataEntry from '../data-components/like-data-entry'; +import withCopyEdit from '../data-container'; + import { CategoryViewProps } from './category-view-props'; /** @@ -16,7 +17,7 @@ const LikeView: React.FunctionComponent = (props) => ( onLike={props.onLike} /> -) +); const LikeContainer = withCopyEdit(LikeView); export default LikeContainer; diff --git a/app/src/frontend/building/data-containers/location.tsx b/app/src/frontend/building/data-containers/location.tsx index a3ecf591..5e437b1f 100644 --- a/app/src/frontend/building/data-containers/location.tsx +++ b/app/src/frontend/building/data-containers/location.tsx @@ -1,11 +1,12 @@ import React, { Fragment } from 'react'; -import withCopyEdit from '../data-container'; +import InfoBox from '../../components/info-box'; +import { dataFields } from '../../data_fields'; import DataEntry from '../data-components/data-entry'; import NumericDataEntry from '../data-components/numeric-data-entry'; import UPRNsDataEntry from '../data-components/uprns-data-entry'; -import InfoBox from '../../components/info-box'; -import { dataFields } from '../../data_fields'; +import withCopyEdit from '../data-container'; + import { CategoryViewProps } from './category-view-props'; const LocationView: React.FunctionComponent = (props) => ( @@ -113,7 +114,7 @@ const LocationView: React.FunctionComponent = (props) => ( onChange={props.onChange} /> -) +); const LocationContainer = withCopyEdit(LocationView); export default LocationContainer; diff --git a/app/src/frontend/building/data-containers/planning.tsx b/app/src/frontend/building/data-containers/planning.tsx index 83078714..366ac1eb 100644 --- a/app/src/frontend/building/data-containers/planning.tsx +++ b/app/src/frontend/building/data-containers/planning.tsx @@ -1,11 +1,12 @@ import React, { Fragment } from 'react'; -import withCopyEdit from '../data-container'; -import DataEntry from '../data-components/data-entry'; -import CheckboxDataEntry from '../data-components/checkbox-data-entry'; -import SelectDataEntry from '../data-components/select-data-entry'; -import { DataEntryGroup } from '../data-components/data-entry-group'; import { dataFields } from '../../data_fields'; +import CheckboxDataEntry from '../data-components/checkbox-data-entry'; +import DataEntry from '../data-components/data-entry'; +import { DataEntryGroup } from '../data-components/data-entry-group'; +import SelectDataEntry from '../data-components/select-data-entry'; +import withCopyEdit from '../data-container'; + import { CategoryViewProps } from './category-view-props'; /** @@ -202,7 +203,7 @@ const PlanningView: React.FunctionComponent = (props) => ( /> -) +); const PlanningContainer = withCopyEdit(PlanningView); -export default PlanningContainer +export default PlanningContainer; diff --git a/app/src/frontend/building/data-containers/size.tsx b/app/src/frontend/building/data-containers/size.tsx index 61d100d5..7ae4c2cf 100644 --- a/app/src/frontend/building/data-containers/size.tsx +++ b/app/src/frontend/building/data-containers/size.tsx @@ -1,10 +1,11 @@ import React, { Fragment } from 'react'; -import withCopyEdit from '../data-container'; +import { dataFields } from '../../data_fields'; +import { DataEntryGroup } from '../data-components/data-entry-group'; import NumericDataEntry from '../data-components/numeric-data-entry'; import SelectDataEntry from '../data-components/select-data-entry'; -import { DataEntryGroup } from '../data-components/data-entry-group'; -import { dataFields } from '../../data_fields'; +import withCopyEdit from '../data-container'; + import { CategoryViewProps } from './category-view-props'; /** @@ -146,7 +147,7 @@ const SizeView: React.FunctionComponent = (props) => ( ]} /> -) +); const SizeContainer = withCopyEdit(SizeView); export default SizeContainer; diff --git a/app/src/frontend/building/data-containers/streetscape.tsx b/app/src/frontend/building/data-containers/streetscape.tsx index 8a063319..fe163f09 100644 --- a/app/src/frontend/building/data-containers/streetscape.tsx +++ b/app/src/frontend/building/data-containers/streetscape.tsx @@ -1,6 +1,7 @@ import React, { Fragment } from 'react'; import withCopyEdit from '../data-container'; + import { CategoryViewProps } from './category-view-props'; /** @@ -18,7 +19,7 @@ const StreetscapeView: React.FunctionComponent = (props) => (
  • Building shading
  • -) +); const StreetscapeContainer = withCopyEdit(StreetscapeView); export default StreetscapeContainer; diff --git a/app/src/frontend/building/data-containers/sustainability.tsx b/app/src/frontend/building/data-containers/sustainability.tsx index 6b719b07..b44129a7 100644 --- a/app/src/frontend/building/data-containers/sustainability.tsx +++ b/app/src/frontend/building/data-containers/sustainability.tsx @@ -1,10 +1,10 @@ import React, { Fragment } from 'react'; -import withCopyEdit from '../data-container'; -import DataEntry from '../data-components/data-entry'; -import SelectDataEntry from '../data-components/select-data-entry'; -import NumericDataEntry from '../data-components/numeric-data-entry'; import { dataFields } from '../../data_fields'; +import NumericDataEntry from '../data-components/numeric-data-entry'; +import SelectDataEntry from '../data-components/select-data-entry'; +import withCopyEdit from '../data-container'; + import { CategoryViewProps } from './category-view-props'; const EnergyCategoryOptions = ["A", "B", "C", "D", "E", "F", "G"]; @@ -78,7 +78,7 @@ const SustainabilityView: React.FunctionComponent = (props) = /> ); - } + }; const SustainabilityContainer = withCopyEdit(SustainabilityView); export default SustainabilityContainer; diff --git a/app/src/frontend/building/data-containers/team.tsx b/app/src/frontend/building/data-containers/team.tsx index c8a70a74..4e794353 100644 --- a/app/src/frontend/building/data-containers/team.tsx +++ b/app/src/frontend/building/data-containers/team.tsx @@ -1,7 +1,7 @@ import React, { Fragment } from 'react'; import withCopyEdit from '../data-container'; -import DataEntry from '../data-components/data-entry'; + import { CategoryViewProps } from './category-view-props'; /** @@ -25,7 +25,7 @@ const TeamView: React.FunctionComponent = (props) => ( } -) +); const TeamContainer = withCopyEdit(TeamView); export default TeamContainer; diff --git a/app/src/frontend/building/data-containers/type.tsx b/app/src/frontend/building/data-containers/type.tsx index d8aaf269..0608834a 100644 --- a/app/src/frontend/building/data-containers/type.tsx +++ b/app/src/frontend/building/data-containers/type.tsx @@ -1,10 +1,11 @@ import React, { Fragment } from 'react'; -import withCopyEdit from '../data-container'; -import SelectDataEntry from '../data-components/select-data-entry'; -import NumericDataEntry from '../data-components/numeric-data-entry'; -import DataEntry from '../data-components/data-entry'; import { dataFields } from '../../data_fields'; +import DataEntry from '../data-components/data-entry'; +import NumericDataEntry from '../data-components/numeric-data-entry'; +import SelectDataEntry from '../data-components/select-data-entry'; +import withCopyEdit from '../data-container'; + import { CategoryViewProps } from './category-view-props'; const AttachmentFormOptions = [ @@ -54,7 +55,7 @@ const TypeView: React.FunctionComponent = (props) => { /> ); - } + }; const TypeContainer = withCopyEdit(TypeView); export default TypeContainer; diff --git a/app/src/frontend/building/data-containers/use.tsx b/app/src/frontend/building/data-containers/use.tsx index ac4bb383..aeec0e17 100644 --- a/app/src/frontend/building/data-containers/use.tsx +++ b/app/src/frontend/building/data-containers/use.tsx @@ -1,6 +1,7 @@ import React, { Fragment } from 'react'; import withCopyEdit from '../data-container'; + import { CategoryViewProps } from './category-view-props'; /** @@ -31,7 +32,7 @@ const UseView: React.FunctionComponent = (props) => ( } -) +); const UseContainer = withCopyEdit(UseView); export default UseContainer; diff --git a/app/src/frontend/building/edit-history/building-edit-summary.tsx b/app/src/frontend/building/edit-history/building-edit-summary.tsx index fec2df08..b67ffb3f 100644 --- a/app/src/frontend/building/edit-history/building-edit-summary.tsx +++ b/app/src/frontend/building/edit-history/building-edit-summary.tsx @@ -1,13 +1,15 @@ import React from 'react'; -import { EditHistoryEntry } from '../models/edit-history-entry'; -import { arrayToDictionary, parseDate } from '../../helpers'; + import { dataFields } from '../../data_fields'; +import { arrayToDictionary, parseDate } from '../../helpers'; +import { EditHistoryEntry } from '../../models/edit-history-entry'; + import { CategoryEditSummary } from './category-edit-summary'; import './building-edit-summary.css'; interface BuildingEditSummaryProps { - historyEntry: EditHistoryEntry + historyEntry: EditHistoryEntry; } function formatDate(dt: Date) { @@ -45,7 +47,7 @@ const BuildingEditSummary: React.FunctionComponent = p } ); -} +}; export { BuildingEditSummary diff --git a/app/src/frontend/building/edit-history/category-edit-summary.tsx b/app/src/frontend/building/edit-history/category-edit-summary.tsx index 73a0d542..2c00f211 100644 --- a/app/src/frontend/building/edit-history/category-edit-summary.tsx +++ b/app/src/frontend/building/edit-history/category-edit-summary.tsx @@ -1,8 +1,9 @@ import React from 'react'; -import './category-edit-summary.css'; import { FieldEditSummary } from './field-edit-summary'; +import './category-edit-summary.css'; + interface CategoryEditSummaryProps { category: string; fields: { diff --git a/app/src/frontend/building/edit-history/edit-history.tsx b/app/src/frontend/building/edit-history/edit-history.tsx index 772be6d3..29dadcfb 100644 --- a/app/src/frontend/building/edit-history/edit-history.tsx +++ b/app/src/frontend/building/edit-history/edit-history.tsx @@ -1,10 +1,12 @@ -import React, { useState, useEffect } from 'react'; -import { EditHistoryEntry } from '../models/edit-history-entry'; +import React, { useEffect, useState } from 'react'; + +import { Building } from '../../models/building'; +import { EditHistoryEntry } from '../../models/edit-history-entry'; +import ContainerHeader from '../container-header'; + import { BuildingEditSummary } from './building-edit-summary'; import './edit-history.css'; -import { Building } from '../../models/building'; -import ContainerHeader from '../container-header'; interface EditHistoryProps { building: Building; @@ -39,7 +41,7 @@ const EditHistory: React.FunctionComponent = (props) => { ); -} +}; export { EditHistory diff --git a/app/src/frontend/building/header-buttons/view-edit-control.tsx b/app/src/frontend/building/header-buttons/view-edit-control.tsx index 1eb4801d..2498c45e 100644 --- a/app/src/frontend/building/header-buttons/view-edit-control.tsx +++ b/app/src/frontend/building/header-buttons/view-edit-control.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import { Building } from '../../models/building'; import { NavLink } from 'react-router-dom'; -import { ViewIcon, EditIcon } from '../../components/icons'; + +import { EditIcon, ViewIcon } from '../../components/icons'; +import { Building } from '../../models/building'; interface ViewEditControlProps { cat: string; diff --git a/app/src/frontend/building/multi-edit.tsx b/app/src/frontend/building/multi-edit.tsx index eddd6c85..6197b53c 100644 --- a/app/src/frontend/building/multi-edit.tsx +++ b/app/src/frontend/building/multi-edit.tsx @@ -1,14 +1,15 @@ +import { parse } from 'query-string'; import React from 'react'; import { Link, Redirect, RouteComponentProps } from 'react-router-dom'; -import { parse } from 'query-string'; -import Sidebar from './sidebar'; +import { BackIcon } from '../components/icons'; import InfoBox from '../components/info-box'; -import { BackIcon }from '../components/icons'; -import DataEntry from './data-components/data-entry'; import { dataFields } from '../data_fields'; import { User } from '../models/user'; +import DataEntry from './data-components/data-entry'; +import Sidebar from './sidebar'; + interface MultiEditRouteParams { cat: string; } @@ -19,7 +20,7 @@ interface MultiEditProps extends RouteComponentProps { const MultiEdit: React.FC = (props) => { if (!props.user){ - return + return ; } const cat = props.match.params.cat; if (cat === 'like') { @@ -45,14 +46,14 @@ const MultiEdit: React.FC = (props) => { let data: object; if (cat === 'like'){ - data = { like: true } + data = { like: true }; } else { try { // TODO: verify what happens if data is string[] data = JSON.parse(q.data as string); } catch (error) { - console.error(error, q) - data = {} + console.error(error, q); + data = {}; } } @@ -79,7 +80,7 @@ const MultiEdit: React.FC = (props) => { disabled={true} value={data[key]} /> - ) + ); })) } @@ -90,6 +91,6 @@ const MultiEdit: React.FC = (props) => { ); -} +}; export default MultiEdit; diff --git a/app/src/frontend/components/confirmation-modal.tsx b/app/src/frontend/components/confirmation-modal.tsx index 00067956..3545ac78 100644 --- a/app/src/frontend/components/confirmation-modal.tsx +++ b/app/src/frontend/components/confirmation-modal.tsx @@ -3,14 +3,14 @@ import React from 'react'; import './confirmation-modal.css'; interface ConfirmationModalProps { - show: boolean, - title: string, - description: string, - confirmButtonText?: string, - confirmButtonClass?: string, - cancelButtonClass?: string, - onConfirm: () => void, - onCancel: () => void + show: boolean; + title: string; + description: string; + confirmButtonText?: string; + confirmButtonClass?: string; + cancelButtonClass?: string; + onConfirm: () => void; + onCancel: () => void; } const ConfirmationModal: React.FunctionComponent = ({ diff --git a/app/src/frontend/components/icons.tsx b/app/src/frontend/components/icons.tsx index a7352d20..8f49b932 100644 --- a/app/src/frontend/components/icons.tsx +++ b/app/src/frontend/components/icons.tsx @@ -1,11 +1,11 @@ /** * Mini-library of icons */ -import React from 'react' -import { library } from '@fortawesome/fontawesome-svg-core' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faQuestionCircle, faPaintBrush, faInfoCircle, faTimes, faCheck, faCheckDouble, - faAngleLeft, faCaretDown, faSearch, faEye, faCaretUp, faCaretRight } from '@fortawesome/free-solid-svg-icons' +import { library } from '@fortawesome/fontawesome-svg-core'; +import { faAngleLeft, faCaretDown, faCaretRight, faCaretUp, faCheck, faCheckDouble, + faEye, faInfoCircle, faPaintBrush, faQuestionCircle, faSearch, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import React from 'react'; library.add( faQuestionCircle, diff --git a/app/src/frontend/components/logo.tsx b/app/src/frontend/components/logo.tsx index 1b574183..29a1bf13 100644 --- a/app/src/frontend/components/logo.tsx +++ b/app/src/frontend/components/logo.tsx @@ -1,4 +1,5 @@ import React from 'react'; + import './logo.css'; interface LogoProps { @@ -44,6 +45,6 @@ const LogoGrid: React.FunctionComponent = () => (
    -) +); export { Logo }; diff --git a/app/src/frontend/components/tooltip.tsx b/app/src/frontend/components/tooltip.tsx index 04cb8a28..e8402396 100644 --- a/app/src/frontend/components/tooltip.tsx +++ b/app/src/frontend/components/tooltip.tsx @@ -1,8 +1,9 @@ import React, { Component } from 'react'; -import './tooltip.css'; import { InfoIcon } from './icons'; +import './tooltip.css'; + interface TooltipProps { text: string; } diff --git a/app/src/frontend/helpers.ts b/app/src/frontend/helpers.ts index 3567d5a5..9648c708 100644 --- a/app/src/frontend/helpers.ts +++ b/app/src/frontend/helpers.ts @@ -1,27 +1,27 @@ import urlapi from 'url'; function sanitiseURL(string){ - let url_ + let url_; // http or https if (!(string.substring(0, 7) === 'http://' || string.substring(0, 8) === 'https://')){ - return null + return null; } try { - url_ = document.createElement('a') - url_.href = string + url_ = document.createElement('a'); + url_.href = string; } catch (error) { try { - url_ = urlapi.parse(string) + url_ = urlapi.parse(string); } catch (error) { - return null + return null; } } // required (www.example.com) if (!url_.hostname || url_.hostname === '' || url_.hostname === 'localhost'){ - return null + return null; } // optional (/some/path) @@ -33,7 +33,7 @@ function sanitiseURL(string){ // optional (#anchor) // url_.hash; - return `${url_.protocol}//${url_.hostname}${url_.pathname || ''}${url_.search || ''}${url_.hash || ''}` + return `${url_.protocol}//${url_.hostname}${url_.pathname || ''}${url_.search || ''}${url_.hash || ''}`; } /** @@ -63,8 +63,8 @@ function parseDate(isoUtcDate: string): Date { } function compareObjects(objA: object, objB: object): [object, object] { - const reverse = {} - const forward = {} + const reverse = {}; + const forward = {}; for (const [key, value] of Object.entries(objB)) { if (objA[key] !== value) { reverse[key] = objA[key]; diff --git a/app/src/frontend/map-app.tsx b/app/src/frontend/map-app.tsx index cf4cfda9..71a61db4 100644 --- a/app/src/frontend/map-app.tsx +++ b/app/src/frontend/map-app.tsx @@ -1,15 +1,15 @@ -import React, { Fragment } from 'react'; -import { Switch, Route, RouteComponentProps, Redirect } from 'react-router-dom'; - -import Welcome from './pages/welcome'; -import Sidebar from './building/sidebar'; -import Categories from './building/categories'; -import MultiEdit from './building/multi-edit'; -import BuildingView from './building/building-view'; -import ColouringMap from './map/map'; import { parse } from 'query-string'; +import React, { Fragment } from 'react'; +import { Redirect, Route, RouteComponentProps, Switch } from 'react-router-dom'; + +import BuildingView from './building/building-view'; +import Categories from './building/categories'; import { EditHistory } from './building/edit-history/edit-history'; +import MultiEdit from './building/multi-edit'; +import Sidebar from './building/sidebar'; +import ColouringMap from './map/map'; import { Building } from './models/building'; +import Welcome from './pages/welcome'; interface MapAppRouteParams { mode: 'view' | 'edit' | 'multi-edit'; @@ -85,7 +85,7 @@ class MapApp extends React.Component { revisionId = +revisionId; // bump revision id, only ever increasing if (revisionId > this.state.revision_id) { - this.setState({ revision_id: revisionId }) + this.setState({ revision_id: revisionId }); } } @@ -117,7 +117,7 @@ class MapApp extends React.Component { this.setState({ building: building }); } }).catch((err) => { - console.error(err) + console.error(err); this.setState({ building: building }); }); @@ -138,7 +138,7 @@ class MapApp extends React.Component { this.props.history.push(`/${mode}/${category}/${building.building_id}`); } }).catch((err) => { - console.error(err) + console.error(err); this.setState({ building_like: false }); }); } @@ -157,14 +157,14 @@ class MapApp extends React.Component { const q = parse(window.location.search); if (cat === 'like') { - this.likeBuilding(building.building_id) + this.likeBuilding(building.building_id); } else { try { // TODO: verify what happens if data is string[] const data = JSON.parse(q.data as string); - this.updateBuilding(building.building_id, data) + this.updateBuilding(building.building_id, data); } catch (error) { - console.error(error, q) + console.error(error, q); } } } @@ -181,7 +181,7 @@ class MapApp extends React.Component { res => res.json() ).then(function (res) { if (res.error) { - console.error({ error: res.error }) + console.error({ error: res.error }); } else { this.increaseRevision(res.revision_id); } @@ -202,7 +202,7 @@ class MapApp extends React.Component { res => res.json() ).then(res => { if (res.error) { - console.error({ error: res.error }) + console.error({ error: res.error }); } else { this.increaseRevision(res.revision_id); } diff --git a/app/src/frontend/map/legend.tsx b/app/src/frontend/map/legend.tsx index 75ea3d44..c2cdd552 100644 --- a/app/src/frontend/map/legend.tsx +++ b/app/src/frontend/map/legend.tsx @@ -1,8 +1,9 @@ import React from 'react'; -import './legend.css'; +import { DownIcon, UpIcon } from '../components/icons'; import { Logo } from '../components/logo'; -import { DownIcon, UpIcon, BackIcon } from '../components/icons'; + +import './legend.css'; const LEGEND_CONFIG = { location: { diff --git a/app/src/frontend/map/map.tsx b/app/src/frontend/map/map.tsx index cd0a842b..4d7a5f1b 100644 --- a/app/src/frontend/map/map.tsx +++ b/app/src/frontend/map/map.tsx @@ -1,15 +1,16 @@ -import React, { Component, Fragment } from 'react'; -import { Map, TileLayer, ZoomControl, AttributionControl, GeoJSON } from 'react-leaflet-universal'; import { GeoJsonObject } from 'geojson'; - -import '../../../node_modules/leaflet/dist/leaflet.css' -import './map.css' +import React, { Component, Fragment } from 'react'; +import { AttributionControl, GeoJSON, Map, TileLayer, ZoomControl } from 'react-leaflet-universal'; import { HelpIcon } from '../components/icons'; +import { Building } from '../models/building'; + import Legend from './legend'; import SearchBox from './search-box'; import ThemeSwitcher from './theme-switcher'; -import { Building } from '../models/building'; + +import '../../../node_modules/leaflet/dist/leaflet.css'; +import './map.css'; const OS_API_KEY = 'NVUxtY5r8eA6eIfwrPTAGKrAAsoeI9E9'; @@ -83,7 +84,7 @@ class ColouringMap extends Component { } }.bind(this)).catch( (err) => console.error(err) - ) + ); } themeSwitch(e) { diff --git a/app/src/frontend/map/search-box.tsx b/app/src/frontend/map/search-box.tsx index 79fd03f2..da622bba 100644 --- a/app/src/frontend/map/search-box.tsx +++ b/app/src/frontend/map/search-box.tsx @@ -1,8 +1,9 @@ +import { Point } from 'geojson'; import React, { Component } from 'react'; -import './search-box.css'; import { SearchIcon } from '../components/icons'; -import { Point } from 'geojson'; + +import './search-box.css'; interface SearchResult { type: string; @@ -10,12 +11,12 @@ interface SearchResult { label: string; zoom: number; }; - geometry: Point + geometry: Point; } interface SearchBoxProps { - onLocate: (lat: number, lng: number, zoom: number) => void + onLocate: (lat: number, lng: number, zoom: number) => void; } interface SearchBoxState { @@ -40,7 +41,7 @@ class SearchBox extends Component { collapsedSearch: true, //is this a small screen device? if not we will disable collapse option smallScreen: false - } + }; this.handleChange = this.handleChange.bind(this); this.search = this.search.bind(this); this.handleKeyPress = this.handleKeyPress.bind(this); @@ -93,7 +94,7 @@ class SearchBox extends Component { e.preventDefault(); this.setState({ fetching: true - }) + }); fetch( '/api/search?q='+this.state.q @@ -104,23 +105,23 @@ class SearchBox extends Component { this.setState({ results: data.results, fetching: false - }) + }); } else { console.error(data); this.setState({ results: [], fetching: false - }) + }); } }).catch((err) => { - console.error(err) + console.error(err); this.setState({ results: [], fetching: false - }) - }) + }); + }); } componentDidMount() { @@ -148,7 +149,7 @@ class SearchBox extends Component {
    - ) + ); } const resultsList = this.state.results.length? @@ -159,7 +160,7 @@ class SearchBox extends Component { const lng = result.geometry.coordinates[0]; const lat = result.geometry.coordinates[1]; const zoom = result.attributes.zoom; - const href = `?lng=${lng}&lat=${lat}&zoom=${zoom}` + const href = `?lng=${lng}&lat=${lat}&zoom=${zoom}`; return (
  • { href={href} >{`${label.substring(0, 4)} ${label.substring(4, 7)}`}
  • - ) + ); }) } @@ -196,7 +197,7 @@ class SearchBox extends Component { { resultsList } - ) + ); } } diff --git a/app/src/frontend/building/models/edit-history-entry.ts b/app/src/frontend/models/edit-history-entry.ts similarity index 100% rename from app/src/frontend/building/models/edit-history-entry.ts rename to app/src/frontend/models/edit-history-entry.ts diff --git a/app/src/frontend/pages/about.tsx b/app/src/frontend/pages/about.tsx index 1d3f98ea..9b923d58 100644 --- a/app/src/frontend/pages/about.tsx +++ b/app/src/frontend/pages/about.tsx @@ -1,8 +1,9 @@ import React from 'react'; -import SupporterLogos from '../components/supporter-logos'; -import './about.css'; import Categories from '../building/categories'; +import SupporterLogos from '../components/supporter-logos'; + +import './about.css'; const AboutPage = () => (
    @@ -140,7 +141,7 @@ const AboutPage = () => ( onSubmit={function() {window.open( 'https://tinyletter.com/colouringlondon', 'popupwindow', - 'scrollbars=yes,width=800,height=600'); return true}}> + 'scrollbars=yes,width=800,height=600'); return true;}}>

    Keep in touch

    diff --git a/app/src/frontend/pages/contributor-agreement.tsx b/app/src/frontend/pages/contributor-agreement.tsx index c44da55b..1b3c35f9 100644 --- a/app/src/frontend/pages/contributor-agreement.tsx +++ b/app/src/frontend/pages/contributor-agreement.tsx @@ -1,8 +1,6 @@ import React from 'react'; import { Link } from 'react-router-dom'; -import InfoBox from '../components/info-box'; - const ContributorAgreementPage : React.SFC = () => (

    @@ -40,6 +38,6 @@ const ContributorAgreementPage : React.SFC = () => (
    -) +); export default ContributorAgreementPage; diff --git a/app/src/frontend/pages/data-extracts.tsx b/app/src/frontend/pages/data-extracts.tsx index 16d11748..3482475f 100644 --- a/app/src/frontend/pages/data-extracts.tsx +++ b/app/src/frontend/pages/data-extracts.tsx @@ -1,7 +1,8 @@ import React, { FunctionComponent } from 'react'; +import { Link } from 'react-router-dom'; import { dateReviver } from '../../helpers'; -import { Link } from 'react-router-dom'; + interface ExtractViewModel { extract_id: number; diff --git a/app/src/frontend/pages/ordnance-survey-uprn.tsx b/app/src/frontend/pages/ordnance-survey-uprn.tsx index bff79907..a45b68ac 100644 --- a/app/src/frontend/pages/ordnance-survey-uprn.tsx +++ b/app/src/frontend/pages/ordnance-survey-uprn.tsx @@ -11,4 +11,4 @@ const OrdnanceSurveyUprnPage = () => (
    ); -export default OrdnanceSurveyUprnPage; \ No newline at end of file +export default OrdnanceSurveyUprnPage; diff --git a/app/src/frontend/pages/privacy-policy.tsx b/app/src/frontend/pages/privacy-policy.tsx index b11af2e5..1744a6e3 100644 --- a/app/src/frontend/pages/privacy-policy.tsx +++ b/app/src/frontend/pages/privacy-policy.tsx @@ -1,8 +1,6 @@ import React from 'react'; import { Link } from 'react-router-dom'; -import InfoBox from '../components/info-box'; - const PrivacyPolicyPage: React.SFC = () => (
    @@ -118,6 +116,6 @@ const PrivacyPolicyPage: React.SFC = () => (
    -) +); export default PrivacyPolicyPage; diff --git a/app/src/frontend/user/forgotten-password.tsx b/app/src/frontend/user/forgotten-password.tsx index bc2fe8ec..678132e4 100644 --- a/app/src/frontend/user/forgotten-password.tsx +++ b/app/src/frontend/user/forgotten-password.tsx @@ -1,6 +1,7 @@ -import React, { FormEvent, ChangeEvent } from 'react'; -import InfoBox from '../components/info-box'; +import React, { ChangeEvent, FormEvent } from 'react'; + import ErrorBox from '../components/error-box'; +import InfoBox from '../components/info-box'; interface ForgottenPasswordState { success: boolean; @@ -79,6 +80,6 @@ export default class ForgottenPassword extends React.Component<{}, ForgottenPass - ) + ); } } diff --git a/app/src/frontend/user/login.tsx b/app/src/frontend/user/login.tsx index dbfbb12c..ca36b5ce 100644 --- a/app/src/frontend/user/login.tsx +++ b/app/src/frontend/user/login.tsx @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { Redirect, Link } from 'react-router-dom'; +import { Link, Redirect } from 'react-router-dom'; import ErrorBox from '../components/error-box'; import InfoBox from '../components/info-box'; @@ -7,7 +7,7 @@ import SupporterLogos from '../components/supporter-logos'; import { User } from '../models/user'; interface LoginProps { - user: User, + user: User; login: (user: User) => void; } @@ -37,7 +37,7 @@ class Login extends Component { handleSubmit(event) { event.preventDefault(); - this.setState({error: undefined}) + this.setState({error: undefined}); fetch('/api/login', { method: 'POST', @@ -50,7 +50,7 @@ class Login extends Component { res => res.json() ).then(function(res){ if (res.error) { - this.setState({error: res.error}) + this.setState({error: res.error}); } else { fetch('/api/users/me', { credentials: 'same-origin' @@ -58,13 +58,13 @@ class Login extends Component { (res) => res.json() ).then(user => { if (user.error) { - this.setState({error: user.error}) + this.setState({error: user.error}); } else { - this.props.login(user) + this.props.login(user); } }).catch( (err) => this.setState({error: err}) - ) + ); } }.bind(this)).catch( (err) => this.setState({error: err}) @@ -73,7 +73,7 @@ class Login extends Component { render() { if (this.props.user && !this.props.user.error) { - return + return ; } return (
    @@ -130,7 +130,7 @@ class Login extends Component {
    - ) + ); } } diff --git a/app/src/frontend/user/my-account.tsx b/app/src/frontend/user/my-account.tsx index e8539309..b4676fbc 100644 --- a/app/src/frontend/user/my-account.tsx +++ b/app/src/frontend/user/my-account.tsx @@ -39,7 +39,7 @@ class MyAccountPage extends Component { res => res.json() ).then(function(res){ if (res.error) { - this.setState({error: res.error}) + this.setState({error: res.error}); } else { this.props.logout(); } @@ -59,7 +59,7 @@ class MyAccountPage extends Component { res => res.json() ).then(function(res){ if (res.error) { - this.setState({error: res.error}) + this.setState({error: res.error}); } else { this.props.updateUser(res); } @@ -176,7 +176,7 @@ class MyAccountPage extends Component { } else { return ( - ) + ); } } } diff --git a/app/src/frontend/user/password-reset.tsx b/app/src/frontend/user/password-reset.tsx index e270aa61..6a06ade1 100644 --- a/app/src/frontend/user/password-reset.tsx +++ b/app/src/frontend/user/password-reset.tsx @@ -1,8 +1,8 @@ import React, { FormEvent } from 'react'; -import { RouteComponentProps, Redirect } from 'react-router'; +import { Redirect, RouteComponentProps } from 'react-router'; +import { Link } from 'react-router-dom'; import ErrorBox from '../components/error-box'; -import { Link } from 'react-router-dom'; interface PasswordResetState { error: string; @@ -117,6 +117,6 @@ export default class PasswordReset extends React.Component - ) + ); } } diff --git a/app/src/frontend/user/signup.tsx b/app/src/frontend/user/signup.tsx index 6c1e2835..cf422163 100644 --- a/app/src/frontend/user/signup.tsx +++ b/app/src/frontend/user/signup.tsx @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { Redirect, Link } from 'react-router-dom'; +import { Link, Redirect } from 'react-router-dom'; import ErrorBox from '../components/error-box'; import InfoBox from '../components/info-box'; @@ -50,7 +50,7 @@ class SignUp extends Component { handleSubmit(event) { event.preventDefault(); - this.setState({error: undefined}) + this.setState({error: undefined}); fetch('/api/users', { method: 'POST', @@ -63,7 +63,7 @@ class SignUp extends Component { res => res.json() ).then(function(res){ if (res.error) { - this.setState({error: res.error}) + this.setState({error: res.error}); } else { fetch('/api/users/me', { credentials: 'same-origin' @@ -73,7 +73,7 @@ class SignUp extends Component { (user) => this.props.login(user) ).catch( (err) => this.setState({error: err}) - ) + ); } }.bind(this)).catch( (err) => this.setState({error: err}) @@ -82,7 +82,7 @@ class SignUp extends Component { render() { if (this.props.user) { - return + return ; } return (
    @@ -175,7 +175,7 @@ class SignUp extends Component {
    - ) + ); } } diff --git a/app/src/frontendRoute.tsx b/app/src/frontendRoute.tsx index 3b07e3c2..7a8a6d9c 100644 --- a/app/src/frontendRoute.tsx +++ b/app/src/frontendRoute.tsx @@ -1,20 +1,18 @@ import express from 'express'; import React from 'react'; -import { StaticRouter } from 'react-router-dom'; - import { renderToString } from 'react-dom/server'; +import { StaticRouter } from 'react-router-dom'; import serialize from 'serialize-javascript'; -import App from './frontend/app'; - -import { parseBuildingURL } from './parse'; -import { getUserById } from './api/services/user'; import { getBuildingById, getBuildingLikeById, getBuildingUPRNsById, getLatestRevisionId } from './api/services/building'; +import { getUserById } from './api/services/user'; +import App from './frontend/app'; +import { parseBuildingURL } from './parse'; // reference packed assets diff --git a/app/src/parse.ts b/app/src/parse.ts index a8c680c7..e85c2643 100644 --- a/app/src/parse.ts +++ b/app/src/parse.ts @@ -27,7 +27,7 @@ function parseBuildingURL(url) { const matches = re.exec(url); if (matches && matches.length >= 2) { - return strictParseInt(matches[1]) + return strictParseInt(matches[1]); } return undefined; } diff --git a/app/src/server.tsx b/app/src/server.tsx index 3ed45fe0..8ac21919 100644 --- a/app/src/server.tsx +++ b/app/src/server.tsx @@ -4,15 +4,14 @@ * - entry-point to shared React App * */ -import express from 'express'; - -import session from 'express-session'; import pgConnect from 'connect-pg-simple'; +import express from 'express'; +import session from 'express-session'; -import db from './db'; -import tileserver from './tiles/tileserver'; import apiServer from './api/api'; +import db from './db'; import frontendRoute from './frontendRoute'; +import tileserver from './tiles/tileserver'; // create server const server = express(); @@ -38,9 +37,9 @@ const sess: any = { // TODO: remove any }; if (server.get('env') === 'production') { // trust first proxy - server.set('trust proxy', 1) + server.set('trust proxy', 1); // serve secure cookies - sess.cookie.secure = true + sess.cookie.secure = true; } server.use(session(sess)); diff --git a/app/src/tiles/dataDefinition.ts b/app/src/tiles/dataDefinition.ts index 92eb2c0e..3f029d2b 100644 --- a/app/src/tiles/dataDefinition.ts +++ b/app/src/tiles/dataDefinition.ts @@ -1,4 +1,5 @@ import { strictParseInt } from "../parse"; + import { DataConfig } from "./types"; const BUILDING_LAYER_DEFINITIONS = { diff --git a/app/src/tiles/rendererDefinition.ts b/app/src/tiles/rendererDefinition.ts index bfdd1b5e..bacfe6f3 100644 --- a/app/src/tiles/rendererDefinition.ts +++ b/app/src/tiles/rendererDefinition.ts @@ -1,11 +1,11 @@ -import { TileCache } from "./tileCache"; -import { BoundingBox, TileParams, Tile } from "./types"; -import { getBuildingsDataConfig, getHighlightDataConfig, getAllLayerNames, getBuildingLayerNames } from "./dataDefinition"; -import { isOutsideExtent } from "./util"; -import { renderDataSourceTile } from "./renderers/renderDataSourceTile"; -import { getTileWithCaching } from "./renderers/getTileWithCaching"; -import { stitchTile } from "./renderers/stitchTile"; +import { getAllLayerNames, getBuildingLayerNames, getBuildingsDataConfig, getHighlightDataConfig } from "./dataDefinition"; import { createBlankTile } from "./renderers/createBlankTile"; +import { getTileWithCaching } from "./renderers/getTileWithCaching"; +import { renderDataSourceTile } from "./renderers/renderDataSourceTile"; +import { stitchTile } from "./renderers/stitchTile"; +import { TileCache } from "./tileCache"; +import { BoundingBox, Tile, TileParams } from "./types"; +import { isOutsideExtent } from "./util"; /** * A list of all tilesets handled by the tile server diff --git a/app/src/tiles/renderers/getTileWithCaching.ts b/app/src/tiles/renderers/getTileWithCaching.ts index 6595d82d..451574d0 100644 --- a/app/src/tiles/renderers/getTileWithCaching.ts +++ b/app/src/tiles/renderers/getTileWithCaching.ts @@ -1,5 +1,5 @@ -import { TileParams, RendererFunction, Tile } from "../types"; import { TileCache } from "../tileCache"; +import { RendererFunction, Tile, TileParams } from "../types"; async function getTileWithCaching(tileParams: TileParams, dataParams: any, tileCache: TileCache, renderTile: RendererFunction): Promise { diff --git a/app/src/tiles/renderers/renderDataSourceTile.ts b/app/src/tiles/renderers/renderDataSourceTile.ts index 9cb7d5e5..2c2655b3 100644 --- a/app/src/tiles/renderers/renderDataSourceTile.ts +++ b/app/src/tiles/renderers/renderDataSourceTile.ts @@ -1,11 +1,10 @@ -import path from 'path'; - import mapnik from "mapnik"; - -import { TileParams, Tile, TableDefinitionFunction } from "../types"; -import { getBbox, TILE_SIZE } from "../util"; +import path from 'path'; import { promisify } from "util"; +import { TableDefinitionFunction, Tile, TileParams } from "../types"; +import { getBbox, TILE_SIZE } from "../util"; + const TILE_BUFFER_SIZE = 64; const PROJ4_STRING = '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over'; diff --git a/app/src/tiles/renderers/stitchTile.ts b/app/src/tiles/renderers/stitchTile.ts index eb7acb84..b0c2c840 100644 --- a/app/src/tiles/renderers/stitchTile.ts +++ b/app/src/tiles/renderers/stitchTile.ts @@ -1,6 +1,6 @@ import sharp from 'sharp'; -import { TileParams, RendererFunction, Tile } from "../types"; +import { RendererFunction, Tile, TileParams } from "../types"; import { getBbox, getXYZ, TILE_SIZE } from "../util"; diff --git a/app/src/tiles/tileCache.ts b/app/src/tiles/tileCache.ts index 1176986c..8b97eded 100644 --- a/app/src/tiles/tileCache.ts +++ b/app/src/tiles/tileCache.ts @@ -16,12 +16,12 @@ // Using node-fs package to patch fs // for node >10 we could drop this in favour of fs.mkdir (which has recursive option) // and then use stdlib `import fs from 'fs';` -import fs from 'node-fs'; -import { promisify } from 'util' import { Image } from 'mapnik'; +import fs from 'node-fs'; +import { promisify } from 'util'; -import { TileParams, BoundingBox } from './types'; -import { getXYZ, formatParams } from './util'; +import { BoundingBox, TileParams } from './types'; +import { formatParams, getXYZ } from './util'; // TODO: switch to modern node and use built-in fs with promise-based API const readFile = promisify(fs.readFile), @@ -113,7 +113,7 @@ class TileCache { if(!this.shouldBulkClearTileset(tileset)) continue; for (let z = this.cacheDomain.minZoom; z <= this.cacheDomain.maxZoom; z++) { - let tileBounds = getXYZ(bbox, z) + let tileBounds = getXYZ(bbox, z); for (let x = tileBounds.minX; x <= tileBounds.maxX; x++) { for (let y = tileBounds.minY; y <= tileBounds.maxY; y++) { for (const scale of this.cacheDomain.scales) { diff --git a/app/src/tiles/tileserver.ts b/app/src/tiles/tileserver.ts index 9ebf101a..07c99a58 100644 --- a/app/src/tiles/tileserver.ts +++ b/app/src/tiles/tileserver.ts @@ -5,10 +5,11 @@ */ import express from 'express'; -import { strictParseInt } from '../parse'; -import { TileParams } from './types'; -import { renderTile, allTilesets } from './rendererDefinition'; import asyncController from '../api/routes/asyncController'; +import { strictParseInt } from '../parse'; + +import { allTilesets, renderTile } from './rendererDefinition'; +import { TileParams } from './types'; const handleTileRequest = asyncController(async function (req: express.Request, res: express.Response) { try { @@ -30,7 +31,7 @@ const handleTileRequest = asyncController(async function (req: express.Request, }); // tiles router -const router = express.Router() +const router = express.Router(); router.get('/:tileset/:z/:x/:y(\\d+):scale(@\\dx)?.png', handleTileRequest); diff --git a/app/src/tiles/types.ts b/app/src/tiles/types.ts index eef82868..3d7ae7e1 100644 --- a/app/src/tiles/types.ts +++ b/app/src/tiles/types.ts @@ -44,7 +44,7 @@ type Tile = Image | Sharp; type RendererFunction = (tileParams: TileParams, dataParams: any) => Promise; interface TileRenderer { - getTile: RendererFunction + getTile: RendererFunction; } export { diff --git a/app/src/tiles/util.ts b/app/src/tiles/util.ts index 42f4dab9..7afdfdb8 100644 --- a/app/src/tiles/util.ts +++ b/app/src/tiles/util.ts @@ -1,6 +1,6 @@ import SphericalMercator from '@mapbox/sphericalmercator'; -import { TileParams, BoundingBox } from './types'; +import { BoundingBox, TileParams } from './types'; const TILE_SIZE = 256; @@ -13,7 +13,7 @@ function getBbox(z, x, y) { } function getXYZ(bbox, z) { - return mercator.xyz(bbox, z, false, '900913') + return mercator.xyz(bbox, z, false, '900913'); } function formatParams({ tileset, z, x, y, scale }: TileParams): string { diff --git a/app/tslint.json b/app/tslint.json index a0a32198..d6d58ca2 100644 --- a/app/tslint.json +++ b/app/tslint.json @@ -1,6 +1,19 @@ { "defaultSeverity": "warning", "rules": { - "eofline": true + "eofline": true, + "ordered-imports": [ + true, + { + "grouped-imports": true, + "groups": [ + { "name": "css", "match": "\\.css$", "order": 40 }, + { "name": "parent directories", "match": "^\\.\\.", "order": 20 }, + { "name": "current directory", "match": "^\\.", "order": 30 }, + { "name": "libraries", "match": ".*", "order": 10 } + ] + } + ], + "semicolon": true } } \ No newline at end of file