import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { observer } from 'mobx-react'; import { Link } from 'react-router'; import { defineMessages, intlShape } from 'react-intl'; import normalizeUrl from 'normalize-url'; import Form from '../../../lib/Form'; import User from '../../../models/User'; import Recipe from '../../../models/Recipe'; import Service from '../../../models/Service'; import Tabs, { TabItem } from '../../ui/Tabs'; import Input from '../../ui/Input'; import Toggle from '../../ui/Toggle'; import Button from '../../ui/Button'; import ImageUpload from '../../ui/ImageUpload'; const messages = defineMessages({ saveService: { id: 'settings.service.form.saveButton', defaultMessage: '!!!Save service', }, deleteService: { id: 'settings.service.form.deleteButton', defaultMessage: '!!!Delete Service', }, availableServices: { id: 'settings.service.form.availableServices', defaultMessage: '!!!Available services', }, yourServices: { id: 'settings.service.form.yourServices', defaultMessage: '!!!Your services', }, addServiceHeadline: { id: 'settings.service.form.addServiceHeadline', defaultMessage: '!!!Add {name}', }, editServiceHeadline: { id: 'settings.service.form.editServiceHeadline', defaultMessage: '!!!Edit {name}', }, tabHosted: { id: 'settings.service.form.tabHosted', defaultMessage: '!!!Hosted', }, tabOnPremise: { id: 'settings.service.form.tabOnPremise', defaultMessage: '!!!Self hosted ⭐️', }, useHostedService: { id: 'settings.service.form.useHostedService', defaultMessage: '!!!Use the hosted {name} service.', }, customUrlValidationError: { id: 'settings.service.form.customUrlValidationError', defaultMessage: '!!!Could not validate custom {name} server.', }, customUrlPremiumInfo: { id: 'settings.service.form.customUrlPremiumInfo', defaultMessage: '!!!To add self hosted services, you need a Franz Premium Supporter Account.', }, customUrlUpgradeAccount: { id: 'settings.service.form.customUrlUpgradeAccount', defaultMessage: '!!!Upgrade your account', }, indirectMessageInfo: { id: 'settings.service.form.indirectMessageInfo', defaultMessage: '!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...', }, isMutedInfo: { id: 'settings.service.form.isMutedInfo', defaultMessage: '!!!When disabled, all notification sounds and audio playback are muted', }, headlineNotifications: { id: 'settings.service.form.headlineNotifications', defaultMessage: '!!!Notifications', }, headlineBadges: { id: 'settings.service.form.headlineBadges', defaultMessage: '!!!Unread message dadges', }, headlineGeneral: { id: 'settings.service.form.headlineGeneral', defaultMessage: '!!!General', }, }); @observer export default class EditServiceForm extends Component { static propTypes = { recipe: PropTypes.instanceOf(Recipe).isRequired, service(props, propName) { if (props.action === 'edit' && !(props[propName] instanceof Service)) { return new Error(`'${propName}'' is expected to be of type 'Service' when editing a Service`); } return null; }, user: PropTypes.instanceOf(User).isRequired, action: PropTypes.string.isRequired, form: PropTypes.instanceOf(Form).isRequired, onSubmit: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired, isSaving: PropTypes.bool.isRequired, isDeleting: PropTypes.bool.isRequired, }; static defaultProps = { service: {}, }; static contextTypes = { intl: intlShape, }; state = { isValidatingCustomUrl: false, } submit(e) { const { recipe } = this.props; e.preventDefault(); this.props.form.submit({ onSuccess: async (form) => { const values = form.values(); let isValid = true; const files = form.$('customIcon').files; if (files) { values.iconFile = files[0]; } if (recipe.validateUrl && values.customUrl) { this.setState({ isValidatingCustomUrl: true }); try { values.customUrl = normalizeUrl(values.customUrl, { stripWWW: false }); isValid = await recipe.validateUrl(values.customUrl); } catch (err) { console.warn('ValidateURL', err); isValid = false; } } if (isValid) { this.props.onSubmit(values); } else { form.invalidate('url-validation-error'); } this.setState({ isValidatingCustomUrl: false }); }, onError: () => {}, }); } render() { const { recipe, service, action, user, form, isSaving, isDeleting, onDelete, } = this.props; const { intl } = this.context; const { isValidatingCustomUrl } = this.state; const deleteButton = isDeleting ? ( ) : ( ); let activeTabIndex = 0; if (recipe.hasHostedOption && service.team) { activeTabIndex = 1; } else if (recipe.hasHostedOption && service.customUrl) { activeTabIndex = 2; } return (