diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.tsx index c52fe9efa922..0ad6aa3f174c 100644 --- a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.tsx +++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.tsx @@ -16,7 +16,7 @@ * limitations under the License. */ -import React from 'react'; +import React, { Suspense } from 'react'; import { Switch as AntDSwitch, Layout } from 'antd'; import NavBar from './components/navBar/navBar'; @@ -27,6 +27,8 @@ import { routesV2 } from '@/v2/routes-v2'; import { MakeRouteWithSubRoutes } from '@/makeRouteWithSubRoutes'; import classNames from 'classnames'; +import Loader from '@/v2/components/loader/loader'; + import './app.less'; const { @@ -80,9 +82,11 @@ class App extends React.Component, IAppState> { {(enableNewUI) - ? routesV2.map( - (route, index) => - ) + ? }> + {routesV2.map( + (route, index) => + )} + : routes.map( (route, index) => ) diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/utils/common.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/utils/common.tsx index 6886fd189f6c..f641b8797d9e 100644 --- a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/utils/common.tsx +++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/utils/common.tsx @@ -44,9 +44,8 @@ const showInfoNotification = (title: string, description: string) => { export const showDataFetchError = (error: string) => { let title = 'Error while fetching data'; - if (error.includes('CanceledError')) { - error = 'Previous request cancelled because context changed' - } + + if (error.includes('CanceledError')) return; if (error.includes('metadata')) { title = 'Metadata Initialization:'; showInfoNotification(title, error); diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/aclDrawer/aclDrawer.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/aclDrawer/aclDrawer.tsx new file mode 100644 index 000000000000..af0931c17fac --- /dev/null +++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/aclDrawer/aclDrawer.tsx @@ -0,0 +1,119 @@ +/* + * 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. + */ + +import React, { useEffect, useState } from 'react'; +import { Table, Drawer, Tag } from 'antd'; + +import { AclRightsColorMap, AclIdColorMap } from '@/v2/constants/acl.constants'; +import { Acl, ACLIdentity, ACLIdentityTypeList } from '@/v2/types/acl.types'; +import { ColumnType } from 'antd/es/table'; + +// ------------- Types -------------- // +type AclDrawerProps = { + visible: boolean; + acls: Acl[] | undefined; + entityName: string; + entityType: string; + onClose: () => void; +} + + +// ------------- Component -------------- // +const AclPanel: React.FC = ({ + visible, + acls, + entityType, + entityName, + onClose +}) => { + const [isVisible, setIsVisible] = useState(false); + + useEffect(() => { + setIsVisible(visible); + }, [visible]); + + const renderAclList = (_: string, acl: Acl) => { + return acl.aclList.map(aclRight => ( + + {aclRight} + + )) + } + + const renderAclIdentityType = (acl: string) => { + return ( + + {acl} + + ) + } + + const COLUMNS: ColumnType[] = [ + { + title: 'Name', + dataIndex: 'name', + key: 'name', + sorter: (a: Acl, b: Acl) => a.name.localeCompare(b.name), + }, + { + title: 'ACL Type', + dataIndex: 'type', + key: 'type', + filterMultiple: true, + filters: ACLIdentityTypeList.map(state => ({ text: state, value: state })), + onFilter: (value: ACLIdentity, record: Acl) => (record.type === value), + sorter: (a: Acl, b: Acl) => a.type.localeCompare(b.type), + render: renderAclIdentityType + }, + { + title: 'ACL Scope', + dataIndex: 'scope', + key: 'scope', + }, + { + title: 'ACLs', + dataIndex: 'aclList', + key: 'acls', + render: renderAclList + } + ]; + + return ( +
+ + +
+
+
+ ); +}; + +export default AclPanel; \ No newline at end of file diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/eChart/eChart.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/eChart/eChart.tsx index 8be22fcc9f65..79fa07603386 100644 --- a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/eChart/eChart.tsx +++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/eChart/eChart.tsx @@ -83,7 +83,7 @@ const EChart = ({ } }, [loading, theme]); // If we switch theme we should put chart in loading mode, and also if loading changes i.e completes then hide loader - return
; + return
; } export default EChart; \ No newline at end of file diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/loader/loader.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/loader/loader.tsx new file mode 100644 index 000000000000..b05eaa5f0a59 --- /dev/null +++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/loader/loader.tsx @@ -0,0 +1,40 @@ +/* + * 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. + */ + +import React from "react" +import { Spin } from "antd" +import { LoadingOutlined } from "@ant-design/icons" + +// ------------- Constants -------------- // +const loaderStyle: React.CSSProperties = { + height: '100%', + width: '100%', + textAlign: 'center', + paddingTop: '25%' +} + +// ------------- Component -------------- // +const Loader: React.FC = () => { + return ( +
+ }/> +
+ ) +} + +export default Loader; diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/search/search.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/search/search.tsx new file mode 100644 index 000000000000..21d4341787ed --- /dev/null +++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/search/search.tsx @@ -0,0 +1,70 @@ +/* + * 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. + */ + +import React from 'react'; +import { Input, Select } from 'antd'; + +import { Option } from '@/v2/components/select/singleSelect'; + +// ------------- Types -------------- // +type SearchProps = { + searchColumn?: string; + searchInput: string; + searchOptions?: Option[]; + onSearchChange: ( + arg0: React.ChangeEvent + ) => void; + onChange: ( + value: string, + //OptionType, OptionGroupData and OptionData are not + //currently exported by AntD hence set to any + option: any + ) => void; +} + +// ------------- Component -------------- // +const Search: React.FC = ({ + searchColumn, + searchInput = '', + searchOptions = [], + onSearchChange = () => {}, + onChange = () => {} // Assign default value as a void function +}) => { + + const selectFilter = searchColumn + ? ( + ) +} + +export default Search; diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/select/columnTag.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/select/columnTag.tsx new file mode 100644 index 000000000000..f367504286f2 --- /dev/null +++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/select/columnTag.tsx @@ -0,0 +1,67 @@ +/* + * 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. + */ + +import React from "react"; +import { Tag } from "antd"; +import { createPortal } from "react-dom"; + + +// ------------- Types -------------- // +/** + * Due to design decisions we are currently not using the Tags + * Until we reach a concensus on a better way to display the filter + * Keeping the code in case we require it in the future + */ +export type TagProps = { + label: string; + closable: boolean; + tagRef: React.RefObject; + onClose: (arg0: string) => void; +} + +// ------------- Component -------------- // +const ColumnTag: React.FC = ({ + label = '', + closable = true, + tagRef = null, + onClose = () => {} // Assign default value as void funciton +}) => { + const onPreventMouseDown = (event: React.MouseEvent) => { + // By default when clickin on the tags the text will get selected + // which might interfere with user experience as people would want to close tags + // but accidentally select tag text. Hence we prevent this behaviour. + event.preventDefault(); + event.stopPropagation(); + }; + + if (!tagRef?.current) return null; + + return createPortal( + (onClose(label))} + style={{marginRight: 3}}> + {label} + , + tagRef.current + ); +} + +export default ColumnTag; diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/select/multiSelect.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/select/multiSelect.tsx new file mode 100644 index 000000000000..7a6b494aaeb6 --- /dev/null +++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/select/multiSelect.tsx @@ -0,0 +1,104 @@ +/* + * 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. + */ + +import React from "react"; +import { + default as ReactSelect, + Props as ReactSelectProps, + components, + OptionProps, + ValueType +} from 'react-select'; + +import { selectStyles } from "@/v2/constants/select.constants"; + + +// ------------- Types -------------- // +export type Option = { + label: string; + value: string; +} + +interface MultiSelectProps extends ReactSelectProps { + options: Option[]; + selected: Option[]; + placeholder: string; + fixedColumn: string; + columnLength: number; + onChange: (arg0: ValueType) => void; + onTagClose: (arg0: string) => void; +} + +// ------------- Component -------------- // +const MultiSelect: React.FC = ({ + options = [], + selected = [], + maxSelected = 5, + placeholder = 'Columns', + fixedColumn, + columnLength, + tagRef, + onTagClose = () => { }, // Assign default value as a void function + onChange = () => { }, // Assign default value as a void function + ...props +}) => { + + const Option: React.FC> = (props) => { + return ( +
+ + null} /> + + +
+ ) + } + + return ( + ) => { + if (selected?.length === options.length) return onChange!(options); + return onChange!(selected); + }} + styles={selectStyles} /> + ) +} + +export default MultiSelect; diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/select/singleSelect.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/select/singleSelect.tsx new file mode 100644 index 000000000000..41ab03f5982c --- /dev/null +++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/select/singleSelect.tsx @@ -0,0 +1,87 @@ +/* + * 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. + */ + +import React from "react"; +import Select, { + Props as ReactSelectProps, + components, + ValueType, + ValueContainerProps, + StylesConfig +} from 'react-select'; + +import { selectStyles } from "@/v2/constants/select.constants"; + + +// ------------- Types -------------- // +export type Option = { + label: string; + value: string; +} + +interface SingleSelectProps extends ReactSelectProps { + options: Option[]; + placeholder: string; + onChange: (arg0: ValueType) => void; +} + +// ------------- Component -------------- // +const SingleSelect: React.FC = ({ + options = [], + placeholder = 'Limit', + onChange = () => { }, // Assign default value as a void function + ...props // Desctructure other select props +}) => { + + + const ValueContainer = ({ children, ...props }: ValueContainerProps) => { + const selectedLimit = props.getValue() as Option[]; + return ( + + {React.Children.map(children, (child) => ( + ((child as React.ReactElement> + | React.ReactPortal)?.type as React.JSXElementConstructor)).name === "DummyInput" + ? child + : null + )} + Limit: {selectedLimit[0]?.label ?? ''} + + ); + }; + + return ( +