diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index c59d36c6b7c0..50c7c1f4bb63 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -1502,6 +1502,9 @@ importers:
sealos-desktop-sdk:
specifier: workspace:^
version: link:../../packages/client-sdk
+ swiper:
+ specifier: ^11.0.5
+ version: 11.0.5
typescript:
specifier: 5.2.2
version: 5.2.2
@@ -16150,6 +16153,11 @@ packages:
stable: 0.1.8
dev: true
+ /swiper@11.0.5:
+ resolution: {integrity: sha512-rhCwupqSyRnWrtNzWzemnBLMoyYuoDgGgspAm/8iBD3jCvAWycPLH4Z3TB0O5520DHLzMx94yUMH/B9Efpa48w==}
+ engines: {node: '>= 4.7.0'}
+ dev: false
+
/symbol-tree@3.2.4:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
dev: true
diff --git a/frontend/providers/applaunchpad/src/services/monitorFetch.ts b/frontend/providers/applaunchpad/src/services/monitorFetch.ts
index 044392139e23..83a345939034 100644
--- a/frontend/providers/applaunchpad/src/services/monitorFetch.ts
+++ b/frontend/providers/applaunchpad/src/services/monitorFetch.ts
@@ -2,7 +2,7 @@ import { AxiosRequestConfig } from 'axios';
export const monitorFetch = async (props: AxiosRequestConfig, kubeconfig: string) => {
const { url, params } = props;
- const queryString = new URLSearchParams(params).toString();
+ const queryString = typeof params === 'object' ? new URLSearchParams(params).toString() : params;
const requestOptions = {
method: 'GET',
headers: {
@@ -10,8 +10,18 @@ export const monitorFetch = async (props: AxiosRequestConfig, kubeconfig: string
}
};
const doMain = process.env.MONITOR_URL || 'http://monitor-system.cloud.sealos.run';
- const response = await fetch(`${doMain}${url}?${queryString}`, requestOptions).then((res) =>
- res.json()
- );
- return response;
+
+ try {
+ const response = await fetch(`${doMain}${url}?${queryString}`, requestOptions);
+
+ if (!response.ok) {
+ throw new Error(`Error monitorFetch ${response.status}`);
+ }
+
+ const jsonResponse = await response.json();
+ return jsonResponse;
+ } catch (error) {
+ console.error('Error monitorFetch:', error);
+ throw error;
+ }
};
diff --git a/frontend/providers/template/arrow-right.svg b/frontend/providers/template/arrow-right.svg
new file mode 100644
index 000000000000..15c8bc9e312b
--- /dev/null
+++ b/frontend/providers/template/arrow-right.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/providers/template/package.json b/frontend/providers/template/package.json
index 5178614a302d..be1ec5db44a4 100644
--- a/frontend/providers/template/package.json
+++ b/frontend/providers/template/package.json
@@ -59,6 +59,7 @@
"remark-unwrap-images": "^3.0.1",
"sass": "^1.68.0",
"sealos-desktop-sdk": "workspace:^",
+ "swiper": "^11.0.5",
"typescript": "5.2.2",
"zustand": "^4.4.1"
},
diff --git a/frontend/providers/template/src/components/Banner/index.tsx b/frontend/providers/template/src/components/Banner/index.tsx
new file mode 100644
index 000000000000..f5dc25e44128
--- /dev/null
+++ b/frontend/providers/template/src/components/Banner/index.tsx
@@ -0,0 +1,183 @@
+import { Box, Flex, Image, Text } from '@chakra-ui/react';
+import { useRef } from 'react';
+import { Autoplay } from 'swiper/modules';
+import { Swiper, SwiperRef, SwiperSlide, useSwiper } from 'swiper/react';
+import 'swiper/css';
+import { ArrowRightIcon } from '../icons/ArrowRight';
+
+export const SlideData = [
+ {
+ image:
+ 'https://images.unsplash.com/photo-1546768292-fb12f6c92568?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80',
+ bg: '#824DFF',
+ title: '1111',
+ desc: 'Build the tools you can’t buy off the shelf',
+ borderRadius: '8px',
+ icon: 'https://jsd.onmicrosoft.cn/gh/appsmithorg/appsmith@release/static/logo.png'
+ },
+ {
+ image:
+ 'https://images.unsplash.com/photo-1501446529957-6226bd447c46?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1489&q=80',
+ bg: '#3770FE',
+ title: '222',
+ desc: 'Make AI more knowledgeable about you',
+ borderRadius: '8px',
+ icon: 'https://jsd.onmicrosoft.cn/gh/appsmithorg/appsmith@release/static/logo.png'
+ },
+ {
+ image:
+ 'https://images.unsplash.com/photo-1483729558449-99ef09a8c325?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1350&q=80',
+ bg: '#824DFF',
+ title: '333',
+ desc: 'Build the tools you can’t buy off the shelf',
+ borderRadius: '8px',
+ icon: 'https://jsd.onmicrosoft.cn/gh/appsmithorg/appsmith@release/static/logo.png'
+ },
+ {
+ image:
+ 'https://images.unsplash.com/photo-1475189778702-5ec9941484ae?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1351&q=80',
+ bg: '#824DFF',
+ title: '4444',
+ desc: 'Build the tools you can’t buy off the shelf',
+ borderRadius: '8px',
+ icon: 'https://jsd.onmicrosoft.cn/gh/appsmithorg/appsmith@release/static/logo.png'
+ }
+];
+
+export default function Banner() {
+ const swiperRef = useRef(null);
+ const swiper = useSwiper();
+
+ const handlePrev = () => {
+ if (swiperRef.current) {
+ swiperRef.current?.swiper.slidePrev();
+ }
+ };
+
+ const handleNext = () => {
+ if (swiperRef.current) {
+ swiperRef.current?.swiper.slideNext();
+ }
+ };
+
+ return (
+
+
+ {SlideData.map((item, index) => (
+
+
+
+
+
+
+
+
+
+ {item.title}
+
+
+
+ {item.desc}
+
+
+
+
+
+
+
+
+
+
+
+ {SlideData[(index + 1) % SlideData.length].title}
+
+
+
+ {SlideData[(index + 1) % SlideData.length].desc}
+
+
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/providers/template/src/components/icons/ArrowRight.tsx b/frontend/providers/template/src/components/icons/ArrowRight.tsx
new file mode 100644
index 000000000000..e062da394840
--- /dev/null
+++ b/frontend/providers/template/src/components/icons/ArrowRight.tsx
@@ -0,0 +1,16 @@
+import { Icon, IconProps } from '@chakra-ui/react';
+
+export const ArrowRightIcon = (props: IconProps) => (
+
+
+
+);
diff --git a/frontend/providers/template/src/components/icons/index.ts b/frontend/providers/template/src/components/icons/index.ts
index b9e62018e695..fb9bdcb1522a 100644
--- a/frontend/providers/template/src/components/icons/index.ts
+++ b/frontend/providers/template/src/components/icons/index.ts
@@ -3,3 +3,4 @@ export * from './Share';
export * from './HomePage';
export * from './HtmlIcon';
export * from './MdIcon';
+export * from './ArrowRight';
diff --git a/frontend/providers/template/src/components/layout/appmenu.tsx b/frontend/providers/template/src/components/layout/appmenu.tsx
index 1d7ceb19d1b9..7f59f361d7a8 100644
--- a/frontend/providers/template/src/components/layout/appmenu.tsx
+++ b/frontend/providers/template/src/components/layout/appmenu.tsx
@@ -1,16 +1,38 @@
-import { Box, Flex, Input, InputGroup, InputLeftElement, Text } from '@chakra-ui/react';
+import { useCachedStore } from '@/store/cached';
+import { useSearchStore } from '@/store/search';
+import { getLangStore, setLangStore } from '@/utils/cookieUtils';
+import { Box, Flex, FlexProps, Input, InputGroup, InputLeftElement, Text } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
-import SideBar from './sidebar';
import { useRouter } from 'next/router';
+import { useEffect } from 'react';
import MyIcon from '../Icon';
-import { useGlobalStore } from '@/store/global';
-import { useMemo } from 'react';
-import { useSearchStore } from '@/store/search';
+import SideBar from './sidebar';
export default function AppMenu({ isMobile }: { isMobile: boolean }) {
- const { t } = useTranslation();
+ const { t, i18n } = useTranslation();
const router = useRouter();
const { searchValue, setSearchValue } = useSearchStore();
+ const { insideCloud, setInsideCloud } = useCachedStore();
+
+ const changeI18n = async (newLang: string) => {
+ const lastLang = getLangStore();
+ if (lastLang !== newLang && i18n?.changeLanguage) {
+ i18n.changeLanguage(newLang);
+ setLangStore(newLang);
+ }
+ };
+
+ const baseStyle: FlexProps = {
+ position: 'absolute',
+ justifyContent: 'center',
+ alignItems: 'center',
+ bg: 'rgba(150, 153, 180, 0.15)',
+ userSelect: 'none'
+ };
+
+ useEffect(() => {
+ setInsideCloud(!(window.top === window));
+ }, [setInsideCloud]);
return (
@@ -49,26 +71,48 @@ export default function AppMenu({ isMobile }: { isMobile: boolean }) {
>
)}
-
-
- router.push('/develop')}>
-
- {!isMobile && (
+ {isMobile ? (
+ router.push('/develop')}>
+
+
+ ) : (
+ router.push('/develop')}>
+
{t('develop.Debugging Template')}
- )}
-
+
+ )}
+ {insideCloud && (
+ {
+ changeI18n(i18n?.language === 'en' ? 'zh' : 'en');
+ }}>
+ {i18n?.language === 'en' ? 'En' : '中'}
+
+ )}
);
}
diff --git a/frontend/providers/template/src/pages/api/listTemplate.ts b/frontend/providers/template/src/pages/api/listTemplate.ts
index bc4b1b94c381..e85a704ba29a 100644
--- a/frontend/providers/template/src/pages/api/listTemplate.ts
+++ b/frontend/providers/template/src/pages/api/listTemplate.ts
@@ -41,24 +41,21 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
try {
if (!hasAddCron) {
+ hasAddCron = true;
cron.schedule('*/5 * * * *', async () => {
const result = await (await fetch(`${baseurl}/api/updateRepo`)).json();
- console.log('scheduling cron: */5 * * * *', result);
+ console.log(`scheduling cron ${new Date().toString()}`, result);
});
- hasAddCron = true;
}
- if (fs.existsSync(jsonPath)) {
- console.log(1);
- const templates = readTemplates(jsonPath, cdnUrl);
- return jsonRes(res, { data: templates, code: 200 });
- } else {
- console.log(2);
+ if (!fs.existsSync(jsonPath)) {
+ console.log(`${baseurl}/api/updateRepo`);
await fetch(`${baseurl}/api/updateRepo`);
- return jsonRes(res, { data: [], code: 201 });
}
+
+ const templates = readTemplates(jsonPath, cdnUrl);
+ jsonRes(res, { data: templates, code: 200 });
} catch (error) {
- console.log(error);
jsonRes(res, { code: 500, data: 'error' });
}
}
diff --git a/frontend/providers/template/src/pages/api/updateRepo.ts b/frontend/providers/template/src/pages/api/updateRepo.ts
index c21d6c8bfcc8..290f0fa5b3d5 100644
--- a/frontend/providers/template/src/pages/api/updateRepo.ts
+++ b/frontend/providers/template/src/pages/api/updateRepo.ts
@@ -98,7 +98,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
readFileList(_targetPath, fileList);
const templateStaticMap: { [key: string]: number } = await GetTemplateStatic();
- console.log(templateStaticMap);
let jsonObjArr: unknown[] = [];
fileList.forEach((item: any) => {
@@ -124,7 +123,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
jsonRes(res, { data: `success update template ${repoHttpUrl} branch ${branch}`, code: 200 });
} catch (err: any) {
- console.log(err, '===update repo log===');
jsonRes(res, {
code: 500,
error: err
diff --git a/frontend/providers/template/src/pages/index.tsx b/frontend/providers/template/src/pages/index.tsx
index 3750448e28d7..47f84396ec6f 100644
--- a/frontend/providers/template/src/pages/index.tsx
+++ b/frontend/providers/template/src/pages/index.tsx
@@ -1,3 +1,5 @@
+import Banner from '@/components/Banner';
+import { GET } from '@/services/request';
import { useCachedStore } from '@/store/cached';
import { useSearchStore } from '@/store/search';
import { TemplateType } from '@/types/app';
@@ -15,24 +17,34 @@ import {
Text,
Tooltip
} from '@chakra-ui/react';
+import { useQuery } from '@tanstack/react-query';
import { customAlphabet } from 'nanoid';
import { useTranslation } from 'next-i18next';
import { useRouter } from 'next/router';
import { MouseEvent, useEffect, useMemo } from 'react';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
-export default function AppList({ tempaltes }: { tempaltes: any }) {
+export default function AppList() {
const { t } = useTranslation();
const router = useRouter();
const { searchValue } = useSearchStore();
const { setInsideCloud, insideCloud } = useCachedStore();
+ const { data: FastDeployTemplates, refetch } = useQuery(
+ ['listTemplte'],
+ () => GET('/api/listTemplate'),
+ {
+ refetchInterval: 5 * 60 * 1000,
+ staleTime: 5 * 60 * 1000
+ }
+ );
+
const filterData = useMemo(() => {
- const searchResults = tempaltes?.filter((item: TemplateType) => {
+ const searchResults = FastDeployTemplates?.filter((item: TemplateType) => {
return item?.metadata?.name?.toLowerCase().includes(searchValue.toLowerCase());
});
- return searchValue ? searchResults : tempaltes;
- }, [tempaltes, searchValue]);
+ return searchValue ? searchResults : FastDeployTemplates;
+ }, [FastDeployTemplates, searchValue]);
const goDeploy = (name: string) => {
if (!name) return;
@@ -72,7 +84,8 @@ export default function AppList({ tempaltes }: { tempaltes: any }) {
background={'linear-gradient(180deg, #FFF 0%, rgba(255, 255, 255, 0.70) 100%)'}
py={'36px'}
px="42px">
- {!!tempaltes?.length ? (
+ {/* */}
+ {!!FastDeployTemplates?.length ? (