Skip to content

Commit

Permalink
feat(schedules): icons, mobile, click to copy cmds
Browse files Browse the repository at this point in the history
  • Loading branch information
he3als committed Aug 18, 2024
1 parent 88a53ed commit f3b2720
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 30 deletions.
37 changes: 33 additions & 4 deletions resources/scripts/components/elements/ItemContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,67 @@
import { IconDefinition } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useMemo } from 'react';
import { v4 } from 'uuid';

import CopyOnClick from './CopyOnClick';

export interface ContainerProps {
title: string;
description: string;
children?: React.ReactNode;
icon?: IconDefinition;
labelClasses?: string;
titleClasses?: string;
descriptionClasses?: string;
divClasses?: string;
copyDescription?: boolean;
}

const ItemContainer = ({
title,
description,
children,
icon,
labelClasses,
titleClasses,
descriptionClasses,
divClasses,
copyDescription,
}: ContainerProps) => {
const uuid = useMemo(() => v4(), []);

return (
<div
className={`flex items-center justify-between gap-2 bg-[#3333332a] border-[1px] border-[#ffffff0e] p-4 rounded-lg ${divClasses}`}
>
<div className={`flex flex-col`}>
{icon && (
<div className={`w-10 h-10 items-center justify-center hidden sm:flex`}>
<FontAwesomeIcon icon={icon} />
</div>
)}
<div className={`flex flex-1 flex-col`}>
<label htmlFor={uuid} className={`text-neutral-300 text-md font-bold ${titleClasses} ${labelClasses}`}>
{title}
</label>
<label htmlFor={uuid} className={`text-neutral-500 text-sm font-semibold ${descriptionClasses} ${labelClasses}`}>
{description}
</label>

{/* i don't like how this duplicates the element, but idk how to get it working otherwise */}
{copyDescription ? (
<CopyOnClick text={description}>
<label
htmlFor={uuid}
className={`text-neutral-500 text-sm font-semibold ${descriptionClasses} ${labelClasses}`}
>
{description}
</label>
</CopyOnClick>
) : (
<label
htmlFor={uuid}
className={`text-neutral-500 text-sm font-semibold ${descriptionClasses} ${labelClasses}`}
>
{description}
</label>
)}
</div>
{children}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ import { Button } from '@/components/elements/button/index';
import TaskDetailsModal from '@/components/server/schedules/TaskDetailsModal';

import { Schedule } from '@/api/server/schedules/getServerSchedules';
import clsx from 'clsx';

interface Props {
schedule: Schedule;
className?: string;
}

export default ({ schedule }: Props) => {
export default ({ schedule, className }: Props) => {
const [visible, setVisible] = useState(false);

return (
<>
<TaskDetailsModal schedule={schedule} visible={visible} onModalDismissed={() => setVisible(false)} />
<Button onClick={() => setVisible(true)} className={'flex-1'}>
<Button onClick={() => setVisible(true)} className={clsx(className)}>
New Task
</Button>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function ScheduleContainer() {
<div className='flex h-full w-full flex-col gap-1 overflow-hidden rounded-lg'>
{schedules.map((schedule) => (
<NavLink key={schedule.id} to={`${schedule.id}`} end>
<div className='flex items-center rounded-md bg-[#ffffff11] px-6 py-4 transition duration-100 hover:bg-[#ffffff19] hover:duration-0'>
<div className='flex items-center rounded-md bg-[#ffffff11] px-6 py-4 transition duration-100 hover:bg-[#ffffff19] hover:duration-0 gap-4 flex-col sm:flex-row'>
<ScheduleRow schedule={schedule} />
</div>
</NavLink>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default () => {
<>
<div className={`rounded shadow`}>
<div
className={`bg-[#ffffff09] border-[1px] border-[#ffffff11] flex items-center place-content-between flex-col md:flex-row gap-6 p-6 rounded-2xl mb-6`}
className={`bg-[#ffffff09] border-[1px] border-[#ffffff11] flex items-center place-content-between flex-col md:flex-row gap-6 p-6 rounded-2xl mb-6 overflow-hidden`}
>
<div className={`flex-none self-start`}>
<h3 className={`flex items-center text-neutral-100 text-2xl`}>
Expand All @@ -100,7 +100,8 @@ export default () => {
<span>N/A</span>
)}

<br className={`sm:invisible`} />
<span className={`ml-4 pl-4 border-l-4 border-neutral-600 py-px hidden sm:inline`} />
<br className={`sm:hidden`} />

<strong>Next run at:&nbsp;</strong>
{schedule.nextRunAt ? (
Expand All @@ -110,12 +111,12 @@ export default () => {
)}
</p>
</div>
<div className={`flex flex-col gap-2 md:min-w-60 min-w-full`}>
<div className={`flex gap-2 flex-col md:flex-row md:min-w-0 min-w-full`}>
<Can action={'schedule.update'}>
<Button.Text onClick={toggleEditModal} className={'flex-1'}>
<Button.Text onClick={toggleEditModal} className={'flex-1 min-w-max'}>
Edit
</Button.Text>
<NewTaskButton schedule={schedule} />
<NewTaskButton schedule={schedule} className={'flex-1 min-w-max'} />
</Can>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ export default ({ schedule }: { schedule: Schedule }) => (
</div>
<ScheduleCronRow cron={schedule.cron} />
<div>
<p className='ml-4'>{schedule.isProcessing ? 'Processing' : schedule.isActive ? 'Active' : 'Inactive'}</p>
<p className='ml-4 flex items-center rounded-full px-2 py-px text-xs uppercase bg-neutral-600 text-white'>
{schedule.isProcessing ? 'Processing' : schedule.isActive ? 'Active' : 'Inactive'}
</p>
</div>
</>
);
47 changes: 30 additions & 17 deletions resources/scripts/components/server/schedules/ScheduleTaskRow.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { faPen, faTrash } from '@fortawesome/free-solid-svg-icons';
import {
IconDefinition,
faClone,
faPen,
faPowerOff,
faQuestion,
faTerminal,
faTrash,
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useState } from 'react';

Expand All @@ -21,16 +29,16 @@ interface Props {
task: Task;
}

const getActionDetails = (action: string): [string] => {
const getActionDetails = (action: string): [string, IconDefinition, boolean?] => {
switch (action) {
case 'command':
return ['Send Command'];
return ['Send Command', faTerminal, true];
case 'power':
return ['Send Power Action'];
return ['Send Power Action', faPowerOff];
case 'backup':
return ['Create Backup'];
return ['Create Backup', faClone];
default:
return ['Unknown Action'];
return ['Unknown Action', faQuestion];
}
};

Expand Down Expand Up @@ -59,10 +67,17 @@ export default ({ schedule, task }: Props) => {
});
};

const [title] = getActionDetails(task.action);
const [title, icon, copyOnClick] = getActionDetails(task.action);

return (
<ItemContainer title={title} description={task.payload} divClasses={`mb-2`}>
<ItemContainer
title={title}
description={task.payload}
icon={icon}
divClasses={`mb-2 gap-6`}
copyDescription={copyOnClick}
descriptionClasses={`whitespace-nowrap overflow-hidden overflow-ellipsis`}
>
<SpinnerOverlay visible={isLoading} fixed size={'large'} />
<TaskDetailsModal
schedule={schedule}
Expand Down Expand Up @@ -95,19 +110,17 @@ export default ({ schedule, task }: Props) => {
</div>
)}
</div> */}
<div className={`flex flex-none items-end flex-col sm:flex-row`}>
{task.continueOnFailure && (
<div className={`sm:mr-6`}>
<div className={`flex flex-none items-end sm:items-center flex-col sm:flex-row`}>
<div className='mr-0 sm:mr-6'>
{task.continueOnFailure && (
<div className={`px-2 py-1 bg-yellow-500 text-yellow-800 text-sm rounded-full`}>
Continues on Failure
</div>
</div>
)}
{task.sequenceId > 1 && task.timeOffset > 0 && (
<div className={`sm:mr-6`}>
)}
{task.sequenceId > 1 && task.timeOffset > 0 && (
<div className={`px-2 py-1 bg-zinc-500 text-sm rounded-full`}>{task.timeOffset}s later</div>
</div>
)}
)}
</div>
<Can action={'schedule.update'}>
<button
type={'button'}
Expand Down

0 comments on commit f3b2720

Please sign in to comment.