Skip to content

Commit

Permalink
second_edition
Browse files Browse the repository at this point in the history
  • Loading branch information
zjy365 committed Jul 31, 2024
1 parent d615c6d commit 77d3d6d
Show file tree
Hide file tree
Showing 21 changed files with 667 additions and 449 deletions.
6 changes: 5 additions & 1 deletion frontend/providers/dbprovider/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@
"i18n-ally.displayLanguage": "zh",
// "i18n-ally.namespace": true,
"i18n-ally.pathMatcher": "{locale}/{namespaces}.json",
"i18n-ally.extract.targetPickingStrategy": "most-similar-by-key"
"i18n-ally.extract.targetPickingStrategy": "most-similar-by-key",
"i18n-ally.translate.engines": [
"deepl",
"google",
]
}
11 changes: 10 additions & 1 deletion frontend/providers/dbprovider/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,18 @@
"db_name": "DataBase Name",
"db_table": "DataBase Table",
"dbconfig": {
"change_history": "Modification history",
"commit": "submit",
"confirm_updates": "Please confirm the parameters you modified:",
"get_config_err": "Failed to obtain configuration file",
"modified_value": "Modify value",
"modify_time": "Modify Time",
"no_changes": "No modification yet",
"original_value": "Original value",
"parameter": "Parameter Config",
"parameter_name": "parameter name",
"parameter_value": "Parameter value",
"search": "search",
"updates": "Modified parameters",
"updates_tip": "Changing the configuration of the mongo database will cause the database to restart"
},
Expand Down Expand Up @@ -274,4 +283,4 @@
"use_docs": "Documentation",
"version": "Version",
"yaml_file": "YAML"
}
}
11 changes: 10 additions & 1 deletion frontend/providers/dbprovider/public/locales/zh/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,18 @@
"db_name": "数据库名字",
"db_table": "数据库表",
"dbconfig": {
"change_history": "修改历史",
"commit": "提交",
"confirm_updates": "请确认您修改的参数:",
"get_config_err": "获取配置文件失败",
"modified_value": "修改值",
"modify_time": "修改时间",
"no_changes": "暂无修改",
"original_value": "原始值",
"parameter": "参数配置",
"parameter_name": "参数名",
"parameter_value": "参数值",
"search": "搜索",
"updates": "修改的参数",
"updates_tip": "mongo数据库变更配置会导致数据库重启"
},
Expand Down Expand Up @@ -274,4 +283,4 @@
"use_docs": "使用文档",
"version": "版本",
"yaml_file": "YAML 文件"
}
}
16 changes: 14 additions & 2 deletions frontend/providers/dbprovider/src/api/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,17 @@ export const getMonitorData = (payload: {
end: number;
}) => GET<{ result: MonitorChartDataResult }>(`/api/monitor/getMonitorData`, payload);

