This is an automated email from the ASF dual-hosted git repository.
jialiang pushed a commit to branch frontend-refactor
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/frontend-refactor by this push:
new e5c9eef528 AMBARI-26262: Ambari Admin React Build Fix & add missing
files. (#3914)
e5c9eef528 is described below
commit e5c9eef5283cdaa7896281b26e68b498461b32a8
Author: Sandeep Kumar <[email protected]>
AuthorDate: Tue Dec 24 06:25:32 2024 +0530
AMBARI-26262: Ambari Admin React Build Fix & add missing files. (#3914)
co-authered by: Himanshu Maurya <himanshumaurya09876>
---
.../ambari-admin/src/__mocks__/mockClusterInfo.ts | 31 ++++++++++++++++
.../ui/ambari-admin/src/screens/Views/enums.ts | 41 ++++++++++++++++++++++
.../ui/ambari-admin/src/tests/AddGroup.test.tsx | 7 ++--
.../ui/ambari-admin/src/tests/AddUser.test.tsx | 7 ++--
.../src/tests/DeregisterRemoteCluster.test.tsx | 7 ++--
.../ui/ambari-admin/src/tests/EditGroup.test.tsx | 7 ++--
.../src/tests/EditRemoteCluster.test.tsx | 14 ++++----
.../ui/ambari-admin/src/tests/EditUser.test.tsx | 7 ++--
.../src/tests/ListUsersGroups.test.tsx | 7 ++--
.../src/tests/RegisterRemoteCluster.test.tsx | 14 ++++----
.../ambari-admin/src/tests/RemoteClusters.test.tsx | 15 ++++----
.../src/tests/StackVersions/VersionsList.test.tsx | 39 ++++++++++----------
.../resources/ui/ambari-admin/tsconfig.node.json | 22 ++++++++++++
13 files changed, 150 insertions(+), 68 deletions(-)
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/__mocks__/mockClusterInfo.ts
b/ambari-admin/src/main/resources/ui/ambari-admin/src/__mocks__/mockClusterInfo.ts
new file mode 100644
index 0000000000..322cdb784b
--- /dev/null
+++
b/ambari-admin/src/main/resources/ui/ambari-admin/src/__mocks__/mockClusterInfo.ts
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+const mockClusterInfo = {
+ "href" : "http://example.com",
+ "items" : [
+ {
+ "href" : "http://example.com/api/v1/clusters/cluster1",
+ "Clusters" : {
+ "cluster_id" : 1,
+ "cluster_name" : "cluster1"
+ }
+ }
+ ]
+};
+
+export default mockClusterInfo;
\ No newline at end of file
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/screens/Views/enums.ts
b/ambari-admin/src/main/resources/ui/ambari-admin/src/screens/Views/enums.ts
new file mode 100644
index 0000000000..bcfd2d8782
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/ambari-admin/src/screens/Views/enums.ts
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export enum ControlType {
+ INPUT = "input",
+ TEXT = "text",
+ LINK = "link",
+ CHECKBOX = "checkbox",
+}
+
+export enum ClusterType {
+ LOCAL = "LOCAL_AMBARI",
+ REMOTE = "REMOTE_AMBARI",
+ CUSTOM = "CUSTOM_AMBARI",
+}
+
+export enum ViewTypes {
+ FILES = "FILES",
+ TEZ = "TEZ",
+ CAPACITY_SCHEDULER = "CAPACITY-SCHEDULER",
+}
+
+export enum EntityType {
+ USER = "USER",
+ GROUP = "GROUP",
+ ROLE = "ROLE",
+}
\ No newline at end of file
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/AddGroup.test.tsx
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/AddGroup.test.tsx
index 35412be459..7b754c0ccc 100644
---
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/AddGroup.test.tsx
+++
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/AddGroup.test.tsx
@@ -20,9 +20,8 @@ import AddGroup from "../screens/Users/AddGroup";
import { describe, it, beforeEach, expect, vi } from "vitest";
import "@testing-library/jest-dom/vitest";
import UserGroupApi from "../api/userGroupApi";
-import { Router } from "react-router";
+import { HashRouter } from "react-router-dom";
import AppContent from "../context/AppContext";
-import { createMemoryHistory } from "history";
import toast from "react-hot-toast";
import { userNames } from "../__mocks__/mockUserNames";
import { GroupDataType } from "../api/types";
@@ -68,9 +67,9 @@ describe("AddGroup component", () => {
const renderComponent = (props = mockProps) => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<AddGroup {...props} />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
};
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/AddUser.test.tsx
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/AddUser.test.tsx
index d0c4b3daaa..6763b355f2 100644
--- a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/AddUser.test.tsx
+++ b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/AddUser.test.tsx
@@ -20,9 +20,8 @@ import AddUser from "../screens/Users/AddUser";
import { describe, it, beforeEach, expect, vi } from "vitest";
import "@testing-library/jest-dom/vitest";
import UserGroupApi from "../api/userGroupApi";
-import { Router } from "react-router";
+import { HashRouter } from "react-router-dom";
import AppContent from "../context/AppContext";
-import { createMemoryHistory } from "history";
import { rbacData } from "../__mocks__/mockRbacData";
import toast from "react-hot-toast";
import { UserDataType } from "../api/types";
@@ -67,9 +66,9 @@ describe("AddUser component", () => {
const renderComponent = (props = mockProps) => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<AddUser {...props} />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
};
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/DeregisterRemoteCluster.test.tsx
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/DeregisterRemoteCluster.test.tsx
index 4156b5cc81..78a9da7726 100644
---
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/DeregisterRemoteCluster.test.tsx
+++
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/DeregisterRemoteCluster.test.tsx
@@ -17,8 +17,7 @@
*/
import { describe, it, expect, vi } from "vitest";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
-import { createMemoryHistory } from "history";
-import { Router } from "react-router-dom";
+import { HashRouter } from "react-router-dom";
import "@testing-library/jest-dom/vitest";
import RemoteClusterApi from "../api/remoteCluster";
import DeregisterRemoteCluster from
"../screens/ClusterManagement/RemoteClusters/DeregisterRemoteCluster";
@@ -35,9 +34,9 @@ const mockContext = {
const renderDeregisterRemoteCluster = () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<DeregisterRemoteCluster clusterName={mockClusterName} />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
};
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditGroup.test.tsx
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditGroup.test.tsx
index 164819c752..a75c06b54b 100644
---
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditGroup.test.tsx
+++
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditGroup.test.tsx
@@ -21,9 +21,8 @@ import { describe, it, beforeEach, expect, vi } from "vitest";
import "@testing-library/jest-dom/vitest";
import UserGroupApi from "../api/userGroupApi";
import PrivilegeApi from "../api/privilegeApi";
-import { Router } from "react-router";
+import { HashRouter } from "react-router-dom";
import AppContent from "../context/AppContext";
-import { createMemoryHistory } from "history";
import toast from "react-hot-toast";
import { rbacData } from "../__mocks__/mockRbacData";
import { userNames } from "../__mocks__/mockUserNames";
@@ -66,9 +65,9 @@ describe("EditGroup component", () => {
const renderComponent = () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<EditGroup />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
};
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditRemoteCluster.test.tsx
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditRemoteCluster.test.tsx
index 27d285c1cb..4c59f2b042 100644
---
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditRemoteCluster.test.tsx
+++
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditRemoteCluster.test.tsx
@@ -23,8 +23,7 @@ import {
waitFor,
within,
} from "@testing-library/react";
-import { createMemoryHistory } from "history";
-import { Router } from "react-router-dom";
+import { HashRouter } from "react-router-dom";
import { mockClusterDataForEdit } from "../__mocks__/mockRemoteCluster";
import "@testing-library/jest-dom/vitest";
import RemoteClusterApi from "../api/remoteCluster";
@@ -41,9 +40,9 @@ const mockContext = {
const renderEditRemoteCluster = () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<EditRemoteCluster />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
};
@@ -96,12 +95,11 @@ describe("EditRemoteCluster component", () => {
it("should redirect to /remoteCluster on clicking cancel button", async ()
=> {
RemoteClusterApi.getRemoteClusterByName = async () =>
mockClusterDataForEdit;
- const history = createMemoryHistory();
render(
<AppContent.Provider value={mockContext}>
- <Router history={history}>
+ <HashRouter>
<EditRemoteCluster />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
@@ -113,7 +111,7 @@ describe("EditRemoteCluster component", () => {
await waitFor(() => {});
await waitFor(() => {
- expect(history.location.pathname).toBe("/remoteClusters");
+ expect(window.location.hash).toBe("#/remoteClusters");
});
});
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditUser.test.tsx
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditUser.test.tsx
index 259496675f..ec8af8aadf 100644
---
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditUser.test.tsx
+++
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/EditUser.test.tsx
@@ -20,9 +20,8 @@ import EditUser from "../screens/Users/EditUser";
import { describe, it, beforeEach, expect, vi } from "vitest";
import "@testing-library/jest-dom/vitest";toast
import UserGroupApi from "../api/userGroupApi";
-import { Router } from "react-router";
+import { HashRouter } from "react-router-dom";
import AppContent from "../context/AppContext";
-import { createMemoryHistory } from "history";
import toast from "react-hot-toast";
import { rbacData } from "../__mocks__/mockRbacData";
import { groupNames } from "../__mocks__/mockGroupNames";
@@ -66,9 +65,9 @@ describe("EditUser component", () => {
const renderComponent = () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<EditUser />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
};
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/ListUsersGroups.test.tsx
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/ListUsersGroups.test.tsx
index 2c6f4f294e..282d71eb0e 100644
---
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/ListUsersGroups.test.tsx
+++
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/ListUsersGroups.test.tsx
@@ -25,9 +25,8 @@ import {
import Users from "../screens/Users";
import { describe, it, beforeEach, expect, vi } from "vitest";
import "@testing-library/jest-dom/vitest";
- import { Router } from "react-router";
+ import { HashRouter } from "react-router-dom";
import AppContent from "../context/AppContext";
- import { createMemoryHistory } from "history";
import UserGroupApi from "../api/userGroupApi";
import { usersList, paginatedUsersList } from "../__mocks__/mockUsersList";
import { groupsList, paginatedGroupsList } from
"../__mocks__/mockGroupsList";
@@ -66,9 +65,9 @@ import {
const renderUserComponent = () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<Users />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
};
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/RegisterRemoteCluster.test.tsx
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/RegisterRemoteCluster.test.tsx
index 2761864039..d8167e0bff 100644
---
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/RegisterRemoteCluster.test.tsx
+++
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/RegisterRemoteCluster.test.tsx
@@ -17,8 +17,7 @@
*/
import { describe, it, expect } from "vitest";
import { render, screen, waitFor, fireEvent } from "@testing-library/react";
-import { createMemoryHistory } from "history";
-import { Router } from "react-router-dom";
+import { HashRouter } from "react-router-dom";
import "@testing-library/jest-dom/vitest";
import RemoteClusterApi from "../api/remoteCluster";
import RegisterRemoteCluster from
"../screens/ClusterManagement/RemoteClusters/RegisterRemoteCluster";
@@ -34,9 +33,9 @@ const mockContext = {
const renderRegisterRemoteCluster = () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<RegisterRemoteCluster />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
};
@@ -68,12 +67,11 @@ describe("RegisterRemoteCluster component", () => {
});
it("should redirect to /remoteCluster on clicking cancel button", async ()
=> {
- const history = createMemoryHistory();
render(
<AppContent.Provider value={mockContext}>
- <Router history={history}>
+ <HashRouter>
<RegisterRemoteCluster />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
expect(getClusterName()).toBeInTheDocument();
@@ -88,7 +86,7 @@ describe("RegisterRemoteCluster component", () => {
await waitFor(() => {});
await waitFor(() => {
- expect(history.location.pathname).toBe("/remoteClusters");
+ expect(window.location.hash).toBe("#/remoteClusters");
});
});
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/RemoteClusters.test.tsx
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/RemoteClusters.test.tsx
index 7f83961137..f740450146 100644
---
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/RemoteClusters.test.tsx
+++
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/RemoteClusters.test.tsx
@@ -17,8 +17,7 @@
*/
import { describe, it, expect } from "vitest";
import { render, waitFor, screen, fireEvent } from "@testing-library/react";
-import { createMemoryHistory } from "history";
-import { Router } from "react-router-dom";
+import { HashRouter } from "react-router-dom";
import "@testing-library/jest-dom/vitest";
import RemoteClusters from "../screens/ClusterManagement/RemoteClusters/Index"
import RemoteClusterApi from "../api/remoteCluster";
@@ -37,9 +36,9 @@ const mockContext = {
const renderRemoteCluster = () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<RemoteClusters />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
};
@@ -86,12 +85,12 @@ describe("RemoteClusters component", () => {
it("renders the Register Remote cluster button and navigates to the create
route on click", async () => {
RemoteClusterApi.getRemoteClusters = async () => mockData;
- const history = createMemoryHistory();
+
render(
<AppContent.Provider value={mockContext}>
- <Router history={history}>
+ <HashRouter>
<RemoteClusters />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
await waitFor(() => screen.getByText(/TestCluster1/i));
@@ -104,7 +103,7 @@ describe("RemoteClusters component", () => {
fireEvent.click(registerButton);
await waitFor(() =>
- expect(history.location.pathname).toBe("/remoteClusters/create")
+ expect(window.location.hash).toBe("#/remoteClusters/create")
);
});
diff --git
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/StackVersions/VersionsList.test.tsx
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/StackVersions/VersionsList.test.tsx
index 1a65ac1f6c..42cda34347 100644
---
a/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/StackVersions/VersionsList.test.tsx
+++
b/ambari-admin/src/main/resources/ui/ambari-admin/src/tests/StackVersions/VersionsList.test.tsx
@@ -17,15 +17,14 @@
*/
import { describe, it, beforeEach, expect } from "vitest";
import { render, waitFor, screen } from "@testing-library/react";
-import { createMemoryHistory } from "history";
-import { Router } from "react-router-dom";
+import { HashRouter } from "react-router-dom";
import "@testing-library/jest-dom/vitest";
import VersionsApi from "../../api/versions";
import mockRepos, { paginatedRepos } from "../../__mocks__/mockRepos";
-import mockClusterInfo from "../../__mocks__/mockClusterInfo";
+import mockClusterInfo from "../../__mocks__/mockClusterInfo.ts";
import mockVersionList from "../../__mocks__/mockVersionList";
import AppContent from "../../context/AppContext";
-import StackVersionsList from
"../../screens/ClusterManagement/StackVersions/List";
+import StackVersionsList from "../../screens/StackVersions/List";
describe("StackVersionsList", () => {
const mockClusterName = "testCluster";
@@ -43,9 +42,9 @@ describe("StackVersionsList", () => {
it("renders without crashing", () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<StackVersionsList />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
});
@@ -73,9 +72,9 @@ describe("StackVersionsList", () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<StackVersionsList />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
@@ -85,9 +84,9 @@ describe("StackVersionsList", () => {
it("renders correct number of items", async () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<StackVersionsList />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
@@ -100,9 +99,9 @@ describe("StackVersionsList", () => {
it("renders data for a specific item correctly", async () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<StackVersionsList />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
@@ -115,9 +114,9 @@ describe("StackVersionsList", () => {
it("renders loading spinner when data is being fetched", async () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<StackVersionsList />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
@@ -136,9 +135,9 @@ describe("StackVersionsList", () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<StackVersionsList />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
@@ -149,9 +148,9 @@ describe("StackVersionsList", () => {
it("renders Register Version button", async () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<StackVersionsList />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
await waitFor(() => screen.getByText(/Stack1-1.0.0/i)); // wait for the
data to be loaded
@@ -167,9 +166,9 @@ describe("StackVersionsList", () => {
render(
<AppContent.Provider value={mockContext}>
- <Router history={createMemoryHistory()}>
+ <HashRouter>
<StackVersionsList />
- </Router>
+ </HashRouter>
</AppContent.Provider>
);
diff --git a/ambari-admin/src/main/resources/ui/ambari-admin/tsconfig.node.json
b/ambari-admin/src/main/resources/ui/ambari-admin/tsconfig.node.json
new file mode 100644
index 0000000000..8d8997a76f
--- /dev/null
+++ b/ambari-admin/src/main/resources/ui/ambari-admin/tsconfig.node.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["vite.config.ts"]
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]