This is an automated email from the ASF dual-hosted git repository.

likyh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/main by this push:
     new b65a518fd feat(config-ui): add page project-detail (#3897)
b65a518fd is described below

commit b65a518fd12f1bf5f4578cee458ade5c69b03dbb
Author: 青湛 <[email protected]>
AuthorDate: Fri Dec 9 16:47:42 2022 +0800

    feat(config-ui): add page project-detail (#3897)
    
    * feat(config-ui): extend the loading component
    
    * feat(config-ui): add page project-detail
---
 config-ui/src/App.js                               |  11 +++
 .../{pages/project => components/loading}/index.ts |   3 +-
 .../components/loading/{index.tsx => loading.tsx}  |   0
 .../loading/page-loading.tsx}                      |  13 ++-
 config-ui/src/components/loading/styled.ts         |   9 +-
 config-ui/src/images/no-webhook.svg                |  24 +++++
 .../index.tsx => pages/project/detail/api.ts}      |  29 +++---
 config-ui/src/pages/project/detail/index.tsx       |  73 +++++++++++++++
 .../src/pages/project/detail/panel/blueprint.tsx   |  61 ++++++++++++
 .../project/detail/panel/incoming-webhooks.tsx     |  56 +++++++++++
 .../src/pages/project/{ => detail/panel}/index.ts  |   4 +-
 .../src/pages/project/detail/panel/settings.tsx    |  76 +++++++++++++++
 config-ui/src/pages/project/detail/styled.ts       | 103 +++++++++++++++++++++
 .../pages/project/{index.ts => detail/types.ts}    |   7 +-
 config-ui/src/pages/project/detail/use-project.ts  |  84 +++++++++++++++++
 config-ui/src/pages/project/index.ts               |   1 +
 16 files changed, 535 insertions(+), 19 deletions(-)

diff --git a/config-ui/src/App.js b/config-ui/src/App.js
index e498742e7..bded3e797 100644
--- a/config-ui/src/App.js
+++ b/config-ui/src/App.js
@@ -38,6 +38,7 @@ import useDatabaseMigrations from 
'@/hooks/useDatabaseMigrations'
 import { BaseLayout } from '@/layouts'
 import {
   ProjectHomePage,
+  ProjectDetailPage,
   CreateBlueprintPage,
   WebHookConnectionPage
 } from '@/pages'
