1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-06 00:07:44 +01:00
unleash.unleash/frontend/src/component/common/FormTemplate/FormTemplate.tsx
Youssef Khedher eeda7ab5e4 feat: add segments (#780)
* feat: create segmentation structure and list

* feat: remove unused deps and change route

* feat: change header style and add renderNoSegments

* fix: style table header

* feat: create useSegments hook

* feat: add segmentApi hook

* feat: create segment

* fix: errors

* feat: add contextfields list

* fix: remove user from create segment api

* feat: add form structure

* feat: add SegmentFormStepOne

* fix: tests and routes

* feat: add constraint view

* feat: UI to match the sketch

* feat: add constraint on context select

* fix: duplication

* fix adding constraints

Co-authored-by: olav <mail@olav.io>

* fix: input date not showing up in constraint view

Co-authored-by: olav <mail@olav.io>

* fix: minor bugs

Co-authored-by: olav <mail@olav.io>

* fix: create context modal in segment page

Co-authored-by: olav <mail@olav.io>

* fix: validate constraint before create segment

Co-authored-by: olav <mail@olav.io>

* feat: create useSegment hook

Co-authored-by: olav <mail@olav.io>

* feat: create edit component

Co-authored-by: olav <mail@olav.io>

* refactor: move constraint validation endpoint

* refactor: add missing route snapshot

* refactor: fix segment constraints unsaved/editing state

* refactor: remove create segment from mobile header menu

* refactor: update segments form description

* refactor: extract SegmentFormStepList component

* refactor: add an optional FormTemplate docs link label

* refactor: fix update segment payload

* feat: finish edit component

Co-authored-by: olav <mail@olav.io>

* refactor: move step list above segment form

* fix: update PR based on feedback

Co-authored-by: olav <mail@olav.io>

* refactor: fix constraint validation endpoint path

* refactor: improve constraint state field name

* refactor: extract AutocompleteBox component

* feat: add strategy segment selection

* refactor: add strategy segment previews

* refactor: fix double section separator line

* feat: disable deleting a usable segment

* refactor: warn about segments without constraints

* refactor: update text in delete segment dialogue

* refactur: improve arg names

* refactor: improve index var name

* refactor: clarify steps list logic

* refactor: use a required prop for the segment name

* refactor: use ConditionallyRender for segment deletion

* refactor: fix segments refetch

* refactor: improve CreateUnleashContext component names

* refactor: adjust segment form styles

* refactor: adjust text

* refactor: fix info icon tooltip hover target

* refactor: add missing aria attrs to preview button

* refactor: add strat name to delete segment modal

* refactor: fix segment chip text alighment

* refactor: use bulk endpoint for strategy segments

* refactor: fix imports after merge

Co-authored-by: Fredrik Oseberg <fredrik.no@gmail.com>
Co-authored-by: olav <mail@olav.io>
2022-03-29 09:30:57 +02:00

182 lines
5.6 KiB
TypeScript

import { useStyles } from './FormTemplate.styles';
import MenuBookIcon from '@material-ui/icons/MenuBook';
import Codebox from '../Codebox/Codebox';
import { Collapse, IconButton, useMediaQuery } from '@material-ui/core';
import { FileCopy, Info } from '@material-ui/icons';
import ConditionallyRender from '../ConditionallyRender';
import Loader from '../Loader/Loader';
import copy from 'copy-to-clipboard';
import useToast from 'hooks/useToast';
import React, { useState } from 'react';
import classNames from 'classnames';
import { ReactComponent as MobileGuidanceBG } from 'assets/img/mobileGuidanceBg.svg';
import { useCommonStyles } from 'common.styles';
interface ICreateProps {
title: string;
description: string;
documentationLink: string;
documentationLinkLabel?: string;
loading?: boolean;
modal?: boolean;
formatApiCode: () => string;
}
const FormTemplate: React.FC<ICreateProps> = ({
title,
description,
children,
documentationLink,
documentationLinkLabel,
loading,
modal,
formatApiCode,
}) => {
const { setToastData } = useToast();
const styles = useStyles();
const commonStyles = useCommonStyles();
const smallScreen = useMediaQuery(`(max-width:${1099}px)`);
const copyCommand = () => {
if (copy(formatApiCode())) {
setToastData({
title: 'Successfully copied the command',
text: 'The command should now be automatically copied to your clipboard',
autoHideDuration: 6000,
type: 'success',
show: true,
});
} else {
setToastData({
title: 'Could not copy the command',
text: 'Sorry, but we could not copy the command.',
autoHideDuration: 6000,
type: 'error',
show: true,
});
}
};
return (
<section
className={classNames(styles.container, modal && styles.modal)}
>
<ConditionallyRender
condition={smallScreen}
show={
<div className={commonStyles.relative}>
<MobileGuidance
description={description}
documentationLink={documentationLink}
documentationLinkLabel={documentationLinkLabel}
/>
</div>
}
/>
<div className={styles.formContent}>
<ConditionallyRender
condition={loading || false}
show={<Loader />}
elseShow={
<>
<h2 className={styles.title}>{title}</h2>
{children}
</>
}
/>{' '}
</div>
<ConditionallyRender
condition={!smallScreen}
show={
<Guidance
description={description}
documentationLink={documentationLink}
documentationLinkLabel={documentationLinkLabel}
>
<h3 className={styles.subtitle}>
API Command{' '}
<IconButton onClick={copyCommand}>
<FileCopy className={styles.icon} />
</IconButton>
</h3>
<Codebox text={formatApiCode()} />
</Guidance>
}
/>
</section>
);
};
interface IMobileGuidance {
description: string;
documentationLink: string;
documentationLinkLabel?: string;
}
const MobileGuidance = ({
description,
documentationLink,
documentationLinkLabel,
}: IMobileGuidance) => {
const [open, setOpen] = useState(false);
const styles = useStyles();
return (
<>
<div className={styles.mobileGuidanceBgContainer}>
<MobileGuidanceBG className={styles.mobileGuidanceBackground} />
</div>
<IconButton
className={styles.mobileGuidanceButton}
onClick={() => setOpen(prev => !prev)}
>
<Info className={styles.infoIcon} />
</IconButton>
<Collapse in={open} timeout={500}>
<Guidance
description={description}
documentationLink={documentationLink}
documentationLinkLabel={documentationLinkLabel}
/>
</Collapse>
</>
);
};
interface IGuidanceProps {
description: string;
documentationLink: string;
documentationLinkLabel?: string;
}
const Guidance: React.FC<IGuidanceProps> = ({
description,
children,
documentationLink,
documentationLinkLabel = 'Learn more',
}) => {
const styles = useStyles();
return (
<aside className={styles.sidebar}>
<p className={styles.description}>{description}</p>
<div className={styles.linkContainer}>
<MenuBookIcon className={styles.linkIcon} />
<a
className={styles.documentationLink}
href={documentationLink}
rel="noopener noreferrer"
target="_blank"
>
{documentationLinkLabel}
</a>
</div>
{children}
</aside>
);
};
export default FormTemplate;