feat: retrofits DocumentDrawer into relationship AddNew
This commit is contained in:
@@ -1,117 +0,0 @@
|
||||
@import '../../../../../../scss/styles.scss';
|
||||
|
||||
.relationship-add-new-modal {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
height: 100vh;
|
||||
|
||||
&__blur-bg {
|
||||
@include blur-bg();
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
transition: all 300ms ease-out;
|
||||
}
|
||||
|
||||
.collection-edit {
|
||||
@include blur-bg();
|
||||
transform: translateX(#{base(4)});
|
||||
opacity: 0;
|
||||
transition: all 300ms ease-out;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.collection-edit__form {
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.collection-edit__document-actions {
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
||||
&--animated {
|
||||
|
||||
.collection-edit,
|
||||
.relationship-add-new-modal__blur-bg,
|
||||
.relationship-add-new-modal__close {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.collection-edit {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.collection-edit__document-actions {
|
||||
margin-top: base(2.75);
|
||||
}
|
||||
|
||||
&__close {
|
||||
@extend %btn-reset;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
flex-shrink: 0;
|
||||
text-indent: -9999px;
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: all 300ms ease-in-out;
|
||||
transition-delay: 100ms;
|
||||
|
||||
&:active,
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-top: base(2.5);
|
||||
}
|
||||
|
||||
&__header-close {
|
||||
svg {
|
||||
width: base(2.5);
|
||||
height: base(2.5);
|
||||
position: relative;
|
||||
top: base(-.5);
|
||||
right: base(-.75);
|
||||
|
||||
.stroke {
|
||||
stroke-width: .5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
&__header-close {
|
||||
svg {
|
||||
top: base(-.75);
|
||||
}
|
||||
}
|
||||
|
||||
&__close {
|
||||
width: base(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme=dark] {
|
||||
.relationship-add-new-modal__close {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Modal, useModal } from '@faceless-ui/modal';
|
||||
import { useWindowInfo } from '@faceless-ui/window-info';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Button from '../../../../../elements/Button';
|
||||
import { Props } from './types';
|
||||
import { useAuth } from '../../../../../utilities/Auth';
|
||||
import RenderCustomComponent from '../../../../../utilities/RenderCustomComponent';
|
||||
import { useLocale } from '../../../../../utilities/Locale';
|
||||
import { useConfig } from '../../../../../utilities/Config';
|
||||
import DefaultEdit from '../../../../../views/collections/Edit/Default';
|
||||
import X from '../../../../../icons/X';
|
||||
import { Fields } from '../../../../Form/types';
|
||||
import buildStateFromSchema from '../../../../Form/buildStateFromSchema';
|
||||
import { EditDepthContext, useEditDepth } from '../../../../../utilities/EditDepth';
|
||||
import { getTranslation } from '../../../../../../../utilities/getTranslation';
|
||||
import { DocumentInfoProvider } from '../../../../../utilities/DocumentInfo';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'relationship-add-new-modal';
|
||||
|
||||
export const AddNewRelationModal: React.FC<Props> = ({ modalCollection, onSave, modalSlug }) => {
|
||||
const { serverURL, routes: { api } } = useConfig();
|
||||
const { toggleModal } = useModal();
|
||||
const { breakpoints: { m: midBreak } } = useWindowInfo();
|
||||
const locale = useLocale();
|
||||
const { permissions, user } = useAuth();
|
||||
const [initialState, setInitialState] = useState<Fields>();
|
||||
const [isAnimated, setIsAnimated] = useState(false);
|
||||
const editDepth = useEditDepth();
|
||||
const { t, i18n } = useTranslation('fields');
|
||||
|
||||
const modalAction = `${serverURL}${api}/${modalCollection.slug}?locale=${locale}&depth=0&fallback-locale=null`;
|
||||
|
||||
useEffect(() => {
|
||||
const buildState = async () => {
|
||||
const state = await buildStateFromSchema({ fieldSchema: modalCollection.fields, data: {}, user, operation: 'create', locale, t });
|
||||
setInitialState(state);
|
||||
};
|
||||
|
||||
buildState();
|
||||
}, [modalCollection, locale, user, t]);
|
||||
|
||||
useEffect(() => {
|
||||
setIsAnimated(true);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
slug={modalSlug}
|
||||
className={[
|
||||
baseClass,
|
||||
isAnimated && `${baseClass}--animated`,
|
||||
].filter(Boolean).join(' ')}
|
||||
>
|
||||
{editDepth === 1 && (
|
||||
<div className={`${baseClass}__blur-bg`} />
|
||||
)}
|
||||
<DocumentInfoProvider collection={modalCollection}>
|
||||
<EditDepthContext.Provider value={editDepth + 1}>
|
||||
<button
|
||||
className={`${baseClass}__close`}
|
||||
type="button"
|
||||
onClick={() => toggleModal(modalSlug)}
|
||||
style={{
|
||||
width: `calc(${midBreak ? 'var(--gutter-h)' : 'var(--nav-width)'} + ${editDepth - 1} * 25px)`,
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
Close
|
||||
</span>
|
||||
</button>
|
||||
<RenderCustomComponent
|
||||
DefaultComponent={DefaultEdit}
|
||||
CustomComponent={modalCollection.admin?.components?.views?.Edit}
|
||||
componentProps={{
|
||||
isLoading: !initialState,
|
||||
data: {},
|
||||
collection: modalCollection,
|
||||
permissions: permissions.collections[modalCollection.slug],
|
||||
isEditing: false,
|
||||
onSave,
|
||||
initialState,
|
||||
hasSavePermission: true,
|
||||
action: modalAction,
|
||||
disableEyebrow: true,
|
||||
disableActions: true,
|
||||
disableLeaveWithoutSaving: true,
|
||||
customHeader: (
|
||||
<div className={`${baseClass}__header`}>
|
||||
<h2>
|
||||
{t('addNewLabel', { label: getTranslation(modalCollection.labels.singular, i18n) })}
|
||||
</h2>
|
||||
<Button
|
||||
buttonStyle="none"
|
||||
className={`${baseClass}__header-close`}
|
||||
onClick={() => toggleModal(modalSlug)}
|
||||
>
|
||||
<X />
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</EditDepthContext.Provider>
|
||||
</DocumentInfoProvider>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
import { SanitizedCollectionConfig } from '../../../../../../../collections/config/types';
|
||||
|
||||
export type Props = {
|
||||
modalSlug: string
|
||||
modalCollection: SanitizedCollectionConfig
|
||||
onSave: (json: Record<string, unknown>) => void
|
||||
}
|
||||
@@ -12,28 +12,16 @@
|
||||
|
||||
&__add-button {
|
||||
@include formInput;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
margin-left: -1px;
|
||||
display: flex;
|
||||
padding: 0;
|
||||
|
||||
.btn__content,
|
||||
.btn__label {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.btn__content,
|
||||
.btn__label {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.btn__label {
|
||||
padding: 0 base(.5);
|
||||
align-items: center;
|
||||
}
|
||||
padding: 0 base(0.5);
|
||||
align-items: center;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
&__relations {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
@@ -57,4 +45,4 @@
|
||||
opacity: .7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import React, { Fragment, useCallback, useEffect, useState } from 'react';
|
||||
import { useModal } from '@faceless-ui/modal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Button from '../../../../elements/Button';
|
||||
@@ -7,10 +7,11 @@ import { SanitizedCollectionConfig } from '../../../../../../collections/config/
|
||||
import Popup from '../../../../elements/Popup';
|
||||
import { useRelatedCollections } from './useRelatedCollections';
|
||||
import { useAuth } from '../../../../utilities/Auth';
|
||||
import { AddNewRelationModal } from './Modal';
|
||||
import { useEditDepth } from '../../../../utilities/EditDepth';
|
||||
import Plus from '../../../../icons/Plus';
|
||||
import { getTranslation } from '../../../../../../utilities/getTranslation';
|
||||
import { DocumentDrawer, DocumentDrawerToggler } from '../../../../elements/DocumentDrawer';
|
||||
import Tooltip from '../../../../elements/Tooltip';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
@@ -18,30 +19,26 @@ const baseClass = 'relationship-add-new';
|
||||
|
||||
export const AddNewRelation: React.FC<Props> = ({ path, hasMany, relationTo, value, setValue, dispatchOptions }) => {
|
||||
const relatedCollections = useRelatedCollections(relationTo);
|
||||
const { toggleModal, isModalOpen } = useModal();
|
||||
const { isModalOpen } = useModal();
|
||||
const { permissions } = useAuth();
|
||||
const [hasPermission, setHasPermission] = useState(false);
|
||||
const [modalCollection, setModalCollection] = useState<SanitizedCollectionConfig>();
|
||||
const [selectedCollection, setSelectedCollection] = useState<SanitizedCollectionConfig>();
|
||||
const [popupOpen, setPopupOpen] = useState(false);
|
||||
const editDepth = useEditDepth();
|
||||
const { t, i18n } = useTranslation('fields');
|
||||
const [showTooltip, setShowTooltip] = useState(false);
|
||||
|
||||
const modalSlug = `${path}-add-modal-depth-${editDepth}`;
|
||||
|
||||
const openModal = useCallback(async (collection: SanitizedCollectionConfig) => {
|
||||
setModalCollection(collection);
|
||||
toggleModal(modalSlug);
|
||||
}, [toggleModal, modalSlug]);
|
||||
|
||||
const onSave = useCallback((json) => {
|
||||
const newValue = Array.isArray(relationTo) ? {
|
||||
relationTo: modalCollection.slug,
|
||||
relationTo: selectedCollection.slug,
|
||||
value: json.doc.id,
|
||||
} : json.doc.id;
|
||||
|
||||
dispatchOptions({
|
||||
type: 'ADD',
|
||||
collection: modalCollection,
|
||||
collection: selectedCollection,
|
||||
docs: [
|
||||
json.doc,
|
||||
],
|
||||
@@ -55,9 +52,9 @@ export const AddNewRelation: React.FC<Props> = ({ path, hasMany, relationTo, val
|
||||
setValue(newValue);
|
||||
}
|
||||
|
||||
setModalCollection(undefined);
|
||||
toggleModal(modalSlug);
|
||||
}, [relationTo, modalCollection, dispatchOptions, i18n, hasMany, toggleModal, modalSlug, setValue, value]);
|
||||
setSelectedCollection(undefined);
|
||||
// toggleModal(modalSlug);
|
||||
}, [relationTo, selectedCollection, dispatchOptions, i18n, hasMany, setValue, value]);
|
||||
|
||||
const onPopopToggle = useCallback((state) => {
|
||||
setPopupOpen(state);
|
||||
@@ -75,7 +72,7 @@ export const AddNewRelation: React.FC<Props> = ({ path, hasMany, relationTo, val
|
||||
|
||||
useEffect(() => {
|
||||
if (!isModalOpen(modalSlug)) {
|
||||
setModalCollection(undefined);
|
||||
setSelectedCollection(undefined);
|
||||
}
|
||||
}, [isModalOpen, modalSlug]);
|
||||
|
||||
@@ -85,56 +82,75 @@ export const AddNewRelation: React.FC<Props> = ({ path, hasMany, relationTo, val
|
||||
id={`${path}-add-new`}
|
||||
>
|
||||
{relatedCollections.length === 1 && (
|
||||
<Button
|
||||
className={`${baseClass}__add-button`}
|
||||
onClick={() => openModal(relatedCollections[0])}
|
||||
buttonStyle="none"
|
||||
tooltip={t('addNewLabel', { label: relatedCollections[0].labels.singular })}
|
||||
>
|
||||
<Plus />
|
||||
</Button>
|
||||
<Fragment>
|
||||
<DocumentDrawerToggler
|
||||
className={`${baseClass}__add-button`}
|
||||
collection={relatedCollections[0].slug}
|
||||
onMouseEnter={() => setShowTooltip(true)}
|
||||
onMouseLeave={() => setShowTooltip(false)}
|
||||
>
|
||||
{showTooltip && (
|
||||
<Tooltip className={`${baseClass}__tooltip`}>
|
||||
{t('addNewLabel', { label: relatedCollections[0].labels.singular })}
|
||||
</Tooltip>
|
||||
)}
|
||||
<Plus />
|
||||
</DocumentDrawerToggler>
|
||||
{relatedCollections[0] && (
|
||||
<DocumentDrawer
|
||||
collection={relatedCollections[0].slug}
|
||||
onSave={onSave}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
{relatedCollections.length > 1 && (
|
||||
<Popup
|
||||
buttonType="custom"
|
||||
horizontalAlign="center"
|
||||
onToggleOpen={onPopopToggle}
|
||||
button={(
|
||||
<Button
|
||||
className={`${baseClass}__add-button`}
|
||||
buttonStyle="none"
|
||||
tooltip={popupOpen ? undefined : t('addNew')}
|
||||
>
|
||||
<Plus />
|
||||
</Button>
|
||||
<Fragment>
|
||||
<Popup
|
||||
buttonType="custom"
|
||||
horizontalAlign="center"
|
||||
onToggleOpen={onPopopToggle}
|
||||
button={(
|
||||
<Button
|
||||
className={`${baseClass}__add-button`}
|
||||
buttonStyle="none"
|
||||
tooltip={popupOpen ? undefined : t('addNew')}
|
||||
>
|
||||
<Plus />
|
||||
</Button>
|
||||
)}
|
||||
render={({ close: closePopup }) => (
|
||||
<ul className={`${baseClass}__relations`}>
|
||||
{relatedCollections.map((relatedCollection) => {
|
||||
if (permissions.collections[relatedCollection.slug].create.permission) {
|
||||
return (
|
||||
<li key={relatedCollection.slug}>
|
||||
<button
|
||||
className={`${baseClass}__relation-button ${baseClass}__relation-button--${relatedCollection.slug}`}
|
||||
type="button"
|
||||
onClick={() => { closePopup(); openModal(relatedCollection); }}
|
||||
>
|
||||
{getTranslation(relatedCollection.labels.singular, i18n)}
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
render={({ close: closePopup }) => (
|
||||
<ul className={`${baseClass}__relations`}>
|
||||
{relatedCollections.map((relatedCollection) => {
|
||||
if (permissions.collections[relatedCollection.slug].create.permission) {
|
||||
return (
|
||||
<li key={relatedCollection.slug}>
|
||||
<DocumentDrawerToggler
|
||||
collection={relatedCollection.slug}
|
||||
className={`${baseClass}__relation-button ${baseClass}__relation-button--${relatedCollection.slug}`}
|
||||
onClick={() => {
|
||||
closePopup();
|
||||
setSelectedCollection(relatedCollection);
|
||||
}}
|
||||
>
|
||||
{getTranslation(relatedCollection.labels.singular, i18n)}
|
||||
</DocumentDrawerToggler>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
})}
|
||||
</ul>
|
||||
return null;
|
||||
})}
|
||||
</ul>
|
||||
)}
|
||||
/>
|
||||
{selectedCollection && (
|
||||
<DocumentDrawer
|
||||
collection={selectedCollection.slug}
|
||||
onSave={onSave}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{modalCollection && (
|
||||
<AddNewRelationModal
|
||||
{...{ onSave, modalSlug, modalCollection }}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
Reference in New Issue
Block a user