refactor(config-ui): the blueprints list page (#4047)
diff --git a/config-ui/src/App.js b/config-ui/src/App.js
index 91c2b91..9e0d779 100644
--- a/config-ui/src/App.js
+++ b/config-ui/src/App.js
@@ -31,13 +31,12 @@
ConnectionHomePage,
WebHookConnectionPage,
CreateBlueprintPage,
+ BlueprintHomePage,
BlueprintDetailPage
} from '@/pages'
-import Integration from '@/pages/configure/integration/index'
import ManageIntegration from '@/pages/configure/integration/manage'
import AddConnection from '@/pages/configure/connections/AddConnection'
import ConfigureConnection from '@/pages/configure/connections/ConfigureConnection'
-import Blueprints from '@/pages/blueprints/index'
function App() {
return (
@@ -80,7 +79,11 @@
path='/connections/configure/:providerId/:connectionId'
component={() => <ConfigureConnection />}
/>
- <Route exact path='/blueprints' component={() => <Blueprints />} />
+ <Route
+ exact
+ path='/blueprints'
+ component={() => <BlueprintHomePage />}
+ />
<Route
exact
path='/blueprints/create'
diff --git a/config-ui/src/pages/blueprint/home/api.ts b/config-ui/src/pages/blueprint/home/api.ts
new file mode 100644
index 0000000..869eca9
--- /dev/null
+++ b/config-ui/src/pages/blueprint/home/api.ts
@@ -0,0 +1,21 @@
+/*
+ * 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 request from '@/components/utils/request'
+
+export const getBlueprints = () => request('/blueprints')
diff --git a/config-ui/src/pages/blueprint/home/index.tsx b/config-ui/src/pages/blueprint/home/index.tsx
new file mode 100644
index 0000000..a6ec6da
--- /dev/null
+++ b/config-ui/src/pages/blueprint/home/index.tsx
@@ -0,0 +1,125 @@
+/*
+ * 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, { useMemo } from 'react'
+import { useHistory } from 'react-router-dom'
+import { ButtonGroup, Button, Intent } from '@blueprintjs/core'
+
+import { PageLoading, PageHeader, Table, ColumnType } from '@/components'
+import { getCron, getCronOptions } from '@/config'
+import { formatTime } from '@/utils'
+
+import type { BlueprintType } from '../types'
+import { ModeEnum } from '../types'
+
+import { useHome } from './use-home'
+import * as S from './styled'
+
+export const BlueprintHomePage = () => {
+ const history = useHistory()
+
+ const { loading, dataSource, type, onChangeType } = useHome()
+
+ const options = useMemo(() => getCronOptions(), [])
+
+ const columns = useMemo(
+ () =>
+ [
+ {
+ title: 'Blueprint Name',
+ dataIndex: 'name',
+ key: 'name'
+ },
+ {
+ title: 'Data Connections',
+ key: 'connections',
+ render: (_, row) => {
+ if (row.mode === ModeEnum.advanced) {
+ return 'Advanced Mode'
+ }
+ return row.settings.connections.map((cs) => cs.plugin).join(',')
+ }
+ },
+ {
+ title: 'Frequency',
+ key: 'frequency',
+ render: (_, row) => {
+ const cron = getCron(row.isManual, row.cronConfig)
+ return cron.label
+ }
+ },
+ {
+ title: 'Next Run Time',
+ key: 'nextRunTime',
+ render: (_, row) => {
+ const cron = getCron(row.isManual, row.cronConfig)
+ return formatTime(cron.nextTime)
+ }
+ },
+ {
+ title: '',
+ dataIndex: 'id',
+ key: 'action',
+ align: 'center',
+ render: (val) => (
+ <Button
+ minimal
+ intent={Intent.PRIMARY}
+ icon='cog'
+ onClick={() => history.push(`/blueprints/${val}`)}
+ />
+ )
+ }
+ ] as ColumnType<BlueprintType>,
+ []
+ )
+
+ if (loading) {
+ return <PageLoading />
+ }
+
+ return (
+ <PageHeader breadcrumbs={[{ name: 'Blueprints', path: '/blueprints' }]}>
+ <S.Wrapper>
+ <div className='action'>
+ <ButtonGroup>
+ <Button
+ intent={type === 'all' ? Intent.PRIMARY : Intent.NONE}
+ text='All'
+ onClick={() => onChangeType('all')}
+ />
+ {options.map(({ label, value }) => (
+ <Button
+ key={value}
+ intent={type === value ? Intent.PRIMARY : Intent.NONE}
+ text={label}
+ onClick={() => onChangeType(value)}
+ />
+ ))}
+ </ButtonGroup>
+ <Button
+ intent={Intent.PRIMARY}
+ text='Create Blueprint'
+ onClick={() => history.push('/blueprints/create')}
+ />
+ </div>
+ <Table columns={columns} dataSource={dataSource} />
+ </S.Wrapper>
+ </PageHeader>
+ )
+}
diff --git a/config-ui/src/pages/blueprint/home/styled.ts b/config-ui/src/pages/blueprint/home/styled.ts
new file mode 100644
index 0000000..fc47e76
--- /dev/null
+++ b/config-ui/src/pages/blueprint/home/styled.ts
@@ -0,0 +1,28 @@
+/*
+ * 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 'styled-components'
+
+export const Wrapper = styled.div`
+ .action {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 16px;
+ }
+`
diff --git a/config-ui/src/pages/blueprint/home/use-home.ts b/config-ui/src/pages/blueprint/home/use-home.ts
new file mode 100644
index 0000000..dd6c23a
--- /dev/null
+++ b/config-ui/src/pages/blueprint/home/use-home.ts
@@ -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 { useState, useEffect, useMemo } from 'react'
+
+import { cronPresets } from '@/config'
+
+import type { BlueprintType } from '../types'
+
+import * as API from './api'
+
+export const useHome = () => {
+ const [loading, setLoading] = useState(false)
+ const [blueprints, setBlueprints] = useState<BlueprintType[]>([])
+ const [dataSource, setDataSource] = useState<BlueprintType[]>([])
+ const [type, setType] = useState('all')
+
+ const presets = cronPresets.map((preset) => preset.config)
+
+ const getBlueprints = async () => {
+ setLoading(true)
+ try {
+ const res = await API.getBlueprints()
+ setBlueprints(res.blueprints)
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ useEffect(() => {
+ getBlueprints()
+ }, [])
+
+ useEffect(() => {
+ setDataSource(
+ blueprints.filter((bp) => {
+ switch (type) {
+ case 'all':
+ return true
+ case 'manual':
+ return bp.isManual
+ case 'custom':
+ return !presets.includes(bp.cronConfig)
+ default:
+ return bp.cronConfig === type
+ }
+ })
+ )
+ }, [blueprints, type])
+
+ return useMemo(
+ () => ({
+ loading,
+ blueprints,
+ dataSource,
+ type,
+ onChangeType: setType
+ }),
+ [loading, blueprints, dataSource, type]
+ )
+}
diff --git a/config-ui/src/pages/blueprint/index.ts b/config-ui/src/pages/blueprint/index.ts
index 824bde2..52e04f1 100644
--- a/config-ui/src/pages/blueprint/index.ts
+++ b/config-ui/src/pages/blueprint/index.ts
@@ -17,5 +17,6 @@
*/
export * from './types'
+export * from './home'
export * from './create'
export * from './detail'