Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Name modification and deployment count display #4453

Merged
merged 1 commit into from Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion frontend/.gitignore
@@ -1 +1,4 @@
node_modules/
node_modules/
.next
.env*.local
next-env.d.ts
4 changes: 3 additions & 1 deletion frontend/providers/template/.env.template
@@ -1,4 +1,6 @@
NEXT_PUBLIC_MOCK_USER=
SEALOS_CLOUD_DOMAIN=
SEALOS_CERT_SECRET_NAME=
TEMPLATE_REPO_URL="https://github.com/labring-actions/templates"
TEMPLATE_REPO_URL="https://github.com/labring-actions/templates"
# The CDN_URL environment variable is used to specify a CDN address; when set, it replaces raw.githubusercontent.com in the resource loading URL. If not set, the default address is used.
CDN_URL=
10 changes: 7 additions & 3 deletions frontend/providers/template/public/locales/en/common.json
Expand Up @@ -148,15 +148,15 @@
"Heading to sealos soon": "Heading to sealos soon",
"develop": {
"publish": "publish",
"YAML Detection Tool": "YAML Detection Tool",
"Development": "Development",
"Please enter YAML code": "Please enter YAML code",
"Preview": "Preview",
"Configure Form": "Configure Form",
"YAML File": "YAML File",
"Template Development": "Template Development",
"Dryrun Deploy": "Dryrun Deploy",
"Formal Deploy": "Formal Deploy"
"Formal Deploy": "Formal Deploy",
"Debugging Template": "Debugging Template"
},
"SideBar": {
"Applications": "Applications",
Expand All @@ -183,5 +183,9 @@
"Markdown Part": "Markdown Part",
"Button Effect": "Button Effect",
"Type": "Type",
"Deployment successful, please go to My Application to view": "Deployment successful, please go to My Application to view"
"Deployment successful, please go to My Application to view": "Deployment successful, please go to My Application to view",
"Edit": "Edit",
"Edit App Name": "Edit App Name",
"Installation Time": "Installation Time",
"users installed the app": "{{count}} users have installed the app"
}
10 changes: 7 additions & 3 deletions frontend/providers/template/public/locales/zh/common.json
Expand Up @@ -154,15 +154,15 @@
"Heading to sealos soon": "即将前往sealos",
"develop": {
"publish": "发布",
"YAML Detection Tool": "YAML 检测工具",
"Development": "开发",
"Please enter YAML code": "请输入yaml代码",
"Preview": "预览",
"Configure Form": "配置表单",
"YAML File": "YAML 文件",
"Template Development": "模板开发",
"Dryrun Deploy": "试运行部署",
"Formal Deploy": "正式部署"
"Formal Deploy": "正式部署",
"Debugging Template": "在线调试模板"
},
"SideBar": {
"Applications": "所有应用",
Expand All @@ -189,5 +189,9 @@
"Markdown Part": "Markdown 片段",
"Button Effect": "按钮效果",
"Deployment successful, please go to My Application to view": "部署成功,请前往我的应用查看",
"Type": "类型"
"Type": "类型",
"Edit": "编辑",
"Edit App Name": "编辑应用名称",
"Installation Time": "安装时间",
"users installed the app": "已有 {{count}} 名用户安装应用"
}
8 changes: 3 additions & 5 deletions frontend/providers/template/src/components/layout/appmenu.tsx
Expand Up @@ -26,8 +26,7 @@ export default function AppMenu({ isMobile }: { isMobile: boolean }) {
width="16"
height="17"
viewBox="0 0 16 17"
fill="none"
>
fill="none">
<path
d="M14.4733 14.2786L12 11.8252C12.9601 10.6282 13.425 9.10876 13.2992 7.57942C13.1734 6.05009 12.4664 4.62708 11.3237 3.60299C10.1809 2.57889 8.6892 2.03156 7.15528 2.07354C5.62136 2.11551 4.16181 2.7436 3.07676 3.82865C1.99171 4.9137 1.36362 6.37325 1.32164 7.90717C1.27967 9.44109 1.827 10.9328 2.85109 12.0756C3.87519 13.2183 5.2982 13.9253 6.82753 14.0511C8.35686 14.1769 9.87627 13.712 11.0733 12.7519L13.5267 15.2052C13.5886 15.2677 13.6624 15.3173 13.7436 15.3512C13.8249 15.385 13.912 15.4024 14 15.4024C14.088 15.4024 14.1751 15.385 14.2564 15.3512C14.3376 15.3173 14.4114 15.2677 14.4733 15.2052C14.5935 15.0809 14.6607 14.9148 14.6607 14.7419C14.6607 14.569 14.5935 14.4029 14.4733 14.2786ZM7.33333 12.7519C6.41035 12.7519 5.5081 12.4782 4.74067 11.9654C3.97324 11.4526 3.3751 10.7238 3.02189 9.87108C2.66868 9.01836 2.57627 8.08005 2.75633 7.1748C2.9364 6.26956 3.38085 5.43804 4.0335 4.78539C4.68614 4.13275 5.51766 3.68829 6.42291 3.50822C7.32815 3.32816 8.26646 3.42058 9.11919 3.77378C9.97191 4.12699 10.7007 4.72513 11.2135 5.49256C11.7263 6.25999 12 7.16224 12 8.08522C12 9.3229 11.5083 10.5099 10.6332 11.3851C9.75799 12.2602 8.57101 12.7519 7.33333 12.7519Z"
fill="#5A646E"
Expand Down Expand Up @@ -62,12 +61,11 @@ export default function AppMenu({ isMobile }: { isMobile: boolean }) {
borderRadius={'40px'}
bottom={'28px'}
userSelect={'none'}
onClick={() => router.push('/develop')}
>
onClick={() => router.push('/develop')}>
<MyIcon name="tool" fill={'transparent'} />
{!isMobile && (
<Text ml="8px" color={'#485058'} fontWeight={500} cursor={'pointer'} fontSize={'12px'}>
{t('develop.YAML Detection Tool')}
{t('develop.Debugging Template')}
</Text>
)}
</Flex>
Expand Down
2 changes: 2 additions & 0 deletions frontend/providers/template/src/constants/keys.ts
Expand Up @@ -10,6 +10,8 @@ export const gpuNodeSelectorKey = 'nvidia.com/gpu.product';
export const gpuResourceKey = 'nvidia.com/gpu';
// template
export const templateDeployKey = 'cloud.sealos.io/deploy-on-sealos';
export const templateDisplayNameKey = 'cloud.sealos.io/deploy-on-sealos-displayName';

// db
export const kubeblocksTypeKey = 'clusterdefinition.kubeblocks.io/name';
export const dbProviderKey = 'sealos-db-provider-cr';
Expand Down
Expand Up @@ -63,6 +63,8 @@ export async function GetTemplateByName({
templateName: string;
}) {
const cdnUrl = process.env.CDN_URL;
const targetFolder = process.env.TEMPLATE_REPO_FOLDER || 'template';

const TemplateEnvs = {
SEALOS_CLOUD_DOMAIN: process.env.SEALOS_CLOUD_DOMAIN || 'cloud.sealos.io',
SEALOS_CERT_SECRET_NAME: process.env.SEALOS_CERT_SECRET_NAME || 'wildcard-cert',
Expand All @@ -72,13 +74,15 @@ export async function GetTemplateByName({
};

const originalPath = process.cwd();
const targetPath = path.resolve(originalPath, 'FastDeployTemplates', 'template');
const targetPath = path.resolve(originalPath, 'FastDeployTemplates', targetFolder);
// Query by file name in template details
const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json');
const jsonData: TemplateType[] = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
const _tempalte = jsonData.find((item) => item.metadata.name === templateName);
const _tempalteName = _tempalte ? _tempalte.spec.fileName : `${templateName}.yaml`;
const yamlString = fs.readFileSync(`${targetPath}/${_tempalteName}`, 'utf-8');
const yamlString = _tempalte?.spec?.filePath
? fs.readFileSync(_tempalte?.spec?.filePath, 'utf-8')
: fs.readFileSync(`${targetPath}/${_tempalteName}`, 'utf-8');

const yamlData = yaml.loadAll(yamlString);
const templateYaml: TemplateType = yamlData.find(
Expand All @@ -90,6 +94,7 @@ export async function GetTemplateByName({
message: 'Lack of kind template'
};
}
templateYaml.spec.deployCount = _tempalte?.spec?.deployCount;
if (cdnUrl) {
templateYaml.spec.readme = replaceRawWithCDN(templateYaml.spec.readme, cdnUrl);
templateYaml.spec.icon = replaceRawWithCDN(templateYaml.spec.icon, cdnUrl);
Expand Down
1 change: 0 additions & 1 deletion frontend/providers/template/src/pages/api/listTemplate.ts
Expand Up @@ -20,7 +20,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const originalPath = process.cwd();
const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json');
const cdnUrl = process.env.CDN_URL;

try {
if (fs.existsSync(jsonPath)) {
const jsonData = fs.readFileSync(jsonPath, 'utf8');
Expand Down
38 changes: 34 additions & 4 deletions frontend/providers/template/src/pages/api/updateRepo.ts
@@ -1,3 +1,4 @@
import { K8sApiDefault } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';
import { ApiResp } from '@/services/kubernet';
import { TemplateType } from '@/types/app';
Expand All @@ -7,9 +8,10 @@ import JSYAML from 'js-yaml';
import type { NextApiRequest, NextApiResponse } from 'next';
import path from 'path';
import util from 'util';
import * as k8s from '@kubernetes/client-node';
const execAsync = util.promisify(exec);

const readFileList = (targetPath: string, fileList: unknown[] = [], handlePath: string) => {
const readFileList = (targetPath: string, fileList: unknown[] = []) => {
// fix ci
const sanitizePath = (inputPath: string) => {
if (typeof inputPath !== 'string') {
Expand All @@ -26,16 +28,39 @@ const readFileList = (targetPath: string, fileList: unknown[] = [], handlePath:
const isYamlFile = path.extname(item) === '.yaml' || path.extname(item) === '.yml';
if (stats.isFile() && isYamlFile && item !== 'template.yaml') {
fileList.push(filePath);
} else if (stats.isDirectory() && item === handlePath) {
readFileList(filePath, fileList, handlePath);
} else if (stats.isDirectory()) {
readFileList(filePath, fileList);
}
});
};

export async function GetTemplateStatic() {
try {
const defaultKC = K8sApiDefault();
const result = await defaultKC
.makeApiClient(k8s.CoreV1Api)
.readNamespacedConfigMap('template-static', 'template-frontend');

const inputString = result?.body?.data?.['install-count'] || '';
const installCountArray = inputString.split(/\n/).filter(Boolean);

const temp: { [key: string]: number } = {};
installCountArray.forEach((item) => {
const [count, name] = item.trim().split(/\s/);
temp[name] = parseInt(count, 10);
});
return temp;
} catch (error) {
console.log(error, 'error: kubectl get configmap/template-static ');
return {};
}
}

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
const repoHttpUrl =
process.env.TEMPLATE_REPO_URL || 'https://github.com/labring-actions/templates';
const targetFolder = process.env.TEMPLATE_REPO_FOLDER || 'template';
const originalPath = process.cwd();
const targetPath = path.resolve(originalPath, 'FastDeployTemplates');
const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json');
Expand All @@ -60,8 +85,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
}

let fileList: unknown[] = [];
readFileList(targetPath, fileList, 'template');
const _targetPath = path.join(targetPath, targetFolder);
readFileList(_targetPath, fileList);

const templateStaticMap: { [key: string]: number } = await GetTemplateStatic();
let jsonObjArr: unknown[] = [];
fileList.forEach((item: any) => {
try {
Expand All @@ -70,6 +97,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const content = fs.readFileSync(item, 'utf-8');
const yamlTemplate = JSYAML.loadAll(content)[0] as TemplateType;
if (!!yamlTemplate) {
const appTitle = yamlTemplate.spec.title.toUpperCase();
yamlTemplate.spec['deployCount'] = templateStaticMap[appTitle];
yamlTemplate.spec['filePath'] = item;
yamlTemplate.spec['fileName'] = fileName;
jsonObjArr.push(yamlTemplate);
}
Expand Down
86 changes: 47 additions & 39 deletions frontend/providers/template/src/pages/app/components/list.tsx
Expand Up @@ -37,8 +37,7 @@ export default function InstanceList() {
w={'48px'}
h={'48px'}
justifyContent="center"
alignItems={'center'}
>
alignItems={'center'}>
<MyIcon color={'#7B838B'} name="empty"></MyIcon>
</Flex>
<Text mt={'12px'} fontSize={14} color={'#5A646E'}>
Expand All @@ -52,14 +51,13 @@ export default function InstanceList() {
<Grid
justifyContent={'center'}
w={'100%'}
gridTemplateColumns="repeat(auto-fill,minmax(300px,1fr))"
gridTemplateColumns="repeat(auto-fill,minmax(344px,1fr))"
gridGap={'24px'}
minW={'765px'}
pt="24px"
pr="42px"
pb="42px"
overflow={'auto'}
>
overflow={'auto'}>
{data &&
data?.map((item) => {
return (
Expand All @@ -73,48 +71,58 @@ export default function InstanceList() {
}}
key={item.id}
flexDirection={'column'}
minH={'214px'}
// h="214px"
p={'24px'}
borderRadius={'8px'}
backgroundColor={'#fff'}
boxShadow={'0px 2px 4px 0px rgba(187, 196, 206, 0.25)'}
border={'1px solid #EAEBF0'}
>
<Box
p={'6px'}
w={'48px'}
h={'48px'}
boxShadow={'0px 1px 2px 0.5px rgba(84, 96, 107, 0.20)'}
borderRadius={'4px'}
backgroundColor={'#fff'}
border={' 1px solid rgba(255, 255, 255, 0.50)'}
>
<Image src={item?.icon} alt="" width={'36px'} height={'36px'} />
</Box>
<Text fontSize="24px" fontWeight={600} color="#24282C">
{item?.id}
</Text>
<Text
pt={'8px'}
pb="16px"
fontSize={'12px'}
color={'#5A646E'}
fontWeight={400}
mt="auto"
>
{t('Creation Time')}: {item?.createTime}
</Text>
<Flex justifyContent={'space-between'} alignItems={'center'} gap={'20px'}>
border={'1px solid #EAEBF0'}>
<Flex alignItems={'center'}>
<Box
p={'6px'}
w={'48px'}
h={'48px'}
boxShadow={'0px 1px 2px 0.5px rgba(84, 96, 107, 0.20)'}
borderRadius={'4px'}
backgroundColor={'#fff'}
border={' 1px solid rgba(255, 255, 255, 0.50)'}>
<Image src={item?.icon} alt="" width={'36px'} height={'36px'} />
</Box>
<Box ml="16px">
<Text fontSize="24px" fontWeight={600} color="#24282C">
{item?.displayName ? item.displayName : item?.id}
</Text>
<Text fontSize={'16px'} color={'#111824'} fontWeight={400}>
{item?.id}
</Text>
</Box>
</Flex>
<Flex alignItems={'center'} gap={'6px'} h="18px" mt="16px">
<Icon
xmlns="http://www.w3.org/2000/svg"
width="14px"
height="15px"
viewBox="0 0 14 15"
fill="none">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M7 2.66056C4.32721 2.66056 2.16049 4.82728 2.16049 7.50007C2.16049 10.1729 4.32721 12.3396 7 12.3396C9.67278 12.3396 11.8395 10.1729 11.8395 7.50007C11.8395 4.82728 9.67278 2.66056 7 2.66056ZM0.993828 7.50007C0.993828 4.18295 3.68288 1.4939 7 1.4939C10.3171 1.4939 13.0062 4.18295 13.0062 7.50007C13.0062 10.8172 10.3171 13.5062 7 13.5062C3.68288 13.5062 0.993828 10.8172 0.993828 7.50007ZM7 3.66303C7.32217 3.66303 7.58333 3.9242 7.58333 4.24637V7.13955L9.43001 8.06289C9.71816 8.20696 9.83496 8.55736 9.69088 8.84551C9.54681 9.13366 9.19641 9.25046 8.90826 9.10639L6.73913 8.02182C6.5415 7.92301 6.41667 7.72102 6.41667 7.50007V4.24637C6.41667 3.9242 6.67783 3.66303 7 3.66303Z"
fill="#485264"
/>
</Icon>
<Text fontSize={'12px'} color={'#5A646E'} fontWeight={400}>
{t('Installation Time')}: {item?.createTime}
</Text>
</Flex>
{/* <Flex justifyContent={'space-between'} alignItems={'center'} gap={'20px'}>
<Flex
w="100%"
h="32px"
justifyContent={'center'}
alignItems={'center'}
cursor={'pointer'}
background={'#F4F6F8'}
borderRadius={'4px'}
>
borderRadius={'4px'}>
<Icon width="16px" height="17px" viewBox="0 0 16 17" fill="#363C42">
<g mask="url(#mask0_821_49862)">
<path
Expand All @@ -127,7 +135,7 @@ export default function InstanceList() {
{t('Details')}
</Text>
</Flex>
{/* <Flex
<Flex
w="100%"
h="32px"
justifyContent={'center'}
Expand All @@ -148,8 +156,8 @@ export default function InstanceList() {
<Text pl="8px " color={'#363C42'} fontWeight={500}>
{t('Unload')}
</Text>
</Flex> */}
</Flex>
</Flex>
</Flex> */}
</Flex>
);
})}
Expand Down