Skip to content

Commit

Permalink
feat(Service): Add custom service icon upload
Browse files Browse the repository at this point in the history
  • Loading branch information
adlk committed Jan 2, 2018
1 parent 150cfe7 commit 6b97e42
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 84 deletions.
75 changes: 43 additions & 32 deletions src/components/settings/services/EditServiceForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ const messages = defineMessages({
id: 'settings.service.form.headlineGeneral',
defaultMessage: '!!!General',
},
iconDelete: {
id: 'settings.service.form.iconDelete',
defaultMessage: '!!!Delete',
},
iconUpload: {
id: 'settings.service.form.iconUpload',
defaultMessage: '!!!Drop your image, or click here',
},
});

@observer
Expand Down Expand Up @@ -223,14 +231,8 @@ export default class EditServiceForm extends Component {
</div>
<div className="settings__body">
<form onSubmit={e => this.submit(e)} id="form">
<div className="service-flex-grid">
<div className="service-name">
<Input field={form.$('name')} focus />
</div>
<div className="service-icon">
{/* <Input field={form.$('name')} focus /> */}
<ImageUpload field={form.$('customIcon')} />
</div>
<div className="service-name">
<Input field={form.$('name')} focus />
</div>
{(recipe.hasTeamId || recipe.hasCustomUrl) && (
<Tabs
Expand Down Expand Up @@ -275,32 +277,41 @@ export default class EditServiceForm extends Component {
)}
</Tabs>
)}
<div className="settings__options">
<div className="settings__settings-group">
<h3>{intl.formatMessage(messages.headlineNotifications)}</h3>
<Toggle field={form.$('isNotificationEnabled')} />
<Toggle field={form.$('isMuted')} />
<p className="settings__help">
{intl.formatMessage(messages.isMutedInfo)}
</p>
</div>
<div className="service-flex-grid">
<div className="settings__options">
<div className="settings__settings-group">
<h3>{intl.formatMessage(messages.headlineNotifications)}</h3>
<Toggle field={form.$('isNotificationEnabled')} />
<Toggle field={form.$('isMuted')} />
<p className="settings__help">
{intl.formatMessage(messages.isMutedInfo)}
</p>
</div>

<div className="settings__settings-group">
<h3>{intl.formatMessage(messages.headlineBadges)}</h3>
<Toggle field={form.$('isBadgeEnabled')} />
{recipe.hasIndirectMessages && form.$('isBadgeEnabled').value && (
<div>
<Toggle field={form.$('isIndirectMessageBadgeEnabled')} />
<p className="settings__help">
{intl.formatMessage(messages.indirectMessageInfo)}
</p>
</div>
)}
</div>
<div className="settings__settings-group">
<h3>{intl.formatMessage(messages.headlineBadges)}</h3>
<Toggle field={form.$('isBadgeEnabled')} />
{recipe.hasIndirectMessages && form.$('isBadgeEnabled').value && (
<div>
<Toggle field={form.$('isIndirectMessageBadgeEnabled')} />
<p className="settings__help">
{intl.formatMessage(messages.indirectMessageInfo)}
</p>
</div>
)}
</div>