@@ -84,6 +85,16 @@ function App(props) {
                 path='/projects'
                 component={() => <ProjectHomePage />}
               />
+              <Route
+                exact
+                path='/projects/:pname'
+                component={() => <ProjectDetailPage />}
+              />
+              <Route
+                exact
+                path='/projects/:pname/create-blueprint'
+                component={() => <CreateBlueprintPage from='project' />}
+              />
               <Route
                 exact
                 path='/integrations'
diff --git a/config-ui/src/pages/project/index.ts 
b/config-ui/src/components/loading/index.ts
similarity index 93%
copy from config-ui/src/pages/project/index.ts
copy to config-ui/src/components/loading/index.ts
index 761b787e5..e20521a17 100644
--- a/config-ui/src/pages/project/index.ts
+++ b/config-ui/src/components/loading/index.ts
@@ -16,4 +16,5 @@
  *
  */
 
-export * from './home'
+export * from './loading'
+export * from './page-loading'
diff --git a/config-ui/src/components/loading/index.tsx 
b/config-ui/src/components/loading/loading.tsx
similarity index 100%
copy from config-ui/src/components/loading/index.tsx
copy to config-ui/src/components/loading/loading.tsx
diff --git a/config-ui/src/pages/project/index.ts 
b/config-ui/src/components/loading/page-loading.tsx
similarity index 77%
copy from config-ui/src/pages/project/index.ts
copy to config-ui/src/components/loading/page-loading.tsx
index 761b787e5..90d522f5c 100644
--- a/config-ui/src/pages/project/index.ts
+++ b/config-ui/src/components/loading/page-loading.tsx
@@ -16,4 +16,15 @@
  *
  */
 
-export * from './home'
+import React from 'react'
+
+import { Loading } from './loading'
+import * as S from './styled'
+
+export const PageLoading = () => {
+  return (
+    <S.PageWrapper>
+      <Loading size={40} text='Loading...' />
+    </S.PageWrapper>
+  )
+}
diff --git a/config-ui/src/components/loading/styled.ts 
b/config-ui/src/components/loading/styled.ts
index 13616bf36..181239472 100644
--- a/config-ui/src/components/loading/styled.ts
+++ b/config-ui/src/components/loading/styled.ts
@@ -48,5 +48,12 @@ export const Spin = styled.div<{ size: number }>`
 `
 
 export const Text = styled.div`
-  margin-top: 6px;
+  margin-top: 12px;
+`
+
+export const PageWrapper = styled.div`
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  min-height: 400px;
 `
diff --git a/config-ui/src/images/no-webhook.svg 
b/config-ui/src/images/no-webhook.svg
new file mode 100644
index 000000000..18e78babe
--- /dev/null
+++ b/config-ui/src/images/no-webhook.svg
@@ -0,0 +1,24 @@
+<!--
+  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.
+-->
+<svg width="120" height="120" viewBox="0 0 120 120" fill="none" 
xmlns="http://www.w3.org/2000/svg";>
+  <path fill-rule="evenodd" clip-rule="evenodd" d="M96.0375 
30.5939V34.9997H91.6312C89.9062 34.9997 88.5187 36.3872 88.5187 38.1122C88.5187 
39.8372 89.9062 41.2247 91.6312 41.2247H96.0375V45.6314C96.0375 47.3564 97.425 
48.7439 99.15 48.7439C100.875 48.7439 102.262 47.3564 102.262 
45.6314V41.2247H106.669C108.394 41.2247 109.781 39.8372 109.781 38.1122C109.781 
36.406 108.394 34.9997 106.669 34.9997H102.262V30.5939C102.262 28.8689 100.875 
27.4814 99.15 27.4814C97.4437 27.4814 96.0375 28.868 [...]
+  <path d="M61.2799 55.2372C58.334 60.0876 55.5104 64.786 52.6285 
69.4482C51.8892 70.6437 51.5224 71.6187 52.1143 73.1411C53.7464 77.3434 51.4428 
81.4336 47.1152 82.5454C43.0398 83.5927 39.0577 80.9641 38.2484 76.6858C37.5304 
72.8979 40.5325 69.184 44.7961 68.5929C45.1532 68.5416 45.518 68.5359 46.1177 
68.4922L52.6053 57.8487C48.5299 53.8764 46.0964 49.2312 46.6339 43.4761C47.022 
39.4088 48.6483 35.8926 51.633 33.0113C54.3784 30.3359 57.9754 28.6605 61.827 
28.2633C65.6786 27.8661 69.5531 [...]
+  <path d="M69.6945 49.4992C71.7691 53.0857 73.8785 56.7216 75.9667 
60.3328C86.5257 57.1341 94.4862 62.8568 97.3409 68.9864C100.791 76.3893 98.4335 
85.1569 91.6587 89.7241C84.7054 94.413 75.9104 93.6109 69.7489 87.5897L74.583 
83.6269C80.6688 87.4871 85.9901 87.3046 89.9412 82.7355C91.5721 80.8336 92.4519 
78.4217 92.4206 75.9382C92.3892 73.4548 91.4489 71.0648 89.7704 69.203C85.7708 
64.7993 80.4107 64.6643 73.9329 68.8932C71.2451 64.2234 68.5107 59.5916 65.9083 
54.8894C65.0312 53.3043 64. [...]
+  <path d="M74.6587 78.8183H61.9456C60.7268 83.7257 58.0953 87.6885 53.562 
90.2088C50.1259 92.1513 46.1032 92.8527 42.1937 92.1911C34.7494 91.0146 28.6655 
84.4518 28.126 77.0602C27.5206 68.688 33.3949 61.247 41.2273 59.5745C41.7687 
61.4979 42.314 63.4403 42.8555 65.3581C35.6751 68.9484 33.1833 73.4719 35.1938 
79.13C36.9637 84.1078 41.9861 86.8371 47.4529 85.7822C53.0303 84.7046 55.8403 
80.1659 55.4987 72.8808C60.785 72.8808 66.0752 72.8275 71.3615 72.9074C73.4264 
72.9397 75.0196 72.7306  [...]
+</svg>
+  
+  
\ No newline at end of file
diff --git a/config-ui/src/components/loading/index.tsx 
b/config-ui/src/pages/project/detail/api.ts
similarity index 65%
rename from config-ui/src/components/loading/index.tsx
rename to config-ui/src/pages/project/detail/api.ts
index 8b3f18477..151bf28f6 100644
--- a/config-ui/src/components/loading/index.tsx
+++ b/config-ui/src/pages/project/detail/api.ts
@@ -16,21 +16,22 @@
  *
  */
 
-import React from 'react'
+import request from '@/components/utils/request'
 
-import * as S from './styled'
+export const getProject = (name: string) => request(`/projects/${name}`)
 
-interface Props {
-  size?: number
-  text?: string
-  style?: React.CSSProperties
+type UpdateProjectPayload = {
+  name: string
+  description: string
+  metrics: Array<{
+    pluginName: string
+    pluginOption: string
+    enable: boolean
+  }>
 }
 
-export const Loading = ({ size = 24, text, style }: Props) => {
-  return (
-    <S.Wrapper style={style}>
-      <S.Spin size={size} />
-      {text && <S.Text>{text}</S.Text>}
-    </S.Wrapper>
-  )
-}
+export const updateProject = (name: string, payload: UpdateProjectPayload) =>
+  request(`/projects/${name}`, {
+    method: 'patch',
+    data: payload
+  })
diff --git a/config-ui/src/pages/project/detail/index.tsx 
b/config-ui/src/pages/project/detail/index.tsx
new file mode 100644
index 000000000..cf990397e
--- /dev/null
+++ b/config-ui/src/pages/project/detail/index.tsx
@@ -0,0 +1,73 @@
+/*
+ * 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'
+import { useParams } from 'react-router-dom'
+
+import { PageHeader, PageLoading } from '@/components'
+
+import { useProject } from './use-project'
+import { BlueprintPanel, IncomingWebhooksPanel, SettingsPanel } from './panel'
+import * as S from './styled'
+
+export const ProjectDetailPage = () => {
+  const { pname } = useParams<{ pname: string }>()
+
+  const [activeTab, setActiveTab] = useState<'bp' | 'iw' | 'st'>('bp')
+
+  const { loading, project, updateProject } = useProject(pname)
+
+  if (loading) {
+    return <PageLoading />
+  }
+
+  return (
+    <PageHeader
+      breadcrumbs={[
+        { name: 'Projects', path: '/projects' },
+        { name: pname, path: `/projects/${pname}` }
+      ]}
+    >
+      <S.Tabs>
+        <S.Tab active={activeTab === 'bp'} onClick={() => setActiveTab('bp')}>
+          Blueprint
+        </S.Tab>
+        <S.Tab
+          active={activeTab === 'iw'}
+          disabled={!project?.blueprint}
+          onClick={() => {
+            if (!project?.blueprint) {
+              return
+            }
+            setActiveTab('iw')
+          }}
+        >
+          Incoming Webhooks
+        </S.Tab>
+        <S.Tab active={activeTab === 'st'} onClick={() => setActiveTab('st')}>
+          Settings
+        </S.Tab>
+      </S.Tabs>
+      {activeTab === 'bp' && <BlueprintPanel name={pname} project={project} />}
+      {activeTab === 'iw' && <IncomingWebhooksPanel project={project} />}
+      {activeTab === 'st' && (
+        <SettingsPanel project={project} onUpdate={updateProject} />
+      )}
+    </PageHeader>
+  )
+}
diff --git a/config-ui/src/pages/project/detail/panel/blueprint.tsx 
b/config-ui/src/pages/project/detail/panel/blueprint.tsx
new file mode 100644
index 000000000..79d47ea15
--- /dev/null
+++ b/config-ui/src/pages/project/detail/panel/blueprint.tsx
@@ -0,0 +1,61 @@
+/*
+ * 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 { useHistory } from 'react-router-dom'
+import { Button, Intent } from '@blueprintjs/core'
+
+import NoData from '@/images/no-data.svg'
+
+import type { ProjectType } from '../types'
+import * as S from '../styled'
+
+interface Props {
+  name: string
+  project?: ProjectType
+}
+
+export const BlueprintPanel = ({ name, project }: Props) => {
+  const history = useHistory()
+
+  const handleGoCreateBlueprint = () =>
+    history.push(`/projects/${name}/create-blueprint`)
+
+  return !project?.blueprint ? (
+    <S.Panel>
+      <div className='blueprint'>
+        <div className='logo'>
+          <img src={NoData} alt='' />
+        </div>
+        <div className='desc'>
+          <p>Create a blueprint to collect data from data sources.</p>
+        </div>
+        <div className='action'>
+          <Button
+            intent={Intent.PRIMARY}
+            icon='plus'
+            text='Create a Blueprint'
+            onClick={handleGoCreateBlueprint}
+          />
+        </div>
+      </div>
+    </S.Panel>
+  ) : (
+    <div>blueprint detail</div>
+  )
+}
diff --git a/config-ui/src/pages/project/detail/panel/incoming-webhooks.tsx 
b/config-ui/src/pages/project/detail/panel/incoming-webhooks.tsx
new file mode 100644
index 000000000..d50b8c833
--- /dev/null
+++ b/config-ui/src/pages/project/detail/panel/incoming-webhooks.tsx
@@ -0,0 +1,56 @@
+/*
+ * 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 { Button, Intent } from '@blueprintjs/core'
+
+import NoData from '@/images/no-webhook.svg'
+
+import type { ProjectType } from '../types'
+import * as S from '../styled'
+
+interface Props {
+  project?: ProjectType
+}
+
+export const IncomingWebhooksPanel = ({ project }: Props) => {
+  return (
+    <S.Panel>
+      <div className='webhook'>
+        <div className='logo'>
+          <img src={NoData} alt='' />
+        </div>
+        <div className='desc'>
+          <p>
+            Push `incidents` or `deployments` from your tools by incoming
+            webhooks.
+          </p>
+        </div>
+        <div className='action'>
+          <Button intent={Intent.PRIMARY} icon='plus' text='Add a Webhook' />
+          <span className='or'>or</span>
+          <Button
+            outlined
+            intent={Intent.PRIMARY}
+            text='Select Existing Webhooks'
+          />
+        </div>
+      </div>
+    </S.Panel>
+  )
+}
diff --git a/config-ui/src/pages/project/index.ts 
b/config-ui/src/pages/project/detail/panel/index.ts
similarity index 89%
copy from config-ui/src/pages/project/index.ts
copy to config-ui/src/pages/project/detail/panel/index.ts
index 761b787e5..cc590448f 100644
--- a/config-ui/src/pages/project/index.ts
+++ b/config-ui/src/pages/project/detail/panel/index.ts
@@ -16,4 +16,6 @@
  *
  */
 
-export * from './home'
+export * from './blueprint'
+export * from './incoming-webhooks'
+export * from './settings'
diff --git a/config-ui/src/pages/project/detail/panel/settings.tsx 
b/config-ui/src/pages/project/detail/panel/settings.tsx
new file mode 100644
index 000000000..ef1751566
--- /dev/null
+++ b/config-ui/src/pages/project/detail/panel/settings.tsx
@@ -0,0 +1,76 @@
+/*
+ * 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 {
+  InputGroup,
+  Checkbox,
+  ButtonGroup,
+  Button,
+  Intent
+} from '@blueprintjs/core'
+
+import type { ProjectType } from '../types'
+import * as S from '../styled'
+
+interface Props {
+  project: ProjectType
+  onUpdate: (name: string, enableDora: boolean) => void
+}
+
+export const SettingsPanel = ({ project, onUpdate }: Props) => {
+  const [name, setName] = useState('')
+  const [enableDora, setEnableDora] = useState(false)
+
+  useEffect(() => {
+    if (project) {
+      setName(project.name)
+      setEnableDora(project.enableDora)
+    }
+  }, [project])
+
+  const handleSave = () => onUpdate(name, enableDora)
+
+  return (
+    <S.Panel>
+      <div className='settings'>
+        <div className='block'>
+          <h3>Project Name *</h3>
+          <p>Edit your project name.</p>
+          <InputGroup value={name} onChange={(e) => setName(e.target.value)} />
+        </div>
+        <div className='block'>
+          <Checkbox
+            label='Enable DORA Metrics'
+            checked={enableDora}
+            onChange={(e) =>
+              setEnableDora((e.target as HTMLInputElement).checked)
+            }
+          />
+          <p>
+            DORA metrics are four widely-adopted metrics for measuring software
+            delivery performance.
+          </p>
+        </div>
+        <ButtonGroup>
+          <Button text='Save' intent={Intent.PRIMARY} onClick={handleSave} />
+        </ButtonGroup>
+      </div>
+    </S.Panel>
+  )
+}
diff --git a/config-ui/src/pages/project/detail/styled.ts 
b/config-ui/src/pages/project/detail/styled.ts
new file mode 100644
index 000000000..2f2eaba0c
--- /dev/null
+++ b/config-ui/src/pages/project/detail/styled.ts
@@ -0,0 +1,103 @@
+/*
+ * 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 styled from '@emotion/styled'
+
+export const Tabs = styled.ul`
+  margin: 0;
+  padding: 0;
+  list-style: none;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+`
+
+export const Tab = styled.li<{ active: boolean; disabled?: boolean }>`
+  margin-right: 24px;
+  padding: 6px 0;
+  font-size: 14px;
+  border-bottom: 2px solid transparent;
+  transition: all 0.3s ease;
+  cursor: pointer;
+
+  ${({ active }) =>
+    active
+      ? `
+    color: #7497F7;
+    border-color: #7497F7;
+  `
+      : ''}
+
+  ${({ disabled }) =>
+    disabled
+      ? `
+  color: #a1a1a1;
+    cursor: no-drop;
+  `
+      : ''}
+
+  &:last-child {
+    margin-right: 0;
+  }
+`
+
+export const Panel = styled.div`
+  margin-top: 24px;
+  background-color: #ffffff;
+  box-shadow: 0px 2.4px 4.8px -0.8px rgba(0, 0, 0, 0.1),
+    0px 1.6px 8px rgba(0, 0, 0, 0.07);
+  border-radius: 4px;
+
+  .blueprint,
+  .webhook {
+    padding: 24px;
+    text-align: center;
+
+    .logo > img {
+      display: inline-block;
+      width: 120px;
+      height: 120px;
+    }
+
+    .desc {
+      margin: 20px 0;
+    }
+
+    .action > .or {
+      display: block;
+      margin: 8px 0;
+    }
+  }
+
+  .settings {
+    padding: 24px;
+
+    h3 {
+      margin: 0;
+      padding: 0;
+    }
+
+    .block {
+      margin-bottom: 16px;
+    }
+
+    .bp3-input-group {
+      width: 386px;
+    }
+  }
+`
diff --git a/config-ui/src/pages/project/index.ts 
b/config-ui/src/pages/project/detail/types.ts
similarity index 87%
copy from config-ui/src/pages/project/index.ts
copy to config-ui/src/pages/project/detail/types.ts
index 761b787e5..747c0b888 100644
--- a/config-ui/src/pages/project/index.ts
+++ b/config-ui/src/pages/project/detail/types.ts
@@ -16,4 +16,9 @@
  *
  */
 
-export * from './home'
+export type ProjectType = {
+  name: string
+  description: string
+  blueprint: any | null
+  enableDora: boolean
+} | null
diff --git a/config-ui/src/pages/project/detail/use-project.ts 
b/config-ui/src/pages/project/detail/use-project.ts
new file mode 100644
index 000000000..0ea20986c
--- /dev/null
+++ b/config-ui/src/pages/project/detail/use-project.ts
@@ -0,0 +1,84 @@
+/*
+ * 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 { useState, useEffect, useMemo } from 'react'
+import { useHistory } from 'react-router-dom'
+
+import { operator } from '@/utils'
+
+import type { ProjectType } from './types'
+import * as API from './api'
+
+export const useProject = (name: string) => {
+  const [loading, setLoading] = useState(false)
+  const [project, setProject] = useState<ProjectType>(null)
+
+  const history = useHistory()
+
+  const getProject = async (name: string) => {
+    setLoading(true)
+    try {
+      const res = await API.getProject(name)
+      const doraMetrics = res.metrics.find(
+        (ms: any) => ms.pluginName === 'dora'
+      )
+
+      setProject({
+        name: res.name,
+        description: res.description,
+        blueprint: res.blueprint,
+        enableDora: doraMetrics.enable
+      })
+    } finally {
+      setLoading(false)
+    }
+  }
+
+  useEffect(() => {
+    getProject(name)
+  }, [name])
+
+  const updateProject = async (newName: string, enableDora: boolean) => {
+    const payload = {
+      name: newName,
+      description: '',
+      metrics: [
+        {
+          pluginName: 'dora',
+          pluginOption: '',
+          enable: enableDora
+        }
+      ]
+    }
+
+    const [success] = await operator(() => API.updateProject(name, payload))
+
+    if (success) {
+      history.push(`/projects/${newName}`)
+    }
+  }
+
+  return useMemo(
+    () => ({
+      loading,
+      project,
+      updateProject
+    }),
+    [loading, project]
+  )
+}
diff --git a/config-ui/src/pages/project/index.ts 
b/config-ui/src/pages/project/index.ts
index 761b787e5..188478fcd 100644
--- a/config-ui/src/pages/project/index.ts
+++ b/config-ui/src/pages/project/index.ts
@@ -17,3 +17,4 @@
  */
 
 export * from './home'
+export * from './detail'

Reply via email to