This is an automated email from the ASF dual-hosted git repository. morningman pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/doris-website.git
The following commit(s) were added to refs/heads/master by this push: new ca1778c1149 (feat) update ecosystem page & users swiper (#398) ca1778c1149 is described below commit ca1778c114965a3a247344162d89e54f495ca645 Author: hututu <53259809+hututu...@users.noreply.github.com> AuthorDate: Wed Jan 31 22:15:40 2024 +0800 (feat) update ecosystem page & users swiper (#398) --- docusaurus.config.js | 10 +- src/components/Icons/checked-icon.tsx | 4 +- .../components/icons/data-loading.tsx | 42 +++++++++ .../ecomsystem-category/components/tab-item.tsx | 2 +- .../ecomsystem-category/ecomsystem-category.tsx | 21 +++-- src/components/ecomsystem/ecomsystem.data.ts | 1 + src/components/newsletter-swiper/index.tsx | 3 +- src/pages/ecosystem/connectors/index.tsx | 9 +- src/pages/ecosystem/data-loading/index.tsx | 44 +++++++++ src/pages/users/index.tsx | 85 +---------------- src/pages/users/user-swiper.tsx | 102 +++++++++++++++++++++ src/theme/BlogPostPage/index.tsx | 4 +- static/images/ecomsystem/doris-stream-loader.png | Bin 0 -> 29207 bytes 13 files changed, 226 insertions(+), 101 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index 869e405ac1b..a1ec4f62f86 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -253,11 +253,11 @@ const config = { to: '/ecosystem/cluster-management', position: 'left', }, - // { - // label: 'Community', - // to: '/community/join-community', - // position: 'left', - // }, + { + label: 'Community', + to: '/community/join-community', + position: 'left', + }, { type: 'search', position: 'right', diff --git a/src/components/Icons/checked-icon.tsx b/src/components/Icons/checked-icon.tsx index 98429084d1f..ad4b0678189 100644 --- a/src/components/Icons/checked-icon.tsx +++ b/src/components/Icons/checked-icon.tsx @@ -1,8 +1,8 @@ import React from 'react'; -export function CheckedIcon() { +export function CheckedIcon(props: any) { return ( - <span> + <span {...props}> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none"> <rect width="16" height="16" fill="white" /> <path diff --git a/src/components/ecomsystem/ecomsystem-category/components/icons/data-loading.tsx b/src/components/ecomsystem/ecomsystem-category/components/icons/data-loading.tsx new file mode 100644 index 00000000000..6da18b5b18c --- /dev/null +++ b/src/components/ecomsystem/ecomsystem-category/components/icons/data-loading.tsx @@ -0,0 +1,42 @@ +import React from 'react'; + +export function DataLoadingIcon() { + return ( + <svg xmlns="http://www.w3.org/2000/svg" width="54" height="54" viewBox="0 0 54 54" fill="none"> + <rect width="54" height="54" fill="white" /> + <path + d="M32.7729 41.3351C32.7729 40.6693 33.3127 40.1296 33.9785 40.1296H41.2117C41.8775 40.1296 42.4172 40.6693 42.4172 41.3351C42.4172 42.0009 41.8775 42.5407 41.2117 42.5407H33.9785C33.3127 42.5407 32.7729 42.0009 32.7729 41.3351Z" + fill="#24195E" + /> + <path + d="M7.05469 41.3351C7.05469 40.6693 7.59442 40.1296 8.26022 40.1296H15.4934C16.1592 40.1296 16.699 40.6693 16.699 41.3351C16.699 42.0009 16.1592 42.5407 15.4934 42.5407H8.26022C7.59442 42.5407 7.05469 42.0009 7.05469 41.3351Z" + fill="#24195E" + /> + <path + d="M7.09766 11.025C7.09766 9.90662 8.00428 9 9.12266 9H41.5573C42.6757 9 43.5823 9.90662 43.5823 11.025V23.3819C43.5823 24.5003 42.6757 25.4069 41.5573 25.4069H9.12266C8.00428 25.4069 7.09766 24.5003 7.09766 23.3819V11.025Z" + fill="#444FD9" + /> + <path + d="M7.09766 30.6539C7.09766 29.5355 8.00428 28.6289 9.12266 28.6289H37.0827C38.2011 28.6289 39.1077 29.5355 39.1077 30.6539V43.0107C39.1077 44.1291 38.2011 45.0357 37.0827 45.0357H9.12266C8.00428 45.0357 7.09766 44.1291 7.09766 43.0107V30.6539Z" + fill="#444FD9" + /> + <rect x="13.3057" y="15.4534" width="10.5" height="3.5" rx="1.75" fill="white" /> + <rect x="13.3057" y="35.0823" width="10.5" height="3.5" rx="1.75" fill="white" /> + <path + d="M47.6322 37.8733C47.6322 43.121 43.3782 47.375 38.1306 47.375C32.8829 47.375 28.6289 43.121 28.6289 37.8733C28.6289 32.6257 32.8829 28.3717 38.1306 28.3717C43.3782 28.3717 47.6322 32.6257 47.6322 37.8733Z" + fill="white" + stroke="#444FD9" + stroke-width="3.5" + stroke-linecap="round" + stroke-linejoin="round" + /> + <path + d="M42.5957 37.8733L34.4993 37.8733M34.4993 37.8733L38.3094 41.2071M34.4993 37.8733L38.3094 34.5395" + stroke="#444FD9" + stroke-width="2.5" + stroke-linecap="round" + stroke-linejoin="round" + /> + </svg> + ); +} diff --git a/src/components/ecomsystem/ecomsystem-category/components/tab-item.tsx b/src/components/ecomsystem/ecomsystem-category/components/tab-item.tsx index 771ec171e0c..a9005f99c09 100644 --- a/src/components/ecomsystem/ecomsystem-category/components/tab-item.tsx +++ b/src/components/ecomsystem/ecomsystem-category/components/tab-item.tsx @@ -14,7 +14,7 @@ interface PriceTabProps { export function TabItem({ title, content, icon, active, setActive, url }: PriceTabProps) { return ( <Link - to={url} + to={`/ecosystem/${url}`} onClick={() => { setActive(); }} diff --git a/src/components/ecomsystem/ecomsystem-category/ecomsystem-category.tsx b/src/components/ecomsystem/ecomsystem-category/ecomsystem-category.tsx index e49be97a497..86e394665e5 100644 --- a/src/components/ecomsystem/ecomsystem-category/ecomsystem-category.tsx +++ b/src/components/ecomsystem/ecomsystem-category/ecomsystem-category.tsx @@ -4,21 +4,22 @@ import { EcomsystemCategoryEnum } from '../ecomsystem.data'; import { ClusterManagementIcon } from './components/icons/cluster-management-icon'; import { ConnectorsIcon } from './components/icons/connectors-icon'; import { DistributionsAndPackagingIcon } from './components/icons/distributions-packaging-icon'; +import { DataLoadingIcon } from './components/icons/data-loading'; + import { TabItem } from './components/tab-item'; export default function EcomsystemCategory() { const location = useLocation(); const pathnames = location.pathname.split('/'); - - const current = pathnames.length > 0 ? pathnames[pathnames.length - 1] : ''; let currentActive: EcomsystemCategoryEnum = EcomsystemCategoryEnum.ClusterManagement; - if (current === EcomsystemCategoryEnum.ClusterManagement) { + if (pathnames.some(current => current === EcomsystemCategoryEnum.ClusterManagement)) { currentActive = EcomsystemCategoryEnum.ClusterManagement; - } else if (current === EcomsystemCategoryEnum.Connectors) { + } else if (pathnames.some(current => current === EcomsystemCategoryEnum.Connectors)) { currentActive = EcomsystemCategoryEnum.Connectors; } else { - currentActive = EcomsystemCategoryEnum.DistributionsAndPackaging; + currentActive = EcomsystemCategoryEnum.DataLoading; + // currentActive = EcomsystemCategoryEnum.DistributionsAndPackaging; } const [active, setActive] = useState<EcomsystemCategoryEnum | string>(currentActive); @@ -42,13 +43,21 @@ export default function EcomsystemCategory() { content="Integrate with Flink, Spark, dbt and more" /> <TabItem + url={EcomsystemCategoryEnum.DataLoading} + setActive={() => setActive(EcomsystemCategoryEnum.DataLoading)} + active={active === EcomsystemCategoryEnum.DataLoading} + icon={<DataLoadingIcon />} + title={'Data loading'} + content="Accelerate large-scale data loading" + /> + {/* <TabItem url={EcomsystemCategoryEnum.DistributionsAndPackaging} setActive={() => setActive(EcomsystemCategoryEnum.DistributionsAndPackaging)} active={active === EcomsystemCategoryEnum.DistributionsAndPackaging} icon={<DistributionsAndPackagingIcon />} title={'Distributions'} content="Complement Apache Doris" - /> + /> */} </div> ); } diff --git a/src/components/ecomsystem/ecomsystem.data.ts b/src/components/ecomsystem/ecomsystem.data.ts index 5e8895cc559..677c1d9e353 100644 --- a/src/components/ecomsystem/ecomsystem.data.ts +++ b/src/components/ecomsystem/ecomsystem.data.ts @@ -2,4 +2,5 @@ export enum EcomsystemCategoryEnum { ClusterManagement = 'cluster-management', Connectors = 'connectors', DistributionsAndPackaging = 'distributions-and-packaging', + DataLoading = 'data-loading', } diff --git a/src/components/newsletter-swiper/index.tsx b/src/components/newsletter-swiper/index.tsx index ee1f9ea4b65..1f4d8e8611e 100644 --- a/src/components/newsletter-swiper/index.tsx +++ b/src/components/newsletter-swiper/index.tsx @@ -25,6 +25,7 @@ export function NewsLetterSwiper() { useAnimationFrame(deltaTime => { // Pass on a function to the setter of the state // to make sure we always have the latest state + console.log(deltaTime); setProgressCount(prevProgressCount => { if (prevProgressCount >= 100) { @@ -33,7 +34,7 @@ export function NewsLetterSwiper() { } if (deltaTime > 100) return prevProgressCount; - return prevProgressCount + deltaTime * 0.01; + return prevProgressCount + deltaTime * 0.02; }); }, stop); diff --git a/src/pages/ecosystem/connectors/index.tsx b/src/pages/ecosystem/connectors/index.tsx index 3609904a0a4..c833cc223ef 100644 --- a/src/pages/ecosystem/connectors/index.tsx +++ b/src/pages/ecosystem/connectors/index.tsx @@ -3,6 +3,7 @@ import EcomsystemLayout from '@site/src/components/ecomsystem/ecomsystem-layout/ import ExternalLink from '@site/src/components/external-link/external-link'; import CollapseBox from '@site/src/components/collapse-box/collapse-box'; import '../index.scss'; +import { ExternalLinkArrowIcon } from '@site/src/components/Icons/external-link-arrow-icon'; export default function Connectors() { return ( @@ -21,13 +22,14 @@ export default function Connectors() { moreLink={ <> <ExternalLink - href="https://github.com/apache/doris-flink-connector" + href="https://github.com/apache/doris-flink-connector/releases" label="Download" ></ExternalLink> <ExternalLink href="https://doris.apache.org/docs/ecosystem/flink-doris-connector" className="sub-btn" label="Docs" + linkIcon={<ExternalLinkArrowIcon />} ></ExternalLink> </> } @@ -43,13 +45,15 @@ export default function Connectors() { moreLink={ <> <ExternalLink - href="https://github.com/apache/doris-spark-connector" + href="https://github.com/apache/doris-spark-connector/releases" label="Download" ></ExternalLink> + <ExternalLink href="https://doris.apache.org/docs/ecosystem/spark-doris-connector" className="sub-btn" label="Docs" + linkIcon={<ExternalLinkArrowIcon />} ></ExternalLink> </> } @@ -69,6 +73,7 @@ export default function Connectors() { href="https://doris.apache.org/docs/ecosystem/dbt-doris-adapter" className="sub-btn" label="Docs" + linkIcon={<ExternalLinkArrowIcon />} ></ExternalLink> </> } diff --git a/src/pages/ecosystem/data-loading/index.tsx b/src/pages/ecosystem/data-loading/index.tsx new file mode 100644 index 00000000000..8ac5490a71d --- /dev/null +++ b/src/pages/ecosystem/data-loading/index.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import EcomsystemLayout from '@site/src/components/ecomsystem/ecomsystem-layout/ecomsystem-layout'; +import ExternalLink from '@site/src/components/external-link/external-link'; +import CollapseBox from '@site/src/components/collapse-box/collapse-box'; +import '../index.scss'; +import { ExternalLinkArrowIcon } from '@site/src/components/Icons/external-link-arrow-icon'; + +export default function DistributionsAndPackaging() { + return ( + <EcomsystemLayout> + <div className="container mx-auto flex flex-col flex-wrap items-center justify-center mb-[5.5rem] lg:flex-row"> + <CollapseBox + title="Doris Streamloader" + description="A robust, high-performance and user-friendly alternative to the traditional curl-based stream load." + characteristic={[ + 'Split data files automatically and perform parallel loading', + 'Support multiple files and directories load with one shot', + 'Support path traversal when the target is a directory', + 'Resume loading from previous failures and cancellations', + 'Retry automatically when failure', + ]} + rightContent={ + <img src={require(`@site/static/images/ecomsystem/doris-stream-loader.png`).default} alt="" /> + } + moreLink={ + <> + <ExternalLink + href="https://github.com/apache/doris-streamloader/releases" + label="GitHub" + ></ExternalLink> + + <ExternalLink + href="https://doris.apache.org/docs/ecosystem/doris-streamloader" + className="sub-btn" + label="Docs" + linkIcon={<ExternalLinkArrowIcon />} + ></ExternalLink> + </> + } + /> + </div> + </EcomsystemLayout> + ); +} diff --git a/src/pages/users/index.tsx b/src/pages/users/index.tsx index fb9effaea4c..08d8aba417f 100644 --- a/src/pages/users/index.tsx +++ b/src/pages/users/index.tsx @@ -5,9 +5,7 @@ import { translate } from '@docusaurus/Translate'; import './index.scss'; import userCasesEn from '@site/userCases/en_US.json'; import { Swiper, SwiperClass, SwiperSlide } from 'swiper/react'; -import 'swiper/css'; -import 'swiper/css/pagination'; -import 'swiper/css/navigation'; + import { Pagination } from 'swiper'; import usePhone from '@site/src/hooks/use-phone'; import PageHeader from '@site/src/components/PageHeader'; @@ -17,6 +15,7 @@ import UserItem from './user-item'; import USERS from '../../constant/users.data.json'; import ReadMore from '@site/src/components/ReadMore'; import LinkWithArrow from '@site/src/components/link-arrow'; +import { UserSwiper } from './user-swiper'; const ALL_TEXT = 'All'; @@ -42,25 +41,8 @@ export default function Users(): JSX.Element { setActive(ALL_TEXT); }, []); - const [swiperRef, setSwiperRef] = useState<SwiperClass>(); - const theSlides = useMemo(() => ['slide one', 'slide two'], []); - const handlePrevious = useCallback(() => { - swiperRef?.slidePrev(); - }, [swiperRef]); - - const handleNext = useCallback(() => { - swiperRef?.slideNext(); - }, [swiperRef]); - - const pagination = { - clickable: true, - renderBullet: function (index, className) { - return '<span class="' + className + '"></span>'; - }, - }; - function changeCategory(category: string) { setActive(category); let currentCategory = USER_STORIES_CATEGORIES.find(item => item === category); @@ -76,67 +58,6 @@ export default function Users(): JSX.Element { } } - function renderSwiper() { - const modules = [Pagination]; - // if (!isPhone) { - // modules.push(Navigation); - // } - return ( - <div style={{ position: 'relative' }}> - {!isPhone && ( - <div - onClick={handlePrevious} - className="swiper-button-prev invisible group-hover:visible" - style={{ position: 'absolute', top: 'calc(50% - 2rem)', left: '-3rem', zIndex: 99 }} - ></div> - )} - - <Swiper - pagination={pagination} - spaceBetween={50} - slidesPerView={1} - navigation={false} - modules={modules} - loop={true} - className="mySwiper" - // style={{ minHeight: 480 }} - onSlideChange={() => console.log('slide change')} - onSwiper={setSwiperRef} - > - {USER_STORIES.map(userStory => { - return ( - <SwiperSlide key={userStory.title}> - <div className="users-wall-list row flex flex-start pb-8 lg:pb-16"> - <div> - <img - className="users-wall-img lg:w-[580px] lg:h-[248px]" - src={`${require(`@site/static/images/${userStory.image}`).default}`} - alt="users-wall-img" - /> - </div> - <div className="w-[35.75rem] ml-4 lg:ml-12 flex flex-col py-4"> - <h3 className="leading-[38px] text-2xl">{userStory.title}</h3> - <p className="my-6 text-base"> - <strong className="font-normal">{userStory.author.name}</strong> - <span className="ml-6 text-[#4C576C]">{userStory.author.title}</span> - </p> - <ReadMore to={userStory.to} className="text-primary" /> - </div> - </div> - </SwiperSlide> - ); - })} - </Swiper> - {!isPhone && ( - <div - onClick={handleNext} - className="swiper-button-next invisible group-hover:visible" - style={{ position: 'absolute', top: 'calc(50% - 2rem)', right: '-3rem', zIndex: 99 }} - ></div> - )} - </div> - ); - } return ( <Layout title={translate({ id: 'users.title', message: 'User Stories' })} @@ -162,7 +83,7 @@ export default function Users(): JSX.Element { /> <section className="group"> - <div className="users-wall container lg:pt-[88px] ">{renderSwiper()}</div> + <div className="users-wall container lg:pt-[88px] ">{<UserSwiper />}</div> </section> <section className="lg:pt-[5.5rem] container pb-[88px]"> <div className="blog-list-wrap row mt-28 lg:mt-0"> diff --git a/src/pages/users/user-swiper.tsx b/src/pages/users/user-swiper.tsx new file mode 100644 index 00000000000..291b6bd9a4a --- /dev/null +++ b/src/pages/users/user-swiper.tsx @@ -0,0 +1,102 @@ +import usePhone from '@site/src/hooks/use-phone'; +import { Pagination } from 'swiper'; +import React, { useCallback, useState } from 'react'; +import { Swiper, SwiperClass, SwiperSlide } from 'swiper/react'; +import 'swiper/css'; +import 'swiper/css/pagination'; +import 'swiper/css/navigation'; +import { USER_STORIES, USER_STORIES_CATEGORIES } from '@site/src/constant/user.data'; +import ReadMore from '@site/src/components/ReadMore'; +import { useAnimationFrame } from '../../hooks/use-animation-frame'; + +export function UserSwiper() { + const { isPhone } = usePhone(); + const [progressCount, setProgressCount] = useState<number>(0); + const [stop, setStop] = useState<boolean>(false); + + const [swiperRef, setSwiperRef] = useState<SwiperClass>(); + + const handlePrevious = useCallback(() => { + swiperRef?.slidePrev(); + }, [swiperRef]); + + const handleNext = useCallback(() => { + swiperRef?.slideNext(); + }, [swiperRef]); + + const pagination = { + clickable: true, + renderBullet: function (index, className) { + return '<span class="' + className + '"></span>'; + }, + }; + + useAnimationFrame(deltaTime => { + // Pass on a function to the setter of the state + // to make sure we always have the latest state + console.log(deltaTime); + setProgressCount(prevProgressCount => { + if (prevProgressCount >= 100) { + handleNext(); + return 0; + } + if (deltaTime > 100) return prevProgressCount; + + return prevProgressCount + deltaTime * 0.02; + }); + }, stop); + + return ( + <div style={{ position: 'relative' }} onMouseMove={() => setStop(true)} onMouseLeave={() => setStop(false)}> + {!isPhone && ( + <div + onClick={handlePrevious} + className="swiper-button-prev invisible group-hover:visible" + style={{ position: 'absolute', top: 'calc(50% - 2rem)', left: '-3rem', zIndex: 99 }} + ></div> + )} + + <Swiper + pagination={pagination} + spaceBetween={50} + slidesPerView={1} + navigation={false} + modules={[Pagination]} + loop={true} + onSlideChange={() => setProgressCount(0)} + onSwiper={setSwiperRef} + > + {USER_STORIES.map(userStory => { + return ( + <SwiperSlide key={userStory.title}> + <div className="users-wall-list row flex flex-start pb-8 lg:pb-16"> + <div> + <img + className="users-wall-img lg:w-[580px] lg:h-[248px]" + src={`${require(`@site/static/images/${userStory.image}`).default}`} + alt="users-wall-img" + /> + </div> + <div className="w-[35.75rem] ml-4 lg:ml-12 flex flex-col py-4"> + <h3 className="leading-[38px] text-2xl">{userStory.title}</h3> + <p className="my-6 text-base"> + <strong className="font-normal">{userStory.author.name}</strong> + <span className="ml-6 text-[#4C576C]">{userStory.author.title}</span> + </p> + <ReadMore to={userStory.to} className="text-primary" /> + </div> + </div> + </SwiperSlide> + ); + })} + </Swiper> + {!isPhone && ( + <div + onClick={handleNext} + className="swiper-button-next invisible group-hover:visible" + style={{ position: 'absolute', top: 'calc(50% - 2rem)', right: '-3rem', zIndex: 99 }} + ></div> + )} + </div> + ); +} diff --git a/src/theme/BlogPostPage/index.tsx b/src/theme/BlogPostPage/index.tsx index 0a75fb8a1ae..b6351a8c52b 100644 --- a/src/theme/BlogPostPage/index.tsx +++ b/src/theme/BlogPostPage/index.tsx @@ -33,7 +33,7 @@ function BlogPostPageContent(props: { sidebar: BlogSidebar; children: ReactNode } > <BlogPostItem>{children}</BlogPostItem> - <div className="scrollbar-none w-[100%] mt-6 custom-scrollbar m-auto flex gap-3 overflow-auto text-[#4C576C] lg:mt-12 lg:gap-4 pl-4"> + {/* <div className="scrollbar-none w-[100%] mt-6 custom-scrollbar m-auto flex gap-3 overflow-auto text-[#4C576C] lg:mt-12 lg:gap-4 pl-4"> {tags.map((item: any, index) => ( <Link className="py-px" to={`/blog?currentPage=1¤tCategory=${item.label}`} key={index}> <span @@ -43,7 +43,7 @@ function BlogPostPageContent(props: { sidebar: BlogSidebar; children: ReactNode </span> </Link> ))} - </div> + </div> */} {/* {(nextItem || prevItem) && <BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />} */} <RecentBlogs /> </BlogLayout> diff --git a/static/images/ecomsystem/doris-stream-loader.png b/static/images/ecomsystem/doris-stream-loader.png new file mode 100644 index 00000000000..4951b807026 Binary files /dev/null and b/static/images/ecomsystem/doris-stream-loader.png differ --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org