Merge pull request #369 from mz8i/feature/typescript
Move code base to TypeScript
This commit is contained in:
commit
ab14d2af25
7202
app/package-lock.json
generated
7202
app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -36,10 +36,44 @@
|
|||||||
"sharp": "^0.21.3"
|
"sharp": "^0.21.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/express": "^4.17.0",
|
||||||
|
"@types/express-session": "^1.15.13",
|
||||||
|
"@types/jest": "^24.0.17",
|
||||||
|
"@types/node": "^12.7.1",
|
||||||
|
"@types/prop-types": "^15.7.1",
|
||||||
|
"@types/react": "^16.9.0",
|
||||||
|
"@types/react-dom": "^16.8.5",
|
||||||
|
"@types/react-router-dom": "^4.3.4",
|
||||||
|
"@types/webpack-env": "^1.14.0",
|
||||||
"babel-eslint": "^10.0.2",
|
"babel-eslint": "^10.0.2",
|
||||||
"eslint": "^5.16.0",
|
"eslint": "^5.16.0",
|
||||||
"eslint-plugin-jest": "^22.7.2",
|
"eslint-plugin-jest": "^22.7.2",
|
||||||
"eslint-plugin-react": "^7.14.2",
|
"eslint-plugin-react": "^7.14.2",
|
||||||
"razzle": "^3.0.0"
|
"razzle": "^3.0.0",
|
||||||
|
"razzle-plugin-typescript": "^3.0.0",
|
||||||
|
"ts-jest": "^24.0.2",
|
||||||
|
"tslint": "^5.18.0",
|
||||||
|
"tslint-react": "^4.0.0",
|
||||||
|
"typescript": "^3.5.3"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"transform": {
|
||||||
|
"\\.(ts|tsx)$": "ts-jest",
|
||||||
|
"\\.css$": "<rootDir>/node_modules/razzle/config/jest/cssTransform.js",
|
||||||
|
"^(?!.*\\.(js|jsx|css|json)$)": "<rootDir>/node_modules/razzle/config/jest/fileTransform.js"
|
||||||
|
},
|
||||||
|
"testMatch": [
|
||||||
|
"<rootDir>/src/**/__tests__/**/*.(ts|js)?(x)",
|
||||||
|
"<rootDir>/src/**/?(*.)(spec|test).(ts|js)?(x)"
|
||||||
|
],
|
||||||
|
"moduleFileExtensions": [
|
||||||
|
"ts",
|
||||||
|
"tsx",
|
||||||
|
"js",
|
||||||
|
"json"
|
||||||
|
],
|
||||||
|
"collectCoverageFrom": [
|
||||||
|
"src/**/*.{js,jsx,ts,tsx}"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
|
plugins: ['typescript'],
|
||||||
modify: (config, { target, dev }, webpack) => {
|
modify: (config, { target, dev }, webpack) => {
|
||||||
// load webfonts
|
// load webfonts
|
||||||
rules = config.module.rules || [];
|
rules = config.module.rules || [];
|
||||||
|
@ -72,7 +72,7 @@ function queryBuildingsByReference(key, id) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return { error: 'Key must be UPRN or TOID' };
|
return Promise.resolve({ error: 'Key must be UPRN or TOID' });
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBuildingById(id) {
|
function getBuildingById(id) {
|
@ -8,7 +8,7 @@ import { hydrate } from 'react-dom';
|
|||||||
|
|
||||||
import App from './frontend/app';
|
import App from './frontend/app';
|
||||||
|
|
||||||
const data = window.__PRELOADED_STATE__;
|
const data = (window as any).__PRELOADED_STATE__; // TODO: remove any
|
||||||
|
|
||||||
hydrate(
|
hydrate(
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
@ -15,10 +15,10 @@ const pgp = pg();
|
|||||||
// database connection (default to env vars)
|
// database connection (default to env vars)
|
||||||
const db = pgp({
|
const db = pgp({
|
||||||
'host': process.env.PGHOST,
|
'host': process.env.PGHOST,
|
||||||
'dbname': process.env.PGDATABASE,
|
'database': process.env.PGDATABASE,
|
||||||
'user': process.env.PGUSER,
|
'user': process.env.PGUSER,
|
||||||
'password': process.env.PGPASSWORD,
|
'password': process.env.PGPASSWORD,
|
||||||
'port': process.env.PGPORT
|
'port': parseInt(process.env.PGPORT)
|
||||||
});
|
});
|
||||||
|
|
||||||
export default db;
|
export default db;
|
@ -31,7 +31,13 @@ import { parseCategoryURL } from '../parse';
|
|||||||
* map or other pages are rendered, based on the URL. Use a react-router-dom <Link /> in
|
* map or other pages are rendered, based on the URL. Use a react-router-dom <Link /> in
|
||||||
* child components to navigate without a full page reload.
|
* child components to navigate without a full page reload.
|
||||||
*/
|
*/
|
||||||
class App extends React.Component {
|
class App extends React.Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
user: PropTypes.object,
|
||||||
|
building: PropTypes.object,
|
||||||
|
building_like: PropTypes.bool
|
||||||
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
// set building revision id, default 0
|
// set building revision id, default 0
|
||||||
@ -130,7 +136,7 @@ class App extends React.Component {
|
|||||||
colourBuilding(building) {
|
colourBuilding(building) {
|
||||||
const cat = parseCategoryURL(window.location.pathname);
|
const cat = parseCategoryURL(window.location.pathname);
|
||||||
const q = parse(window.location.search);
|
const q = parse(window.location.search);
|
||||||
const data = (cat === 'like')? {like: true}: JSON.parse(q.data);
|
const data = (cat === 'like')? {like: true}: JSON.parse(q.data as string); // TODO: verify what happens if data is string[]
|
||||||
if (cat === 'like'){
|
if (cat === 'like'){
|
||||||
this.likeBuilding(building.building_id)
|
this.likeBuilding(building.building_id)
|
||||||
} else {
|
} else {
|
||||||
@ -257,12 +263,6 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
App.propTypes = {
|
|
||||||
user: PropTypes.object,
|
|
||||||
building: PropTypes.object,
|
|
||||||
building_like: PropTypes.bool
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component to fall back on in case of 404 or no other match
|
* Component to fall back on in case of 404 or no other match
|
||||||
*/
|
*/
|
@ -47,17 +47,36 @@ BuildingEdit.propTypes = {
|
|||||||
building_id: PropTypes.number
|
building_id: PropTypes.number
|
||||||
}
|
}
|
||||||
|
|
||||||
class EditForm extends Component {
|
class EditForm extends Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
title: PropTypes.string,
|
||||||
|
slug: PropTypes.string,
|
||||||
|
cat: PropTypes.string,
|
||||||
|
help: PropTypes.string,
|
||||||
|
error: PropTypes.object,
|
||||||
|
like: PropTypes.bool,
|
||||||
|
building_like: PropTypes.bool,
|
||||||
|
selectBuilding: PropTypes.func,
|
||||||
|
building_id: PropTypes.number,
|
||||||
|
inactive: PropTypes.bool,
|
||||||
|
fields: PropTypes.array
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
// create object and spread into state to avoid TS complaining about modifying readonly state
|
||||||
|
let fieldsObj = {};
|
||||||
|
for (const field of props.fields) {
|
||||||
|
fieldsObj[field.slug] = props[field.slug];
|
||||||
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
error: this.props.error || undefined,
|
error: this.props.error || undefined,
|
||||||
like: this.props.like || undefined,
|
like: this.props.like || undefined,
|
||||||
copying: false,
|
copying: false,
|
||||||
keys_to_copy: {}
|
keys_to_copy: {},
|
||||||
}
|
...fieldsObj
|
||||||
for (const field of props.fields) {
|
|
||||||
this.state[field.slug] = props[field.slug]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
@ -353,20 +372,6 @@ class EditForm extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EditForm.propTypes = {
|
|
||||||
title: PropTypes.string,
|
|
||||||
slug: PropTypes.string,
|
|
||||||
cat: PropTypes.string,
|
|
||||||
help: PropTypes.string,
|
|
||||||
error: PropTypes.object,
|
|
||||||
like: PropTypes.bool,
|
|
||||||
building_like: PropTypes.bool,
|
|
||||||
selectBuilding: PropTypes.func,
|
|
||||||
building_id: PropTypes.number,
|
|
||||||
inactive: PropTypes.bool,
|
|
||||||
fields: PropTypes.array
|
|
||||||
}
|
|
||||||
|
|
||||||
const TextInput = (props) => (
|
const TextInput = (props) => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
||||||
@ -424,7 +429,20 @@ LongTextInput.propTypes = {
|
|||||||
handleChange: PropTypes.func
|
handleChange: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultiTextInput extends Component {
|
class MultiTextInput extends Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
slug: PropTypes.string,
|
||||||
|
title: PropTypes.string,
|
||||||
|
tooltip: PropTypes.string,
|
||||||
|
value: PropTypes.arrayOf(PropTypes.string),
|
||||||
|
placeholder: PropTypes.string,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
handleChange: PropTypes.func,
|
||||||
|
copy: PropTypes.bool,
|
||||||
|
toggleCopyAttribute: PropTypes.func,
|
||||||
|
copying: PropTypes.bool
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.edit = this.edit.bind(this);
|
this.edit = this.edit.bind(this);
|
||||||
@ -497,19 +515,6 @@ class MultiTextInput extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiTextInput.propTypes = {
|
|
||||||
slug: PropTypes.string,
|
|
||||||
title: PropTypes.string,
|
|
||||||
tooltip: PropTypes.string,
|
|
||||||
value: PropTypes.arrayOf(PropTypes.string),
|
|
||||||
placeholder: PropTypes.string,
|
|
||||||
disabled: PropTypes.bool,
|
|
||||||
handleChange: PropTypes.func,
|
|
||||||
copy: PropTypes.bool,
|
|
||||||
toggleCopyAttribute: PropTypes.func,
|
|
||||||
copying: PropTypes.bool
|
|
||||||
}
|
|
||||||
|
|
||||||
const TextListInput = (props) => (
|
const TextListInput = (props) => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
||||||
@ -521,7 +526,7 @@ const TextListInput = (props) => (
|
|||||||
id={props.slug} name={props.slug}
|
id={props.slug} name={props.slug}
|
||||||
value={props.value || ''}
|
value={props.value || ''}
|
||||||
disabled={props.disabled}
|
disabled={props.disabled}
|
||||||
list={`${props.slug}_suggestions`}
|
// list={`${props.slug}_suggestions`} TODO: investigate whether this was needed
|
||||||
onChange={props.handleChange}>
|
onChange={props.handleChange}>
|
||||||
<option value="">Select a source</option>
|
<option value="">Select a source</option>
|
||||||
{
|
{
|
||||||
@ -571,7 +576,22 @@ NumberInput.propTypes = {
|
|||||||
handleChange: PropTypes.func
|
handleChange: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
class YearEstimator extends Component {
|
class YearEstimator extends Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
slug: PropTypes.string,
|
||||||
|
title: PropTypes.string,
|
||||||
|
tooltip: PropTypes.string,
|
||||||
|
date_year: PropTypes.number,
|
||||||
|
date_upper: PropTypes.number,
|
||||||
|
date_lower: PropTypes.number,
|
||||||
|
value: PropTypes.number,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
handleChange: PropTypes.func,
|
||||||
|
copy: PropTypes.bool,
|
||||||
|
toggleCopyAttribute: PropTypes.func,
|
||||||
|
copying: PropTypes.bool
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -594,21 +614,6 @@ class YearEstimator extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
YearEstimator.propTypes = {
|
|
||||||
slug: PropTypes.string,
|
|
||||||
title: PropTypes.string,
|
|
||||||
tooltip: PropTypes.string,
|
|
||||||
date_year: PropTypes.number,
|
|
||||||
date_upper: PropTypes.number,
|
|
||||||
date_lower: PropTypes.number,
|
|
||||||
value: PropTypes.number,
|
|
||||||
disabled: PropTypes.bool,
|
|
||||||
handleChange: PropTypes.func,
|
|
||||||
copy: PropTypes.bool,
|
|
||||||
toggleCopyAttribute: PropTypes.func,
|
|
||||||
copying: PropTypes.bool
|
|
||||||
}
|
|
||||||
|
|
||||||
const CheckboxInput = (props) => (
|
const CheckboxInput = (props) => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
||||||
@ -675,7 +680,7 @@ LikeButton.propTypes = {
|
|||||||
handleLike: PropTypes.func
|
handleLike: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
const Label = (props) => {
|
const Label: React.SFC<any> = (props) => { // TODO: remove any
|
||||||
return (
|
return (
|
||||||
<label htmlFor={props.slug}>
|
<label htmlFor={props.slug}>
|
||||||
{props.title}
|
{props.title}
|
@ -46,7 +46,18 @@ BuildingView.propTypes = {
|
|||||||
building_like: PropTypes.bool
|
building_like: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataSection extends React.Component {
|
class DataSection extends React.Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
title: PropTypes.string,
|
||||||
|
cat: PropTypes.string,
|
||||||
|
slug: PropTypes.string,
|
||||||
|
intro: PropTypes.string,
|
||||||
|
help: PropTypes.string,
|
||||||
|
inactive: PropTypes.bool,
|
||||||
|
building_id: PropTypes.number,
|
||||||
|
children: PropTypes.node
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -194,18 +205,7 @@ class DataSection extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DataSection.propTypes = {
|
const DataEntry: React.SFC<any> = (props) => { // TODO: remove any
|
||||||
title: PropTypes.string,
|
|
||||||
cat: PropTypes.string,
|
|
||||||
slug: PropTypes.string,
|
|
||||||
intro: PropTypes.string,
|
|
||||||
help: PropTypes.string,
|
|
||||||
inactive: PropTypes.bool,
|
|
||||||
building_id: PropTypes.number,
|
|
||||||
children: PropTypes.node
|
|
||||||
}
|
|
||||||
|
|
||||||
const DataEntry = (props) => {
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<dt>
|
<dt>
|
||||||
@ -241,9 +241,9 @@ DataEntry.propTypes = {
|
|||||||
value: PropTypes.any
|
value: PropTypes.any
|
||||||
}
|
}
|
||||||
|
|
||||||
const LikeDataEntry = (props) => {
|
const LikeDataEntry: React.SFC<any> = (props) => { // TODO: remove any
|
||||||
const data_string = JSON.stringify({like: true});
|
const data_string = JSON.stringify({like: true});
|
||||||
(
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<dt>
|
<dt>
|
||||||
{ props.title }
|
{ props.title }
|
||||||
@ -280,7 +280,7 @@ LikeDataEntry.propTypes = {
|
|||||||
user_building_like: PropTypes.bool
|
user_building_like: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const MultiDataEntry = (props) => {
|
const MultiDataEntry: React.SFC<any> = (props) => { // TODO: remove any
|
||||||
let content;
|
let content;
|
||||||
|
|
||||||
if (props.value && props.value.length) {
|
if (props.value && props.value.length) {
|
@ -8,7 +8,13 @@ import './header.css';
|
|||||||
/**
|
/**
|
||||||
* Render the main header using a responsive design
|
* Render the main header using a responsive design
|
||||||
*/
|
*/
|
||||||
class Header extends React.Component {
|
class Header extends React.Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
user: PropTypes.shape({
|
||||||
|
username: PropTypes.string
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {collapseMenu: true};
|
this.state = {collapseMenu: true};
|
||||||
@ -106,10 +112,4 @@ class Header extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Header.propTypes = {
|
|
||||||
user: PropTypes.shape({
|
|
||||||
username: PropTypes.string
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Header;
|
export default Header;
|
@ -97,7 +97,12 @@ const LEGEND_CONFIG = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Legend extends React.Component {
|
class Legend extends React.Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
slug: PropTypes.string,
|
||||||
|
color: PropTypes.string,
|
||||||
|
text: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -195,11 +200,4 @@ class Legend extends React.Component {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Legend.propTypes = {
|
|
||||||
slug: PropTypes.string,
|
|
||||||
color: PropTypes.string,
|
|
||||||
text: PropTypes.string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Legend;
|
export default Legend;
|
@ -6,7 +6,12 @@ import ErrorBox from './error-box';
|
|||||||
import InfoBox from './info-box';
|
import InfoBox from './info-box';
|
||||||
import SupporterLogos from './supporter-logos';
|
import SupporterLogos from './supporter-logos';
|
||||||
|
|
||||||
class Login extends Component {
|
class Login extends Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
login: PropTypes.func,
|
||||||
|
user: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -127,9 +132,4 @@ class Login extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Login.propTypes = {
|
|
||||||
login: PropTypes.func,
|
|
||||||
user: PropTypes.object
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Login;
|
export default Login;
|
@ -16,8 +16,16 @@ const OS_API_KEY = 'NVUxtY5r8eA6eIfwrPTAGKrAAsoeI9E9';
|
|||||||
/**
|
/**
|
||||||
* Map area
|
* Map area
|
||||||
*/
|
*/
|
||||||
class ColouringMap extends Component {
|
class ColouringMap extends Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
building: PropTypes.object,
|
||||||
|
revision_id: PropTypes.number,
|
||||||
|
selectBuilding: PropTypes.func,
|
||||||
|
colourBuilding: PropTypes.func,
|
||||||
|
match: PropTypes.object,
|
||||||
|
history: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -167,13 +175,4 @@ class ColouringMap extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColouringMap.propTypes = {
|
|
||||||
building: PropTypes.object,
|
|
||||||
revision_id: PropTypes.number,
|
|
||||||
selectBuilding: PropTypes.func,
|
|
||||||
colourBuilding: PropTypes.func,
|
|
||||||
match: PropTypes.object,
|
|
||||||
history: PropTypes.object
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ColouringMap;
|
export default ColouringMap;
|
@ -35,7 +35,7 @@ const MultiEdit = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const q = parse(props.location.search);
|
const q = parse(props.location.search);
|
||||||
const data = JSON.parse(q.data)
|
const data = JSON.parse(q.data as string) // TODO: verify what happens when data is string[]
|
||||||
const title = sectionTitleFromCat(cat);
|
const title = sectionTitleFromCat(cat);
|
||||||
return (
|
return (
|
||||||
<Sidebar
|
<Sidebar
|
||||||
@ -116,7 +116,7 @@ function fieldTitleFromSlug(slug) {
|
|||||||
(prev, section) => {
|
(prev, section) => {
|
||||||
const el = prev.concat(
|
const el = prev.concat(
|
||||||
section.fields.filter(
|
section.fields.filter(
|
||||||
field => field.slug === slug
|
(field: any) => field.slug === slug // TODO: remove any
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return el
|
return el
|
@ -4,7 +4,19 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
import ErrorBox from './error-box';
|
import ErrorBox from './error-box';
|
||||||
|
|
||||||
class MyAccountPage extends Component {
|
class MyAccountPage extends Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
user: PropTypes.shape({
|
||||||
|
username: PropTypes.string,
|
||||||
|
email: PropTypes.string,
|
||||||
|
registered: PropTypes.instanceOf(Date), // TODO: check if fix correct
|
||||||
|
api_key: PropTypes.string,
|
||||||
|
error: PropTypes.object
|
||||||
|
}),
|
||||||
|
updateUser: PropTypes.func,
|
||||||
|
logout: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -110,16 +122,4 @@ class MyAccountPage extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MyAccountPage.propTypes = {
|
|
||||||
user: PropTypes.shape({
|
|
||||||
username: PropTypes.string,
|
|
||||||
email: PropTypes.string,
|
|
||||||
registered: PropTypes.date,
|
|
||||||
api_key: PropTypes.string,
|
|
||||||
error: PropTypes.object
|
|
||||||
}),
|
|
||||||
updateUser: PropTypes.func,
|
|
||||||
logout: PropTypes.func
|
|
||||||
}
|
|
||||||
|
|
||||||
export default MyAccountPage;
|
export default MyAccountPage;
|
@ -6,8 +6,12 @@ import { SearchIcon } from './icons';
|
|||||||
/**
|
/**
|
||||||
* Search for location
|
* Search for location
|
||||||
*/
|
*/
|
||||||
class SearchBox extends Component {
|
class SearchBox extends Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
onLocate: PropTypes.func,
|
||||||
|
isBuilding: PropTypes.bool
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -178,9 +182,4 @@ class SearchBox extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchBox.propTypes = {
|
|
||||||
onLocate: PropTypes.func,
|
|
||||||
isBuilding: PropTypes.bool
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SearchBox;
|
export default SearchBox;
|
@ -6,7 +6,12 @@ import ErrorBox from './error-box';
|
|||||||
import InfoBox from './info-box';
|
import InfoBox from './info-box';
|
||||||
import SupporterLogos from './supporter-logos';
|
import SupporterLogos from './supporter-logos';
|
||||||
|
|
||||||
class SignUp extends Component {
|
class SignUp extends Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
login: PropTypes.func.isRequired,
|
||||||
|
user: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -157,9 +162,4 @@ class SignUp extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SignUp.propTypes = {
|
|
||||||
login: PropTypes.func.isRequired,
|
|
||||||
user: PropTypes.object
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SignUp;
|
export default SignUp;
|
@ -4,7 +4,11 @@ import PropTypes from 'prop-types';
|
|||||||
import './tooltip.css';
|
import './tooltip.css';
|
||||||
import { InfoIcon } from './icons';
|
import { InfoIcon } from './icons';
|
||||||
|
|
||||||
class Tooltip extends Component {
|
class Tooltip extends Component<any, any> { // TODO: add proper types
|
||||||
|
static propTypes = { // TODO: generate propTypes from TS
|
||||||
|
text: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -44,8 +48,4 @@ class Tooltip extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Tooltip.propTypes = {
|
|
||||||
text: PropTypes.string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Tooltip;
|
export default Tooltip;
|
@ -10,12 +10,10 @@ const server = http.createServer(app);
|
|||||||
|
|
||||||
let currentApp = app;
|
let currentApp = app;
|
||||||
|
|
||||||
server.listen(process.env.PORT || 3000, error => {
|
server.listen(process.env.PORT || 3000, () => {
|
||||||
if (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('🚀 started');
|
console.log('🚀 started');
|
||||||
|
}).on('error', error => {
|
||||||
|
console.log(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
// In development mode, enable hot module reloading (HMR)
|
// In development mode, enable hot module reloading (HMR)
|
@ -48,7 +48,7 @@ server.use(bodyParser.json());
|
|||||||
|
|
||||||
// handle user sessions
|
// handle user sessions
|
||||||
const pgSession = pgConnect(session);
|
const pgSession = pgConnect(session);
|
||||||
const sess = {
|
const sess: any = { // TODO: remove any
|
||||||
name: 'cl.session',
|
name: 'cl.session',
|
||||||
store: new pgSession({
|
store: new pgSession({
|
||||||
pgPromise: db,
|
pgPromise: db,
|
||||||
@ -72,8 +72,8 @@ server.get('/*.html', frontendRoute);
|
|||||||
server.get('/', frontendRoute);
|
server.get('/', frontendRoute);
|
||||||
|
|
||||||
function frontendRoute(req, res) {
|
function frontendRoute(req, res) {
|
||||||
const context = {};
|
const context: any = {}; // TODO: remove any
|
||||||
const data = {};
|
const data: any = {}; // TODO: remove any
|
||||||
context.status = 200;
|
context.status = 200;
|
||||||
|
|
||||||
const userId = req.session.user_id;
|
const userId = req.session.user_id;
|
||||||
@ -339,7 +339,7 @@ server.post('/users', function (req, res) {
|
|||||||
|
|
||||||
// POST user auth
|
// POST user auth
|
||||||
server.post('/login', function (req, res) {
|
server.post('/login', function (req, res) {
|
||||||
authUser(req.body.username, req.body.password).then(function (user) {
|
authUser(req.body.username, req.body.password).then(function (user: any) { // TODO: remove any
|
||||||
if (user.user_id) {
|
if (user.user_id) {
|
||||||
req.session.user_id = user.user_id;
|
req.session.user_id = user.user_id;
|
||||||
} else {
|
} else {
|
16
app/tsconfig.json
Normal file
16
app/tsconfig.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./build",
|
||||||
|
"allowJs": true,
|
||||||
|
"target": "es2017",
|
||||||
|
"jsx": "react",
|
||||||
|
"lib": ["es6", "es2015", "es2017", "dom"],
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"noImplicitAny": false
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"./src/**/*"
|
||||||
|
]
|
||||||
|
}
|
5
app/tslint.json
Normal file
5
app/tslint.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"rules": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user