<div className="settings__settings-group">
<h3>{intl.formatMessage(messages.headlineGeneral)}</h3>
<Toggle field={form.$('isEnabled')} />
<div className="settings__settings-group">
<h3>{intl.formatMessage(messages.headlineGeneral)}</h3>
<Toggle field={form.$('isEnabled')} />
</div>
</div>
<div className="service-icon">
<ImageUpload
field={form.$('customIcon')}
textDelete={intl.formatMessage(messages.iconDelete)}
textUpload={intl.formatMessage(messages.iconUpload)}
/>
</div>
</div>
{recipe.message && (
Expand Down
93 changes: 51 additions & 42 deletions src/components/ui/ImageUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export default class ImageUpload extends Component {
field: PropTypes.instanceOf(Field).isRequired,
className: PropTypes.string,
multiple: PropTypes.bool,
textDelete: PropTypes.string.isRequired,
textUpload: PropTypes.string.isRequired,
};

static defaultProps = {
Expand Down Expand Up @@ -39,56 +41,63 @@ export default class ImageUpload extends Component {
field,
className,
multiple,
textDelete,
textUpload,
} = this.props;

const cssClasses = classnames({
'franz-form__button': true,
'image-upload__dropzone': true,
[`${className}`]: className,
});

return (
<div>
{field.label}
{(field.value && field.value !== 'delete') || this.state.path ? (
<div
className="image-upload"
>
<div
className="image-upload__preview"
style={({
backgroundImage: `url(${field.value || this.state.path})`,
})}
/>
<div className="image-upload__action">
<button
type="button"
onClick={() => {
if (field.value) {
field.value = 'delete';
} else {
this.setState({
path: null,
});
}
}}
>
remove icon

</button>
<div className="image-upload__action-background" />
<div className="image-upload-wrapper">
<label className="franz-form__label" htmlFor="iconUpload">{field.label}</label>
<div className="image-upload">
{(field.value && field.value !== 'delete') || this.state.path ? (
<div>
<div
className="image-upload__preview"
style={({
backgroundImage: `url("${field.value || this.state.path}")`,
})}
/>
<div className="image-upload__action">
<button
type="button"
onClick={() => {
if (field.value) {
field.set('delete');
} else {
this.setState({
path: null,
});
}
}}
>
<i className="mdi mdi-delete" />
<p>
{textDelete}
</p>
</button>
<div className="image-upload__action-background" />
</div>
</div>
</div>
) : (
<Dropzone
ref={(node) => { this.dropzoneRef = node; }}
onDrop={this.onDrop.bind(this)}
className={cssClasses}
multiple={multiple}
accept="image/jpeg, image/png"
>
<p>Try dropping some files here, or click to select files to upload.</p>
</Dropzone>
)}
) : (
<Dropzone
ref={(node) => { this.dropzoneRef = node; }}
onDrop={this.onDrop.bind(this)}
className={cssClasses}
multiple={multiple}
accept="image/jpeg, image/png"
>
<i className="mdi mdi-file-image" />
<p>
{textUpload}
</p>
</Dropzone>
)}
</div>
</div>
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/containers/settings/EditServiceScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const messages = defineMessages({
},
icon: {
id: 'settings.service.form.icon',
defaultMessage: '!!!Icon',
defaultMessage: '!!!Custom icon',
},
});

Expand Down Expand Up @@ -108,7 +108,7 @@ export default class EditServiceScreen extends Component {
},
customIcon: {
label: intl.formatMessage(messages.icon),
value: service.hasCustomIcon ? service.icon : false,
value: service.hasCustomUploadedIcon ? service.icon : false,
default: null,
type: 'file',
},
Expand Down
4 changes: 3 additions & 1 deletion src/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@
"settings.service.form.headlineNotifications": "Notifications",
"settings.service.form.headlineBadges": "Unread message badges",
"settings.service.form.headlineGeneral": "General",
"settings.service.form.icon": "Icon",
"settings.service.form.icon": "Custom icon",
"settings.service.form.iconDelete": "Delete",
"settings.service.form.iconUpload": "Drop your image, or click here",
"settings.service.error.headline": "Error",
"settings.service.error.goBack": "Back to services",
"settings.service.error.message": "Could not load service recipe.",
Expand Down
3 changes: 3 additions & 0 deletions src/models/Service.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default class Service {
@observable isBadgeEnabled = true;
@observable isIndirectMessageBadgeEnabled = true;
@observable iconUrl = '';
@observable hasCustomUploadedIcon = false;
@observable hasCrashed = false;
constructor(data, recipe) {
Expand Down Expand Up @@ -62,6 +63,8 @@ export default class Service {
this.isMuted = data.isMuted !== undefined ? data.isMuted : this.isMuted;
this.hasCustomUploadedIcon = data.hasCustomIcon !== undefined ? data.hasCustomIcon : this.hasCustomUploadedIcon;
this.recipe = recipe;
autorun(() => {
Expand Down
10 changes: 9 additions & 1 deletion src/stores/ServicesStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,21 @@ export default class ServicesStore extends Store {
await request._promise;

newData.iconUrl = request.result.data.iconUrl;
newData.hasCustomUploadedIcon = true;
}

this.allServicesRequest.patch((result) => {
if (!result) return;

// patch custom icon deletion
if (data.customIcon === 'delete') {
data.iconUrl = '';
data.hasCustomUploadedIcon = false;
}

// patch custom icon url
if (data.customIconUrl) {
data.iconUrl = data.customIconUrl;
}

Object.assign(result.find(c => c.id === serviceId), newData);
Expand Down Expand Up @@ -328,7 +336,7 @@ export default class ServicesStore extends Store {
}
} else if (channel === 'avatar') {
const url = args[0];
if (service.customIconUrl !== url) {
if (service.iconUrl !== url && !service.hasCustomUploadedIcon) {
service.customIconUrl = url;

this.actions.service.updateService({
Expand Down
47 changes: 43 additions & 4 deletions src/styles/image-upload.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
.image-upload {
position: absolute;
width: 100px;
height: 100px;
border-radius: $theme-border-radius;
width: 140px;
height: 140px;
border: 1px solid $theme-gray-lighter;
border-radius: $theme-border-radius-small;
background: $theme-gray-lightest;
overflow: hidden;
margin-top: 5px;

&__preview,
&__action {
Expand All @@ -19,14 +22,16 @@
background-size: 100%;
background-repeat: no-repeat;
background-position: center center;
margin: 5px;
border-radius: 3px;
}

&__action {
position: relative;
z-index: 10;
opacity: 0;
transition: opacity 0.5s;
display: flex;
justify-content: center;

&-background {
position: absolute;
Expand All @@ -41,6 +46,33 @@
button {
position: relative;
z-index: 100;
color: #FFF;

.mdi {
color: #FFF;
}
}
}

&__dropzone {
text-align: center;
border-radius: 5px;
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}

&__dropzone,
button {
.mdi {
margin-bottom: 5px;
}

p {
font-size: 10px;
line-height: 10px;
}
}

Expand All @@ -49,4 +81,11 @@
opacity: 1;
}
}
}

.image-upload-wrapper {
.mdi {
font-size: 40px;
color: $theme-gray-light;
}
}
11 changes: 9 additions & 2 deletions src/styles/settings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,15 @@
}

.service-icon {
width: 30%;
min-width: 100px;
width: 140px;
float: right;
margin-top: 30px;
margin-left: 40px;

label {
font-weight: bold;
letter-spacing: -0.1px;
}
}
}

Expand Down Expand Up @@ -167,6 +173,7 @@

&__options {
margin-top: 20px;
flex: 1;
}

&__settings-group {
Expand Down

0 comments on commit 6b97e42

Please sign in to comment.