mirror of https://github.com/buster-so/buster.git
initial slack build out (no apis)
This commit is contained in:
parent
12fa022cfe
commit
66cae400d6
|
@ -7,7 +7,7 @@ import { Button } from '@/components/ui/buttons';
|
|||
import { Plus } from '@/components/ui/icons';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { useDebounceSearch } from '@/hooks/useDebounceSearch';
|
||||
import { SettingsPageHeader } from '../../_components/SettingsPageHeader';
|
||||
import { SettingsPageHeader } from '@/components/features/settings';
|
||||
import { ListDatasetGroupsComponent } from './ListDatasetGroupsComponent';
|
||||
|
||||
export default function Page() {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { Button } from '@/components/ui/buttons';
|
|||
import { Plus } from '@/components/ui/icons';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { useDebounceSearch } from '@/hooks/useDebounceSearch';
|
||||
import { SettingsPageHeader } from '../../_components/SettingsPageHeader';
|
||||
import { SettingsPageHeader } from '@/components/features/settings';
|
||||
import { ListPermissionGroupsComponent } from './ListPermissionGroupsComponent';
|
||||
|
||||
export default function Page() {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { useInviteModalStore } from '@/context/BusterAppLayout';
|
|||
import { useUserConfigContextSelector } from '@/context/Users';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { useDebounceSearch } from '@/hooks/useDebounceSearch';
|
||||
import { SettingsPageHeader } from '../../_components/SettingsPageHeader';
|
||||
import { SettingsPageHeader } from '@/components/features/settings';
|
||||
import { ListUsersComponent } from './ListUsersComponent';
|
||||
|
||||
export default function Page() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { SettingsPageHeader } from '../../../_components/SettingsPageHeader';
|
||||
import { SettingsPageHeader } from '@/components/features/settings';
|
||||
import { ApiKeysController } from './ApiKeysController';
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { SettingsPageHeader } from '../../../_components/SettingsPageHeader';
|
||||
import { SettingsPageHeader } from '@/components/features/settings';
|
||||
import { DatasourceList } from './_DatasourceList';
|
||||
|
||||
export default function Page() {
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import { SlackIntegrations } from '@/components/features/integrations/SlackIntegrations';
|
||||
import { SettingsPageHeader } from '@/components/features/settings';
|
||||
import { SettingsCards } from '@/components/features/settings';
|
||||
|
||||
export default function IntegrationsPage() {
|
||||
return (
|
||||
<>
|
||||
<SettingsPageHeader
|
||||
title="Integrations"
|
||||
description="Connect Buster with other apps and services"
|
||||
/>
|
||||
|
||||
<div className="flex flex-col space-y-6">
|
||||
<SlackIntegrations />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,23 +1,21 @@
|
|||
import { InviteLinks } from '@/components/features/security/InviteLinks';
|
||||
import { SettingsPageHeader } from '../../../_components/SettingsPageHeader';
|
||||
import { SettingsPageHeader } from '@/components/features/settings';
|
||||
import { ApprovedEmailDomains } from '@/components/features/security/ApprovedEmailDomains';
|
||||
import { WorkspaceRestrictions } from '@/components/features/security/WorkspaceRestrictions';
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="flex flex-col space-y-4">
|
||||
<div>
|
||||
<SettingsPageHeader
|
||||
title="Security"
|
||||
description="Manage security and general permission settings"
|
||||
/>
|
||||
<>
|
||||
<SettingsPageHeader
|
||||
title="Security"
|
||||
description="Manage security and general permission settings"
|
||||
/>
|
||||
|
||||
<div className="flex flex-col space-y-6">
|
||||
<InviteLinks />
|
||||
<ApprovedEmailDomains />
|
||||
<WorkspaceRestrictions />
|
||||
</div>
|
||||
<div className="flex flex-col space-y-6">
|
||||
<InviteLinks />
|
||||
<ApprovedEmailDomains />
|
||||
<WorkspaceRestrictions />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Avatar } from '@/components/ui/avatar';
|
|||
import { Text, Title } from '@/components/ui/typography';
|
||||
import { useUserConfigContextSelector } from '@/context/Users/BusterUserConfigProvider';
|
||||
import { formatDate } from '@/lib/date';
|
||||
import { SettingsPageHeader } from '../../_components/SettingsPageHeader';
|
||||
import { SettingsPageHeader } from '@/components/features/settings';
|
||||
|
||||
export default function ProfilePage() {
|
||||
const user = useUserConfigContextSelector((state) => state.user);
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
import React from 'react';
|
||||
import { SettingsCards } from '../settings/SettingsCard';
|
||||
import { SlackIcon } from '@/components/ui/icons/customIcons/SlackIcon';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
|
||||
export const SlackIntegrations = React.memo(() => {
|
||||
return (
|
||||
<SettingsCards
|
||||
title="Slack"
|
||||
description="Connect Buster with Slack"
|
||||
cards={[{ sections: [<ConnectSlackCard />] }]}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
SlackIntegrations.displayName = 'SlackIntegrations';
|
||||
|
||||
const ConnectSlackCard = React.memo(() => {
|
||||
return (
|
||||
<div className="flex items-center justify-between gap-x-2">
|
||||
<div className="flex space-x-2">
|
||||
<div className="bg-item-select flex items-center justify-center rounded p-2">
|
||||
<SlackIcon size={16} />
|
||||
</div>
|
||||
<div className="flex flex-col space-y-0.5">
|
||||
<Text>Slack account</Text>
|
||||
<Text variant="secondary" size={'xs'}>
|
||||
Link your slack account to use Buster from Slack
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<Button prefix={<SlackIcon size={16} />} size={'tall'}>
|
||||
Connect Slack
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
});
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { SecurityCards } from './SecurityCards';
|
||||
import { SettingsCards } from '../settings/SettingsCard';
|
||||
import { Input } from '@/components/ui/inputs';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
|
@ -71,7 +71,7 @@ export const ApprovedEmailDomains = React.memo(() => {
|
|||
);
|
||||
|
||||
return (
|
||||
<SecurityCards
|
||||
<SettingsCards
|
||||
title="Approved email domains"
|
||||
description="Anyone with an email address at these domains is allowed to sign up for this workspace"
|
||||
cards={[{ sections }]}
|
||||
|
@ -91,7 +91,7 @@ const AddDomainInput = React.memo(
|
|||
const handleAddDomain = useMemoizedFn(async () => {
|
||||
const domain = newDomain.trim();
|
||||
if (!domain) return;
|
||||
|
||||
|
||||
const domainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]\.[a-zA-Z]{2,}$/;
|
||||
if (!domainRegex.test(domain)) {
|
||||
openErrorMessage('Please enter a valid domain name');
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { SecurityCards } from './SecurityCards';
|
||||
import { SettingsCards } from '../settings/SettingsCard';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { Input } from '@/components/ui/inputs';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
|
@ -34,7 +34,7 @@ export const InviteLinks = React.memo(() => {
|
|||
};
|
||||
|
||||
return (
|
||||
<SecurityCards
|
||||
<SettingsCards
|
||||
title="Invite links"
|
||||
description="A uniquely generated invite link allows anyone with the link to join your workspace"
|
||||
cards={[
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
'use client';
|
||||
|
||||
import React, { useMemo, type ReactNode } from 'react';
|
||||
import { SecurityCards } from './SecurityCards';
|
||||
import { SettingsCards } from '../settings/SettingsCard';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import {
|
||||
useGetWorkspaceSettings,
|
||||
|
@ -45,7 +44,7 @@ export const WorkspaceRestrictions = React.memo(() => {
|
|||
);
|
||||
|
||||
return (
|
||||
<SecurityCards
|
||||
<SettingsCards
|
||||
title="Workspace restrictions"
|
||||
description="Restrict the workspace to only allow users with an email address at these domains"
|
||||
cards={[{ sections }]}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { SecurityCards } from './SecurityCards';
|
||||
import { SettingsCards } from './SettingsCard';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { Pill } from '@/components/ui/pills/Pill';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
|
||||
const meta: Meta<typeof SecurityCards> = {
|
||||
title: 'Features/SecurityCards',
|
||||
component: SecurityCards,
|
||||
const meta: Meta<typeof SettingsCards> = {
|
||||
title: 'Features/SettingsCards',
|
||||
component: SettingsCards,
|
||||
parameters: {
|
||||
layout: 'padded',
|
||||
docs: {
|
||||
|
@ -20,7 +20,7 @@ const meta: Meta<typeof SecurityCards> = {
|
|||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof SecurityCards>;
|
||||
type Story = StoryObj<typeof SettingsCards>;
|
||||
|
||||
// Mock data for different use cases
|
||||
const basicSections = [
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { Title, Paragraph } from '@/components/ui/typography';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
|
||||
interface SecurityCardsProps {
|
||||
interface SettingsCardsProps {
|
||||
title: string;
|
||||
description: string;
|
||||
cards: {
|
||||
|
@ -10,7 +10,7 @@ interface SecurityCardsProps {
|
|||
}[];
|
||||
}
|
||||
|
||||
export const SecurityCards: React.FC<SecurityCardsProps> = ({ title, description, cards }) => {
|
||||
export const SettingsCards: React.FC<SettingsCardsProps> = ({ title, description, cards }) => {
|
||||
return (
|
||||
<div className="flex flex-col space-y-3.5">
|
||||
<div className="flex flex-col space-y-1.5">
|
||||
|
@ -20,17 +20,17 @@ export const SecurityCards: React.FC<SecurityCardsProps> = ({ title, description
|
|||
<Paragraph variant="secondary">{description}</Paragraph>
|
||||
</div>
|
||||
{cards.map((card, index) => (
|
||||
<SecurityCard key={index} sections={card.sections} />
|
||||
<SettingsCard key={index} sections={card.sections} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SecurityCard = ({ sections }: { sections: React.ReactNode[] }) => {
|
||||
const SettingsCard = ({ sections }: { sections: React.ReactNode[] }) => {
|
||||
return (
|
||||
<div className="flex flex-col rounded border">
|
||||
{sections.map((section, index) => (
|
||||
<div key={index} className={cn(index !== sections.length - 1 && 'border-b', 'px-4 py-2.5')}>
|
||||
<div key={index} className={cn(index !== sections.length - 1 && 'border-b', 'px-4 py-3.5')}>
|
||||
{section}
|
||||
</div>
|
||||
))}
|
|
@ -1,2 +1,3 @@
|
|||
export * from './SettingsEmptyState';
|
||||
export * from './SettingsPageHeader';
|
||||
export * from './SettingsCard';
|
|
@ -39,6 +39,11 @@ const workspaceItems = (currentParentRoute: BusterRoutes): ISidebarGroup => ({
|
|||
label: 'Data Sources',
|
||||
route: createBusterRoute({ route: BusterRoutes.SETTINGS_DATASOURCES }),
|
||||
id: BusterRoutes.SETTINGS_DATASOURCES
|
||||
},
|
||||
{
|
||||
label: 'Integrations',
|
||||
route: createBusterRoute({ route: BusterRoutes.SETTINGS_INTEGRATIONS }),
|
||||
id: createBusterRoute({ route: BusterRoutes.SETTINGS_INTEGRATIONS })
|
||||
}
|
||||
].map((item) => ({
|
||||
...item,
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import React from 'react';
|
||||
|
||||
export const SlackIcon: React.FC<
|
||||
React.SVGProps<SVGSVGElement> & {
|
||||
size?: number;
|
||||
}
|
||||
> = ({ className, size = 24, ...props }) => {
|
||||
return (
|
||||
<svg
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 127 127"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={className}
|
||||
{...props}>
|
||||
<path
|
||||
d="M27.2 80c0 7.3-5.9 13.2-13.2 13.2C6.7 93.2.8 87.3.8 80c0-7.3 5.9-13.2 13.2-13.2h13.2V80zm6.6 0c0-7.3 5.9-13.2 13.2-13.2 7.3 0 13.2 5.9 13.2 13.2v33c0 7.3-5.9 13.2-13.2 13.2-7.3 0-13.2-5.9-13.2-13.2V80z"
|
||||
fill="#E01E5A"
|
||||
/>
|
||||
<path
|
||||
d="M47 27c-7.3 0-13.2-5.9-13.2-13.2C33.8 6.5 39.7.6 47 .6c7.3 0 13.2 5.9 13.2 13.2V27H47zm0 6.7c7.3 0 13.2 5.9 13.2 13.2 0 7.3-5.9 13.2-13.2 13.2H13.9C6.6 60.1.7 54.2.7 46.9c0-7.3 5.9-13.2 13.2-13.2H47z"
|
||||
fill="#36C5F0"
|
||||
/>
|
||||
<path
|
||||
d="M99.9 46.9c0-7.3 5.9-13.2 13.2-13.2 7.3 0 13.2 5.9 13.2 13.2 0 7.3-5.9 13.2-13.2 13.2H99.9V46.9zm-6.6 0c0 7.3-5.9 13.2-13.2 13.2-7.3 0-13.2-5.9-13.2-13.2V13.8C66.9 6.5 72.8.6 80.1.6c7.3 0 13.2 5.9 13.2 13.2v33.1z"
|
||||
fill="#2EB67D"
|
||||
/>
|
||||
<path
|
||||
d="M80.1 99.8c7.3 0 13.2 5.9 13.2 13.2 0 7.3-5.9 13.2-13.2 13.2-7.3 0-13.2-5.9-13.2-13.2V99.8h13.2zm0-6.6c-7.3 0-13.2-5.9-13.2-13.2 0-7.3 5.9-13.2 13.2-13.2h33.1c7.3 0 13.2 5.9 13.2 13.2 0 7.3-5.9 13.2-13.2 13.2H80.1z"
|
||||
fill="#ECB22E"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue