diff options
author | Stefan Malzner <stefan@adlk.io> | 2018-01-06 23:51:04 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-06 23:51:04 +0100 |
commit | fb16f121e8ff6678c74148cd456b964a85742fbe (patch) | |
tree | 5534162572aca6bda4d22984ab6103c76510d193 /src/components | |
parent | Merge pull request #541 from meetfranz/feature/external-links (diff) | |
parent | fix displaying old icon while uploading new icon (diff) | |
download | ferdium-app-fb16f121e8ff6678c74148cd456b964a85742fbe.tar.gz ferdium-app-fb16f121e8ff6678c74148cd456b964a85742fbe.tar.zst ferdium-app-fb16f121e8ff6678c74148cd456b964a85742fbe.zip |
Merge pull request #525 from meetfranz/feature/icon-upload
[PR] Feature/icon upload
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/settings/services/EditServiceForm.js | 75 | ||||
-rw-r--r-- | src/components/ui/ImageUpload.js | 108 |
2 files changed, 158 insertions, 25 deletions
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index b1a1c2e68..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'; | |||
13 | import Input from '../../ui/Input'; | 13 | import Input from '../../ui/Input'; |
14 | import Toggle from '../../ui/Toggle'; | 14 | import Toggle from '../../ui/Toggle'; |
15 | import Button from '../../ui/Button'; | 15 | import Button from '../../ui/Button'; |
16 | import ImageUpload from '../../ui/ImageUpload'; | ||
16 | 17 | ||
17 | const messages = defineMessages({ | 18 | const messages = defineMessages({ |
18 | saveService: { | 19 | saveService: { |
@@ -83,6 +84,14 @@ const messages = defineMessages({ | |||
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/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 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { observer } from 'mobx-react'; | ||
4 | import { Field } from 'mobx-react-form'; | ||
5 | // import Loader from 'react-loader'; | ||
6 | import classnames from 'classnames'; | ||
7 | import Dropzone from 'react-dropzone'; | ||
8 | |||
9 | @observer | ||
10 | export 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 | } | ||