diff --git a/src/components/layers-panel/insert-panel/insert-panel.spec.tsx b/src/components/layers-panel/insert-panel/insert-panel.spec.tsx
index 27d2bec2..14ccdaf4 100644
--- a/src/components/layers-panel/insert-panel/insert-panel.spec.tsx
+++ b/src/components/layers-panel/insert-panel/insert-panel.spec.tsx
@@ -1,25 +1,31 @@
import { fireEvent, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
-import { renderWithTheme } from "../../../utils/testing-utils/render-with-theme";
+import { renderWithThemeProviders } from "../../../utils/testing-utils/render-with-theme";
import { InsertPanel } from "./insert-panel";
+import { setupStore } from "../../../redux/store";
const onInsertMock = jest.fn();
const onCancelMock = jest.fn();
-const callRender = (renderFunc, props = {}) => {
+function sleep(ms) {
+ return new Promise((resolve) => setTimeout(resolve, ms));
+}
+
+const callRender = (renderFunc, props = {}, store = setupStore()) => {
return renderFunc(
+ />,
+ store
);
};
describe("Insert panel", () => {
it("Should render insert panel", () => {
- const { container } = callRender(renderWithTheme);
+ const { container } = callRender(renderWithThemeProviders);
expect(container).toBeInTheDocument();
expect(screen.getByText("Test Title")).toBeInTheDocument();
@@ -30,47 +36,47 @@ describe("Insert panel", () => {
expect(screen.getByText("Insert")).toBeInTheDocument();
});
- it("Should show name error and url error if they are not provided", () => {
- const { container } = callRender(renderWithTheme);
+ it("Should show name error and url error if they are not provided", async () => {
+ const { container } = callRender(renderWithThemeProviders);
userEvent.click(screen.getByText("Insert"));
-
+ await sleep(200);
expect(container).toBeInTheDocument();
expect(screen.getByText("Please enter name")).toBeInTheDocument();
expect(screen.getByText("Invalid URL")).toBeInTheDocument();
});
- it("Should show only url error if Name field is filled in", () => {
- callRender(renderWithTheme);
+ it("Should show only url error if Name field is filled in", async () => {
+ callRender(renderWithThemeProviders);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const nameInput = document.querySelector("input[name=Name]")!;
- fireEvent.change(nameInput, { target: { value: 'test name' } });
+ fireEvent.change(nameInput, { target: { value: "test name" } });
userEvent.click(screen.getByText("Insert"));
-
+ await sleep(200);
expect(screen.getByText("Invalid URL")).toBeInTheDocument();
expect(screen.queryByText("Please enter name")).toBeNull();
});
- it("Should show URL error if it is not valid", () => {
- callRender(renderWithTheme);
+ it("Should show URL error if it is not valid", async () => {
+ callRender(renderWithThemeProviders);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const nameInput = document.querySelector("input[name=Name]")!;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const urlInput = document.querySelector("input[name=URL]")!;
- fireEvent.change(nameInput, { target: { value: 'test name' } });
- fireEvent.change(urlInput, { target: { value: 'test url' } });
+ fireEvent.change(nameInput, { target: { value: "test name" } });
+ fireEvent.change(urlInput, { target: { value: "test url" } });
userEvent.click(screen.getByText("Insert"));
-
+ await sleep(200);
expect(screen.getByText("Invalid URL")).toBeInTheDocument();
expect(screen.queryByText("Please enter name")).toBeNull();
});
- it("Should insert if everything is good", () => {
- callRender(renderWithTheme);
+ it("Should insert if everything is good", async () => {
+ callRender(renderWithThemeProviders);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const nameInput = document.querySelector("input[name=Name]")!;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -78,16 +84,17 @@ describe("Insert panel", () => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const tokenInput = document.querySelector("input[name=Token]")!;
- fireEvent.change(nameInput, { target: { value: 'test name' } });
- fireEvent.change(urlInput, { target: { value: 'http://123.com' } });
- fireEvent.change(tokenInput, { target: { value: 'test token' } });
+ fireEvent.change(nameInput, { target: { value: "test name" } });
+ fireEvent.change(urlInput, { target: { value: "http://123.com" } });
+ fireEvent.change(tokenInput, { target: { value: "test token" } });
userEvent.click(screen.getByText("Insert"));
+ await sleep(200);
expect(onInsertMock).toBeCalled();
});
it("Should be able to cancel panel", () => {
- callRender(renderWithTheme);
+ callRender(renderWithThemeProviders);
userEvent.click(screen.getByText("Cancel"));
expect(onCancelMock).toBeCalled();
diff --git a/src/components/layers-panel/insert-panel/insert-panel.tsx b/src/components/layers-panel/insert-panel/insert-panel.tsx
index e7140711..b8dd4310 100644
--- a/src/components/layers-panel/insert-panel/insert-panel.tsx
+++ b/src/components/layers-panel/insert-panel/insert-panel.tsx
@@ -1,13 +1,24 @@
-import { useState } from "react";
+import { useEffect, useState } from "react";
import styled from "styled-components";
-import { ActionButtonVariant } from "../../../types";
+import {
+ ActionButtonVariant,
+ FetchingStatus,
+ TilesetType,
+} from "../../../types";
import {
getCurrentLayoutProperty,
useAppLayout,
} from "../../../utils/hooks/layout";
import { ActionButton } from "../../action-button/action-button";
import { InputText } from "./input-text/input-text";
+import { getTilesetType } from "../../../utils/url-utils";
+import { LoadingSpinner } from "../../loading-spinner/loading-spinner";
+import { useAppDispatch, useAppSelector } from "../../../redux/hooks";
+import {
+ getLayerNameInfo,
+ selectLayerNames,
+} from "../../../redux/slices/layer-names-slice";
const NO_NAME_ERROR = "Please enter name";
const INVALID_URL_ERROR = "Invalid URL";
@@ -23,6 +34,10 @@ type LayoutProps = {
layout: string;
};
+type VisibilityProps = {
+ visible: boolean;
+};
+
const Container = styled.div`
position: relative;
display: flex;
@@ -65,6 +80,16 @@ const ButtonsWrapper = styled.div`
padding: 0 6px;
`;
+const SpinnerContainer = styled.div`
+ background: rgba(0, 0, 0, 0.3);
+ position: absolute;
+ left: calc(50% - 44px);
+ top: calc(50% - 44px);
+ padding: 22px;
+ border-radius: 8px;
+ visibility: ${({ visible }) => (visible ? "visible" : "hidden")};
+`;
+
export const InsertPanel = ({
title,
onInsert,
@@ -77,14 +102,13 @@ export const InsertPanel = ({
const [nameError, setNameError] = useState("");
const [urlError, setUrlError] = useState("");
+ const [isValidateInProgress, setValidateInProgress] = useState(false);
+ const layerNames = useAppSelector(selectLayerNames);
+ const dispatch = useAppDispatch();
const validateFields = () => {
let isFormValid = true;
-
- if (!name) {
- setNameError(NO_NAME_ERROR);
- isFormValid = false;
- }
+ const type = getTilesetType(url);
try {
new URL(url);
@@ -93,16 +117,43 @@ export const InsertPanel = ({
isFormValid = false;
}
- return isFormValid;
- };
-
- const handleInsert = (event) => {
- const isFormValid = validateFields();
+ if (
+ (type !== TilesetType.I3S && !name) ||
+ (type === TilesetType.I3S && !name && !layerNames[url]?.name)
+ ) {
+ setNameError(NO_NAME_ERROR);
+ isFormValid = false;
+ }
if (isFormValid) {
- onInsert({ name, url, token });
+ onInsert({ name: name || layerNames[url]?.name, url, token });
+ }
+ };
+
+ useEffect(() => {
+ const type = getTilesetType(url);
+ if (isValidateInProgress && type === TilesetType.I3S) {
+ if (
+ (layerNames[url] !== undefined &&
+ layerNames[url].status === FetchingStatus.ready) ||
+ name.length > 0
+ ) {
+ setValidateInProgress(false);
+ validateFields();
+ } else if (!layerNames[url]) {
+ dispatch(getLayerNameInfo({ layerUrl: url, token, type }));
+ }
}
+ }, [isValidateInProgress, layerNames]);
+
+ const handleInsert = async (event) => {
event.preventDefault();
+
+ if (getTilesetType(url) !== TilesetType.I3S) {
+ validateFields();
+ } else {
+ setValidateInProgress(true);
+ }
};
const handleInputChange = (event) => {
@@ -122,11 +173,19 @@ export const InsertPanel = ({
}
};
+ const onCancelHandler = () => {
+ setValidateInProgress(false);
+ onCancel();
+ };
+
const layout = useAppLayout();
return (
{title}
+
+
+