Skip to content
Snippets Groups Projects
Unverified Commit 28562379 authored by Anton Kulyk's avatar Anton Kulyk Committed by GitHub
Browse files

Remove `redux-form` from collection create/edit forms (#22586)

* Turn `CollectionCreate` into functional component

* Convert `CollectionCreate` to TypeScript

* Add `onChangeField` to Form container

* Remove `redux-form` from `CollectionCreate`

* Fix collection form selector

* Move `CollectionEdit` to its own directory

* Move `CollectionEditForm` to its own file

* Turn `CollectionEdit` into functional component

* Migrate `CollectionEdit` components to TypeScript

* Fix `CollectionCreate`

* Fix `CollectionEdit`

* Fix optional `Form` `onChange` prop
parent f948ea6f
No related branches found
No related tags found
No related merge requests found
Showing
with 320 additions and 126 deletions
/* eslint-disable react/prop-types */
import React, { Component } from "react";
import { connect } from "react-redux";
import { getValues } from "redux-form";
import { withRouter } from "react-router";
import { goBack } from "react-router-redux";
import _ from "underscore";
import Collection from "metabase/entities/collections";
import { PLUGIN_COLLECTIONS } from "metabase/plugins";
const { REGULAR_COLLECTION } = PLUGIN_COLLECTIONS;
const FORM_NAME = "create-collection";
const mapStateToProps = (state, props) => {
const formValues = getValues(state.form[FORM_NAME]);
return {
form: Collection.selectors.getForm(state, { ...props, formValues }),
initialCollectionId: Collection.selectors.getInitialCollectionId(
state,
props,
),
};
};
const mapDispatchToProps = {
goBack,
};
class CollectionCreate extends Component {
handleClose = () => {
const { goBack, onClose } = this.props;
return onClose ? onClose() : goBack();
};
handleSaved = collection => {
const { goBack, onSaved } = this.props;
return onSaved ? onSaved(collection) : goBack();
};
render() {
const { form, initialCollectionId } = this.props;
return (
<Collection.ModalForm
overwriteOnInitialValuesChange
formName={FORM_NAME}
form={form}
collection={{
parent_id: initialCollectionId,
authority_level: REGULAR_COLLECTION.type,
}}
onSaved={this.handleSaved}
onClose={this.handleClose}
/>
);
}
}
export default _.compose(
withRouter,
connect(mapStateToProps, mapDispatchToProps),
)(CollectionCreate);
import React, { useCallback, useEffect, useState } from "react";
import { connect } from "react-redux";
import { withRouter } from "react-router";
import { goBack } from "react-router-redux";
import _ from "underscore";
import { Collection as BaseCollection, CollectionId } from "metabase-types/api";
import { State } from "metabase-types/store";
import Collections from "metabase/entities/collections";
import CollectionCreateForm from "./CollectionCreateForm";
type Collection = BaseCollection & {
parent_id: CollectionId;
};
interface CollectionCreateOwnProps {
goBack?: () => void;
onClose?: () => void;
onSaved?: (collection: Collection) => void;
}
interface CollectionCreateStateProps {
initialCollectionId: CollectionId;
}
interface CollectionCreateProps
extends CollectionCreateOwnProps,
CollectionCreateStateProps {}
function mapStateToProps(state: State, props: CollectionCreateOwnProps) {
return {
initialCollectionId: Collections.selectors.getInitialCollectionId(
state,
props,
),
};
}
const mapDispatchToProps = {
goBack,
};
function CollectionCreate({
initialCollectionId,
goBack,
onClose,
onSaved,
}: CollectionCreateProps) {
const [parentCollectionId, setParentCollectionId] = useState<CollectionId>(
initialCollectionId,
);
const [hasSetParentCollection, setHasSetParentCollection] = useState(false);
useEffect(() => {
if (!hasSetParentCollection) {
setParentCollectionId(initialCollectionId);
}
}, [initialCollectionId, hasSetParentCollection]);
const onChangeValues = useCallback(
(collection: Collection) => {
if (collection.parent_id !== parentCollectionId) {
setParentCollectionId(collection.parent_id);
setHasSetParentCollection(true);
}
},
[parentCollectionId],
);
const handleClose = useCallback(() => {
if (onClose) {
onClose();
} else {
goBack?.();
}
}, [goBack, onClose]);
const handleSave = useCallback(
(collection: Collection) => {
if (onSaved) {
onSaved(collection);
} else {
goBack?.();
}
},
[goBack, onSaved],
);
return (
<CollectionCreateForm
parentCollectionId={parentCollectionId}
onChange={onChangeValues}
onSaved={handleSave}
onClose={handleClose}
/>
);
}
export default _.compose(
withRouter,
connect(mapStateToProps, mapDispatchToProps),
)(CollectionCreate);
import React from "react";
import { connect } from "react-redux";
import { withRouter } from "react-router";
import _ from "underscore";
import { Collection as BaseCollection, CollectionId } from "metabase-types/api";
import { State } from "metabase-types/store";
import Collections from "metabase/entities/collections";
import { PLUGIN_COLLECTIONS } from "metabase/plugins";
const { REGULAR_COLLECTION } = PLUGIN_COLLECTIONS;
type Collection = BaseCollection & {
parent_id: CollectionId;
};
interface CollectionCreateFormOwnProps {
parentCollectionId: CollectionId;
onChange: (collection: Collection) => void;
onSaved?: (collection: Collection) => void;
onClose?: () => void;
}
interface CollectionCreateFormStateProps {
form: unknown;
}
interface CollectionCreateFormProps
extends CollectionCreateFormOwnProps,
CollectionCreateFormStateProps {}
function mapStateToProps(state: State, props: CollectionCreateFormOwnProps) {
return {
form: Collections.selectors.getForm(state, props),
};
}
function CollectionCreateForm({
form,
parentCollectionId,
onChange,
onSaved,
onClose,
}: CollectionCreateFormProps) {
return (
<Collections.ModalForm
form={form}
collection={{
parent_id: parentCollectionId,
authority_level: REGULAR_COLLECTION.type,
}}
overwriteOnInitialValuesChange
onChange={onChange}
onSaved={onSaved}
onClose={onClose}
/>
);
}
export default _.compose(
withRouter,
connect(mapStateToProps),
)(CollectionCreateForm);
export { default } from "./CollectionCreate";
/* eslint-disable react/prop-types */
import React, { Component } from "react";
import { connect } from "react-redux";
import { goBack, push } from "react-router-redux";
import * as Urls from "metabase/lib/urls";
import Collection from "metabase/entities/collections";
function mapStateToProps(state, props) {
return {
form: Collection.selectors.getForm(state, props),
};
}
function CollectionForm({ form, collection, onSave, onClose }) {
return (
<Collection.ModalForm
form={form}
collection={collection}
onSaved={onSave}
onClose={onClose}
/>
);
}
const UpdateCollectionForm = connect(mapStateToProps)(CollectionForm);
const mapDispatchToProps = {
push,
goBack,
};
class CollectionEdit extends Component {
onSave = updatedCollection => {
const url = Urls.collection(updatedCollection);
this.props.push(url);
};
render() {
const collectionId = Urls.extractCollectionId(this.props.params.slug);
return (
<Collection.Loader id={collectionId}>
{({ collection, update }) => (
<UpdateCollectionForm
collection={collection}
onSave={this.onSave}
onClose={this.props.goBack}
/>
)}
</Collection.Loader>
);
}
}
export default connect(null, mapDispatchToProps)(CollectionEdit);
import React, { useCallback, useEffect, useState } from "react";
import { connect } from "react-redux";
import { goBack, push, LocationAction } from "react-router-redux";
import _ from "underscore";
import * as Urls from "metabase/lib/urls";
import Collections from "metabase/entities/collections";
import { Collection as BaseCollection, CollectionId } from "metabase-types/api";
import { State } from "metabase-types/store";
import CollectionEditForm from "./CollectionEditForm";
type Collection = BaseCollection & {
parent_id: CollectionId;
};
interface CollectionEditOwnProps {
params: {
slug: string;
};
}
interface CollectionEditLoaderProps {
collection: Collection;
}
interface CollectionEditDispatchProps {
push: LocationAction;
goBack: () => void;
}
interface CollectionEditProps
extends CollectionEditOwnProps,
CollectionEditLoaderProps,
CollectionEditDispatchProps {}
const mapDispatchToProps = {
push,
goBack,
};
function CollectionEdit({ collection, push, goBack }: CollectionEditProps) {
const [parentCollectionId, setParentCollectionId] = useState<CollectionId>(
collection?.parent_id,
);
const [hasSetParentCollection, setHasSetParentCollection] = useState(false);
useEffect(() => {
if (collection && !hasSetParentCollection) {
setParentCollectionId(collection.parent_id);
}
}, [collection, hasSetParentCollection]);
const onChangeValues = useCallback(
(collection: Collection) => {
if (collection.parent_id !== parentCollectionId) {
setParentCollectionId(collection.parent_id);
setHasSetParentCollection(true);
}
},
[parentCollectionId],
);
const onSave = useCallback(
collection => {
push(Urls.collection(collection));
},
[push],
);
return (
<CollectionEditForm
collection={collection}
parentCollectionId={parentCollectionId}
onChange={onChangeValues}
onSave={onSave}
onClose={goBack}
/>
);
}
export default _.compose(
connect<unknown, CollectionEditDispatchProps, CollectionEditOwnProps, State>(
null,
mapDispatchToProps,
),
Collections.load({
id: (state: State, props: CollectionEditOwnProps) =>
Urls.extractCollectionId(props.params.slug),
}),
)(CollectionEdit);
import React from "react";
import { connect } from "react-redux";
import Collections from "metabase/entities/collections";
import { Collection as BaseCollection, CollectionId } from "metabase-types/api";
import { State } from "metabase-types/store";
type Collection = BaseCollection & {
parent_id: CollectionId;
};
interface CollectionEditFormOwnProps {
collection: Collection;
parentCollectionId: CollectionId;
onChange: (collection: Collection) => void;
onSave: (collection: Collection) => void;
onClose: () => void;
}
interface CollectionEditFormStateProps {
form: unknown;
}
interface CollectionEditProps
extends CollectionEditFormOwnProps,
CollectionEditFormStateProps {}
function mapStateToProps(state: State, props: CollectionEditFormOwnProps) {
return {
form: Collections.selectors.getForm(state, props),
};
}
function CollectionEditForm({
form,
collection,
onChange,
onSave,
onClose,
}: CollectionEditProps) {
return (
<Collections.ModalForm
form={form}
collection={collection}
overwriteOnInitialValuesChange
onChange={onChange}
onSaved={onSave}
onClose={onClose}
/>
);
}
export default connect(mapStateToProps)(CollectionEditForm);
export { default } from "./CollectionEdit";
......@@ -169,6 +169,7 @@ class Form extends React.Component {
initialize(this.props.formName, this._getInitialValues(), newFields),
);
}
this.props.onChange?.(this.props.values);
}
_registerFormField = field => {
......
......@@ -63,19 +63,15 @@ function isPersonalOrPersonalChild(collection, collectionList) {
export const getFormSelector = createSelector(
[
(state, props) => props.collection || {},
(state, props) => props.formValues || {},
(state, props) => props.parentCollectionId,
state => state.entities.collections || {},
getUser,
],
(collection, formValues, allCollections, user) => {
(collection, parentCollectionId, allCollections, user) => {
const collectionList = Object.values(allCollections);
const extraFields = [];
const creatingNewCollection = !collection.id;
const parentId = creatingNewCollection
? formValues.parent_id
: collection.parent_id;
const parentId = parentCollectionId || collection?.parent_id;
const parentCollection = allCollections[parentId];
const canManageAuthorityLevel =
user.is_superuser &&
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment