You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by mi...@apache.org on 2024/01/04 07:45:51 UTC
(incubator-devlake) branch feat-redux-tips created (now b2fa3b2a7)
This is an automated email from the ASF dual-hosted git repository.
mintsweet pushed a change to branch feat-redux-tips
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
at b2fa3b2a7 feat(config-ui): use redux tips to replace context tips
This branch includes the following new commits:
new b2fa3b2a7 feat(config-ui): use redux tips to replace context tips
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(incubator-devlake) 01/01: feat(config-ui): use redux tips to replace context tips
Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
mintsweet pushed a commit to branch feat-redux-tips
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
commit b2fa3b2a709845a23faa75bbe22f5f4b472fc3cb
Author: mintsweet <0x...@gmail.com>
AuthorDate: Thu Jan 4 20:45:30 2024 +1300
feat(config-ui): use redux tips to replace context tips
---
config-ui/src/app/store.ts | 6 +-
config-ui/src/features/index.ts | 1 +
config-ui/src/{store => features/tips}/index.ts | 2 +-
config-ui/src/features/tips/slice.ts | 58 +++++++
config-ui/src/hooks/index.ts | 1 -
config-ui/src/hooks/use-tips.ts | 23 ---
.../pages/blueprint/connection-detail/index.tsx | 37 ++---
.../pages/blueprint/detail/configuration-panel.tsx | 2 +-
.../src/plugins/register/jira/transformation.tsx | 2 +-
config-ui/src/routes/connection/connection.tsx | 12 +-
config-ui/src/routes/layout/layout.tsx | 180 +++++++++++++--------
config-ui/src/routes/layout/styled.ts | 2 +-
config-ui/src/store/tips/context.tsx | 44 -----
config-ui/src/store/tips/index.ts | 19 ---
14 files changed, 195 insertions(+), 194 deletions(-)
diff --git a/config-ui/src/app/store.ts b/config-ui/src/app/store.ts
index b838101b5..5725ddc7a 100644
--- a/config-ui/src/app/store.ts
+++ b/config-ui/src/app/store.ts
@@ -17,11 +17,13 @@
*/
import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
-import connectionsSlice from '@/features/connections/slice';
+
+import { connectionsSlice, tipsSlice } from '@/features';
export const store = configureStore({
reducer: {
- connections: connectionsSlice,
+ connections: connectionsSlice.reducer,
+ tips: tipsSlice.reducer,
},
});
diff --git a/config-ui/src/features/index.ts b/config-ui/src/features/index.ts
index 4e6e8a4de..a247f9b21 100644
--- a/config-ui/src/features/index.ts
+++ b/config-ui/src/features/index.ts
@@ -17,3 +17,4 @@
*/
export * from './connections';
+export * from './tips';
diff --git a/config-ui/src/store/index.ts b/config-ui/src/features/tips/index.ts
similarity index 96%
rename from config-ui/src/store/index.ts
rename to config-ui/src/features/tips/index.ts
index 378c0c717..513ab48a7 100644
--- a/config-ui/src/store/index.ts
+++ b/config-ui/src/features/tips/index.ts
@@ -16,4 +16,4 @@
*
*/
-export * from './tips';
+export * from './slice';
diff --git a/config-ui/src/features/tips/slice.ts b/config-ui/src/features/tips/slice.ts
new file mode 100644
index 000000000..b817aaa5c
--- /dev/null
+++ b/config-ui/src/features/tips/slice.ts
@@ -0,0 +1,58 @@
+/*
+ * 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 { createSlice } from '@reduxjs/toolkit';
+
+import { RootState } from '@/app/store';
+
+const initialState: {
+ show: boolean;
+ type?: 'data-scope-changed' | 'scope-config-changed';
+ payload?: {
+ pname?: string;
+ blueprintId: ID;
+ };
+} = {
+ show: false,
+};
+
+export const tipsSlice = createSlice({
+ name: 'tips',
+ initialState,
+ reducers: {
+ showTips: (state, action) => {
+ state.show = true;
+ state.type = action.payload.type;
+ state.payload = action.payload.payload;
+ },
+ hideTips: (state) => {
+ state.show = false;
+ state.type = undefined;
+ },
+ },
+});
+
+export const { showTips, hideTips } = tipsSlice.actions;
+
+export default tipsSlice.reducer;
+
+export const selectTipsShow = (state: RootState) => state.tips.show;
+
+export const selectTipsType = (state: RootState) => state.tips.type;
+
+export const selectTipsPayload = (state: RootState) => state.tips.payload;
diff --git a/config-ui/src/hooks/index.ts b/config-ui/src/hooks/index.ts
index 1fd63d10a..076b27375 100644
--- a/config-ui/src/hooks/index.ts
+++ b/config-ui/src/hooks/index.ts
@@ -19,5 +19,4 @@
export * from './extend-redux';
export * from './use-auto-refresh';
export * from './use-refresh-data';
-export * from './use-tips';
export * from './user-proxy-prefix';
diff --git a/config-ui/src/hooks/use-tips.ts b/config-ui/src/hooks/use-tips.ts
deleted file mode 100644
index 2478efade..000000000
--- a/config-ui/src/hooks/use-tips.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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 { useContext } from 'react';
-
-import { TipsContext } from '@/store';
-
-export const useTips = () => useContext(TipsContext);
diff --git a/config-ui/src/pages/blueprint/connection-detail/index.tsx b/config-ui/src/pages/blueprint/connection-detail/index.tsx
index d9dd0ffc4..a2fb25a88 100644
--- a/config-ui/src/pages/blueprint/connection-detail/index.tsx
+++ b/config-ui/src/pages/blueprint/connection-detail/index.tsx
@@ -22,8 +22,9 @@ import { DeleteOutlined, FormOutlined } from '@ant-design/icons';
import { Flex, Table, Popconfirm, Modal, Button } from 'antd';
import API from '@/api';
-import { PageLoading, PageHeader, ExternalLink, Message } from '@/components';
-import { useRefreshData, useTips } from '@/hooks';
+import { PageLoading, PageHeader, ExternalLink } from '@/components';
+import { showTips } from '@/features';
+import { useAppDispatch, useRefreshData } from '@/hooks';
import { DataScopeSelect, getPluginConfig, getPluginScopeId } from '@/plugins';
import { operator } from '@/utils';
@@ -34,12 +35,11 @@ import * as S from './styled';
export const BlueprintConnectionDetailPage = () => {
const [version, setVersion] = useState(1);
const [open, setOpen] = useState(false);
- const [operating, setOperating] = useState(false);
const { pname, bid, unique } = useParams() as { pname?: string; bid?: string; unique: string };
const navigate = useNavigate();
- const { setTips } = useTips();
+ const dispatch = useAppDispatch();
const getBlueprint = async (pname?: string, bid?: string) => {
if (pname) {
@@ -93,27 +93,16 @@ export const BlueprintConnectionDetailPage = () => {
const handleShowDataScope = () => setOpen(true);
const handleHideDataScope = () => setOpen(false);
- const handleRunBP = async (skipCollectors: boolean) => {
- const [success] = await operator(() => API.blueprint.trigger(blueprint.id, { skipCollectors, fullSync: false }), {
- setOperating,
- formatMessage: () => 'Trigger blueprint successful.',
- });
-
- if (success) {
- navigate(pname ? `/projects/${pname}` : `/advanced/blueprints/${blueprint.id}`);
- }
- };
-
- const handleShowTips = () => {
- setTips(
- <Flex gap="middle">
- <Message content="The change of Data Scope(s) will affect the metrics of this project. Would you like to recollect the data to get them updated?" />
- <Button type="primary" loading={operating} onClick={() => handleRunBP(false)}>
- Recollect Data
- </Button>
- </Flex>,
+ const handleShowTips = () =>
+ dispatch(
+ showTips({
+ type: 'data-scope-changed',
+ payload: {
+ pname,
+ blueprintId: blueprint.id,
+ },
+ }),
);
- };
const handleRemoveConnection = async () => {
const [success] = await operator(() =>
diff --git a/config-ui/src/pages/blueprint/detail/configuration-panel.tsx b/config-ui/src/pages/blueprint/detail/configuration-panel.tsx
index 363b8ae35..0d62a9d35 100644
--- a/config-ui/src/pages/blueprint/detail/configuration-panel.tsx
+++ b/config-ui/src/pages/blueprint/detail/configuration-panel.tsx
@@ -19,7 +19,7 @@
import { useState, useEffect, useMemo } from 'react';
import { Link } from 'react-router-dom';
import { FormOutlined, PlusOutlined } from '@ant-design/icons';
-import { Flex, Table, Space, Button } from 'antd';
+import { Flex, Table, Button } from 'antd';
import API from '@/api';
import { NoData } from '@/components';
diff --git a/config-ui/src/plugins/register/jira/transformation.tsx b/config-ui/src/plugins/register/jira/transformation.tsx
index ad8aec07c..11b383fa0 100644
--- a/config-ui/src/plugins/register/jira/transformation.tsx
+++ b/config-ui/src/plugins/register/jira/transformation.tsx
@@ -16,7 +16,7 @@
*
*/
-import { useState, useEffect, useMemo } from 'react';
+import { useState, useEffect } from 'react';
import { uniqWith } from 'lodash';
import { CaretRightOutlined } from '@ant-design/icons';
import { theme, Collapse, Tag, Form, Select } from 'antd';
diff --git a/config-ui/src/routes/connection/connection.tsx b/config-ui/src/routes/connection/connection.tsx
index 6fabafbdc..d17711245 100644
--- a/config-ui/src/routes/connection/connection.tsx
+++ b/config-ui/src/routes/connection/connection.tsx
@@ -24,8 +24,8 @@ import { theme, Table, Button, Modal, message, Space } from 'antd';
import API from '@/api';
import { useAppDispatch, useAppSelector } from '@/hooks';
import { PageHeader, Message } from '@/components';
-import { selectConnection, removeConnection } from '@/features';
-import { useTips, useRefreshData } from '@/hooks';
+import { selectConnection, removeConnection, showTips } from '@/features';
+import { useRefreshData } from '@/hooks';
import {
ConnectionStatus,
DataScopeRemote,
@@ -70,7 +70,6 @@ export const Connection = () => {
const connection = useAppSelector((state) => selectConnection(state, `${plugin}-${connectionId}`)) as IConnection;
const navigate = useNavigate();
- const { setTips } = useTips();
const { ready, data } = useRefreshData(
() => API.scope.list(plugin, connectionId, { page, pageSize, blueprints: true }),
[version, page, pageSize],
@@ -218,12 +217,7 @@ export const Connection = () => {
if (success) {
setVersion((v) => v + 1);
- setTips(
- <Message
- content="Scope Config(s) have been updated. If you would like to re-transform or re-collect the data in the related
- project(s), please go to the Project page and do so."
- />,
- );
+ dispatch(showTips({ type: 'scope-config-changed' }));
handleHideDialog();
}
};
diff --git a/config-ui/src/routes/layout/layout.tsx b/config-ui/src/routes/layout/layout.tsx
index 84f66cd2c..0b2423aa2 100644
--- a/config-ui/src/routes/layout/layout.tsx
+++ b/config-ui/src/routes/layout/layout.tsx
@@ -20,12 +20,21 @@ import { useState, useEffect, useRef } from 'react';
import { useLoaderData, Outlet, useNavigate, useLocation } from 'react-router-dom';
import { CSSTransition } from 'react-transition-group';
import { CloseOutlined } from '@ant-design/icons';
-import { Layout as AntdLayout, Menu, Divider, Button } from 'antd';
+import { Layout as AntdLayout, Menu, Flex, Divider, Tooltip, Button } from 'antd';
+import API from '@/api';
+import { PageLoading, Logo, ExternalLink, Message } from '@/components';
+import {
+ init,
+ selectError,
+ selectStatus,
+ selectTipsShow,
+ selectTipsType,
+ selectTipsPayload,
+ hideTips,
+} from '@/features';
import { useAppDispatch, useAppSelector } from '@/hooks';
-import { PageLoading, Logo, ExternalLink } from '@/components';
-import { init, selectError, selectStatus } from '@/features';
-import { TipsContextProvider, TipsContextConsumer } from '@/store';
+import { operator } from '@/utils';
import { loader } from './loader';
import { menuItems, menuItemsMatch, headerItems } from './config';
@@ -37,6 +46,7 @@ const { Sider, Header, Content, Footer } = AntdLayout;
export const Layout = () => {
const [openKeys, setOpenKeys] = useState<string[]>([]);
const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
+ const [operating, setOperating] = useState(false);
const { version, plugins } = useLoaderData() as Awaited<ReturnType<typeof loader>>;
@@ -46,6 +56,9 @@ export const Layout = () => {
const dispatch = useAppDispatch();
const status = useAppSelector(selectStatus);
const error = useAppSelector(selectError);
+ const tipsShow = useAppSelector(selectTipsShow);
+ const tipsType = useAppSelector(selectTipsType);
+ const tipsPayload = useAppSelector(selectTipsPayload);
const tipsRef = useRef(null);
@@ -82,70 +95,101 @@ export const Layout = () => {
throw error.message;
}
+ const handleRunBP = async () => {
+ if (!tipsPayload) {
+ return;
+ }
+
+ const { blueprintId, pname } = tipsPayload;
+
+ const [success] = await operator(
+ () => API.blueprint.trigger(tipsPayload.blueprintId, { skipCollectors: false, fullSync: false }),
+ {
+ setOperating,
+ formatMessage: () => 'Trigger blueprint successful.',
+ },
+ );
+
+ if (success) {
+ navigate(pname ? `/projects/${pname}` : `/advanced/blueprints/${blueprintId}`);
+ }
+ };
+
return (
- <TipsContextProvider>
- <TipsContextConsumer>
- {({ tips, setTips }) => (
- <AntdLayout style={{ minHeight: '100vh' }}>
- <Sider
- style={{
- position: 'fixed',
- top: 0,
- bottom: 0,
- left: 0,
- height: '100vh',
- overflow: 'auto',
- }}
- >
- <Logo style={{ padding: 24 }} />
- <Menu
- mode="inline"
- theme="dark"
- items={menuItems}
- openKeys={openKeys}
- selectedKeys={selectedKeys}
- onClick={({ key }) => navigate(key)}
- onOpenChange={(keys) => setOpenKeys(keys)}
- />
- <div style={{ position: 'absolute', right: 0, bottom: 20, left: 0, color: '#fff', textAlign: 'center' }}>
- {version}
- </div>
- </Sider>
- <AntdLayout style={{ marginLeft: 200 }}>
- <Header
- style={{
- display: 'flex',
- justifyContent: 'flex-end',
- alignItems: 'center',
- padding: '0 24px',
- height: 50,
- background: 'transparent',
- }}
- >
- {headerItems.map((item, i) => (
- <ExternalLink key={item.label} link={item.link} style={{ display: 'flex', alignItems: 'center' }}>
- {item.icon}
- <span style={{ marginLeft: 4 }}>{item.label}</span>
- {i !== headerItems.length - 1 && <Divider type="vertical" />}
- </ExternalLink>
- ))}
- </Header>
- <Content style={{ margin: '0 auto', width: 1188 }}>
- <Outlet />
- </Content>
- <Footer style={{ color: '#a1a1a1', textAlign: 'center' }}>
- {import.meta.env.DEVLAKE_COPYRIGHT ?? 'Apache 2.0 License'}
- </Footer>
- <CSSTransition in={!!tips} unmountOnExit timeout={300} nodeRef={tipsRef} classNames="tips">
- <S.Tips ref={tipsRef}>
- <div className="content">{tips}</div>
- <Button type="primary" icon={<CloseOutlined />} onClick={() => setTips('')} />
- </S.Tips>
- </CSSTransition>
- </AntdLayout>
- </AntdLayout>
- )}
- </TipsContextConsumer>
- </TipsContextProvider>
+ <AntdLayout style={{ minHeight: '100vh' }}>
+ <Sider
+ style={{
+ position: 'fixed',
+ top: 0,
+ bottom: 0,
+ left: 0,
+ height: '100vh',
+ overflow: 'auto',
+ }}
+ >
+ <Logo style={{ padding: 24 }} />
+ <Menu
+ mode="inline"
+ theme="dark"
+ items={menuItems}
+ openKeys={openKeys}
+ selectedKeys={selectedKeys}
+ onClick={({ key }) => navigate(key)}
+ onOpenChange={(keys) => setOpenKeys(keys)}
+ />
+ <div style={{ position: 'absolute', right: 0, bottom: 20, left: 0, color: '#fff', textAlign: 'center' }}>
+ {version}
+ </div>
+ </Sider>
+ <AntdLayout style={{ marginLeft: 200 }}>
+ <Header
+ style={{
+ display: 'flex',
+ justifyContent: 'flex-end',
+ alignItems: 'center',
+ padding: '0 24px',
+ height: 50,
+ background: 'transparent',
+ }}
+ >
+ {headerItems.map((item, i) => (
+ <ExternalLink key={item.label} link={item.link} style={{ display: 'flex', alignItems: 'center' }}>
+ {item.icon}
+ <span style={{ marginLeft: 4 }}>{item.label}</span>
+ {i !== headerItems.length - 1 && <Divider type="vertical" />}
+ </ExternalLink>
+ ))}
+ </Header>
+ <Content style={{ margin: '0 auto', width: 1188 }}>
+ <Outlet />
+ </Content>
+ <Footer style={{ color: '#a1a1a1', textAlign: 'center' }}>
+ {import.meta.env.DEVLAKE_COPYRIGHT ?? 'Apache 2.0 License'}
+ </Footer>
+ <CSSTransition in={!!tipsShow} unmountOnExit timeout={300} nodeRef={tipsRef} classNames="tips">
+ <S.Tips ref={tipsRef}>
+ <div className="content">
+ {tipsType === 'data-scope-changed' && (
+ <Flex gap="middle">
+ <Message content="The change of Data Scope(s) will affect the metrics of this project. Would you like to recollect the data to get them updated?" />
+ <Button type="primary" loading={operating} onClick={handleRunBP}>
+ Recollect Data
+ </Button>
+ </Flex>
+ )}
+ {tipsType === 'scope-config-changed' && (
+ <Message
+ content="Scope Config(s) have been updated. If you would like to re-transform or re-collect the data in the related
+ project(s), please go to the Project page and do so."
+ />
+ )}
+ </div>
+ <Tooltip title="Close">
+ <Button shape="circle" ghost icon={<CloseOutlined />} onClick={() => dispatch(hideTips())} />
+ </Tooltip>
+ </S.Tips>
+ </CSSTransition>
+ </AntdLayout>
+ </AntdLayout>
);
};
diff --git a/config-ui/src/routes/layout/styled.ts b/config-ui/src/routes/layout/styled.ts
index 10511f645..3129357a4 100644
--- a/config-ui/src/routes/layout/styled.ts
+++ b/config-ui/src/routes/layout/styled.ts
@@ -21,7 +21,7 @@ import styled from 'styled-components';
export const Tips = styled.div`
display: flex;
align-items: center;
- padding: 14px 0;
+ padding: 12px 24px;
color: #fff;
background-color: #3c5088;
diff --git a/config-ui/src/store/tips/context.tsx b/config-ui/src/store/tips/context.tsx
deleted file mode 100644
index 7bb06d447..000000000
--- a/config-ui/src/store/tips/context.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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, { useState } from 'react';
-
-export const TipsContext = React.createContext<{
- tips: React.ReactNode;
- setTips: React.Dispatch<React.SetStateAction<React.ReactNode>>;
-}>({
- tips: '',
- setTips: () => {},
-});
-
-export const TipsContextProvider = ({ children }: { children: React.ReactNode }) => {
- const [tips, setTips] = useState<React.ReactNode>();
-
- return (
- <TipsContext.Provider
- value={{
- tips,
- setTips,
- }}
- >
- {children}
- </TipsContext.Provider>
- );
-};
-
-export const TipsContextConsumer = TipsContext.Consumer;
diff --git a/config-ui/src/store/tips/index.ts b/config-ui/src/store/tips/index.ts
deleted file mode 100644
index 5cdc9167c..000000000
--- a/config-ui/src/store/tips/index.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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 * from './context';