Update automations UX for more consistency (#856)

* Update the automations UI to be a more suitable color distribution based on new designs

* Use accented colors for the metadata, update dark mode colors

* Update form to use icons as well and render more pretty inline form labels
This commit is contained in:
sabaimran
2024-07-20 23:52:23 -07:00
committed by GitHub
parent bf815e4463
commit 9cf52bb7e4
3 changed files with 318 additions and 188 deletions

View File

@@ -4,6 +4,11 @@ div.automationsLayout {
gap: 1rem; gap: 1rem;
} }
div.automationCard {
display: grid;
grid-template-rows: auto 1fr auto;
}
@media screen and (max-width: 768px) { @media screen and (max-width: 768px) {
div.automationsLayout { div.automationsLayout {
grid-template-columns: 1fr; grid-template-columns: 1fr;

View File

@@ -47,8 +47,8 @@ import styles from './automations.module.css';
import ShareLink from '../components/shareLink/shareLink'; import ShareLink from '../components/shareLink/shareLink';
import { useSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
import { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover'; import { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover';
import { Clock, DotsThreeVertical, Envelope, Info, MapPinSimple, Pencil, Play, Plus, Trash } from '@phosphor-icons/react'; import { CalendarCheck, CalendarDot, CalendarDots, Clock, ClockAfternoon, ClockCounterClockwise, DotsThreeVertical, Envelope, Info, Lightning, MapPinSimple, Pencil, Play, Plus, Trash } from '@phosphor-icons/react';
import { useAuthenticatedData } from '../common/auth'; import { useAuthenticatedData, UserProfile } from '../common/auth';
import LoginPrompt from '../components/loginPrompt/loginPrompt'; import LoginPrompt from '../components/loginPrompt/loginPrompt';
import { useToast } from '@/components/ui/use-toast'; import { useToast } from '@/components/ui/use-toast';
import { ToastAction } from '@/components/ui/toast'; import { ToastAction } from '@/components/ui/toast';
@@ -223,6 +223,7 @@ interface AutomationsCardProps {
setNewAutomationData?: (data: AutomationsData) => void; setNewAutomationData?: (data: AutomationsData) => void;
isLoggedIn: boolean; isLoggedIn: boolean;
setShowLoginPrompt: (showLoginPrompt: boolean) => void; setShowLoginPrompt: (showLoginPrompt: boolean) => void;
authenticatedData: UserProfile | null;
} }
@@ -235,6 +236,33 @@ function AutomationsCard(props: AutomationsCardProps) {
const automation = props.automation; const automation = props.automation;
const [timeRecurrence, setTimeRecurrence] = useState('');
const [intervalString, setIntervalString] = useState('');
useEffect(() => {
// The updated automation data, if present, takes priority over the original automation data
const automationData = updatedAutomationData || automation;
setTimeRecurrence(getTimeRecurrenceFromCron(automationData.crontime));
const frequency = getEveryBlahFromCron(automationData.crontime);
console.log('frequency', frequency);
if (frequency === 'Day') {
setIntervalString('Daily');
} else if (frequency === 'Week') {
const dayOfWeek = getDayOfWeekFromCron(automationData.crontime);
if (dayOfWeek === undefined) {
setIntervalString('Weekly');
} else {
setIntervalString(`${weekDays[dayOfWeek]}`);
}
} else if (frequency === 'Month') {
const dayOfMonth = getDayOfMonthFromCron(automationData.crontime);
setIntervalString(`Monthly on the ${dayOfMonth}`);
}
}, [updatedAutomationData, props.automation]);
useEffect(() => { useEffect(() => {
const toastTitle = `Automation: ${updatedAutomationData?.subject || automation.subject}`; const toastTitle = `Automation: ${updatedAutomationData?.subject || automation.subject}`;
if (toastMessage) { if (toastMessage) {
@@ -254,8 +282,7 @@ function AutomationsCard(props: AutomationsCardProps) {
} }
return ( return (
<div className='p-2 rounded-lg bg-secondary hover:shadow-md'> <Card className={`bg-secondary h-full shadow-sm rounded-lg bg-gradient-to-b from-background to-slate-50 dark:to-gray-950 border ${styles.automationCard}`}>
<Card className='bg-secondary h-full shadow-none border-l-4 border-t-0 border-r-0 border-b-0 border-l-green-400 dark:border-green-600 rounded-none'>
<CardHeader> <CardHeader>
<CardTitle className='line-clamp-2 leading-normal flex justify-between'> <CardTitle className='line-clamp-2 leading-normal flex justify-between'>
{updatedAutomationData?.subject || automation.subject} {updatedAutomationData?.subject || automation.subject}
@@ -263,7 +290,7 @@ function AutomationsCard(props: AutomationsCardProps) {
<PopoverTrigger asChild> <PopoverTrigger asChild>
<Button className='bg-background' variant={'ghost'}><DotsThreeVertical className='h-4 w-4' /></Button> <Button className='bg-background' variant={'ghost'}><DotsThreeVertical className='h-4 w-4' /></Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent className='w-auto grid gap-2 text-left'> <PopoverContent className='w-auto grid gap-2 text-left bg-secondary'>
<Button variant={'destructive'} <Button variant={'destructive'}
className='justify-start' className='justify-start'
onClick={() => { onClick={() => {
@@ -291,6 +318,7 @@ function AutomationsCard(props: AutomationsCardProps) {
<DialogContent> <DialogContent>
<DialogTitle>Edit Automation</DialogTitle> <DialogTitle>Edit Automation</DialogTitle>
<EditCard <EditCard
authenticatedData={props.authenticatedData}
automation={automation} automation={automation}
setIsEditing={setIsEditing} setIsEditing={setIsEditing}
isLoggedIn={props.isLoggedIn} isLoggedIn={props.isLoggedIn}
@@ -312,18 +340,39 @@ function AutomationsCard(props: AutomationsCardProps) {
</Button> </Button>
) )
} }
<ShareLink
buttonTitle="Share"
includeIcon={true}
buttonClassName='justify-start px-4 py-2 h-10'
buttonVariant={'outline' as keyof typeof buttonVariants}
title="Share Automation"
description="Copy the link below and share it with your coworkers or friends."
url={createShareLink(automation)}
onShare={() => {
navigator.clipboard.writeText(createShareLink(automation));
}} />
</PopoverContent> </PopoverContent>
</Popover> </Popover>
</CardTitle> </CardTitle>
<CardDescription className='mt-2'>
{updatedAutomationData?.schedule || cronToHumanReadableString(automation.crontime)}
</CardDescription>
</CardHeader> </CardHeader>
<CardContent> <CardContent className='text-secondary-foreground'>
{updatedAutomationData?.query_to_run || automation.query_to_run} {updatedAutomationData?.query_to_run || automation.query_to_run}
</CardContent> </CardContent>
<CardFooter className="flex justify-end gap-2"> <CardFooter className="flex flex-col items-start md:flex-row md:justify-between md:items-center gap-2">
<div className='flex gap-2'>
<div className='flex items-center bg-blue-50 rounded-lg p-1.5 border-blue-200 border dark:bg-blue-800 dark:border-blue-500'>
<CalendarCheck className='h-4 w-4 mr-2 text-blue-700 dark:text-blue-300' />
<div className='text-s text-blue-700 dark:text-blue-300'>
{timeRecurrence}
</div>
</div>
<div className='flex items-center bg-purple-50 rounded-lg p-1.5 border-purple-200 border dark:bg-purple-800 dark:border-purple-500'>
<ClockAfternoon className='h-4 w-4 mr-2 text-purple-700 dark:text-purple-300' />
<div className='text-s text-purple-700 dark:text-purple-300'>
{intervalString}
</div>
</div>
</div>
{ {
props.suggestedCard && props.setNewAutomationData && ( props.suggestedCard && props.setNewAutomationData && (
<Dialog <Dialog
@@ -341,6 +390,7 @@ function AutomationsCard(props: AutomationsCardProps) {
<DialogContent> <DialogContent>
<DialogTitle>Add Automation</DialogTitle> <DialogTitle>Add Automation</DialogTitle>
<EditCard <EditCard
authenticatedData={props.authenticatedData}
createNew={true} createNew={true}
automation={automation} automation={automation}
setIsEditing={setIsEditing} setIsEditing={setIsEditing}
@@ -352,19 +402,8 @@ function AutomationsCard(props: AutomationsCardProps) {
</Dialog> </Dialog>
) )
} }
<ShareLink
buttonTitle="Share"
includeIcon={true}
buttonVariant={'outline' as keyof typeof buttonVariants}
title="Share Automation"
description="Copy the link below and share it with your coworkers or friends."
url={createShareLink(automation)}
onShare={() => {
navigator.clipboard.writeText(createShareLink(automation));
}} />
</CardFooter> </CardFooter>
</Card> </Card>
</div>
) )
} }
@@ -373,6 +412,7 @@ interface SharedAutomationCardProps {
setNewAutomationData: (data: AutomationsData) => void; setNewAutomationData: (data: AutomationsData) => void;
isLoggedIn: boolean; isLoggedIn: boolean;
setShowLoginPrompt: (showLoginPrompt: boolean) => void; setShowLoginPrompt: (showLoginPrompt: boolean) => void;
authenticatedData: UserProfile | null;
} }
function SharedAutomationCard(props: SharedAutomationCardProps) { function SharedAutomationCard(props: SharedAutomationCardProps) {
@@ -407,8 +447,12 @@ function SharedAutomationCard(props: SharedAutomationCardProps) {
<DialogTrigger> <DialogTrigger>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>
<DialogTitle>Create Automation</DialogTitle> <DialogTitle>
<Plus className='h-4 w-4 mr-2' />
Create Automation
</DialogTitle>
<EditCard <EditCard
authenticatedData={props.authenticatedData}
createNew={true} createNew={true}
setIsEditing={setIsCreating} setIsEditing={setIsCreating}
setUpdatedAutomationData={props.setNewAutomationData} setUpdatedAutomationData={props.setNewAutomationData}
@@ -438,6 +482,7 @@ interface EditCardProps {
createNew?: boolean; createNew?: boolean;
isLoggedIn: boolean; isLoggedIn: boolean;
setShowLoginPrompt: (showLoginPrompt: boolean) => void; setShowLoginPrompt: (showLoginPrompt: boolean) => void;
authenticatedData: UserProfile | null;
} }
function EditCard(props: EditCardProps) { function EditCard(props: EditCardProps) {
@@ -524,7 +569,14 @@ function EditCard(props: EditCardProps) {
} }
return ( return (
<AutomationModificationForm form={form} onSubmit={onSubmit} create={props.createNew} isLoggedIn={props.isLoggedIn} setShowLoginPrompt={props.setShowLoginPrompt} /> <AutomationModificationForm
authenticatedData={props.authenticatedData}
locationData={props.locationData || null}
form={form}
onSubmit={onSubmit}
create={props.createNew}
isLoggedIn={props.isLoggedIn}
setShowLoginPrompt={props.setShowLoginPrompt} />
) )
} }
@@ -535,6 +587,8 @@ interface AutomationModificationFormProps {
create?: boolean; create?: boolean;
isLoggedIn: boolean; isLoggedIn: boolean;
setShowLoginPrompt: (showLoginPrompt: boolean) => void; setShowLoginPrompt: (showLoginPrompt: boolean) => void;
authenticatedData: UserProfile | null;
locationData: LocationData | null;
} }
function AutomationModificationForm(props: AutomationModificationFormProps) { function AutomationModificationForm(props: AutomationModificationFormProps) {
@@ -547,7 +601,7 @@ function AutomationModificationForm(props: AutomationModificationFormProps) {
function recommendationPill(recommendationText: string, onChange: (value: any, event: React.MouseEvent<HTMLButtonElement>) => void) { function recommendationPill(recommendationText: string, onChange: (value: any, event: React.MouseEvent<HTMLButtonElement>) => void) {
return ( return (
<Button <Button
className='text-xs bg-slate-50 h-auto p-1.5 m-1 rounded-full' className='text-xs bg-slate-50 dark:bg-slate-950 h-auto p-1.5 m-1 rounded-full'
variant="ghost" variant="ghost"
key={recommendationText} key={recommendationText}
onClick={(event) => { onClick={(event) => {
@@ -572,6 +626,16 @@ function AutomationModificationForm(props: AutomationModificationFormProps) {
props.onSubmit(values); props.onSubmit(values);
setIsSaving(true); setIsSaving(true);
})} className="space-y-8"> })} className="space-y-8">
<FormItem>
<FormLabel>Setup</FormLabel>
<FormDescription>
Emails will be sent to this address. Timezone and location data will be used to schedule automations.
{
props.locationData &&
metadataMap(props.locationData, props.authenticatedData)
}
</FormDescription>
</FormItem>
{ {
!props.create && ( !props.create && (
<FormField <FormField
@@ -600,14 +664,20 @@ function AutomationModificationForm(props: AutomationModificationFormProps) {
<FormItem <FormItem
className='w-full' className='w-full'
> >
<FormLabel>Frequency</FormLabel> <FormLabel>
Frequency
</FormLabel>
<FormDescription> <FormDescription>
How frequently should this automation run? How often should this automation run?
</FormDescription> </FormDescription>
<Select onValueChange={field.onChange} defaultValue={field.value}> <Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl> <FormControl>
<SelectTrigger className='w-[200px]'> <SelectTrigger className='w-[200px]'>
Every <SelectValue placeholder="" /> <div className='flex items-center'>
<CalendarDots className='h-4 w-4 mr-2 inline' />
Every
</div>
<SelectValue placeholder="" />
</SelectTrigger> </SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <SelectContent>
@@ -631,11 +701,17 @@ function AutomationModificationForm(props: AutomationModificationFormProps) {
render={({ field }) => ( render={({ field }) => (
<FormItem <FormItem
className='w-full'> className='w-full'>
<FormLabel>Day of Week</FormLabel> <FormDescription>
Every week, on which day should this automation run?
</FormDescription>
<Select onValueChange={(value) => field.onChange(Number(value))} defaultValue={String(field.value)}> <Select onValueChange={(value) => field.onChange(Number(value))} defaultValue={String(field.value)}>
<FormControl> <FormControl>
<SelectTrigger className='w-[200px]'> <SelectTrigger className='w-[200px]'>
On <SelectValue placeholder="" /> <div className='flex items-center'>
<CalendarDot className='h-4 w-4 mr-2 inline' />
On
</div>
<SelectValue placeholder="" />
</SelectTrigger> </SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <SelectContent>
@@ -663,11 +739,15 @@ function AutomationModificationForm(props: AutomationModificationFormProps) {
render={({ field }) => ( render={({ field }) => (
<FormItem <FormItem
className='w-full'> className='w-full'>
<FormLabel>Day of Month</FormLabel> <FormDescription>Every month, on which day should the automation run?</FormDescription>
<Select onValueChange={field.onChange} defaultValue={field.value}> <Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl> <FormControl>
<SelectTrigger className='w-[200px]'> <SelectTrigger className='w-[200px]'>
On the <SelectValue placeholder="" /> <div className='flex items-center'>
<CalendarDot className='h-4 w-4 mr-2 inline' />
On the
</div>
<SelectValue placeholder="" />
</SelectTrigger> </SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <SelectContent>
@@ -705,7 +785,11 @@ function AutomationModificationForm(props: AutomationModificationFormProps) {
<Select onValueChange={field.onChange} defaultValue={field.value}> <Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl> <FormControl>
<SelectTrigger className='w-[200px]'> <SelectTrigger className='w-[200px]'>
At <SelectValue placeholder="" /> <div className='flex items-center'>
<ClockAfternoon className='h-4 w-4 mr-2 inline' />
At
</div>
<SelectValue placeholder="" />
</SelectTrigger> </SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <SelectContent>
@@ -781,6 +865,30 @@ function AutomationModificationForm(props: AutomationModificationFormProps) {
) )
} }
function metadataMap(ipLocationData: LocationData, authenticatedData: UserProfile | null) {
return (
<div className='flex flex-wrap gap-2 items-center md:justify-start justify-end'>
{
authenticatedData ? (
<span className='rounded-lg text-sm border-secondary border p-1 flex items-center shadow-sm' ><Envelope className='h-4 w-4 mr-2 inline text-orange-500' shadow-s />{authenticatedData.email}</span>
)
: null
}
{
ipLocationData && (
<span className='rounded-lg text-sm border-secondary border p-1 flex items-center shadow-sm' ><MapPinSimple className='h-4 w-4 mr-2 inline text-purple-500' />{ipLocationData ? `${ipLocationData.city}, ${ipLocationData.country}` : 'Unknown'}</span>
)
}
{
ipLocationData && (
<span className='rounded-lg text-sm border-secondary border p-1 flex items-center shadow-sm' ><Clock className='h-4 w-4 mr-2 inline text-green-500' />{ipLocationData ? `${ipLocationData.timezone}` : 'Unknown'}</span>
)
}
</div>
)
}
export default function Automations() { export default function Automations() {
const authenticatedData = useAuthenticatedData(); const authenticatedData = useAuthenticatedData();
@@ -819,10 +927,31 @@ export default function Automations() {
return ( return (
<div> <div>
<div className='py-4 flex justify-between'>
<h3 <h3
className='text-xl py-4'> className='text-xl font-bold'>
Automations Automations
</h3> </h3>
<div className='flex flex-wrap gap-2 items-center md:justify-start justify-end'>
{
authenticatedData ? (
<span className='rounded-lg text-sm border-secondary border p-1 flex items-center shadow-sm' ><Envelope className='h-4 w-4 mr-2 inline text-orange-500' shadow-s />{authenticatedData.email}</span>
)
: null
}
{
ipLocationData && (
<span className='rounded-lg text-sm border-secondary border p-1 flex items-center shadow-sm' ><MapPinSimple className='h-4 w-4 mr-2 inline text-purple-500' />{ipLocationData ? `${ipLocationData.city}, ${ipLocationData.country}` : 'Unknown'}</span>
)
}
{
ipLocationData && (
<span className='rounded-lg text-sm border-secondary border p-1 flex items-center shadow-sm' ><Clock className='h-4 w-4 mr-2 inline text-green-500' />{ipLocationData ? `${ipLocationData.timezone}` : 'Unknown'}</span>
)
}
</div>
</div>
{ {
showLoginPrompt && ( showLoginPrompt && (
<LoginPrompt <LoginPrompt
@@ -830,44 +959,17 @@ export default function Automations() {
loginRedirectMessage={"Create an account to make your own automation"} /> loginRedirectMessage={"Create an account to make your own automation"} />
) )
} }
<Alert> <Alert className='bg-secondary border-none'>
<Info className="h-4 w-4" />
<AlertTitle>How this works!</AlertTitle>
<AlertDescription> <AlertDescription>
Automations help you structure your time by automating tasks you do regularly. Build your own, or try out our presets. Get results straight to your inbox. <Lightning weight={'fill'} className='h-4 w-4 text-purple-400 inline' />
<div className='mt-3' /> <span className='font-bold'>How it works</span> Automations help you structure your time by automating tasks you do regularly. Build your own, or try out our presets. Get results straight to your inbox.
{
authenticatedData ? (
<span className='rounded-full text-sm bg-blue-200 dark:bg-blue-600 p-2 m-1' ><Envelope className='h-4 w-4 mr-2 inline' />{authenticatedData.email}</span>
)
: (
<span> Sign in to create your own automations.</span>
)
}
{
ipLocationData && (
<span className='rounded-full text-sm bg-purple-200 dark:bg-purple-600 p-2 m-1' ><MapPinSimple className='h-4 w-4 mr-2 inline' />{ipLocationData ? `${ipLocationData.city}, ${ipLocationData.country}` : 'Unknown'}</span>
)
}
{
ipLocationData && (
<span className='rounded-full text-sm bg-green-200 dark:bg-green-600 p-2 m-1' ><Clock className='h-4 w-4 mr-2 inline' />{ipLocationData ? `${ipLocationData.timezone}` : 'Unknown'}</span>
)
}
</AlertDescription> </AlertDescription>
</Alert> </Alert>
<div className='flex justify-between py-4'>
<h3 <h3
className="text-xl py-4"> className="text-xl">
Your Creations Your Creations
</h3> </h3>
<Suspense>
<SharedAutomationCard
locationData={ipLocationData}
isLoggedIn={authenticatedData ? true : false}
setShowLoginPrompt={setShowLoginPrompt}
setNewAutomationData={setNewAutomationData} />
</Suspense>
{ {
authenticatedData ? ( authenticatedData ? (
<Dialog <Dialog
@@ -876,8 +978,13 @@ export default function Automations() {
setIsCreating(open); setIsCreating(open);
}} }}
> >
<DialogTrigger asChild className='fixed bottom-4 right-4'> <DialogTrigger asChild>
<Button variant="default">Create New</Button> <Button
className='shadow-sm'
variant="outline">
<Plus className='h-4 w-4 mr-2' />
Create Automation
</Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>
<DialogTitle>Create Automation</DialogTitle> <DialogTitle>Create Automation</DialogTitle>
@@ -885,6 +992,7 @@ export default function Automations() {
createNew={true} createNew={true}
setIsEditing={setIsCreating} setIsEditing={setIsCreating}
isLoggedIn={authenticatedData ? true : false} isLoggedIn={authenticatedData ? true : false}
authenticatedData={authenticatedData}
setShowLoginPrompt={setShowLoginPrompt} setShowLoginPrompt={setShowLoginPrompt}
setUpdatedAutomationData={setNewAutomationData} setUpdatedAutomationData={setNewAutomationData}
locationData={ipLocationData} /> locationData={ipLocationData} />
@@ -893,12 +1001,23 @@ export default function Automations() {
) )
: ( : (
<Button <Button
className='shadow-sm'
onClick={() => setShowLoginPrompt(true)} onClick={() => setShowLoginPrompt(true)}
className='fixed bottom-4 right-4' variant={'default'}> variant={'outline'}>
Create New <Plus className='h-4 w-4 mr-2' />
Create Automation
</Button> </Button>
) )
} }
</div>
<Suspense>
<SharedAutomationCard
authenticatedData={authenticatedData}
locationData={ipLocationData}
isLoggedIn={authenticatedData ? true : false}
setShowLoginPrompt={setShowLoginPrompt}
setNewAutomationData={setNewAutomationData} />
</Suspense>
{ {
((!personalAutomations || personalAutomations.length === 0) && (allNewAutomations.length == 0)) && ( ((!personalAutomations || personalAutomations.length === 0) && (allNewAutomations.length == 0)) && (
<div> <div>
@@ -918,6 +1037,7 @@ export default function Automations() {
<DialogContent> <DialogContent>
<DialogTitle>Create Automation</DialogTitle> <DialogTitle>Create Automation</DialogTitle>
<EditCard <EditCard
authenticatedData={authenticatedData}
createNew={true} createNew={true}
isLoggedIn={authenticatedData ? true : false} isLoggedIn={authenticatedData ? true : false}
setShowLoginPrompt={setShowLoginPrompt} setShowLoginPrompt={setShowLoginPrompt}
@@ -945,6 +1065,7 @@ export default function Automations() {
personalAutomations && personalAutomations.map((automation) => ( personalAutomations && personalAutomations.map((automation) => (
<AutomationsCard <AutomationsCard
key={automation.id} key={automation.id}
authenticatedData={authenticatedData}
automation={automation} automation={automation}
locationData={ipLocationData} locationData={ipLocationData}
isLoggedIn={authenticatedData ? true : false} isLoggedIn={authenticatedData ? true : false}
@@ -952,7 +1073,9 @@ export default function Automations() {
))} ))}
{ {
allNewAutomations.map((automation) => ( allNewAutomations.map((automation) => (
<AutomationsCard key={automation.id} <AutomationsCard
key={automation.id}
authenticatedData={authenticatedData}
automation={automation} automation={automation}
locationData={ipLocationData} locationData={ipLocationData}
isLoggedIn={authenticatedData ? true : false} isLoggedIn={authenticatedData ? true : false}
@@ -971,6 +1094,7 @@ export default function Automations() {
<AutomationsCard <AutomationsCard
setNewAutomationData={setNewAutomationData} setNewAutomationData={setNewAutomationData}
key={automation.id} key={automation.id}
authenticatedData={authenticatedData}
automation={automation} automation={automation}
locationData={ipLocationData} locationData={ipLocationData}
isLoggedIn={authenticatedData ? true : false} isLoggedIn={authenticatedData ? true : false}

View File

@@ -20,6 +20,7 @@ interface ShareLinkProps {
onShare: () => void; onShare: () => void;
buttonVariant?: keyof typeof buttonVariants; buttonVariant?: keyof typeof buttonVariants;
includeIcon?: boolean; includeIcon?: boolean;
buttonClassName?: string;
} }
function copyToClipboard(text: string) { function copyToClipboard(text: string) {
@@ -36,7 +37,7 @@ export default function ShareLink(props: ShareLinkProps) {
<DialogTrigger <DialogTrigger
asChild asChild
onClick={props.onShare}> onClick={props.onShare}>
<Button size="sm" className={`px-3`} variant={props.buttonVariant ?? 'default' as const}> <Button size="sm" className={`${props.buttonClassName || 'px-3'}`} variant={props.buttonVariant ?? 'default' as const}>
{ {
props.includeIcon && ( props.includeIcon && (
<Share className="w-4 h-4 mr-2" /> <Share className="w-4 h-4 mr-2" />