aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar muhamedsalih-tw <104364298+muhamedsalih-tw@users.noreply.github.com>2022-10-28 07:37:55 +0530
committerLibravatar GitHub <noreply@github.com>2022-10-28 02:07:55 +0000
commitd95573393206bc3931202d363bfb6c54974e0203 (patch)
treebd1428342f8d6124f747612a3711546a972108eb
parent6.2.1-nightly.31 [skip ci] (diff)
downloadferdium-app-d95573393206bc3931202d363bfb6c54974e0203.tar.gz
ferdium-app-d95573393206bc3931202d363bfb6c54974e0203.tar.zst
ferdium-app-d95573393206bc3931202d363bfb6c54974e0203.zip
Transform welcome component tree to TS (#715)v6.2.1-nightly.31
-rw-r--r--src/components/auth/Welcome.tsx (renamed from src/components/auth/Welcome.jsx)61
-rw-r--r--src/components/ui/Link.js86
-rw-r--r--src/components/ui/Link.tsx73
-rw-r--r--src/components/ui/button/index.tsx76
-rw-r--r--src/components/ui/input/index.tsx2
-rw-r--r--src/containers/auth/WelcomeScreen.tsx15
-rw-r--r--src/helpers/array-helpers.ts4
7 files changed, 153 insertions, 164 deletions
diff --git a/src/components/auth/Welcome.jsx b/src/components/auth/Welcome.tsx
index 9e5d10126..1aa8da4d6 100644
--- a/src/components/auth/Welcome.jsx
+++ b/src/components/auth/Welcome.tsx
@@ -1,14 +1,14 @@
1/* eslint jsx-a11y/anchor-is-valid: 0 */ 1import { Component, ReactElement } from 'react';
2import { Component } from 'react'; 2import { observer, inject } from 'mobx-react';
3import PropTypes from 'prop-types'; 3import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
4import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; 4import { noop } from 'lodash';
5import { defineMessages, injectIntl } from 'react-intl';
6import serverlessLogin from '../../helpers/serverless-helpers'; 5import serverlessLogin from '../../helpers/serverless-helpers';
7import shuffleArray from '../../helpers/array-helpers'; 6import shuffleArray from '../../helpers/array-helpers';
8import { serverName } from '../../api/apiBase'; 7import { serverName } from '../../api/apiBase';
9
10import Link from '../ui/Link'; 8import Link from '../ui/Link';
11import { H1 } from '../ui/headline'; 9import { H1 } from '../ui/headline';
10import { StoresProps } from '../../@types/ferdium-components.types';
11import RecipePreview from '../../models/RecipePreview';
12 12
13const messages = defineMessages({ 13const messages = defineMessages({
14 signupButton: { 14 signupButton: {
@@ -34,24 +34,28 @@ const messages = defineMessages({
34 }, 34 },
35}); 35});
36 36
37class Welcome extends Component { 37interface IProps extends Partial<StoresProps>, WrappedComponentProps {
38 static propTypes = { 38 loginRoute: string;
39 loginRoute: PropTypes.string.isRequired, 39 signupRoute: string;
40 signupRoute: PropTypes.string.isRequired, 40 changeServerRoute: string;
41 changeServerRoute: PropTypes.string.isRequired, 41 recipes: RecipePreview[];
42 recipes: MobxPropTypes.arrayOrObservableArray.isRequired, 42}
43 actions: PropTypes.object.isRequired,
44 };
45 43
46 useLocalServer() { 44@inject('actions')
45@observer
46class Welcome extends Component<IProps> {
47 constructor(props: IProps) {
48 super(props);
49 }
50
51 useLocalServer(): void {
47 serverlessLogin(this.props.actions); 52 serverlessLogin(this.props.actions);
48 } 53 }
49 54
50 render() { 55 render(): ReactElement {
51 const { intl } = this.props; 56 const { loginRoute, signupRoute, changeServerRoute, intl } = this.props;
52 const { loginRoute, signupRoute, changeServerRoute } = this.props;
53 let { recipes } = this.props; 57 let { recipes } = this.props;
54 recipes = shuffleArray(recipes); 58 recipes = shuffleArray<RecipePreview>(recipes);
55 recipes.length = 8 * 2; 59 recipes.length = 8 * 2;
56 60
57 let serverNameParse = serverName(); 61 let serverNameParse = serverName();
@@ -87,17 +91,22 @@ class Welcome extends Component {
87 <span>{intl.formatMessage(messages.changeServer)}</span> 91 <span>{intl.formatMessage(messages.changeServer)}</span>
88 </Link> 92 </Link>
89 </div> 93 </div>
90 <br /> 94 <hr
91 <hr /> 95 className="settings__hr-sections"
92 <br /> 96 style={{ marginTop: 24, marginBottom: 24, borderStyle: 'solid' }}
93 <a className="button" onClick={this.useLocalServer.bind(this)}> 97 />
98 <button
99 className="button"
100 onClick={this.useLocalServer.bind(this)}
101 onKeyDown={noop}
102 >
94 {intl.formatMessage(messages.serverless)} 103 {intl.formatMessage(messages.serverless)}
95 </a> 104 </button>
96 </div> 105 </div>
97 <div className="welcome__featured-services"> 106 <div className="welcome__featured-services">
98 {recipes.map(recipe => ( 107 {recipes.map(recipe => (
99 <div key={recipe.id} className="welcome__featured-service"> 108 <div key={recipe.id} className="welcome__featured-service">
100 <img key={recipe.id} src={recipe.icons.svg} alt="" /> 109 <img key={recipe.id} src={recipe.icons?.svg} alt="" />
101 </div> 110 </div>
102 ))} 111 ))}
103 </div> 112 </div>
@@ -106,4 +115,4 @@ class Welcome extends Component {
106 } 115 }
107} 116}
108 117
109export default injectIntl(inject('actions')(observer(Welcome))); 118export default injectIntl(Welcome);
diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js
deleted file mode 100644
index 714fc5a68..000000000
--- a/src/components/ui/Link.js
+++ /dev/null
@@ -1,86 +0,0 @@
1import { Component } from 'react';
2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react';
4import { RouterStore } from '@superwf/mobx-react-router';
5import classnames from 'classnames';
6
7import { oneOrManyChildElements } from '../../prop-types';
8import matchRoute from '../../helpers/routing-helpers';
9import { openExternalUrl } from '../../helpers/url-helpers';
10
11// Should this file be converted into the coding style similar to './toggle/index.tsx'?
12// TODO: create container component for this component
13class Link extends Component {
14 onClick(e) {
15 if (this.props.disabled) {
16 e.preventDefault();
17 } else if (this.props.target === '_blank') {
18 e.preventDefault();
19 openExternalUrl(this.props.to, true);
20 }
21 // Note: if neither of the above, then let the other onClick handlers process it
22 }
23
24 render() {
25 const {
26 children,
27 stores,
28 to,
29 className,
30 activeClassName,
31 strictFilter,
32 style,
33 } = this.props;
34 const { router } = stores;
35
36 let filter = `${to}(*action)`;
37 if (strictFilter) {
38 filter = `${to}`;
39 }
40
41 const match = matchRoute(filter, router.location.pathname);
42
43 const linkClasses = classnames({
44 [`${className}`]: true,
45 [`${activeClassName}`]: match,
46 'is-disabled': this.props.disabled,
47 });
48
49 return (
50 <a
51 href={router.history.createHref(to)}
52 className={linkClasses}
53 style={style}
54 onClick={e => this.onClick(e)}
55 >
56 {children}
57 </a>
58 );
59 }
60}
61
62Link.propTypes = {
63 stores: PropTypes.shape({
64 router: PropTypes.instanceOf(RouterStore).isRequired,
65 }).isRequired,
66 children: PropTypes.oneOfType([oneOrManyChildElements, PropTypes.string])
67 .isRequired,
68 to: PropTypes.string.isRequired,
69 className: PropTypes.string,
70 activeClassName: PropTypes.string,
71 strictFilter: PropTypes.bool,
72 target: PropTypes.string,
73 style: PropTypes.object,
74 disabled: PropTypes.bool,
75};
76
77Link.defaultProps = {
78 className: '',
79 activeClassName: '',
80 strictFilter: false,
81 disabled: false,
82 target: '',
83 style: {},
84};
85
86export default inject('stores')(observer(Link));
diff --git a/src/components/ui/Link.tsx b/src/components/ui/Link.tsx
new file mode 100644
index 000000000..b5890ebd1
--- /dev/null
+++ b/src/components/ui/Link.tsx
@@ -0,0 +1,73 @@
1import { Component, CSSProperties, ReactNode, MouseEvent } from 'react';
2import { inject, observer } from 'mobx-react';
3import classnames from 'classnames';
4import matchRoute from '../../helpers/routing-helpers';
5import { openExternalUrl } from '../../helpers/url-helpers';
6import { StoresProps } from '../../@types/ferdium-components.types';
7
8interface IProps extends Partial<StoresProps> {
9 children: ReactNode;
10 to: string;
11 className?: string;
12 activeClassName?: string;
13 strictFilter?: boolean;
14 target?: string;
15 style?: CSSProperties;
16 disabled?: boolean;
17}
18
19// TODO: create container component for this component
20@inject('stores')
21@observer
22class Link extends Component<IProps> {
23 constructor(props: IProps) {
24 super(props);
25 }
26
27 onClick(e: MouseEvent<HTMLAnchorElement>): void {
28 const { disabled = false, target = '', to } = this.props;
29 if (disabled) {
30 e.preventDefault();
31 } else if (target === '_blank') {
32 e.preventDefault();
33 openExternalUrl(to, true);
34 }
35 // Note: if neither of the above, then let the other onClick handlers process it
36 }
37
38 render() {
39 const {
40 children,
41 stores,
42 to,
43 className = '',
44 activeClassName = '',
45 strictFilter = false,
46 disabled = false,
47 style = {},
48 } = this.props;
49 const { router } = stores!;
50
51 const filter = strictFilter ? `${to}` : `${to}(*action)`;
52 const match = matchRoute(filter, router.location.pathname);
53
54 const linkClasses = classnames({
55 [`${className}`]: true,
56 [`${activeClassName}`]: match,
57 'is-disabled': disabled,
58 });
59
60 return (
61 <a
62 href={router.history.createHref(to)}
63 className={linkClasses}
64 style={style}
65 onClick={e => this.onClick(e)}
66 >
67 {children}
68 </a>
69 );
70 }
71}
72
73export default Link;
diff --git a/src/components/ui/button/index.tsx b/src/components/ui/button/index.tsx
index a8bbfe730..c1e647bc0 100644
--- a/src/components/ui/button/index.tsx
+++ b/src/components/ui/button/index.tsx
@@ -1,10 +1,10 @@
1import Icon from '@mdi/react'; 1import Icon from '@mdi/react';
2import classnames from 'classnames'; 2import classnames from 'classnames';
3import { Property } from 'csstype'; 3import { Property } from 'csstype';
4import { noop } from 'lodash';
4import { Component, MouseEvent } from 'react'; 5import { Component, MouseEvent } from 'react';
5import withStyles, { WithStylesProps } from 'react-jss'; 6import withStyles, { WithStylesProps } from 'react-jss';
6import Loader from 'react-loader'; 7import Loader from 'react-loader';
7
8import { Theme } from '../../../themes'; 8import { Theme } from '../../../themes';
9import { IFormField } from '../typings/generic'; 9import { IFormField } from '../typings/generic';
10 10
@@ -16,24 +16,6 @@ type ButtonType =
16 | 'warning' 16 | 'warning'
17 | 'inverted'; 17 | 'inverted';
18 18
19interface IProps extends IFormField, WithStylesProps<typeof styles> {
20 className?: string;
21 label?: string;
22 disabled?: boolean;
23 id?: string;
24 type?: 'button' | 'reset' | 'submit' | undefined;
25 onClick: (
26 event: MouseEvent<HTMLButtonElement> | MouseEvent<HTMLAnchorElement>,
27 ) => void;
28 buttonType?: ButtonType;
29 loaded?: boolean;
30 busy?: boolean;
31 icon?: string;
32 href?: string;
33 target?: string;
34 htmlForm?: string;
35}
36
37let buttonTransition: string = 'none'; 19let buttonTransition: string = 'none';
38let loaderContainerTransition: string = 'none'; 20let loaderContainerTransition: string = 'none';
39 21
@@ -148,38 +130,38 @@ const styles = (theme: Theme) => ({
148 }, 130 },
149}); 131});
150 132
151class ButtonComponent extends Component<IProps> { 133interface IProps extends IFormField, WithStylesProps<typeof styles> {
152 customDefaultProps: { 134 className?: string;
153 disabled: boolean; 135 label?: string;
154 type: 'button' | 'reset' | 'submit' | undefined; 136 disabled?: boolean;
155 onClick: ( 137 id?: string;
156 event: MouseEvent<HTMLButtonElement> | MouseEvent<HTMLAnchorElement>, 138 type?: 'button' | 'reset' | 'submit' | undefined;
157 ) => void; 139 onClick: (event: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;
158 buttonType: ButtonType; 140 buttonType?: ButtonType;
159 busy: boolean; 141 loaded?: boolean;
160 } = { 142 busy?: boolean;
161 type: 'button', 143 icon?: string;
162 disabled: false, 144 href?: string;
163 onClick: () => null, 145 target?: string;
164 buttonType: 'primary' as ButtonType, 146 htmlForm?: string;
165 busy: false, 147}
166 };
167 148
168 state = { 149interface IState {
169 busy: false, 150 busy: boolean;
170 }; 151}
171 152
153class ButtonComponent extends Component<IProps, IState> {
172 constructor(props: IProps) { 154 constructor(props: IProps) {
173 super(props); 155 super(props);
174 156
175 this.state = { 157 this.state = {
176 busy: props.busy || false, 158 busy: this.props.busy || false,
177 }; 159 };
178 } 160 }
179 161
180 static getDerivedStateFromProps(nextProps: IProps) { 162 static getDerivedStateFromProps(nextProps: IProps): IState {
181 return { 163 return {
182 busy: nextProps.busy, 164 busy: nextProps.busy || false,
183 }; 165 };
184 } 166 }
185 167
@@ -188,27 +170,29 @@ class ButtonComponent extends Component<IProps> {
188 classes, 170 classes,
189 className, 171 className,
190 // theme, 172 // theme,
191 disabled,
192 id, 173 id,
193 label, 174 label,
194 type,
195 onClick,
196 buttonType,
197 loaded, 175 loaded,
198 icon, 176 icon,
199 href, 177 href,
200 target, 178 target,
201 htmlForm, 179 htmlForm,
202 } = { ...this.customDefaultProps, ...this.props }; 180 type = 'button',
181 disabled = false,
182 onClick = noop,
183 buttonType = 'primary' as ButtonType,
184 } = this.props;
203 185
204 const { busy } = this.state; 186 const { busy } = this.state;
205 let showLoader = false; 187 let showLoader = false;
188
206 if (loaded) { 189 if (loaded) {
207 showLoader = !loaded; 190 showLoader = !loaded;
208 console.warn( 191 console.warn(
209 'Ferdium Button prop `loaded` will be deprecated in the future. Please use `busy` instead', 192 'Ferdium Button prop `loaded` will be deprecated in the future. Please use `busy` instead',
210 ); 193 );
211 } 194 }
195
212 if (busy) { 196 if (busy) {
213 showLoader = busy; 197 showLoader = busy;
214 } 198 }
diff --git a/src/components/ui/input/index.tsx b/src/components/ui/input/index.tsx
index b19bb4bc9..3bafc93e7 100644
--- a/src/components/ui/input/index.tsx
+++ b/src/components/ui/input/index.tsx
@@ -106,6 +106,7 @@ class InputComponent extends Component<IProps, IState> {
106 showPasswordToggle = false, 106 showPasswordToggle = false,
107 type = 'text', 107 type = 'text',
108 disabled = false, 108 disabled = false,
109 readOnly,
109 } = this.props; 110 } = this.props;
110 111
111 const { showPassword, passwordScore } = this.state; 112 const { showPassword, passwordScore } = this.state;
@@ -152,6 +153,7 @@ class InputComponent extends Component<IProps, IState> {
152 min={min} 153 min={min}
153 max={max} 154 max={max}
154 step={step} 155 step={step}
156 readOnly={readOnly}
155 /> 157 />
156 {suffix && <span className={classes.suffix}>{suffix}</span>} 158 {suffix && <span className={classes.suffix}>{suffix}</span>}
157 {showPasswordToggle && ( 159 {showPasswordToggle && (
diff --git a/src/containers/auth/WelcomeScreen.tsx b/src/containers/auth/WelcomeScreen.tsx
index c03319179..561eef236 100644
--- a/src/containers/auth/WelcomeScreen.tsx
+++ b/src/containers/auth/WelcomeScreen.tsx
@@ -1,12 +1,19 @@
1import { Component, ReactElement } from 'react'; 1import { Component, ReactElement } from 'react';
2import { inject, observer } from 'mobx-react'; 2import { inject, observer } from 'mobx-react';
3
4import { StoresProps } from '../../@types/ferdium-components.types'; 3import { StoresProps } from '../../@types/ferdium-components.types';
5import Welcome from '../../components/auth/Welcome'; 4import Welcome from '../../components/auth/Welcome';
6 5
7class WelcomeScreen extends Component<StoresProps> { 6interface IProps extends Partial<StoresProps> {}
7
8@inject('stores', 'actions')
9@observer
10class WelcomeScreen extends Component<IProps> {
11 constructor(props: IProps) {
12 super(props);
13 }
14
8 render(): ReactElement { 15 render(): ReactElement {
9 const { user, recipePreviews } = this.props.stores; 16 const { user, recipePreviews } = this.props.stores!;
10 17
11 return ( 18 return (
12 <Welcome 19 <Welcome
@@ -19,4 +26,4 @@ class WelcomeScreen extends Component<StoresProps> {
19 } 26 }
20} 27}
21 28
22export default inject('stores', 'actions')(observer(WelcomeScreen)); 29export default WelcomeScreen;
diff --git a/src/helpers/array-helpers.ts b/src/helpers/array-helpers.ts
index 33be12fa7..ffb584eab 100644
--- a/src/helpers/array-helpers.ts
+++ b/src/helpers/array-helpers.ts
@@ -1,6 +1,6 @@
1export default function shuffleArray(arr: any[]): any[] { 1export default function shuffleArray<T>(arr: T[]): T[] {
2 return arr 2 return arr
3 .map(a => [Math.random(), a]) 3 .map(a => [Math.random(), a] as [number, T])
4 .sort((a, b) => a[0] - b[0]) 4 .sort((a, b) => a[0] - b[0])
5 .map(a => a[1]); 5 .map(a => a[1]);
6} 6}