Skip to content
Snippets Groups Projects
Unverified Commit a016ecca authored by Ryan Laurie's avatar Ryan Laurie Committed by GitHub
Browse files

Collection moving with EntityPicker (#39869)

* wip - collection moving

fix subcollection detection

make stuff nice

update e2e tests

prettier

new e2e coverage

fix unit tests

fix stacked modals

cleanup

less diff

sneaky-ass modal wrappers

fix some e2e tests

* rebase rejigger

* fix tricky e2e flake
parent 0c9e3d55
Branches
Tags
No related merge requests found
Showing
with 260 additions and 163 deletions
import { getFullName, modal, popover } from "e2e/support/helpers";
import { entityPickerModal, getFullName, popover } from "e2e/support/helpers";
/**
* Clicks the "+" icon on the collection page and selects one of the menu options
......@@ -75,13 +75,12 @@ export const moveOpenedCollectionTo = newParent => {
openCollectionMenu();
popover().within(() => cy.findByText("Move").click());
cy.findAllByTestId("item-picker-item").contains(newParent).click();
modal().within(() => {
entityPickerModal().within(() => {
cy.findByText(newParent).click();
cy.button("Move").click();
});
// Make sure modal closed
modal().should("not.exist");
entityPickerModal().should("not.exist");
};
export function pickEntity({ path, select }) {
......
......@@ -11,7 +11,6 @@ import {
} from "e2e/support/cypress_sample_instance_data";
import {
restore,
modal,
popover,
openOrdersTable,
navigationSidebar,
......@@ -24,6 +23,7 @@ import {
moveOpenedCollectionTo,
pickEntity,
entityPickerModal,
openCollectionMenu,
} from "e2e/support/helpers";
import { displaySidebarChildOf } from "./helpers/e2e-collections-sidebar.js";
......@@ -36,6 +36,8 @@ describe("scenarios > collection defaults", () => {
restore();
cy.signInAsAdmin();
cy.intercept("GET", "/api/**/items?pinned_state*").as("getPinnedItems");
cy.intercept("GET", "/api/collection/tree**").as("getTree");
cy.intercept("GET", "/api/collection/*/items?**").as("getCollectionItems");
});
describe("new collection modal", () => {
......@@ -397,14 +399,9 @@ describe("scenarios > collection defaults", () => {
cy.findByText("Move").click();
});
modal().within(() => {
cy.findByText("My personal collection")
.parent()
.find(".Icon-chevronright")
.click();
entityPickerModal().within(() => {
cy.findByText("Bobby Tables's Personal Collection").click();
cy.findByText(COLLECTION).click();
cy.button("Move").should("not.be.disabled");
});
});
......@@ -424,7 +421,30 @@ describe("scenarios > collection defaults", () => {
visitCollection(SECOND_COLLECTION_ID);
moveOpenedCollectionTo("Our analytics");
openCollectionMenu();
popover().findByText("Move").click();
// we need to do this manually because we need to await the correct number of api requests to keep this from flaking
cy.wait([
"@getCollectionItems",
"@getCollectionItems",
"@getCollectionItems",
]);
entityPickerModal().within(() => {
cy.findByTestId("loading-spinner").should("not.exist");
// make sure the first collection (current parent) is selected
findPickerItem("First collection").should(
"have.attr",
"data-active",
"true",
);
// then click our analytics
cy.findByText("Our analytics").click();
cy.button("Move").click();
});
entityPickerModal().should("not.exist");
cy.wait("@getTree");
navigationSidebar().within(() => {
ensureCollectionHasNoChildren("First collection");
......@@ -440,6 +460,7 @@ describe("scenarios > collection defaults", () => {
);
moveOpenedCollectionTo(NEW_COLLECTION);
cy.wait("@getTree");
navigationSidebar().within(() => {
ensureCollectionHasNoChildren("Second collection");
......@@ -472,8 +493,7 @@ describe("scenarios > collection defaults", () => {
// Select all
cy.findByLabelText("Select all items").click();
cy.icon("dash").should("not.exist");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(/\d+ items selected/);
cy.findByTestId("toast-card").findByText(/\d+ items selected/);
// Deselect all
cy.findByLabelText("Select all items").click();
......@@ -507,16 +527,11 @@ describe("scenarios > collection defaults", () => {
cy.visit("/collection/root");
selectItemUsingCheckbox("Orders");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(/item(s)? selected/)
.parent()
.button("Archive")
.click();
cy.findByTestId("toast-card").parent().button("Archive").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Orders").should("not.exist");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(/item(s)? selected/).should("not.exist");
cy.findByTestId("toast-card").should("not.exist");
});
});
......@@ -525,21 +540,16 @@ describe("scenarios > collection defaults", () => {
cy.visit("/collection/root");
selectItemUsingCheckbox("Orders");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(/item(s)? selected/)
.parent()
.button("Move")
.click();
cy.findByTestId("toast-card").button("Move").click();
modal().within(() => {
entityPickerModal().within(() => {
cy.findByText("First collection").click();
cy.button("Move").click();
});
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Orders").should("not.exist");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(/item(s)? selected/).should("not.exist");
cy.findByTestId("toast-card").should("not.exist");
// Check that items were actually moved
navigationSidebar().findByText("First collection").click();
......@@ -554,6 +564,77 @@ describe("scenarios > collection defaults", () => {
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Undo").should("not.exist");
});
it("moving collections should disable moving into any of the moving collections", () => {
cy.createCollection({ name: "Another collection" });
cy.log("moving a single collection");
cy.visit(`/collection/${SECOND_COLLECTION_ID}`);
cy.log("from the collection header");
cy.findByTestId("collection-menu").icon("ellipsis").click();
popover().findByText("Move").click();
entityPickerModal().within(() => {
cy.log("parent collection should be selected");
findPickerItem("First collection").should(
"have.attr",
"data-active",
"true",
);
cy.log("moving collection should be visible but disabled");
findPickerItem("Second collection").should("have.attr", "disabled");
cy.findByText("Cancel").click();
});
cy.log("from the collection items list");
cy.findByTestId("collection-table").within(() => {
openEllipsisMenuFor("Third collection");
});
popover().findByText("Move").click();
entityPickerModal().within(() => {
cy.log("parent collection should be selected");
findPickerItem("Second collection").should(
"have.attr",
"data-active",
"true",
);
cy.log("moving collection should be visible but disabled");
findPickerItem("Third collection").should("have.attr", "disabled");
cy.findByText("Cancel").click();
});
cy.log("bulk moving items that include collections");
cy.visit("/collection/root");
cy.findByTestId("collection-table").within(() => {
selectItemUsingCheckbox("Orders");
selectItemUsingCheckbox("Another collection");
selectItemUsingCheckbox("First collection");
});
cy.findByTestId("toast-card").button("Move").click();
entityPickerModal().within(() => {
cy.log("should disable all moving collections");
findPickerItem("First collection").should("have.attr", "disabled");
findPickerItem("Another collection").should(
"have.attr",
"disabled",
);
findPickerItem("Our analytics").should(
"have.attr",
"data-active",
"true",
);
});
});
});
});
......@@ -630,11 +711,8 @@ function visitRootCollection() {
function ensureCollectionHasNoChildren(collection) {
cy.findByText(collection)
.closest("li")
.within(() => {
// We used should.not.exist previously, but
// this icon is now only hidden. It still exists in the DOM.
cy.icon("chevronright").should("be.hidden");
});
.icon("chevronright")
.should("be.hidden");
}
function ensureCollectionIsExpanded(collection, { children = [] } = {}) {
......@@ -672,3 +750,8 @@ function moveItemToCollection(itemName, collectionName) {
return collection.find(item => item.name === itemName);
}
}
// the button element that gets attributes is 2 levels up from the text
function findPickerItem(name) {
return cy.findByText(name).parent().parent();
}
......@@ -13,6 +13,7 @@ import {
modal,
setTokenFeatures,
sidebar,
entityPickerModal,
} from "e2e/support/helpers";
import { displaySidebarChildOf } from "./helpers/e2e-collections-sidebar.js";
......@@ -104,34 +105,6 @@ describe("collection permissions", () => {
it("should let a user move/undo move a dashboard", () => {
move("Orders in a dashboard");
});
function move(item) {
cy.visit("/collection/root");
openCollectionItemMenu(item);
popover().within(() => {
cy.findByText("Move").click();
});
cy.get(".Modal").within(() => {
cy.findByText(`Move "${item}"?`);
// Let's move it into a nested collection
cy.findByText("First collection")
.siblings("[data-testid='expand-btn']")
.click();
cy.findByText("Second collection").click();
cy.findByText("Move").click();
});
cy.findByText(item).should("not.exist");
// Make sure item was properly moved to a correct sub-collection
exposeChildrenFor("First collection");
cy.findByText("Second collection").click();
cy.findByText(item);
// Undo the whole thing
cy.findByText(/Moved (question|dashboard)/);
cy.findByText("Undo").click();
cy.findByText(item).should("not.exist");
cy.visit("/collection/root");
cy.findByText(item);
}
});
describe("duplicate", () => {
......@@ -142,20 +115,6 @@ describe("collection permissions", () => {
it.skip("should be able to duplicate the question (metabase#15255)", () => {
duplicate("Orders");
});
function duplicate(item) {
cy.visit("/collection/root");
openCollectionItemMenu(item);
cy.findByText("Duplicate").click();
cy.get(".Modal")
.as("modal")
.within(() => {
clickButton("Duplicate");
cy.findByText("Failed").should("not.exist");
});
cy.get("@modal").should("not.exist");
cy.findByText(`${item} - Duplicate`);
}
});
describe("archive", () => {
......@@ -485,3 +444,42 @@ function exposeChildrenFor(collectionName) {
.eq(0) // there may be more nested icons, but we need the top level one
.click();
}
function move(item) {
cy.visit("/collection/root");
openCollectionItemMenu(item);
popover().findByText("Move").click();
entityPickerModal().within(() => {
cy.findByText(`Move "${item}"?`);
// Let's move it into a nested collection
cy.findByText("First collection").click();
cy.findByText("Second collection").click();
cy.button("Move").click();
});
cy.findByText(item).should("not.exist");
// Make sure item was properly moved to a correct sub-collection
exposeChildrenFor("First collection");
cy.findByText("Second collection").click();
cy.findByText(item);
// Undo the whole thing
cy.findByText(/Moved (question|dashboard)/);
cy.findByText("Undo").click();
cy.findByText(item).should("not.exist");
cy.visit("/collection/root");
cy.findByText(item);
}
function duplicate(item) {
cy.visit("/collection/root");
openCollectionItemMenu(item);
cy.findByText("Duplicate").click();
cy.get(".Modal")
.as("modal")
.within(() => {
clickButton("Duplicate");
cy.findByText("Failed").should("not.exist");
});
cy.get("@modal").should("not.exist");
cy.findByText(`${item} - Duplicate`);
}
......@@ -15,6 +15,7 @@ import {
undoToast,
openDashboardMenu,
toggleDashboardInfoSidebar,
entityPickerModal,
} from "e2e/support/helpers";
const PERMISSIONS = {
......@@ -223,9 +224,9 @@ describe("managing dashboard from the dashboard's edit menu", () => {
popover().findByText("Move").click();
cy.location("pathname").should("eq", `/dashboard/${id}/move`);
modal().within(() => {
entityPickerModal().within(() => {
cy.findByText("First collection").click();
clickButton("Move");
cy.button("Move").click();
});
assertOnRequest("updateDashboard");
......@@ -258,7 +259,7 @@ describe("managing dashboard from the dashboard's edit menu", () => {
);
modal().within(() => {
cy.findByRole("heading", { name: "Archive this dashboard?" }); //Without this, there is some race condition and the button click fails
clickButton("Archive");
cy.button("Archive").click();
assertOnRequest("updateDashboard");
});
......@@ -269,7 +270,7 @@ describe("managing dashboard from the dashboard's edit menu", () => {
);
undoToast().within(() => {
cy.findByText("Archived dashboard");
clickButton("Undo");
cy.button("Undo").click();
assertOnRequest("updateDashboard");
});
......@@ -313,10 +314,6 @@ describe("managing dashboard from the dashboard's edit menu", () => {
});
});
function clickButton(name) {
cy.findByRole("button", { name }).should("not.be.disabled").click();
}
function assertOnRequest(xhr_alias) {
cy.wait("@" + xhr_alias).then(xhr => {
expect(xhr.status).not.to.eq(403);
......
......@@ -312,8 +312,8 @@ describe("scenarios > dashboard", () => {
cy.findByTestId("edit-bar").button("Cancel").click();
openDashboardMenu();
popover().findByText("Move").click();
modal().within(() => {
cy.findByRole("heading", { name: myPersonalCollection }).click();
entityPickerModal().within(() => {
cy.findByText("Bobby Tables's Personal Collection").click();
cy.button("Move").click();
});
......@@ -330,8 +330,8 @@ describe("scenarios > dashboard", () => {
cy.findByTestId("edit-bar").button("Cancel").click();
openDashboardMenu();
popover().findByText("Move").click();
modal().within(() => {
cy.findByRole("heading", { name: "Our analytics" }).click();
entityPickerModal().within(() => {
cy.findByText("Our analytics").click();
cy.button("Move").click();
});
......
import {
dashboardHeader,
editDashboard,
modal,
openQuestionsSidebar,
popover,
restore,
......@@ -9,6 +8,7 @@ import {
rightSidebar,
toggleDashboardInfoSidebar,
visitDashboard,
entityPickerModal,
} from "e2e/support/helpers";
const dashboardDetails = {
......@@ -81,7 +81,7 @@ describe("issue 16559", () => {
cy.log("Move dashboard to another collection");
dashboardHeader().icon("ellipsis").click();
popover().findByText("Move").click();
modal().within(() => {
entityPickerModal().within(() => {
cy.findByText("First collection").click();
cy.button("Move").click();
});
......
import {
restore,
modal,
popover,
navigationSidebar,
openNavigationSidebar,
entityPickerModal,
} from "e2e/support/helpers";
const modelName = "Orders Model";
const personalCollectionName = "Bobby Tables's Personal Collection";
describe("issue 19737", () => {
beforeEach(() => {
......@@ -17,7 +18,7 @@ describe("issue 19737", () => {
it("should show moved model in the data picker without refreshing (metabase#19737)", () => {
cy.visit("/collection/root");
moveModel(modelName, "My personal collection");
moveModel(modelName, personalCollectionName);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Moved model");
......@@ -64,7 +65,7 @@ describe("issue 19737", () => {
openNavigationSidebar();
navigationSidebar().findByText("First collection").click();
moveModel(modelName, "My personal collection");
moveModel(modelName, personalCollectionName);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Moved model");
......@@ -84,11 +85,11 @@ describe("issue 19737", () => {
function moveModel(modelName, collectionName) {
openEllipsisMenuFor(modelName);
popover().contains("Move").click();
popover().findByText("Move").click();
modal().within(() => {
entityPickerModal().within(() => {
cy.findByText(collectionName).click();
cy.findByText("Move").click();
cy.button("Move").click();
});
}
......
......@@ -2,6 +2,8 @@ import {
restore,
openNativeEditor,
openQuestionActions,
popover,
entityPickerModal,
} from "e2e/support/helpers";
describe("scenarios > native question > data reference sidebar", () => {
......@@ -52,11 +54,12 @@ describe("scenarios > native question > data reference sidebar", () => {
);
// Move question to personal collection
openQuestionActions();
cy.findByTestId("move-button").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("My personal collection").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Move").click();
popover().findByTestId("move-button").click();
entityPickerModal().within(() => {
cy.findByText("Bobby Tables's Personal Collection").click();
cy.button("Move").click();
});
openNativeEditor();
cy.icon("reference").click();
......
......@@ -6,6 +6,7 @@ import {
visitQuestion,
startNewNativeQuestion,
runNativeQuery,
entityPickerModal,
} from "e2e/support/helpers";
import * as SQLFilter from "../native-filters/helpers/e2e-sql-filter-helpers";
......@@ -76,8 +77,10 @@ describe("scenarios > question > native subquery", () => {
cy.visit(`/question/${questionId2}`);
openQuestionActions();
cy.findByTestId("move-button").click();
cy.findByText("My personal collection").click();
cy.findByText("Move").click();
entityPickerModal().within(() => {
cy.findByText("Bobby Tables's Personal Collection").click();
cy.button("Move").click();
});
openNativeEditor();
cy.reload(); // Refresh the state, so previously created questions need to be loaded again.
......
......@@ -12,6 +12,7 @@ import {
import type { StructuredQuestionDetails } from "e2e/support/helpers";
import {
createQuestion,
entityPickerModal,
isEE,
isOSS,
openNotebook,
......@@ -330,14 +331,13 @@ describe("scenarios > notebook > data source", () => {
});
function moveToCollection(collection: string) {
cy.intercept("GET", "/api/collection/tree**").as("updateCollectionTree");
openQuestionActions();
popover().findByTextEnsureVisible("Move").click();
cy.findByRole("dialog").within(() => {
cy.intercept("GET", "/api/collection/tree**").as("updateCollectionTree");
cy.findAllByTestId("item-picker-item")
.filter(`:contains(${collection})`)
.click();
entityPickerModal().within(() => {
cy.findByText(collection).click();
cy.button("Move").click();
cy.wait("@updateCollectionTree");
});
......
......@@ -23,6 +23,7 @@ import {
expectNoBadSnowplowEvents,
expectGoodSnowplowEvents,
modal,
entityPickerModal,
} from "e2e/support/helpers";
const PERMISSIONS = {
......@@ -89,11 +90,7 @@ describe(
.should("have.attr", "aria-selected", "false");
});
openQuestionActions();
cy.findByTestId("move-button").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("My personal collection").click();
clickButton("Move");
moveQuestionTo(/Personal Collection/);
assertOnRequest("updateQuestion");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.contains("37.65");
......@@ -117,22 +114,25 @@ describe(
});
it("should be able to move the question to a collection created on the go", () => {
const NEW_COLLECTION_NAME = "Foo";
openQuestionActions();
cy.findByTestId("move-button").click();
const NEW_COLLECTION = "Foo";
modal().within(() => {
cy.findByText("New collection").click();
entityPickerModal().within(() => {
cy.findByText(/Personal Collection/).click();
cy.findByText("Create a new collection").click();
});
cy.findByTestId("new-collection-modal").then(modal => {
cy.findByPlaceholderText(
"My new fantastic collection",
).type(NEW_COLLECTION);
cy.findByText("Create").click();
cy.findByTestId("create-collection-on-the-go").within(() => {
cy.findByPlaceholderText("My new collection").type(
NEW_COLLECTION_NAME,
);
cy.button("Create").click();
});
cy.get("header").findByText(NEW_COLLECTION);
entityPickerModal().button("Move").click();
cy.get("header").findByText(NEW_COLLECTION_NAME);
});
it("should be able to move models", () => {
......@@ -152,11 +152,7 @@ describe(
.should("have.attr", "aria-selected", "false");
});
openQuestionActions();
cy.findByTestId("move-button").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("My personal collection").click();
clickButton("Move");
moveQuestionTo(/Personal Collection/);
assertOnRequest("updateQuestion");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.contains("37.65");
......@@ -243,14 +239,8 @@ describe(
cy.reload();
cy.log("Move the question to a personal collection");
openQuestionActions();
popover().findByText("Move").click();
modal().within(() => {
cy.findByRole("heading", {
name: myPersonalCollection,
}).click();
cy.button("Move").click();
});
moveQuestionTo(/Personal Collection/);
cy.log("assert public collections are not visible");
openQuestionActions();
......@@ -267,12 +257,7 @@ describe(
});
cy.log("Move the question to the root collection");
openQuestionActions();
popover().findByText("Move").click();
modal().within(() => {
cy.findByRole("heading", { name: "Our analytics" }).click();
cy.button("Move").click();
});
moveQuestionTo("Our analytics");
cy.log("assert all collections are visible");
openQuestionActions();
......@@ -501,3 +486,12 @@ function turnIntoModel() {
function findSelectedItem() {
return cy.findByRole("dialog").findByRole("option", { selected: true });
}
function moveQuestionTo(newCollectionName) {
openQuestionActions();
cy.findByTestId("move-button").click();
entityPickerModal().within(() => {
cy.findByText(newCollectionName).click();
cy.button("Move").click();
});
}
......@@ -6,7 +6,7 @@ import _ from "underscore";
import CollectionCopyEntityModal from "metabase/collections/components/CollectionCopyEntityModal";
import { canArchiveItem, canMoveItem } from "metabase/collections/utils";
import Modal from "metabase/components/Modal";
import { MoveModal } from "metabase/containers/MoveModal";
import { BulkMoveModal } from "metabase/containers/MoveModal";
import { Transition } from "metabase/ui";
import {
......@@ -49,7 +49,7 @@ function BulkActions({
>
{styles => (
<BulkActionsToast style={styles} isNavbarOpen={isNavbarOpen}>
<ToastCard dark>
<ToastCard dark data-testid="toast-card">
<CardSide>
{ngettext(
msgid`${selected.length} item selected`,
......@@ -88,17 +88,12 @@ function BulkActions({
</Modal>
)}
{!_.isEmpty(selectedItems) && selectedAction === "move" && (
<Modal onClose={onCloseModal}>
<MoveModal
title={
selectedItems.length > 1
? t`Move ${selectedItems.length} items?`
: t`Move "${selectedItems[0].getName()}"?`
}
onClose={onCloseModal}
onMove={onMove}
/>
</Modal>
<BulkMoveModal
selectedItems={selectedItems}
onClose={onCloseModal}
onMove={onMove}
initialCollectionId={collection.id}
/>
)}
</>
);
......
......@@ -13,7 +13,7 @@ export const BulkActionsToast = styled.div<{ isNavbarOpen: boolean }>`
margin-left: ${props =>
props.isNavbarOpen ? `${parseInt(NAV_SIDEBAR_WIDTH) / 2}px` : "0"};
margin-bottom: ${space(2)};
z-index: 999;
z-index: 400; // needed to put this over popovers (z-index: 300)
`;
export const ToastCard = styled(Card)`
......
......@@ -7,11 +7,18 @@ import { MoveModal } from "metabase/containers/MoveModal";
import Collections from "metabase/entities/collections";
import { useDispatch } from "metabase/lib/redux";
import * as Urls from "metabase/lib/urls";
import type { Collection, CollectionId } from "metabase-types/api";
import type {
Collection,
CollectionItem,
CollectionId,
} from "metabase-types/api";
export interface MoveCollectionModalProps {
collection: Collection;
onMove: (source: Collection, destination: Collection) => void;
onMove: (
source: Collection | CollectionItem,
destination: { id: CollectionId },
) => void;
onClose: () => void;
}
......@@ -21,7 +28,7 @@ const MoveCollectionModalView = ({
onClose,
}: MoveCollectionModalProps): JSX.Element => {
const handleMove = useCallback(
async (destination: Collection) => {
async (destination: { id: CollectionId }) => {
await onMove(collection, destination);
onClose();
},
......@@ -31,7 +38,8 @@ const MoveCollectionModalView = ({
return (
<MoveModal
title={t`Move "${collection.name}"?`}
initialCollectionId={collection.id}
initialCollectionId={collection.parent_id ?? "root"}
movingCollectionId={collection.id}
onMove={handleMove}
onClose={onClose}
/>
......
......@@ -13,6 +13,7 @@ export const CollectionItemPickerResolver = ({
query,
isFolder,
isCurrentLevel,
shouldDisableItem,
}: CollectionItemListProps) => {
if (!query) {
return (
......@@ -22,6 +23,7 @@ export const CollectionItemPickerResolver = ({
onClick={onClick}
isFolder={isFolder}
isCurrentLevel={isCurrentLevel}
shouldDisableItem={shouldDisableItem}
/>
);
}
......@@ -33,6 +35,7 @@ export const CollectionItemPickerResolver = ({
selectedItem={selectedItem}
isFolder={isFolder}
isCurrentLevel={isCurrentLevel}
shouldDisableItem={shouldDisableItem}
options={options}
/>
);
......@@ -45,6 +48,7 @@ export const CollectionItemPickerResolver = ({
selectedItem={selectedItem}
isFolder={isFolder}
isCurrentLevel={isCurrentLevel}
shouldDisableItem={shouldDisableItem}
options={options}
/>
);
......
......@@ -33,6 +33,7 @@ interface CollectionPickerProps {
onItemSelect: (item: CollectionPickerItem) => void;
initialValue?: Partial<CollectionPickerItem>;
options?: CollectionPickerOptions;
shouldDisableItem?: (item: CollectionPickerItem) => boolean;
}
export const CollectionPickerInner = (
......@@ -40,6 +41,7 @@ export const CollectionPickerInner = (
onItemSelect,
initialValue,
options = defaultOptions,
shouldDisableItem,
}: CollectionPickerProps,
ref: Ref<unknown>,
) => {
......@@ -125,6 +127,7 @@ export const CollectionPickerInner = (
<NestedItemPicker
itemName={t`collection`}
isFolder={isFolder}
shouldDisableItem={shouldDisableItem}
options={options}
generateKey={generateKey}
onFolderSelect={onFolderSelect}
......
......@@ -18,6 +18,7 @@ interface CollectionPickerModalProps {
onClose: () => void;
options?: CollectionPickerOptions;
value: Pick<CollectionPickerItem, "id" | "model">;
shouldDisableItem?: (item: CollectionPickerItem) => boolean;
}
const canSelectItem = (item: CollectionPickerItem | null): boolean => {
......@@ -36,7 +37,9 @@ export const CollectionPickerModal = ({
onClose,
value,
options = defaultOptions,
shouldDisableItem,
}: CollectionPickerModalProps) => {
options = { ...defaultOptions, ...options };
const [selectedItem, setSelectedItem] = useState<CollectionPickerItem | null>(
null,
);
......@@ -87,6 +90,7 @@ export const CollectionPickerModal = ({
element: (
<CollectionPicker
onItemSelect={handleItemSelect}
shouldDisableItem={shouldDisableItem}
initialValue={value}
options={options}
ref={pickerRef}
......
......@@ -56,6 +56,7 @@ export const NewCollectionDialog = ({
padding: "1rem",
},
}}
zIndex={400} // needs to be above the EntityPickerModal at 400
>
<FormProvider
initialValues={{ name: "" }}
......
......@@ -11,6 +11,7 @@ export const PersonalCollectionsItemList = ({
selectedItem,
isFolder,
isCurrentLevel,
shouldDisableItem,
}: CollectionItemListProps) => {
const {
data: collections,
......@@ -34,6 +35,7 @@ export const PersonalCollectionsItemList = ({
selectedItem={selectedItem}
isFolder={isFolder}
isCurrentLevel={isCurrentLevel}
shouldDisableItem={shouldDisableItem}
/>
);
};
......
......@@ -29,6 +29,7 @@ export const RootItemList = ({
options,
isFolder,
isCurrentLevel,
shouldDisableItem,
}: CollectionItemListProps) => {
const isAdmin = useSelector(getUserIsAdmin);
const currentUser = useSelector(getUser);
......@@ -106,6 +107,7 @@ export const RootItemList = ({
selectedItem={selectedItem}
isFolder={isFolder}
isCurrentLevel={isCurrentLevel}
shouldDisableItem={shouldDisableItem}
/>
);
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment