| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- import React from 'react';
- import { isInteger } from 'core-js/fn/number';
- import { format, parse } from 'date-fns';
- import PropTypes from 'prop-types';
- import { useTranslation } from 'react-i18next';
- import PageContainer from '~/client/services/PageContainer';
- import { toastSuccess, toastError } from '~/client/util/apiNotification';
- import { apiv3Post } from '~/client/util/apiv3-client';
- import { withUnstatedContainers } from '../UnstatedUtils';
- class ShareLinkForm extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- expirationType: 'unlimited',
- numberOfDays: '7',
- description: '',
- customExpirationDate: format(new Date(), 'yyyy-MM-dd'),
- customExpirationTime: format(new Date(), 'HH:mm'),
- };
- this.handleChangeExpirationType = this.handleChangeExpirationType.bind(this);
- this.handleChangeNumberOfDays = this.handleChangeNumberOfDays.bind(this);
- this.handleChangeDescription = this.handleChangeDescription.bind(this);
- this.handleIssueShareLink = this.handleIssueShareLink.bind(this);
- }
- /**
- * change expirationType
- * @param {string} expirationType
- */
- handleChangeExpirationType(expirationType) {
- this.setState({ expirationType });
- }
- /**
- * change numberOfDays
- * @param {string} numberOfDays
- */
- handleChangeNumberOfDays(numberOfDays) {
- this.setState({ numberOfDays });
- }
- /**
- * change description
- * @param {string} description
- */
- handleChangeDescription(description) {
- this.setState({ description });
- }
- /**
- * change customExpirationDate
- * @param {date} customExpirationDate
- */
- handleChangeCustomExpirationDate(customExpirationDate) {
- this.setState({ customExpirationDate });
- }
- /**
- * change customExpirationTime
- * @param {date} customExpirationTime
- */
- handleChangeCustomExpirationTime(customExpirationTime) {
- this.setState({ customExpirationTime });
- }
- /**
- * Generate expiredAt by expirationType
- */
- generateExpired() {
- const { t } = this.props;
- const { expirationType } = this.state;
- let expiredAt;
- if (expirationType === 'unlimited') {
- return null;
- }
- if (expirationType === 'numberOfDays') {
- if (!isInteger(Number(this.state.numberOfDays))) {
- throw new Error(t('share_links.Invalid_Number_of_Date'));
- }
- const date = new Date();
- date.setDate(date.getDate() + Number(this.state.numberOfDays));
- expiredAt = date;
- }
- if (expirationType === 'custom') {
- const { customExpirationDate, customExpirationTime } = this.state;
- expiredAt = parse(`${customExpirationDate}T${customExpirationTime}`, "yyyy-MM-dd'T'HH:mm", new Date());
- }
- return expiredAt;
- }
- closeForm() {
- const { onCloseForm } = this.props;
- if (onCloseForm == null) {
- return;
- }
- onCloseForm();
- }
- async handleIssueShareLink() {
- const {
- t, pageContainer,
- } = this.props;
- const { pageId } = pageContainer.state;
- const { description } = this.state;
- let expiredAt;
- try {
- expiredAt = this.generateExpired();
- }
- catch (err) {
- return toastError(err);
- }
- try {
- await apiv3Post('/share-links/', { relatedPage: pageId, expiredAt, description });
- this.closeForm();
- toastSuccess(t('toaster.issue_share_link'));
- }
- catch (err) {
- toastError(err);
- }
- }
- renderExpirationTypeOptions() {
- const { expirationType } = this.state;
- const { t } = this.props;
- return (
- <div className="form-group row">
- <label htmlFor="inputDesc" className="col-md-5 col-form-label">{t('share_links.expire')}</label>
- <div className="col-md-7">
- <div className="custom-control custom-radio form-group ">
- <input
- type="radio"
- className="custom-control-input"
- id="customRadio1"
- name="expirationType"
- value="customRadio1"
- checked={expirationType === 'unlimited'}
- onChange={() => { this.handleChangeExpirationType('unlimited') }}
- />
- <label className="custom-control-label" htmlFor="customRadio1">{t('share_links.Unlimited')}</label>
- </div>
- <div className="custom-control custom-radio form-group">
- <input
- type="radio"
- className="custom-control-input"
- id="customRadio2"
- value="customRadio2"
- checked={expirationType === 'numberOfDays'}
- onChange={() => { this.handleChangeExpirationType('numberOfDays') }}
- name="expirationType"
- />
- <label className="custom-control-label" htmlFor="customRadio2">
- <div className="row align-items-center m-0">
- <input
- type="number"
- min="1"
- className="col-4"
- name="expirationType"
- value={this.state.numberOfDays}
- onFocus={() => { this.handleChangeExpirationType('numberOfDays') }}
- onChange={e => this.handleChangeNumberOfDays(Number(e.target.value))}
- />
- <span className="col-auto">{t('share_links.Days')}</span>
- </div>
- </label>
- </div>
- <div className="custom-control custom-radio form-group text-nowrap mb-0">
- <input
- type="radio"
- className="custom-control-input"
- id="customRadio3"
- name="expirationType"
- value="customRadio3"
- checked={expirationType === 'custom'}
- onChange={() => { this.handleChangeExpirationType('custom') }}
- />
- <label className="custom-control-label" htmlFor="customRadio3">
- {t('share_links.Custom')}
- </label>
- <div className="d-inline-flex flex-wrap">
- <input
- type="date"
- className="ml-3 mb-2"
- name="customExpirationDate"
- value={this.state.customExpirationDate}
- onFocus={() => { this.handleChangeExpirationType('custom') }}
- onChange={e => this.handleChangeCustomExpirationDate(e.target.value)}
- />
- <input
- type="time"
- className="ml-3 mb-2"
- name="customExpiration"
- value={this.state.customExpirationTime}
- onFocus={() => { this.handleChangeExpirationType('custom') }}
- onChange={e => this.handleChangeCustomExpirationTime(e.target.value)}
- />
- </div>
- </div>
- </div>
- </div>
- );
- }
- renderDescriptionForm() {
- const { t } = this.props;
- return (
- <div className="form-group row">
- <label htmlFor="inputDesc" className="col-md-5 col-form-label">{t('share_links.description')}</label>
- <div className="col-md-4">
- <input
- type="text"
- className="form-control"
- id="inputDesc"
- placeholder={t('share_links.enter_desc')}
- value={this.state.description}
- onChange={e => this.handleChangeDescription(e.target.value)}
- />
- </div>
- </div>
- );
- }
- render() {
- const { t } = this.props;
- return (
- <div className="share-link-form p-3">
- <h3 className="grw-modal-head pb-2"> { t('share_links.share_settings') }</h3>
- <div className=" p-3">
- {this.renderExpirationTypeOptions()}
- {this.renderDescriptionForm()}
- <button type="button" className="btn btn-primary d-block mx-auto px-5" onClick={this.handleIssueShareLink}>
- {t('share_links.Issue')}
- </button>
- </div>
- </div>
- );
- }
- }
- ShareLinkForm.propTypes = {
- t: PropTypes.func.isRequired, // i18next
- pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
- onCloseForm: PropTypes.func,
- };
- const ShareLinkFormWrapperFC = (props) => {
- const { t } = useTranslation();
- return <ShareLinkForm t={t} {...props} />;
- };
- /**
- * Wrapper component for using unstated
- */
- const ShareLinkFormWrapper = withUnstatedContainers(ShareLinkFormWrapperFC, [PageContainer]);
- export default ShareLinkFormWrapper;
|