123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- import {Component, Fragment} from 'react';
- import {WithRouterProps} from 'react-router';
- import * as Sentry from '@sentry/react';
- import scrollToElement from 'scroll-to-element';
- import {defined} from 'sentry/utils';
- import {sanitizeQuerySelector} from 'sentry/utils/sanitizeQuerySelector';
- import withSentryRouter from 'sentry/utils/withSentryRouter';
- import FormPanel from './formPanel';
- import {Field, FieldObject, JsonFormObject} from './types';
- type Props = {
- additionalFieldProps?: {[key: string]: any};
-
- fields?: FieldObject[];
-
- forms?: JsonFormObject[];
- } & WithRouterProps &
- Omit<
- React.ComponentProps<typeof FormPanel>,
- 'highlighted' | 'fields' | 'additionalFieldProps'
- >;
- type State = {
-
- highlighted?: string;
- };
- class JsonForm extends Component<Props, State> {
- state: State = {
-
- highlighted: this.props.location?.hash,
- };
- componentDidMount() {
- this.scrollToHash();
- }
- componentDidUpdate(prevProps: Props) {
- if (this.props.location && this.props.location.hash !== prevProps.location.hash) {
- const hash = this.props.location.hash;
- this.scrollToHash(hash);
- this.setState({highlighted: hash});
- }
- }
- scrollToHash(toHash?: string): void {
-
- const hash = toHash || this.props.location?.hash;
- if (!hash) {
- return;
- }
-
-
-
- try {
- scrollToElement(sanitizeQuerySelector(decodeURIComponent(hash)), {
- align: 'middle',
- offset: -100,
- });
- } catch (err) {
- Sentry.captureException(err);
- }
- }
- shouldDisplayForm(fields: FieldObject[]) {
- const fieldsWithVisibleProp = fields.filter(
- field => typeof field !== 'function' && defined(field?.visible)
- ) as Array<Omit<Field, 'visible'> & Required<Pick<Field, 'visible'>>>;
- if (fields.length === fieldsWithVisibleProp.length) {
- const {additionalFieldProps, ...props} = this.props;
- const areAllFieldsHidden = fieldsWithVisibleProp.every(field => {
- if (typeof field.visible === 'function') {
- return !field.visible({...props, ...additionalFieldProps});
- }
- return !field.visible;
- });
- return !areAllFieldsHidden;
- }
- return true;
- }
- renderForm({
- fields,
- formPanelProps,
- title,
- }: {
- fields: FieldObject[];
- formPanelProps: Pick<
- Props,
- | 'access'
- | 'disabled'
- | 'features'
- | 'additionalFieldProps'
- | 'renderFooter'
- | 'renderHeader'
- > &
- Pick<State, 'highlighted'>;
- title?: React.ReactNode;
- }) {
- const shouldDisplayForm = this.shouldDisplayForm(fields);
- if (
- !shouldDisplayForm &&
- !formPanelProps?.renderFooter &&
- !formPanelProps?.renderHeader
- ) {
- return null;
- }
- return <FormPanel title={title} fields={fields} {...formPanelProps} />;
- }
- render() {
- const {
- access,
- collapsible,
- fields,
- title,
- forms,
- disabled,
- features,
- additionalFieldProps,
- renderFooter,
- renderHeader,
- location: _location,
- params: _params,
- router: _router,
- routes: _routes,
- ...otherProps
- } = this.props;
- const formPanelProps = {
- access,
- disabled,
- features,
- additionalFieldProps,
- renderFooter,
- renderHeader,
- highlighted: this.state.highlighted,
- collapsible,
- };
- return (
- <div {...otherProps}>
- {typeof forms !== 'undefined' &&
- forms.map((formGroup, i) => (
- <Fragment key={i}>{this.renderForm({formPanelProps, ...formGroup})}</Fragment>
- ))}
- {typeof forms === 'undefined' &&
- typeof fields !== 'undefined' &&
- this.renderForm({fields, formPanelProps, title})}
- </div>
- );
- }
- }
- export default withSentryRouter(JsonForm);
|