mirror of
https://github.com/koodiklinikka/koodiklinikka.fi.git
synced 2026-01-26 03:14:08 +00:00
Chore/convert to typescript (#60)
* Convert to using TypeScript Next.js v.9 allows converting an existing project to TS by simply renaming the files as TS files * Fix type errors: Type 'string' is not assignable to type 'number'. * Add mention about missing typings for javascript-time-ago * Add GA_INITIALIZED to window * Fix type error in feed transformers * Model MembershipInfoForm state and props with TS * Silence the typescript warning in MembershipInfoForm * Add threshold to Fader props * Fix Warning: Each child in a list should have a unique "key" prop. Sponsors don't have ids – name is probably unique and can be used as a key * Allow key as prop for SponsorLink * Add type of the props for SponsorLink
This commit is contained in:
committed by
Riku Rouvila
parent
bcc6619aee
commit
f4474523ad
@@ -1,10 +1,14 @@
|
||||
import React from "react";
|
||||
|
||||
type Props = {
|
||||
threshold: number;
|
||||
};
|
||||
|
||||
function clamp(min, max, value) {
|
||||
return Math.min(Math.max(value, min), max);
|
||||
}
|
||||
|
||||
export default class Fader extends React.Component {
|
||||
export default class Fader extends React.Component<Props> {
|
||||
static defaultProps = {
|
||||
threshold: 100,
|
||||
};
|
||||
@@ -8,7 +8,8 @@ import ReactTimeAgo from "react-time-ago";
|
||||
import JavascriptTimeAgo from "javascript-time-ago";
|
||||
import timeagoFi from "javascript-time-ago/locale/fi";
|
||||
|
||||
JavascriptTimeAgo.locale(timeagoFi);
|
||||
// TODO: Add type definitions for javascript-time-ago
|
||||
(JavascriptTimeAgo as any).locale(timeagoFi);
|
||||
|
||||
export default class Feed extends React.Component {
|
||||
state = {
|
||||
@@ -41,7 +42,7 @@ export default class Feed extends React.Component {
|
||||
target="_blank"
|
||||
href={message.imageLink}
|
||||
rel="noopener noreferrer"
|
||||
tabIndex="-1"
|
||||
tabIndex={-1}
|
||||
>
|
||||
{image}
|
||||
</a>
|
||||
@@ -1,7 +1,14 @@
|
||||
import React from "react";
|
||||
import EmailComponent from "./EmailComponent";
|
||||
import sponsors from "../data/sponsors";
|
||||
const SponsorLink = ({ href, name }) => (
|
||||
|
||||
type Props = {
|
||||
href: string;
|
||||
name: string;
|
||||
key: string;
|
||||
};
|
||||
|
||||
const SponsorLink = ({ href, name }: Props) => (
|
||||
<a href={href} target="_blank" rel="noopener noreferrer">
|
||||
<img
|
||||
src={`/static/images/sponsors/${name.toLowerCase()}.svg`}
|
||||
@@ -33,7 +33,7 @@ export default class Members extends React.Component {
|
||||
href="https://github.com/koodiklinikka"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
tabIndex="-1"
|
||||
tabIndex={-1}
|
||||
>
|
||||
{members}
|
||||
</a>
|
||||
@@ -16,7 +16,8 @@ export default {
|
||||
return items.filter(isVisibleGithubEvent).map(item => {
|
||||
const template = lodashTemplate(
|
||||
githubEvent.parse(item).text,
|
||||
templateSettings
|
||||
templateSettings,
|
||||
false
|
||||
);
|
||||
|
||||
const repository = `https://github.com/${item.repo.name}`;
|
||||
@@ -1,10 +1,28 @@
|
||||
import pick from "lodash/pick";
|
||||
import request from "axios";
|
||||
import React from "react";
|
||||
import classSet from "classnames";
|
||||
import api from "../api";
|
||||
import Loader from "../Loader";
|
||||
|
||||
type Props = {
|
||||
onSignupSuccess: () => void;
|
||||
};
|
||||
|
||||
type State = {
|
||||
error: boolean;
|
||||
errors: string[];
|
||||
fields: {
|
||||
name: string;
|
||||
email: string;
|
||||
handle: string;
|
||||
address: string;
|
||||
postcode: string;
|
||||
city: string;
|
||||
};
|
||||
sending: boolean;
|
||||
pristineFields: string[];
|
||||
};
|
||||
|
||||
const fieldNameTranslations = {
|
||||
address: { fi: "Osoite" },
|
||||
city: { fi: "Paikkakunta" },
|
||||
@@ -20,23 +38,26 @@ function validateEmail(email) {
|
||||
return mailValidateRe.test(email);
|
||||
}
|
||||
|
||||
const fieldNames = ["name", "email", "handle", "address", "postcode", "city"];
|
||||
|
||||
function getUserInfo(state) {
|
||||
return pick(state, fieldNames);
|
||||
return state.fields;
|
||||
}
|
||||
|
||||
export default class MembershipInfoForm extends React.Component {
|
||||
state = {
|
||||
address: "",
|
||||
city: "",
|
||||
email: "",
|
||||
handle: "",
|
||||
name: "",
|
||||
postcode: "",
|
||||
sending: false,
|
||||
pristineFields: fieldNames,
|
||||
};
|
||||
export default class MembershipInfoForm extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.setState({
|
||||
fields: {
|
||||
address: "",
|
||||
city: "",
|
||||
email: "",
|
||||
handle: "",
|
||||
name: "",
|
||||
postcode: "",
|
||||
},
|
||||
sending: false,
|
||||
pristineFields: Object.keys(this.state.fields),
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit = async () => {
|
||||
this.setState({
|
||||
@@ -62,7 +83,10 @@ export default class MembershipInfoForm extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
[e.target.name]: e.target.value,
|
||||
fields: {
|
||||
...this.state.fields,
|
||||
[name]: e.target.value,
|
||||
},
|
||||
pristineFields: this.state.pristineFields.filter(
|
||||
fieldName => fieldName !== name
|
||||
),
|
||||
@@ -73,13 +97,13 @@ export default class MembershipInfoForm extends React.Component {
|
||||
getDataErrors = () => {
|
||||
const foundErrors = [];
|
||||
|
||||
fieldNames.forEach(fieldName => {
|
||||
Object.keys(this.state.fields).forEach(fieldName => {
|
||||
if (!this.state[fieldName]) {
|
||||
foundErrors.push({ field: fieldName, type: "missing" });
|
||||
}
|
||||
});
|
||||
|
||||
if (this.state.email && !validateEmail(this.state.email)) {
|
||||
if (this.state.fields.email && !validateEmail(this.state.fields.email)) {
|
||||
foundErrors.push({ field: "email", type: "invalid" });
|
||||
}
|
||||
|
||||
@@ -119,7 +143,7 @@ export default class MembershipInfoForm extends React.Component {
|
||||
|
||||
const fieldsWithErrors = visibleErrors.map(({ field }) => field);
|
||||
|
||||
const inputFields = fieldNames.map(fieldName => {
|
||||
const inputFields = Object.keys(this.state.fields).map(fieldName => {
|
||||
const inputClasses = classSet({
|
||||
input: true,
|
||||
"has-error": fieldsWithErrors.includes(fieldName),
|
||||
2
next-env.d.ts
vendored
Normal file
2
next-env.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
||||
34
package-lock.json
generated
34
package-lock.json
generated
@@ -1089,6 +1089,28 @@
|
||||
"resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz",
|
||||
"integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "12.12.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.5.tgz",
|
||||
"integrity": "sha512-KEjODidV4XYUlJBF3XdjSH5FWoMCtO0utnhtdLf1AgeuZLOrRbvmU/gaRCVg7ZaQDjVf3l84egiY0mRNe5xE4A==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/prop-types": {
|
||||
"version": "15.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
|
||||
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "16.9.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.11.tgz",
|
||||
"integrity": "sha512-UBT4GZ3PokTXSWmdgC/GeCGEJXE5ofWyibCcecRLUVN2ZBpXQGVgQGtG2foS7CrTKFKlQVVswLvf7Js6XA/CVQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/ast": {
|
||||
"version": "1.8.5",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
|
||||
@@ -2942,6 +2964,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"csstype": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.7.tgz",
|
||||
"integrity": "sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ==",
|
||||
"dev": true
|
||||
},
|
||||
"cyclist": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
|
||||
@@ -10318,6 +10346,12 @@
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.6.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.4.tgz",
|
||||
"integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==",
|
||||
"dev": true
|
||||
},
|
||||
"ua-parser-js": {
|
||||
"version": "0.7.20",
|
||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.20.tgz",
|
||||
|
||||
@@ -33,12 +33,15 @@
|
||||
"twitter-text": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "12.12.5",
|
||||
"@types/react": "16.9.11",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"eslint": "^6.6.0",
|
||||
"eslint-config-prettier": "^6.5.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||
"eslint-plugin-react": "^7.16.0",
|
||||
"prettier": "^1.18.2"
|
||||
"prettier": "^1.18.2",
|
||||
"typescript": "3.6.4"
|
||||
},
|
||||
"prettier": {
|
||||
"trailingComma": "es5"
|
||||
|
||||
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"typeRoots": ["./node_modules/@types", "./typings"],
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "./typings/*"]
|
||||
}
|
||||
3
typings/global.d.ts
vendored
Normal file
3
typings/global.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
interface Window {
|
||||
GA_INITIALIZED: boolean;
|
||||
}
|
||||
Reference in New Issue
Block a user