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

dockerzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git


The following commit(s) were added to refs/heads/master by this push:
     new 72671f5541 [INLONG-10468][Dashboard] Audit data showing totals and 
variances (#10469)
72671f5541 is described below

commit 72671f5541c8a308f38d706c04961819017a4757
Author: haifxu <[email protected]>
AuthorDate: Mon Jun 24 11:53:04 2024 +0800

    [INLONG-10468][Dashboard] Audit data showing totals and variances (#10469)
---
 inlong-dashboard/src/ui/locales/cn.json            |   2 +
 inlong-dashboard/src/ui/locales/en.json            |   2 +
 .../src/ui/pages/GroupDetail/Audit/config.tsx      | 110 +++++++++++++++++++--
 .../src/ui/pages/GroupDetail/Audit/index.tsx       |  23 ++++-
 4 files changed, 125 insertions(+), 12 deletions(-)

diff --git a/inlong-dashboard/src/ui/locales/cn.json 
b/inlong-dashboard/src/ui/locales/cn.json
index 14e6b4b353..39e0b01db5 100644
--- a/inlong-dashboard/src/ui/locales/cn.json
+++ b/inlong-dashboard/src/ui/locales/cn.json
@@ -659,6 +659,8 @@
   "pages.GroupDetail.Audit.Hour": "小时",
   "pages.GroupDetail.Audit.Day": "天",
   "pages.GroupDetail.Audit.Sink": "数据目标",
+  "pages.GroupDetail.Audit.Total": "总计",
+  "pages.GroupDetail.Audit.DatepickerRule": "超出可选范围",
   "pages.GroupDetail.Delay.QueryDate": "查询日期",
   "pages.GroupDetail.Delay.AverageTitle": "平均传输时延 (ms)",
   "pages.GroupDetail.Delay.RealTimeTitle": "传输时延 (ms)",
diff --git a/inlong-dashboard/src/ui/locales/en.json 
b/inlong-dashboard/src/ui/locales/en.json
index d048475993..1403297c64 100644
--- a/inlong-dashboard/src/ui/locales/en.json
+++ b/inlong-dashboard/src/ui/locales/en.json
@@ -659,6 +659,8 @@
   "pages.GroupDetail.Audit.Day": "Day",
   "pages.GroupDetail.Audit.Sink": "Sink",
   "pages.GroupDetail.Audit.Item": "Audit item",
+  "pages.GroupDetail.Audit.Total": "Total",
+  "pages.GroupDetail.Audit.DatepickerRule": "Out of selectable time range",
   "pages.GroupDetail.Delay.QueryDate": "Query date",
   "pages.GroupDetail.Delay.AverageTitle": "Average transmission delay (ms)",
   "pages.GroupDetail.Delay.RealTimeTitle": "Transmission delay (ms)",
diff --git a/inlong-dashboard/src/ui/pages/GroupDetail/Audit/config.tsx 
b/inlong-dashboard/src/ui/pages/GroupDetail/Audit/config.tsx
index c1f6d6a651..d98162c712 100644
--- a/inlong-dashboard/src/ui/pages/GroupDetail/Audit/config.tsx
+++ b/inlong-dashboard/src/ui/pages/GroupDetail/Audit/config.tsx
@@ -93,14 +93,70 @@ export const toChartData = (source, sourceDataMap) => {
 };
 
 export const toTableData = (source, sourceDataMap) => {
-  return Object.keys(sourceDataMap)
+  const map = Object.keys(sourceDataMap)
     .reverse()
     .map(logTs => ({
       ...sourceDataMap[logTs],
       logTs,
     }));
+  let sourceData = getSourceDataWithPercent(source, map);
+  return getSourceDataWithCommas(sourceData);
 };
 
+export const getSourceDataWithPercent = (sourceKeys, sourceMap) => {
+  const auditIds = Array.from(
+    new Set(Object.values(sourceKeys).map(({ auditId }) => parseInt(auditId))),
+  );
+  return sourceMap.map(source => {
+    for (const auditId of auditIds) {
+      if (!(auditId in source)) {
+        source[auditId] = 0;
+      }
+    }
+    let newSource = {};
+    const keys = Object.keys(source).filter(key => key !== 'logTs');
+    const firstKey = keys[0];
+    const firstValue = source[firstKey];
+    newSource[firstKey] = firstValue.toString();
+    for (let key of keys.slice(1)) {
+      if (key !== 'logTs') {
+        let diff = getDiff(firstValue, source[key]);
+        newSource[key] = `${source[key]} (${diff})`;
+      }
+    }
+    newSource['logTs'] = source['logTs'];
+    return newSource;
+  });
+};
+
+export const getDiff = (first, current) => {
+  if (first === 0) {
+    return '0%';
+  }
+  let result;
+  const diff = Math.ceil((current / first - 1) * 100);
+  result = diff > 0 ? '+' + diff + '%' : diff + '%';
+  return result;
+};
+
+export const getSourceDataWithCommas = sourceData => {
+  sourceData.map(source => {
+    for (const key in source) {
+      if (key !== 'logTs') {
+        let parts = source[key].split(' ');
+        let numberPart = parts[0];
+        let percentPart = parts[1] || '';
+        let number = parseInt(numberPart, 10);
+        let formattedNumber = number.toLocaleString();
+        source[key] = formattedNumber + ' ' + percentPart;
+      }
+    }
+  });
+  return sourceData;
+};
+
+let endTimeVisible = true;
+
 export const getFormContent = (inlongGroupId, initialValues, onSearch, 
onDataStreamSuccess) => [
   {
     type: 'select',
@@ -179,20 +235,43 @@ export const getFormContent = (inlongGroupId, 
initialValues, onSearch, onDataStr
     label: i18n.t('pages.GroupDetail.Audit.EndDate'),
     name: 'endDate',
     initialValue: dayjs(initialValues.endDate),
+    rules: [
+      { required: true },
+      ({ getFieldValue }) => ({
+        validator(_, value) {
+          const dim = initialValues.timeStaticsDim;
+          if (dim === 'MINUTE') {
+            return Promise.resolve();
+          }
+          const timeDiff = value - getFieldValue('startDate');
+          console.log('timeDiff', value, getFieldValue('startDate'), timeDiff);
+          if (timeDiff >= 0) {
+            const isHourDiff = dim === 'HOUR' && timeDiff < 1000 * 60 * 60 * 
24 * 3;
+            const isDayDiff = dim === 'DAY' && timeDiff < 1000 * 60 * 60 * 24 
* 7;
+            if (isHourDiff || isDayDiff) {
+              return Promise.resolve();
+            }
+          }
+          return Promise.reject(new 
Error(i18n.t('pages.GroupDetail.Audit.DatepickerRule')));
+        },
+      }),
+    ],
     props: {
       allowClear: false,
       format: 'YYYY-MM-DD',
+      disabled: initialValues.timeStaticsDim === 'MINUTE',
       disabledDate: current => {
         const start = dayjs(initialValues.startDate);
         const dim = initialValues.timeStaticsDim;
-        if (dim === 'HOUR' || dim === 'DAY') {
-          const tooLate = current && current <= start.endOf('day');
-          const tooEarly = start && current > start.add(7, 'd').endOf('day');
-          return tooLate || tooEarly;
+        const tooEarly = current < start.add(-1, 'd').endOf('day');
+        let tooLate;
+        if (dim === 'HOUR') {
+          tooLate = current >= start.add(2, 'd').endOf('day');
+        }
+        if (dim === 'DAY') {
+          tooLate = current >= start.add(6, 'd').endOf('day');
         }
-        const tooLate = current && current >= start.endOf('day');
-        const tooEarly = start && current < start.add(-1, 'd').endOf('day');
-        return tooLate || tooEarly;
+        return current && (tooLate || tooEarly);
       },
     },
   },
@@ -244,16 +323,27 @@ export const getFormContent = (inlongGroupId, 
initialValues, onSearch, onDataStr
   },
 ];
 
-export const getTableColumns = source => {
+export const getTableColumns = (source, dim) => {
   const data = source.map(item => ({
     title: item.auditName,
     dataIndex: item.auditId,
-    render: text => text || 0,
+    render: text => {
+      let color = 'black';
+      if (text?.includes('+')) {
+        color = 'red';
+      } else if (text?.includes('-')) {
+        color = 'green';
+      }
+      return <span style={{ color: color }}>{text}</span>;
+    },
   }));
   return [
     {
       title: i18n.t('pages.GroupDetail.Audit.Time'),
       dataIndex: 'logTs',
+      render: text => {
+        return dim === 'MINUTE' ? dayjs(text).format('HH:mm') : text;
+      },
     },
   ].concat(data);
 };
diff --git a/inlong-dashboard/src/ui/pages/GroupDetail/Audit/index.tsx 
b/inlong-dashboard/src/ui/pages/GroupDetail/Audit/index.tsx
index e0a91afa46..f4ba9fbbc4 100644
--- a/inlong-dashboard/src/ui/pages/GroupDetail/Audit/index.tsx
+++ b/inlong-dashboard/src/ui/pages/GroupDetail/Audit/index.tsx
@@ -31,6 +31,8 @@ import {
   getTableColumns,
   timeStaticsDimList,
 } from './config';
+import { Table } from 'antd';
+import i18n from '@/i18n';
 
 type Props = CommonInterface;
 
@@ -92,7 +94,10 @@ const Comp: React.FC<Props> = ({ inlongGroupId }) => {
   }, [sourceData, query.timeStaticsDim]);
 
   const onSearch = async () => {
-    await form.validateFields();
+    let values = await form.validateFields();
+    if (values.timeStaticsDim == 'MINUTE') {
+      setQuery(prev => ({ ...prev, endDate: prev.startDate }));
+    }
     run();
   };
 
@@ -126,9 +131,23 @@ const Comp: React.FC<Props> = ({ inlongGroupId }) => {
 
       <HighTable
         table={{
-          columns: getTableColumns(sourceData),
+          columns: getTableColumns(sourceData, query.timeStaticsDim),
           dataSource: toTableData(sourceData, sourceDataMap),
           rowKey: 'logTs',
+          summary: () => (
+            <Table.Summary fixed>
+              <Table.Summary.Row>
+                <Table.Summary.Cell index={0}>
+                  {i18n.t('pages.GroupDetail.Audit.Total')}
+                </Table.Summary.Cell>
+                {sourceData.map((row, index) => (
+                  <Table.Summary.Cell index={index + 1}>
+                    {row.auditSet.reduce((total, item) => total + item.count, 
0).toLocaleString()}
+                  </Table.Summary.Cell>
+                ))}
+              </Table.Summary.Row>
+            </Table.Summary>
+          ),
         }}
       />
     </>

Reply via email to