Browse Source

chore: add office hour links on the login page and home page (#925)

* add office hour on the login page

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* add more

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

---------

Signed-off-by: ryjiang <jiangruiyi@gmail.com>
ryjiang 2 weeks ago
parent
commit
992e97880b

+ 17 - 0
client/src/components/icons/Icons.tsx

@@ -1027,6 +1027,23 @@ const icons: {
       ></path>
     </SvgIcon>
   ),
+  calendar: (props = {}) => (
+    <SvgIcon
+      width="15"
+      height="15"
+      viewBox="0 0 15 15"
+      fill="none"
+      xmlns="http://www.w3.org/2000/svg"
+      {...props}
+    >
+      <path
+        d="M4.5 1C4.77614 1 5 1.22386 5 1.5V2H10V1.5C10 1.22386 10.2239 1 10.5 1C10.7761 1 11 1.22386 11 1.5V2H12.5C13.3284 2 14 2.67157 14 3.5V12.5C14 13.3284 13.3284 14 12.5 14H2.5C1.67157 14 1 13.3284 1 12.5V3.5C1 2.67157 1.67157 2 2.5 2H4V1.5C4 1.22386 4.22386 1 4.5 1ZM10 3V3.5C10 3.77614 10.2239 4 10.5 4C10.7761 4 11 3.77614 11 3.5V3H12.5C12.7761 3 13 3.22386 13 3.5V5H2V3.5C2 3.22386 2.22386 3 2.5 3H4V3.5C4 3.77614 4.22386 4 4.5 4C4.77614 4 5 3.77614 5 3.5V3H10ZM2 6V12.5C2 12.7761 2.22386 13 2.5 13H12.5C12.7761 13 13 12.7761 13 12.5V6H2ZM7 7.5C7 7.22386 7.22386 7 7.5 7C7.77614 7 8 7.22386 8 7.5C8 7.77614 7.77614 8 7.5 8C7.22386 8 7 7.77614 7 7.5ZM9.5 7C9.22386 7 9 7.22386 9 7.5C9 7.77614 9.22386 8 9.5 8C9.77614 8 10 7.77614 10 7.5C10 7.22386 9.77614 7 9.5 7ZM11 7.5C11 7.22386 11.2239 7 11.5 7C11.7761 7 12 7.22386 12 7.5C12 7.77614 11.7761 8 11.5 8C11.2239 8 11 7.77614 11 7.5ZM11.5 9C11.2239 9 11 9.22386 11 9.5C11 9.77614 11.2239 10 11.5 10C11.7761 10 12 9.77614 12 9.5C12 9.22386 11.7761 9 11.5 9ZM9 9.5C9 9.22386 9.22386 9 9.5 9C9.77614 9 10 9.22386 10 9.5C10 9.77614 9.77614 10 9.5 10C9.22386 10 9 9.77614 9 9.5ZM7.5 9C7.22386 9 7 9.22386 7 9.5C7 9.77614 7.22386 10 7.5 10C7.77614 10 8 9.77614 8 9.5C8 9.22386 7.77614 9 7.5 9ZM5 9.5C5 9.22386 5.22386 9 5.5 9C5.77614 9 6 9.22386 6 9.5C6 9.77614 5.77614 10 5.5 10C5.22386 10 5 9.77614 5 9.5ZM3.5 9C3.22386 9 3 9.22386 3 9.5C3 9.77614 3.22386 10 3.5 10C3.77614 10 4 9.77614 4 9.5C4 9.22386 3.77614 9 3.5 9ZM3 11.5C3 11.2239 3.22386 11 3.5 11C3.77614 11 4 11.2239 4 11.5C4 11.7761 3.77614 12 3.5 12C3.22386 12 3 11.7761 3 11.5ZM5.5 11C5.22386 11 5 11.2239 5 11.5C5 11.7761 5.22386 12 5.5 12C5.77614 12 6 11.7761 6 11.5C6 11.2239 5.77614 11 5.5 11ZM7 11.5C7 11.2239 7.22386 11 7.5 11C7.77614 11 8 11.2239 8 11.5C8 11.7761 7.77614 12 7.5 12C7.22386 12 7 11.7761 7 11.5ZM9.5 11C9.22386 11 9 11.2239 9 11.5C9 11.7761 9.22386 12 9.5 12C9.77614 12 10 11.7761 10 11.5C10 11.2239 9.77614 11 9.5 11Z"
+        fill="currentColor"
+        fillRule="evenodd"
+        clipRule="evenodd"
+      ></path>
+    </SvgIcon>
+  ),
 };
 
 export default icons;

