mirror of
https://github.com/datahub-project/datahub.git
synced 2025-12-24 16:38:19 +00:00
feat(customHomePage): add generic module component (#13922)
This commit is contained in:
parent
68130a33e4
commit
cfadc80843
@ -87,7 +87,7 @@ export type BorderRadiusOptions = 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
||||
|
||||
export type BoxShadowOptions = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'inner' | 'outline' | 'dropdown' | 'none';
|
||||
|
||||
export type SpacingOptions = 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl';
|
||||
export type SpacingOptions = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl';
|
||||
|
||||
export type RotationOptions = '0' | '90' | '180' | '270';
|
||||
|
||||
|
||||
@ -1,12 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
import Module from '@app/homepageV2/module/Module';
|
||||
import { ContentContainer, ContentWrapper, StyledVectorBackground } from '@app/homepageV2/styledComponents';
|
||||
|
||||
const HomePageContent = () => {
|
||||
return (
|
||||
<ContentWrapper>
|
||||
<StyledVectorBackground />
|
||||
<ContentContainer />
|
||||
<ContentContainer>
|
||||
<Module
|
||||
name="Sample large module"
|
||||
description="Description of the sample module"
|
||||
type="sampleLarge"
|
||||
visibility="global"
|
||||
/>
|
||||
</ContentContainer>
|
||||
</ContentWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
14
datahub-web-react/src/app/homepageV2/module/Module.tsx
Normal file
14
datahub-web-react/src/app/homepageV2/module/Module.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import SampleLargeModule from '@app/homepageV2/module/modules/SampleLargeModule';
|
||||
import { ModuleProps } from '@app/homepageV2/module/types';
|
||||
|
||||
export default function Module(props: ModuleProps) {
|
||||
const Component = useMemo(() => {
|
||||
// TODO: implement logic to map props.type to component
|
||||
if (props.type === 'sampleLarge') return SampleLargeModule;
|
||||
return SampleLargeModule;
|
||||
}, [props.type]);
|
||||
|
||||
return <Component {...props} />;
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
import { borders, colors, radius, spacing } from '@components';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import ModuleContainer from '@app/homepageV2/module/components/ModuleContainer';
|
||||
import ModuleDescription from '@app/homepageV2/module/components/ModuleDescription';
|
||||
import ModuleMenu from '@app/homepageV2/module/components/ModuleMenu';
|
||||
import ModuleName from '@app/homepageV2/module/components/ModuleName';
|
||||
import PublicModuleBadge from '@app/homepageV2/module/components/PublicModuleBadge';
|
||||
import { ModuleProps } from '@app/homepageV2/module/types';
|
||||
|
||||
const ModuleHeader = styled.div`
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
border-radius: ${radius.lg} ${radius.lg} 0 0;
|
||||
padding: ${spacing.md} ${spacing.md} ${spacing.xsm} ${spacing.md};
|
||||
border-bottom: ${borders['1px']} ${colors.white};
|
||||
|
||||
:hover {
|
||||
background: linear-gradient(180deg, #fff 0%, #fafafb 100%);
|
||||
border-bottom: 1px solid ${colors.gray[100]};
|
||||
}
|
||||
`;
|
||||
|
||||
const FloatingRightHeaderSection = styled.div`
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding-right: 16px;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const Content = styled.div`
|
||||
padding: 16px;
|
||||
`;
|
||||
|
||||
export default function LargeModule({ children, name, description, visibility }: React.PropsWithChildren<ModuleProps>) {
|
||||
return (
|
||||
<ModuleContainer $height="316px">
|
||||
<ModuleHeader>
|
||||
<ModuleName text={name} />
|
||||
<ModuleDescription text={description} />
|
||||
<FloatingRightHeaderSection>
|
||||
<PublicModuleBadge isPublic={visibility === 'global'} />
|
||||
<ModuleMenu />
|
||||
</FloatingRightHeaderSection>
|
||||
</ModuleHeader>
|
||||
<Content>{children}</Content>
|
||||
</ModuleContainer>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
import { borders, colors, radius } from '@components';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const ModuleContainer = styled.div<{ $height: string }>`
|
||||
background: ${colors.white};
|
||||
border: ${borders['1px']} ${colors.gray[100]};
|
||||
border-radius: ${radius.lg};
|
||||
|
||||
height: ${(props) => props.$height};
|
||||
box-shadow:
|
||||
0px 2px 18px 0px rgba(17, 7, 69, 0.01),
|
||||
0px 4px 12px 0px rgba(17, 7, 69, 0.03);
|
||||
`;
|
||||
|
||||
export default ModuleContainer;
|
||||
@ -0,0 +1,15 @@
|
||||
import { Text } from '@components';
|
||||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
text?: string;
|
||||
}
|
||||
|
||||
export default function ModuleDescription({ text }: Props) {
|
||||
if (!text) return null;
|
||||
return (
|
||||
<Text color="gray" colorLevel={1700} size="md" weight="medium" lineHeight="xs">
|
||||
{text}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
import { Icon, colors } from '@components';
|
||||
import { Dropdown } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const StyledIcon = styled(Icon)`
|
||||
:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
` as typeof Icon;
|
||||
|
||||
export default function ModuleMenu() {
|
||||
return (
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
title: 'Edit',
|
||||
key: 'edit',
|
||||
label: 'Edit',
|
||||
},
|
||||
{
|
||||
title: 'Duplicate',
|
||||
label: 'Duplicate',
|
||||
key: 'duplicate',
|
||||
},
|
||||
{
|
||||
title: 'Delete',
|
||||
label: 'Delete',
|
||||
key: 'delete',
|
||||
style: {
|
||||
color: colors.red[500],
|
||||
},
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
<StyledIcon icon="DotsThreeVertical" source="phosphor" size="lg" />
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
import { Text } from '@components';
|
||||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
text?: string;
|
||||
}
|
||||
|
||||
export default function ModuleName({ text }: Props) {
|
||||
return (
|
||||
<Text color="gray" colorLevel={600} size="xl" weight="bold" lineHeight="sm">
|
||||
{text}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
import { Pill } from '@components';
|
||||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
isPublic?: boolean;
|
||||
}
|
||||
|
||||
export default function PublicModuleBadge({ isPublic }: Props) {
|
||||
if (!isPublic) return null;
|
||||
|
||||
return <Pill label="Public" color="gray" size="xs" />;
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
import React from 'react';
|
||||
|
||||
import LargeModule from '@app/homepageV2/module/components/LargeModule';
|
||||
import { ModuleProps } from '@app/homepageV2/module/types';
|
||||
|
||||
export default function SampleLargeModule(props: ModuleProps) {
|
||||
return <LargeModule {...props}>Content of the sample module</LargeModule>;
|
||||
}
|
||||
9
datahub-web-react/src/app/homepageV2/module/types.ts
Normal file
9
datahub-web-react/src/app/homepageV2/module/types.ts
Normal file
@ -0,0 +1,9 @@
|
||||
// TODO: adapt to DataHubPageModuleProperties
|
||||
// the current props are just to draft some components
|
||||
export interface ModuleProps {
|
||||
name: string;
|
||||
type: string;
|
||||
visibility: 'personal' | 'global';
|
||||
description?: string;
|
||||
isPublic?: boolean;
|
||||
}
|
||||
@ -30,6 +30,7 @@ export const ContentWrapper = styled.div`
|
||||
`;
|
||||
|
||||
export const ContentContainer = styled.div`
|
||||
position: relative; // to enable z-index
|
||||
padding: 40px 160px 16px 160px;
|
||||
background-color: ${colors.white};
|
||||
height: 100%;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user