import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { inject, observer } from 'mobx-react';
import { defineMessages, intlShape } from 'react-intl';
import UserStore from '../../stores/UserStore';
import RecipesStore from '../../stores/RecipesStore';
import ServicesStore from '../../stores/ServicesStore';
import SettingsStore from '../../stores/SettingsStore';
import FeaturesStore from '../../stores/FeaturesStore';
import Form from '../../lib/Form';
import { gaPage } from '../../lib/analytics';
import ServiceError from '../../components/settings/services/ServiceError';
import EditServiceForm from '../../components/settings/services/EditServiceForm';
import { required, url, oneRequired } from '../../helpers/validation-helpers';
import { config as proxyFeature } from '../../features/serviceProxy';
const messages = defineMessages({
name: {
id: 'settings.service.form.name',
defaultMessage: '!!!Name',
},
enableService: {
id: 'settings.service.form.enableService',
defaultMessage: '!!!Enable service',
},
enableNotification: {
id: 'settings.service.form.enableNotification',
defaultMessage: '!!!Enable Notifications',
},
enableBadge: {
id: 'settings.service.form.enableBadge',
defaultMessage: '!!!Show unread message badges',
},
enableAudio: {
id: 'settings.service.form.enableAudio',
defaultMessage: '!!!Enable audio',
},
team: {
id: 'settings.service.form.team',
defaultMessage: '!!!Team',
},
customUrl: {
id: 'settings.service.form.customUrl',
defaultMessage: '!!!Custom server',
},
indirectMessages: {
id: 'settings.service.form.indirectMessages',
defaultMessage: '!!!Show message badge for all new messages',
},
icon: {
id: 'settings.service.form.icon',
defaultMessage: '!!!Custom icon',
},
enableDarkMode: {
id: 'settings.service.form.enableDarkMode',
defaultMessage: '!!!Enable Dark Mode',
},
enableProxy: {
id: 'settings.service.form.proxy.isEnabled',
defaultMessage: '!!!Use Proxy',
},
proxyHost: {
id: 'settings.service.form.proxy.host',
defaultMessage: '!!!Proxy Host/IP',
},
proxyUser: {
id: 'settings.service.form.proxy.user',
defaultMessage: '!!!User',
},
proxyPassword: {
id: 'settings.service.form.proxy.password',
defaultMessage: '!!!Password',
},
});
export default @inject('stores', 'actions') @observer class EditServiceScreen extends Component {
static contextTypes = {
intl: intlShape,
};
componentDidMount() {
gaPage('Settings/Service/Edit');
}
onSubmit(data) {
const { action } = this.props.router.params;
const { recipes, services } = this.props.stores;
const { createService, updateService } = this.props.actions.service;
const serviceData = data;
serviceData.isMuted = !serviceData.isMuted;
if (action === 'edit') {
updateService({ serviceId: services.activeSettings.id, serviceData });
} else {
createService({ recipeId: recipes.active.id, serviceData });
}
}
prepareForm(recipe, service, proxy) {
const { intl } = this.context;
const config = {
fields: {
name: {
label: intl.formatMessage(messages.name),
placeholder: intl.formatMessage(messages.name),
value: service.id ? service.name : recipe.name,
},
isEnabled: {
label: intl.formatMessage(messages.enableService),
value: service.isEnabled,
default: true,
},
isNotificationEnabled: {
label: intl.formatMessage(messages.enableNotification),
value: service.isNotificationEnabled,
default: true,
},
isBadgeEnabled: {
label: intl.formatMessage(messages.enableBadge),
value: service.isBadgeEnabled,
default: true,
},
isMuted: {
label: intl.formatMessage(messages.enableAudio),
value: !service.isMuted,
default: true,
},
customIcon: {
label: intl.formatMessage(messages.icon),
value: service.hasCustomUploadedIcon ? service.icon : false,
default: null,
type: 'file',
},
isDarkModeEnabled: {
label: intl.formatMessage(messages.enableDarkMode),
value: service.isDarkModeEnabled,
default: this.props.stores.settings.all.app.darkMode,
},
},
};
if (recipe.hasTeamId) {
Object.assign(config.fields, {
team: {
label: intl.formatMessage(messages.team),
placeholder: intl.formatMessage(messages.team),
value: service.team,
validators: [required],
},
});
}
if (recipe.hasCustomUrl) {
Object.assign(config.fields, {
customUrl: {
label: intl.formatMessage(messages.customUrl),
placeholder: 'https://',
value: service.customUrl,
validators: [required, url],
},
});
}
// More fine grained and use case specific validation rules
if (recipe.hasTeamId && recipe.hasCustomUrl) {
config.fields.team.validators = [oneRequired(['team', 'customUrl'])];
config.fields.customUrl.validators = [url, oneRequired(['team', 'customUrl'])];
}
// If a service can be hosted and has a teamId or customUrl
if (recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl)) {
if (config.fields.team) {
config.fields.team.validators = [];
}
if (config.fields.customUrl) {
config.fields.customUrl.validators = [url];
}
}
if (recipe.hasIndirectMessages) {
Object.assign(config.fields, {
isIndirectMessageBadgeEnabled: {
label: intl.formatMessage(messages.indirectMessages),
value: service.isIndirectMessageBadgeEnabled,
default: true,
},
});
}
if (proxy.isEnabled) {
const serviceProxyConfig = this.props.stores.settings.proxy[service.id] || {};
Object.assign(config.fields, {
proxy: {
name: 'proxy',
label: 'proxy',
fields: {
isEnabled: {
label: intl.formatMessage(messages.enableProxy),
value: serviceProxyConfig.isEnabled,
default: false,
},
host: {
label: intl.formatMessage(messages.proxyHost),
value: serviceProxyConfig.host,
default: '',
},
user: {
label: intl.formatMessage(messages.proxyUser),
value: serviceProxyConfig.user,
default: '',
},
password: {
label: intl.formatMessage(messages.proxyPassword),
value: serviceProxyConfig.password,
default: '',
type: 'password',
},
},
},
});
}
return new Form(config);
}
deleteService() {
const { deleteService } = this.props.actions.service;
const { action } = this.props.router.params;
if (action === 'edit') {
const { activeSettings: service } = this.props.stores.services;
deleteService({
serviceId: service.id,
redirect: '/settings/services',
});
}
}
render() {
const { recipes, services, user } = this.props.stores;
const { action } = this.props.router.params;
let recipe;
let service = {};
let isLoading = false;
if (action === 'add') {
recipe = recipes.active;
// TODO: render error message when recipe is `null`
if (!recipe) {
return (