aboutsummaryrefslogtreecommitdiffstats
path: root/src/components
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2018-01-17 10:34:22 +0400
committerLibravatar GitHub <noreply@github.com>2018-01-17 10:34:22 +0400
commit81b49fba430959ec4e0946f905dc182d2733831c (patch)
treea1979dafda41ac804986ef57a68912a868cb5ac7 /src/components
parentRemove idle timer dependency (diff)
parentMerge branch 'develop' of github.com:meetfranz/franz into develop (diff)
downloadferdium-app-81b49fba430959ec4e0946f905dc182d2733831c.tar.gz
ferdium-app-81b49fba430959ec4e0946f905dc182d2733831c.tar.zst
ferdium-app-81b49fba430959ec4e0946f905dc182d2733831c.zip
Merge branch 'develop' into feature/remove-miner
Diffstat (limited to 'src/components')
-rw-r--r--src/components/settings/recipes/RecipesDashboard.js20
-rw-r--r--src/components/settings/services/EditServiceForm.js77
-rw-r--r--src/components/settings/services/ServicesDashboard.js42
-rw-r--r--src/components/settings/settings/EditSettingsForm.js38
-rw-r--r--src/components/ui/ImageUpload.js108
-rw-r--r--src/components/ui/SearchInput.js48
6 files changed, 262 insertions, 71 deletions
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js
index b6ade5da4..4610c69a5 100644
--- a/src/components/settings/recipes/RecipesDashboard.js
+++ b/src/components/settings/recipes/RecipesDashboard.js
@@ -16,6 +16,10 @@ const messages = defineMessages({
16 id: 'settings.recipes.headline', 16 id: 'settings.recipes.headline',
17 defaultMessage: '!!!Available Services', 17 defaultMessage: '!!!Available Services',
18 }, 18 },
19 searchService: {
20 id: 'settings.searchService',
21 defaultMessage: '!!!Search service',
22 },
19 mostPopularRecipes: { 23 mostPopularRecipes: {
20 id: 'settings.recipes.mostPopular', 24 id: 'settings.recipes.mostPopular',
21 defaultMessage: '!!!Most popular', 25 defaultMessage: '!!!Most popular',
@@ -81,13 +85,7 @@ export default class RecipesDashboard extends Component {
81 return ( 85 return (
82 <div className="settings__main"> 86 <div className="settings__main">
83 <div className="settings__header"> 87 <div className="settings__header">
84 <SearchInput 88 <h1>{intl.formatMessage(messages.headline)}</h1>
85 className="settings__search-header"
86 defaultValue={intl.formatMessage(messages.headline)}
87 onChange={e => searchRecipes(e)}
88 onReset={() => resetSearch()}
89 throttle
90 />
91 </div> 89 </div>
92 <div className="settings__body recipes"> 90 <div className="settings__body recipes">
93 {serviceStatus.length > 0 && serviceStatus.includes('created') && ( 91 {serviceStatus.length > 0 && serviceStatus.includes('created') && (
@@ -101,7 +99,13 @@ export default class RecipesDashboard extends Component {
101 </Infobox> 99 </Infobox>
102 </Appear> 100 </Appear>
103 )} 101 )}
104 {/* {!searchNeedle && ( */} 102 <SearchInput
103 placeholder={intl.formatMessage(messages.searchService)}
104 onChange={e => searchRecipes(e)}
105 onReset={() => resetSearch()}
106 autoFocus
107 throttle
108 />
105 <div className="recipes__navigation"> 109 <div className="recipes__navigation">
106 <Link 110 <Link
107 to="/settings/recipes" 111 to="/settings/recipes"
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index 4458c4c5a..f6f2df2f3 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -13,6 +13,7 @@ import Tabs, { TabItem } from '../../ui/Tabs';
13import Input from '../../ui/Input'; 13import Input from '../../ui/Input';
14import Toggle from '../../ui/Toggle'; 14import Toggle from '../../ui/Toggle';
15import Button from '../../ui/Button'; 15import Button from '../../ui/Button';
16import ImageUpload from '../../ui/ImageUpload';
16 17
17const messages = defineMessages({ 18const messages = defineMessages({
18 saveService: { 19 saveService: {
@@ -77,12 +78,20 @@ const messages = defineMessages({
77 }, 78 },
78 headlineBadges: { 79 headlineBadges: {
79 id: 'settings.service.form.headlineBadges', 80 id: 'settings.service.form.headlineBadges',
80 defaultMessage: '!!!Unread message dadges', 81 defaultMessage: '!!!Unread message badges',
81 }, 82 },
82 headlineGeneral: { 83 headlineGeneral: {
83 id: 'settings.service.form.headlineGeneral', 84 id: 'settings.service.form.headlineGeneral',
84 defaultMessage: '!!!General', 85 defaultMessage: '!!!General',
85 }, 86 },
87 iconDelete: {
88 id: 'settings.service.form.iconDelete',
89 defaultMessage: '!!!Delete',
90 },
91 iconUpload: {
92 id: 'settings.service.form.iconUpload',
93 defaultMessage: '!!!Drop your image, or click here',
94 },
86}); 95});
87 96
88@observer 97@observer
@@ -126,6 +135,11 @@ export default class EditServiceForm extends Component {
126 const values = form.values(); 135 const values = form.values();
127 let isValid = true; 136 let isValid = true;
128 137
138 const files = form.$('customIcon').files;
139 if (files) {
140 values.iconFile = files[0];
141 }
142
129 if (recipe.validateUrl && values.customUrl) { 143 if (recipe.validateUrl && values.customUrl) {
130 this.setState({ isValidatingCustomUrl: true }); 144 this.setState({ isValidatingCustomUrl: true });
131 try { 145 try {
@@ -217,7 +231,9 @@ export default class EditServiceForm extends Component {
217 </div> 231 </div>
218 <div className="settings__body"> 232 <div className="settings__body">
219 <form onSubmit={e => this.submit(e)} id="form"> 233 <form onSubmit={e => this.submit(e)} id="form">
220 <Input field={form.$('name')} focus /> 234 <div className="service-name">
235 <Input field={form.$('name')} focus />
236 </div>
221 {(recipe.hasTeamId || recipe.hasCustomUrl) && ( 237 {(recipe.hasTeamId || recipe.hasCustomUrl) && (
222 <Tabs 238 <Tabs
223 active={activeTabIndex} 239 active={activeTabIndex}
@@ -261,32 +277,41 @@ export default class EditServiceForm extends Component {
261 )} 277 )}
262 </Tabs> 278 </Tabs>
263 )} 279 )}
264 <div className="settings__options"> 280 <div className="service-flex-grid">
265 <div className="settings__settings-group"> 281 <div className="settings__options">
266 <h3>{intl.formatMessage(messages.headlineNotifications)}</h3> 282 <div className="settings__settings-group">
267 <Toggle field={form.$('isNotificationEnabled')} /> 283 <h3>{intl.formatMessage(messages.headlineNotifications)}</h3>
268 <Toggle field={form.$('isMuted')} /> 284 <Toggle field={form.$('isNotificationEnabled')} />
269 <p className="settings__help"> 285 <Toggle field={form.$('isMuted')} />
270 {intl.formatMessage(messages.isMutedInfo)} 286 <p className="settings__help">
271 </p> 287 {intl.formatMessage(messages.isMutedInfo)}
272 </div> 288 </p>
289 </div>
273 290
274 <div className="settings__settings-group"> 291 <div className="settings__settings-group">
275 <h3>{intl.formatMessage(messages.headlineBadges)}</h3> 292 <h3>{intl.formatMessage(messages.headlineBadges)}</h3>
276 <Toggle field={form.$('isBadgeEnabled')} /> 293 <Toggle field={form.$('isBadgeEnabled')} />
277 {recipe.hasIndirectMessages && form.$('isBadgeEnabled').value && ( 294 {recipe.hasIndirectMessages && form.$('isBadgeEnabled').value && (
278 <div> 295 <div>
279 <Toggle field={form.$('isIndirectMessageBadgeEnabled')} /> 296 <Toggle field={form.$('isIndirectMessageBadgeEnabled')} />
280 <p className="settings__help"> 297 <p className="settings__help">
281 {intl.formatMessage(messages.indirectMessageInfo)} 298 {intl.formatMessage(messages.indirectMessageInfo)}
282 </p> 299 </p>
283 </div> 300 </div>
284 )} 301 )}
285 </div> 302 </div>
286 303
287 <div className="settings__settings-group"> 304 <div className="settings__settings-group">
288 <h3>{intl.formatMessage(messages.headlineGeneral)}</h3> 305 <h3>{intl.formatMessage(messages.headlineGeneral)}</h3>
289 <Toggle field={form.$('isEnabled')} /> 306 <Toggle field={form.$('isEnabled')} />
307 </div>
308 </div>
309 <div className="service-icon">
310 <ImageUpload
311 field={form.$('customIcon')}
312 textDelete={intl.formatMessage(messages.iconDelete)}
313 textUpload={intl.formatMessage(messages.iconUpload)}
314 />
290 </div> 315 </div>
291 </div> 316 </div>
292 {recipe.message && ( 317 {recipe.message && (
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js
index 5f146b5f3..20e451f01 100644
--- a/src/components/settings/services/ServicesDashboard.js
+++ b/src/components/settings/services/ServicesDashboard.js
@@ -15,10 +15,18 @@ const messages = defineMessages({
15 id: 'settings.services.headline', 15 id: 'settings.services.headline',
16 defaultMessage: '!!!Your services', 16 defaultMessage: '!!!Your services',
17 }, 17 },
18 searchService: {
19 id: 'settings.searchService',
20 defaultMessage: '!!!Search service',
21 },
18 noServicesAdded: { 22 noServicesAdded: {
19 id: 'settings.services.noServicesAdded', 23 id: 'settings.services.noServicesAdded',
20 defaultMessage: '!!!You haven\'t added any services yet.', 24 defaultMessage: '!!!You haven\'t added any services yet.',
21 }, 25 },
26 noServiceFound: {
27 id: 'settings.recipes.nothingFound',
28 defaultMessage: '!!!Sorry, but no service matched your search term.',
29 },
22 discoverServices: { 30 discoverServices: {
23 id: 'settings.services.discoverServices', 31 id: 'settings.services.discoverServices',
24 defaultMessage: '!!!Discover services', 32 defaultMessage: '!!!Discover services',
@@ -53,7 +61,13 @@ export default class ServicesDashboard extends Component {
53 servicesRequestFailed: PropTypes.bool.isRequired, 61 servicesRequestFailed: PropTypes.bool.isRequired,
54 retryServicesRequest: PropTypes.func.isRequired, 62 retryServicesRequest: PropTypes.func.isRequired,
55 status: MobxPropTypes.arrayOrObservableArray.isRequired, 63 status: MobxPropTypes.arrayOrObservableArray.isRequired,
64 searchNeedle: PropTypes.string,
56 }; 65 };
66
67 static defaultProps = {
68 searchNeedle: '',
69 }
70
57 static contextTypes = { 71 static contextTypes = {
58 intl: intlShape, 72 intl: intlShape,
59 }; 73 };
@@ -69,20 +83,24 @@ export default class ServicesDashboard extends Component {
69 servicesRequestFailed, 83 servicesRequestFailed,
70 retryServicesRequest, 84 retryServicesRequest,
71 status, 85 status,
86 searchNeedle,
72 } = this.props; 87 } = this.props;
73 const { intl } = this.context; 88 const { intl } = this.context;
74 89
75 return ( 90 return (
76 <div className="settings__main"> 91 <div className="settings__main">
77 <div className="settings__header"> 92 <div className="settings__header">
78 <SearchInput 93 <h1>{intl.formatMessage(messages.headline)}</h1>
79 className="settings__search-header"
80 defaultValue={intl.formatMessage(messages.headline)}
81 onChange={needle => filterServices({ needle })}
82 onReset={() => resetFilter()}
83 />
84 </div> 94 </div>
85 <div className="settings__body"> 95 <div className="settings__body">
96 {!isLoading && (
97 <SearchInput
98 placeholder={intl.formatMessage(messages.searchService)}
99 onChange={needle => filterServices({ needle })}
100 onReset={() => resetFilter()}
101 autoFocus
102 />
103 )}
86 {!isLoading && servicesRequestFailed && ( 104 {!isLoading && servicesRequestFailed && (
87 <div> 105 <div>
88 <Infobox 106 <Infobox
@@ -121,7 +139,7 @@ export default class ServicesDashboard extends Component {
121 </Appear> 139 </Appear>
122 )} 140 )}
123 141
124 {!isLoading && services.length === 0 && ( 142 {!isLoading && services.length === 0 && !searchNeedle && (
125 <div className="align-middle settings__empty-state"> 143 <div className="align-middle settings__empty-state">
126 <p className="settings__empty-text"> 144 <p className="settings__empty-text">
127 <span className="emoji"> 145 <span className="emoji">
@@ -132,6 +150,16 @@ export default class ServicesDashboard extends Component {
132 <Link to="/settings/recipes" className="button">{intl.formatMessage(messages.discoverServices)}</Link> 150 <Link to="/settings/recipes" className="button">{intl.formatMessage(messages.discoverServices)}</Link>
133 </div> 151 </div>
134 )} 152 )}
153 {!isLoading && services.length === 0 && searchNeedle && (
154 <div className="align-middle settings__empty-state">
155 <p className="settings__empty-text">
156 <span className="emoji">
157 <img src="./assets/images/emoji/dontknow.png" alt="" />
158 </span>
159 {intl.formatMessage(messages.noServiceFound)}
160 </p>
161 </div>
162 )}
135 {isLoading ? ( 163 {isLoading ? (
136 <Loader /> 164 <Loader />
137 ) : ( 165 ) : (
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index ff398aa33..72aa5a8af 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -40,6 +40,18 @@ const messages = defineMessages({
40 id: 'settings.app.translationHelp', 40 id: 'settings.app.translationHelp',
41 defaultMessage: '!!!Help us to translate Franz into your language.', 41 defaultMessage: '!!!Help us to translate Franz into your language.',
42 }, 42 },
43 subheadlineCache: {
44 id: 'settings.app.subheadlineCache',
45 defaultMessage: '!!!Cache',
46 },
47 cacheInfo: {
48 id: 'settings.app.cacheInfo',
49 defaultMessage: '!!!Franz cache is currently using {size} of disk space.',
50 },
51 buttonClearAllCache: {
52 id: 'settings.app.buttonClearAllCache',
53 defaultMessage: '!!!Clear cache',
54 },
43 buttonSearchForUpdate: { 55 buttonSearchForUpdate: {
44 id: 'settings.app.buttonSearchForUpdate', 56 id: 'settings.app.buttonSearchForUpdate',
45 defaultMessage: '!!!Check for updates', 57 defaultMessage: '!!!Check for updates',
@@ -77,6 +89,9 @@ export default class EditSettingsForm extends Component {
77 isUpdateAvailable: PropTypes.bool.isRequired, 89 isUpdateAvailable: PropTypes.bool.isRequired,
78 noUpdateAvailable: PropTypes.bool.isRequired, 90 noUpdateAvailable: PropTypes.bool.isRequired,
79 updateIsReadyToInstall: PropTypes.bool.isRequired, 91 updateIsReadyToInstall: PropTypes.bool.isRequired,
92 isClearingAllCache: PropTypes.bool.isRequired,
93 onClearAllCache: PropTypes.func.isRequired,
94 cacheSize: PropTypes.string.isRequired,
80 }; 95 };
81 96
82 static contextTypes = { 97 static contextTypes = {
@@ -103,6 +118,9 @@ export default class EditSettingsForm extends Component {
103 isUpdateAvailable, 118 isUpdateAvailable,
104 noUpdateAvailable, 119 noUpdateAvailable,
105 updateIsReadyToInstall, 120 updateIsReadyToInstall,
121 isClearingAllCache,
122 onClearAllCache,
123 cacheSize,
106 } = this.props; 124 } = this.props;
107 const { intl } = this.context; 125 const { intl } = this.context;
108 126
@@ -155,6 +173,25 @@ export default class EditSettingsForm extends Component {
155 <h2 id="advanced">{intl.formatMessage(messages.headlineAdvanced)}</h2> 173 <h2 id="advanced">{intl.formatMessage(messages.headlineAdvanced)}</h2>
156 <Toggle field={form.$('enableSpellchecking')} /> 174 <Toggle field={form.$('enableSpellchecking')} />
157 {/* <Select field={form.$('spellcheckingLanguage')} /> */} 175 {/* <Select field={form.$('spellcheckingLanguage')} /> */}
176 <div className="settings__settings-group">
177 <h3>
178 {intl.formatMessage(messages.subheadlineCache)}
179 </h3>
180 <p>
181 {intl.formatMessage(messages.cacheInfo, {
182 size: cacheSize,
183 })}
184 </p>
185 <p>
186 <Button
187 buttonType="secondary"
188 label={intl.formatMessage(messages.buttonClearAllCache)}
189 onClick={onClearAllCache}
190 disabled={isClearingAllCache}
191 loaded={!isClearingAllCache}
192 />
193 </p>
194 </div>
158 195
159 {/* Updates */} 196 {/* Updates */}
160 <h2 id="updates">{intl.formatMessage(messages.headlineUpdates)}</h2> 197 <h2 id="updates">{intl.formatMessage(messages.headlineUpdates)}</h2>
@@ -165,6 +202,7 @@ export default class EditSettingsForm extends Component {
165 /> 202 />
166 ) : ( 203 ) : (
167 <Button 204 <Button
205 buttonType="secondary"
168 label={intl.formatMessage(updateButtonLabelMessage)} 206 label={intl.formatMessage(updateButtonLabelMessage)}
169 onClick={checkForUpdates} 207 onClick={checkForUpdates}
170 disabled={isCheckingForUpdates || isUpdateAvailable} 208 disabled={isCheckingForUpdates || isUpdateAvailable}
diff --git a/src/components/ui/ImageUpload.js b/src/components/ui/ImageUpload.js
new file mode 100644
index 000000000..81c3b8da6
--- /dev/null
+++ b/src/components/ui/ImageUpload.js
@@ -0,0 +1,108 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import { Field } from 'mobx-react-form';
5// import Loader from 'react-loader';
6import classnames from 'classnames';
7import Dropzone from 'react-dropzone';
8
9@observer
10export default class ImageUpload extends Component {
11 static propTypes = {
12 field: PropTypes.instanceOf(Field).isRequired,
13 className: PropTypes.string,
14 multiple: PropTypes.bool,
15 textDelete: PropTypes.string.isRequired,
16 textUpload: PropTypes.string.isRequired,
17 };
18
19 static defaultProps = {
20 className: null,
21 multiple: false,
22 };
23
24 state = {
25 path: null,
26 }
27
28 onDrop(acceptedFiles) {
29 const { field } = this.props;
30
31 acceptedFiles.forEach((file) => {
32 this.setState({
33 path: file.path,
34 });
35 this.props.field.onDrop(file);
36 });
37
38 field.set('');
39 }
40
41 dropzoneRef = null;
42
43 render() {
44 const {
45 field,
46 className,
47 multiple,
48 textDelete,
49 textUpload,
50 } = this.props;
51
52 const cssClasses = classnames({
53 'image-upload__dropzone': true,
54 [`${className}`]: className,
55 });
56
57 return (
58 <div className="image-upload-wrapper">
59 <label className="franz-form__label" htmlFor="iconUpload">{field.label}</label>
60 <div className="image-upload">
61 {(field.value && field.value !== 'delete') || this.state.path ? (
62 <div>
63 <div
64 className="image-upload__preview"
65 style={({
66 backgroundImage: `url("${this.state.path || field.value}")`,
67 })}
68 />
69 <div className="image-upload__action">
70 <button
71 type="button"
72 onClick={() => {
73 if (field.value) {
74 field.set('delete');
75 } else {
76 this.setState({
77 path: null,
78 });
79 }
80 }}
81 >
82 <i className="mdi mdi-delete" />
83 <p>
84 {textDelete}
85 </p>
86 </button>
87 <div className="image-upload__action-background" />
88 </div>
89 </div>
90 ) : (
91 <Dropzone
92 ref={(node) => { this.dropzoneRef = node; }}
93 onDrop={this.onDrop.bind(this)}
94 className={cssClasses}
95 multiple={multiple}
96 accept="image/jpeg, image/png"
97 >
98 <i className="mdi mdi-file-image" />
99 <p>
100 {textUpload}
101 </p>
102 </Dropzone>
103 )}
104 </div>
105 </div>
106 );
107 }
108}
diff --git a/src/components/ui/SearchInput.js b/src/components/ui/SearchInput.js
index bca412cef..a94cde201 100644
--- a/src/components/ui/SearchInput.js
+++ b/src/components/ui/SearchInput.js
@@ -9,36 +9,46 @@ import { debounce } from 'lodash';
9export default class SearchInput extends Component { 9export default class SearchInput extends Component {
10 static propTypes = { 10 static propTypes = {
11 value: PropTypes.string, 11 value: PropTypes.string,
12 defaultValue: PropTypes.string, 12 placeholder: PropTypes.string,
13 className: PropTypes.string, 13 className: PropTypes.string,
14 onChange: PropTypes.func, 14 onChange: PropTypes.func,
15 onReset: PropTypes.func, 15 onReset: PropTypes.func,
16 name: PropTypes.string, 16 name: PropTypes.string,
17 throttle: PropTypes.bool, 17 throttle: PropTypes.bool,
18 throttleDelay: PropTypes.number, 18 throttleDelay: PropTypes.number,
19 autoFocus: PropTypes.bool,
19 }; 20 };
20 21
21 static defaultProps = { 22 static defaultProps = {
22 value: '', 23 value: '',
23 defaultValue: '', 24 placeholder: '',
24 className: '', 25 className: '',
25 name: uuidv1(), 26 name: uuidv1(),
26 throttle: false, 27 throttle: false,
27 throttleDelay: 250, 28 throttleDelay: 250,
28 onChange: () => null, 29 onChange: () => null,
29 onReset: () => null, 30 onReset: () => null,
31 autoFocus: false,
30 } 32 }
31 33
32 constructor(props) { 34 constructor(props) {
33 super(props); 35 super(props);
34 36
35 this.state = { 37 this.state = {
36 value: props.value || props.defaultValue, 38 value: props.value,
37 }; 39 };
38 40
39 this.throttledOnChange = debounce(this.throttledOnChange, this.props.throttleDelay); 41 this.throttledOnChange = debounce(this.throttledOnChange, this.props.throttleDelay);
40 } 42 }
41 43
44 componentDidMount() {
45 const { autoFocus } = this.props;
46
47 if (autoFocus) {
48 this.input.focus();
49 }
50 }
51
42 onChange(e) { 52 onChange(e) {
43 const { throttle, onChange } = this.props; 53 const { throttle, onChange } = this.props;
44 const { value } = e.target; 54 const { value } = e.target;
@@ -52,26 +62,6 @@ export default class SearchInput extends Component {
52 } 62 }
53 } 63 }
54 64
55 onClick() {
56 const { defaultValue } = this.props;
57 const { value } = this.state;
58
59 if (value === defaultValue) {
60 this.setState({ value: '' });
61 }
62
63 this.input.focus();
64 }
65
66 onBlur() {
67 const { defaultValue } = this.props;
68 const { value } = this.state;
69
70 if (value === '') {
71 this.setState({ value: defaultValue });
72 }
73 }
74
75 throttledOnChange(e) { 65 throttledOnChange(e) {
76 const { onChange } = this.props; 66 const { onChange } = this.props;
77 67
@@ -79,8 +69,8 @@ export default class SearchInput extends Component {
79 } 69 }
80 70
81 reset() { 71 reset() {
82 const { defaultValue, onReset } = this.props; 72 const { onReset } = this.props;
83 this.setState({ value: defaultValue }); 73 this.setState({ value: '' });
84 74
85 onReset(); 75 onReset();
86 } 76 }
@@ -88,7 +78,7 @@ export default class SearchInput extends Component {
88 input = null; 78 input = null;
89 79
90 render() { 80 render() {
91 const { className, name, defaultValue } = this.props; 81 const { className, name, placeholder } = this.props;
92 const { value } = this.state; 82 const { value } = this.state;
93 83
94 return ( 84 return (
@@ -101,18 +91,16 @@ export default class SearchInput extends Component {
101 <label 91 <label
102 htmlFor={name} 92 htmlFor={name}
103 className="mdi mdi-magnify" 93 className="mdi mdi-magnify"
104 onClick={() => this.onClick()}
105 /> 94 />
106 <input 95 <input
107 name={name} 96 name={name}
108 type="text" 97 type="text"
98 placeholder={placeholder}
109 value={value} 99 value={value}
110 onChange={e => this.onChange(e)} 100 onChange={e => this.onChange(e)}
111 onClick={() => this.onClick()}
112 onBlur={() => this.onBlur()}
113 ref={(ref) => { this.input = ref; }} 101 ref={(ref) => { this.input = ref; }}
114 /> 102 />
115 {value !== defaultValue && value.length > 0 && ( 103 {value.length > 0 && (
116 <span 104 <span
117 className="mdi mdi-close-circle-outline" 105 className="mdi mdi-close-circle-outline"
118 onClick={() => this.reset()} 106 onClick={() => this.reset()}