export const getOpsRequest = ({ name, label }: { name: string; label: string }) =>
GET<OpsRequestItemType[]>(`/api/opsrequest/list?name=${name}&label=${label}`);
export const getOpsRequest = ({
name,
label,
dbType
}: {
name: string;
label: string;
dbType: DBType;
}) =>
GET<OpsRequestItemType[]>(`/api/opsrequest/list`, {
name,
label,
dbType
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const map = {
infoCircle: require('./icons/infoCircle.svg').default,
upperRight: require('./icons/upperRight.svg').default,
arrowUp: require('./icons/arrowUp.svg').default,
search: require('./icons/search.svg').default,
edit: require('./icons/edit.svg').default,
book: require('./icons/book.svg').default,
export: require('./icons/export.svg').default,
Expand Down
3 changes: 2 additions & 1 deletion frontend/providers/dbprovider/src/constants/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const KBBackupNameLabel = 'dataprotection.kubeblocks.io/backup-name';
export const SealosMigrationTaskLabel = 'datamigration.sealos.io/file-migration-task';
export const MigrationRemark = 'migration-remark';
export const templateDeployKey = 'cloud.sealos.io/deploy-on-sealos';
export const DBTypeKey = 'cloud.sealos.io/dbtype';
export const DBReconfigureKey = 'ops.kubeblocks.io/ops-type=Reconfiguring';

export enum DBTypeEnum {
Expand Down Expand Up @@ -326,7 +327,7 @@ export const DBTypeSecretMap = {
}
};

export const DBTypeConfigMap: {
export const DBReconfigureMap: {
[key in DBType]: {
configMapKey: string;
configMapName: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DBTypeConfigMap } from '@/constants/db';
import { DBReconfigureMap } from '@/constants/db';
import { authSession } from '@/services/backend/auth';
import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';
Expand All @@ -17,7 +17,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
kubeconfig: await authSession(req)
});

const dbConfig = DBTypeConfigMap[dbType];
const dbConfig = DBReconfigureMap[dbType];
const key = name + dbConfig.configMapName;
if (!key || !dbConfig.configMapName) {
return jsonRes(res, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';
import { ApiResp } from '@/services/kubernet';
import { KubeBlockOpsRequestType } from '@/types/cluster';
import { DBType } from '@/types/db';
import { adaptOpsRequest } from '@/utils/adapt';
import type { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
const { name, label } = req.query as {
const { name, label, dbType } = req.query as {
name: string;
label: string;
dbType: DBType;
};

const { k8sCustomObjects, namespace } = await getK8s({
Expand All @@ -37,7 +39,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
items: KubeBlockOpsRequestType[];
};
};
const data = opsrequestsList.body.items.map((res) => adaptOpsRequest(res));

const data = opsrequestsList.body.items.map((res) => adaptOpsRequest(res, dbType));

jsonRes(res, {
data: data
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import MyIcon from '@/components/Icon';
import { I18nCommonKey } from '@/types/i18next';
import { Box, Flex, Input, InputGroup, InputLeftElement, Text } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import { useFieldArray, useForm, useWatch } from 'react-hook-form';

export interface ConfigItem {
key: string;
value: string;
isEditing: boolean;
isEdited: boolean;
originalIndex: number;
}

export interface ConfigTableRef {
submit: () => Difference[];
reset: () => void;
}

export interface Difference {
path: string;
oldValue: string;
newValue: string;
}

const ConfigTable = forwardRef<
ConfigTableRef,
{ initialData: ConfigItem[]; onDifferenceChange: (hasDifferences: boolean) => void }
>(function ConfigTable({ initialData = [], onDifferenceChange }, ref) {
const { t } = useTranslation();
const [searchTerm, setSearchTerm] = useState('');

const { register, watch, setValue, control, reset } = useForm<{ configs: ConfigItem[] }>({
defaultValues: {
configs: initialData.map((item) => ({ ...item, isEditing: false, isEdited: false }))
}
});

const { fields } = useFieldArray({
control,
name: 'configs'
});

const watchFieldArray = watch('configs');

const controlledFields = fields
.map((field, index) => {
return {
...field,
...watchFieldArray[index],
originalIndex: index
};
})
.filter((item) => item.key.toLowerCase().includes(searchTerm.toLowerCase()));

const toggleEdit = (index: number) => {
setValue(`configs.${index}.isEditing`, !watchFieldArray[index].isEditing);
};

const handleBlur = (index: number) => {
const config = watchFieldArray[index];
setValue(`configs.${index}.isEdited`, config.value !== initialData[index].value);
setValue(`configs.${index}.isEditing`, false);
};

const getChangedConfigs = (): Difference[] => {
const currentConfigs = watchFieldArray;
return currentConfigs.reduce((acc, config, index) => {
if (config.value !== initialData[index].value) {
acc.push({
path: config.key,
oldValue: initialData[index].value,
newValue: config.value
});
}
return acc;
}, [] as Difference[]);
};

const watchedConfigs = useWatch({
control,
name: 'configs'
});

useEffect(() => {
const differences = getChangedConfigs();
onDifferenceChange(differences.length > 0);
}, [watchedConfigs]);

useImperativeHandle(ref, () => ({
submit: () => {
const changedConfigs = getChangedConfigs();
return changedConfigs;
},
reset: () => {
reset({
configs: initialData.map((item) => ({ ...item, isEditing: false, isEdited: false }))
});
}
}));

const configColumns: {
title: I18nCommonKey;
key: string;
render: (item: ConfigItem, index: number) => React.ReactNode;
}[] = [
{
title: 'dbconfig.parameter_name',
key: 'parameter_name',
render: (item) => (
<Flex flex={1} alignItems={'center'} color={'grayModern.900'}>
{item.key}
</Flex>
)
},
{
title: 'dbconfig.parameter_value',
key: 'parameter_value',
render: (item) => (
<Flex flex={1} alignItems={'center'}>
{item.isEditing ? (
<Input
{...register(`configs.${item.originalIndex}.value`)}
autoFocus
onBlur={() => handleBlur(item.originalIndex)}
/>
) : (
<Flex gap={'4px'} alignItems={'center'}>
<Text maxW={'300px'} color={item.isEdited ? 'red.500' : 'grayModern.600'}>
{item.value}
</Text>
<MyIcon
onClick={() => toggleEdit(item.originalIndex)}
cursor={'pointer'}
name={'edit'}
w={'16px'}
h={'16px'}
/>
</Flex>
)}
</Flex>
)
}
];

return (
<Flex flexDirection={'column'} h={'full'}>
<Flex px={'25px'} backgroundColor={'grayModern.50'}>
<Box
flex={1}
fontSize={'12px'}
py={4}
border={'none'}
fontWeight={'500'}
color={'grayModern.600'}
>
<Flex alignItems="center">
<Text mr={2}>{t('dbconfig.parameter_name')}</Text>
<InputGroup width={'184px'}>
<InputLeftElement ml={'12px'} width={'16px'} height={'28px'}>
<MyIcon name="search" width={'16px'} height={'16px'} color="#485264" />
</InputLeftElement>
<Input
width={'184px'}
height={'28px'}
placeholder={t('dbconfig.search')}
size="sm"
value={searchTerm}
bg={'white'}
onChange={(e) => setSearchTerm(e.target.value)}
/>
</InputGroup>

<Box ml={'4px'} cursor={'pointer'} onClick={() => setSearchTerm('')}>
<MyIcon name="restart" w={'16px'} h={'16px'} />
</Box>
</Flex>
</Box>
<Flex
alignItems={'center'}
flex={1}
fontSize={'12px'}
py={4}
border={'none'}
fontWeight={'500'}
color={'grayModern.600'}
>
{t('dbconfig.parameter_value')}
</Flex>
</Flex>
<Box flex={1} height={'0'} overflowY={'auto'}>
{controlledFields?.map((item, configIndex) => (
<Flex key={item.id} px={'25px'} py={'11px'} fontSize={'12px'}>
{configColumns.map((col) => (
<Box flex={1} key={col.key}>
{col.render(item, configIndex)}
</Box>
))}
</Flex>
))}
</Box>
</Flex>
);
});

export default ConfigTable;
Loading

0 comments on commit 77d3d6d

Please sign in to comment.