+ 2 - 1
client/src/components/icons/Types.ts

@@ -62,4 +62,5 @@ export type IconsType =
   | 'file'
   | 'eye'
   | 'newWindow'
-  | 'caretSort';
+  | 'caretSort'
+  | 'calendar';

+ 11 - 0
client/src/consts/link.ts

@@ -2,3 +2,14 @@ export const MILVUS_BASE_URL = 'https://milvus.io';
 export const CLOUD_DOCS_BASE_URL = `https://docs.zilliz.com`;
 export const MILVUS_RESTFUL_DOC_URL = `${MILVUS_BASE_URL}/api-reference/restful/v2.5.x/About.md`;
 export const CLOUD_RESTFUL_DOC_URL = `${CLOUD_DOCS_BASE_URL}/reference/restful/data-plane-v2`;
+
+// Community links
+export const MILVUS_SOURCE_CODE = 'https://github.com/milvus-io/milvus';
+export const MILVUS_DOCS = 'https://milvus.io/docs';
+export const MILVUS_DISCORD = 'https://milvus.io/discord';
+export const MILVUS_OFFICE_HOURS = 'https://milvus.io/blog/join-milvus-office-hours-to-get-support-from-vectordb-experts.md';
+
+export const ATTU_SOURCE_CODE = 'https://github.com/zilliztech/attu';
+export const ATTU_ISSUES = 'https://github.com/zilliztech/attu/issues';
+export const ATTU_DISCORD = 'https://milvus.io/discord';
+export const ATTU_OFFICE_HOURS = 'https://milvus.io/blog/join-milvus-office-hours-to-get-support-from-vectordb-experts.md';

+ 4 - 0
client/src/i18n/cn/common.ts

@@ -3,6 +3,7 @@ const commonTrans = {
     admin: 'Attu',
     address: 'Milvus 地址',
     fileIssue: '提交问题',
+    fileMilvusIssue: '提交 Milvus 问题',
     discord: 'Discord',
     token: 'Token',
     authentication: '认证',
@@ -20,6 +21,9 @@ const commonTrans = {
     checkHealth: '检查健康状态',
     version: '版本',
     clearHistory: '清空所有历史',
+    officeHours: 'Office Hours',
+    docs: 'Docs',
+    community: '社区',
   },
   status: {
     loaded: '已加载',

+ 4 - 0
client/src/i18n/en/common.ts

@@ -3,6 +3,7 @@ const commonTrans = {
     admin: 'Attu',
     address: 'Milvus Address',
     fileIssue: 'Open an Issue',
+    fileMilvusIssue: 'Open a Milvus Issue',
     discord: 'Discord',
     token: 'token',
     authentication: 'Authentication',
@@ -21,6 +22,9 @@ const commonTrans = {
     checkHealth: 'Check Health',
     version: 'Version',
     clearHistory: 'Clear All History',
+    officeHours: 'Office Hours',
+    docs: 'Docs',
+    community: 'Community',
   },
   status: {
     loaded: 'Loaded',

+ 18 - 10
client/src/pages/connect/ConnectContainer.tsx

@@ -9,6 +9,12 @@ import Box from '@mui/material/Box';
 import type { Theme } from '@mui/material/styles';
 import { ColorModeContext } from '@/context';
 import { IconButton } from '@mui/material';
+import {
+  ATTU_SOURCE_CODE,
+  ATTU_ISSUES,
+  ATTU_DISCORD,
+  ATTU_OFFICE_HOURS,
+} from '@/consts/link';
 
 const ConnectContainer = () => {
   const [version, setVersion] = useState('loading');
@@ -142,9 +148,7 @@ const ConnectContainer = () => {
               startIcon={<Icons.star />}
               fullWidth={true}
               variant="outlined"
-              onClick={() =>
-                window.open('https://github.com/zilliztech/attu', '_blank')
-              }
+              onClick={() => window.open(ATTU_SOURCE_CODE, '_blank')}
             >
               {btnTrans('star')}
             </CustomButton>
@@ -153,12 +157,7 @@ const ConnectContainer = () => {
               startIcon={<Icons.github />}
               fullWidth={true}
               variant="outlined"
-              onClick={() =>
-                window.open(
-                  'https://github.com/zilliztech/attu/issues',
-                  '_blank'
-                )
-              }
+              onClick={() => window.open(ATTU_ISSUES, '_blank')}
             >
               {commonTrans('attu.fileIssue')}
             </CustomButton>
@@ -166,11 +165,20 @@ const ConnectContainer = () => {
             <CustomButton
               startIcon={<Icons.discord />}
               variant="outlined"
-              onClick={() => window.open('https://milvus.io/discord', '_blank')}
+              onClick={() => window.open(ATTU_DISCORD, '_blank')}
               fullWidth={true}
             >
               {commonTrans('attu.discord')}
             </CustomButton>
+
+            <CustomButton
+              startIcon={<Icons.calendar />}
+              variant="outlined"
+              onClick={() => window.open(ATTU_OFFICE_HOURS, '_blank')}
+              fullWidth={true}
+            >
+              {commonTrans('attu.officeHours')}
+            </CustomButton>
           </Box>
         </Box>
         <Box

+ 135 - 0
client/src/pages/home/CommunityLinks.tsx

@@ -0,0 +1,135 @@
+import { Box, Typography, Link } from '@mui/material';
+import { useTranslation } from 'react-i18next';
+import { useContext } from 'react';
+import {
+  MILVUS_SOURCE_CODE,
+  MILVUS_DOCS,
+  MILVUS_DISCORD,
+  MILVUS_OFFICE_HOURS,
+} from '@/consts/link';
+import Icons from '@/components/icons/Icons';
+import { authContext } from '@/context';
+
+const CommunityLinks = () => {
+  const { t } = useTranslation();
+  const { isManaged } = useContext(authContext);
+
+  const links = isManaged
+    ? [
+        {
+          title: t('attu.docs'),
+          url: 'https://docs.zilliz.com/docs/home',
+          icon: <Icons.file sx={{ fontSize: 20 }} />,
+        },
+        {
+          title: 'Support',
+          url: 'https://support.zilliz.com/hc/en-us',
+          icon: <Icons.question sx={{ fontSize: 20 }} />,
+        },
+        {
+          title: 'Pricing',
+          url: 'https://zilliz.com/pricing',
+          icon: <Icons.link sx={{ fontSize: 20 }} />,
+        },
+        {
+          title: t('attu.discord'),
+          url: MILVUS_DISCORD,
+          icon: <Icons.discord sx={{ fontSize: 20 }} />,
+        },
+      ]
+    : [
+        {
+          title: t('attu.fileMilvusIssue'),
+          url: MILVUS_SOURCE_CODE,
+          icon: <Icons.github sx={{ fontSize: 20 }} />,
+        },
+        {
+          title: t('attu.docs'),
+          url: MILVUS_DOCS,
+          icon: <Icons.file sx={{ fontSize: 20 }} />,
+        },
+        {
+          title: t('attu.discord'),
+          url: MILVUS_DISCORD,
+          icon: <Icons.discord sx={{ fontSize: 20 }} />,
+        },
+        {
+          title: t('attu.officeHours'),
+          url: MILVUS_OFFICE_HOURS,
+          icon: <Icons.calendar sx={{ fontSize: 20 }} />,
+        },
+      ];
+
+  return (
+    <Box
+      sx={{
+        width: 270,
+        backgroundColor: 'background.paper',
+        borderRadius: 1,
+        p: 1.5,
+        border: '1px solid',
+        borderColor: 'divider',
+      }}
+    >
+      <Typography
+        variant="h6"
+        sx={{
+          mb: 1.5,
+          fontSize: 16,
+          fontWeight: 600,
+          color: 'text.primary',
+        }}
+      >
+        {isManaged ? 'Zilliz Cloud' : t('attu.community')}
+      </Typography>
+      <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
+        {links.map(link => (
+          <Link
+            key={link.title}
+            href={link.url}
+            target="_blank"
+            rel="noopener noreferrer"
+            sx={{
+              display: 'flex',
+              alignItems: 'center',
+              gap: 1,
+              color: 'text.primary',
+              textDecoration: 'none',
+              '&:hover': {
+                color: 'primary.main',
+                '& .MuiSvgIcon-root': {
+                  color: 'primary.main',
+                },
+              },
+            }}
+          >
+            <Box
+              sx={{
+                display: 'flex',
+                alignItems: 'center',
+                justifyContent: 'center',
+                width: 32,
+                height: 32,
+                borderRadius: 1,
+                backgroundColor: 'action.hover',
+                color: 'text.secondary',
+              }}
+            >
+              {link.icon}
+            </Box>
+            <Typography
+              sx={{
+                fontSize: 14,
+                fontWeight: 500,
+              }}
+            >
+              {link.title}
+            </Typography>
+          </Link>
+        ))}
+      </Box>
+    </Box>
+  );
+};
+
+export default CommunityLinks;

+ 152 - 126
client/src/pages/home/Home.tsx

@@ -16,6 +16,7 @@ import CreateDatabaseDialog from '../dialogs/CreateDatabaseDialog';
 import icons from '@/components/icons/Icons';
 import SysCard from './SysCard';
 import StatusIcon, { LoadingType } from '@/components/status/StatusIcon';
+import CommunityLinks from '@/pages/home/CommunityLinks';
 
 const Home = () => {
   useNavigationHook(ROUTE_PATHS.HOME);
@@ -88,147 +89,114 @@ const Home = () => {
         margin: '12px',
         position: 'relative',
         display: 'flex',
-        flexDirection: 'column',
+        gap: 2,
         height: 'calc(100vh - 80px)',
+        pr: 2,
+        overflow: 'hidden',
       })}
     >
+      {/* Main content */}
       <Box
         sx={{
-          mb: 2,
-          px: 0.5,
-          maxWidth: '90%',
+          flex: 1,
+          display: 'flex',
+          flexDirection: 'column',
+          minWidth: 0,
+          overflow: 'auto',
         }}
       >
-        <Box display="flex" alignItems="center" mb={2}>
-          <Box display="flex" alignItems="center">
-            <Typography
-              variant="h4"
+        <Box
+          sx={{
+            mb: 1.5,
+            px: 0.5,
+            maxWidth: '100%',
+          }}
+        >
+          <Box display="flex" alignItems="center" mb={2}>
+            <Box display="flex" alignItems="center">
+              <Typography
+                variant="h4"
+                sx={{
+                  mr: 1,
+                  position: 'relative',
+                  top: 8,
+                  mb: 2,
+                  color: theme => theme.palette.text.primary,
+                }}
+              >
+                {databaseTrans('databases')}
+              </Typography>
+              <Typography
+                component="span"
+                variant="subtitle1"
+                color="textSecondary"
+                sx={{ position: 'relative', top: 1, mr: 2 }}
+              >
+                ({databases.length})
+              </Typography>
+            </Box>
+            <Button
+              variant="contained"
+              color="primary"
+              size="small"
+              onClick={handleCreateDbClick}
               sx={{
-                mr: 1,
-                position: 'relative',
-                top: 8,
-                mb: 2,
-                color: theme => theme.palette.text.primary,
+                ml: 0,
+                minWidth: 24,
+                width: 24,
+                height: 24,
+                p: 0,
+                display: 'flex',
+                alignItems: 'center',
+                justifyContent: 'center',
               }}
             >
-              {databaseTrans('databases')}
-            </Typography>
-            <Typography
-              component="span"
-              variant="subtitle1"
-              color="textSecondary"
-              sx={{ position: 'relative', top: 1, mr: 2 }}
-            >
-              ({databases.length})
-            </Typography>
+              <PlusIcon sx={{ fontSize: 20 }} />
+            </Button>
           </Box>
-          <Button
-            variant="contained"
-            color="primary"
-            size="small"
-            onClick={handleCreateDbClick}
-            sx={{
-              ml: 0,
-              minWidth: 24,
-              width: 24,
-              height: 24,
-              p: 0,
-              display: 'flex',
-              alignItems: 'center',
-              justifyContent: 'center',
-            }}
-          >
-            <PlusIcon sx={{ fontSize: 20 }} />
-          </Button>
-        </Box>
-        {loadingDatabases ? (
-          <StatusIcon type={LoadingType.CREATING} />
-        ) : (
-          <Box
-            sx={{
-              display: 'flex',
-              flexWrap: 'wrap',
-              flexGrow: 0,
-              gap: 1.5,
-            }}
-          >
-            {databases.map(db => {
-              if (db.name === database) {
-                db.collections = collections.map(c => c.collection_name);
-              }
-              return (
-                <DatabaseCard
-                  database={db}
-                  isActive={db.name === database}
-                  setDatabase={setDatabase}
-                  fetchDatabases={fetchDatabases}
-                  key={db.name}
-                />
-              );
-            })}
-          </Box>
-        )}
-      </Box>
-
-      {data?.systemInfo && (
-        <>
-          <Box
-            sx={{
-              mb: 2,
-              px: 0.5,
-            }}
-          >
-            <Typography
-              variant="h4"
-              sx={{ mb: 2, color: theme => theme.palette.text.primary }}
-            >
-              {homeTrans('sysInfo')}
-            </Typography>
+          {loadingDatabases ? (
+            <StatusIcon type={LoadingType.CREATING} />
+          ) : (
             <Box
               sx={{
                 display: 'flex',
                 flexWrap: 'wrap',
                 flexGrow: 0,
-                gap: 2,
+                gap: 1.5,
               }}
             >
-              <SysCard
-                title={'Milvus Version'}
-                count={data?.systemInfo?.build_version}
-                link="system"
-              />
-
-              <SysCard
-                title={homeTrans('deployMode')}
-                count={data?.deployMode}
-                link="system"
-              />
-              <SysCard
-                title={homeTrans('upTime')}
-                count={duration}
-                link="system"
-              />
-
-              <SysCard
-                title={homeTrans('users')}
-                count={data?.users?.length}
-                link="users"
-              />
-              <SysCard
-                title={homeTrans('roles')}
-                count={data?.roles?.length}
-                link="roles"
-              />
+              {databases.map(db => {
+                if (db.name === database) {
+                  db.collections = collections.map(c => c.collection_name);
+                }
+                return (
+                  <DatabaseCard
+                    database={db}
+                    isActive={db.name === database}
+                    setDatabase={setDatabase}
+                    fetchDatabases={fetchDatabases}
+                    key={db.name}
+                  />
+                );
+              })}
             </Box>
-          </Box>
+          )}
+        </Box>
 
-          {data?.deployMode === MILVUS_DEPLOY_MODE.DISTRIBUTED && (
+        {data?.systemInfo && (
+          <>
             <Box
               sx={{
-                mb: 2,
-                px: 2,
+                mb: 1.5,
+                px: 0.5,
               }}
             >
+              <Typography
+                variant="h4"
+                sx={{ mb: 2, color: theme => theme.palette.text.primary }}
+              >
+                {homeTrans('sysInfo')}
+              </Typography>
               <Box
                 sx={{
                   display: 'flex',
@@ -238,25 +206,83 @@ const Home = () => {
                 }}
               >
                 <SysCard
-                  title={homeTrans('dataNodes')}
-                  count={data?.dataNodes?.length}
+                  title={'Milvus Version'}
+                  count={data?.systemInfo?.build_version}
                   link="system"
                 />
+
                 <SysCard
-                  title={homeTrans('indexNodes')}
-                  count={data?.indexNodes?.length}
+                  title={homeTrans('deployMode')}
+                  count={data?.deployMode}
                   link="system"
                 />
                 <SysCard
-                  title={homeTrans('queryNodes')}
-                  count={data?.queryNodes?.length}
+                  title={homeTrans('upTime')}
+                  count={duration}
                   link="system"
                 />
+
+                <SysCard
+                  title={homeTrans('users')}
+                  count={data?.users?.length}
+                  link="users"
+                />
+                <SysCard
+                  title={homeTrans('roles')}
+                  count={data?.roles?.length}
+                  link="roles"
+                />
               </Box>
             </Box>
-          )}
-        </>
-      )}
+
+            {data?.deployMode === MILVUS_DEPLOY_MODE.DISTRIBUTED && (
+              <Box
+                sx={{
+                  mb: 1.5,
+                  px: 2,
+                }}
+              >
+                <Box
+                  sx={{
+                    display: 'flex',
+                    flexWrap: 'wrap',
+                    flexGrow: 0,
+                    gap: 2,
+                  }}
+                >
+                  <SysCard
+                    title={homeTrans('dataNodes')}
+                    count={data?.dataNodes?.length}
+                    link="system"
+                  />
+                  <SysCard
+                    title={homeTrans('indexNodes')}
+                    count={data?.indexNodes?.length}
+                    link="system"
+                  />
+                  <SysCard
+                    title={homeTrans('queryNodes')}
+                    count={data?.queryNodes?.length}
+                    link="system"
+                  />
+                </Box>
+              </Box>
+            )}
+          </>
+        )}
+      </Box>
+
+      {/* Right sidebar */}
+      <Box
+        sx={{
+          width: 280,
+          flexShrink: 0,
+          display: { xs: 'none', md: 'block' },
+          height: 'fit-content',
+        }}
+      >
+        <CommunityLinks />
+      </Box>
     </Box>
   );
 };