feat(dashboard): add inbox task actions (#32)
* feat(dashboard): add inbox task actions * style(dashboard): format inbox actions
This commit is contained in:
@@ -593,11 +593,17 @@ function ControlRail({ data, t }: { data: DashboardState; t: Messages }) {
|
|||||||
|
|
||||||
function InboxPanel({
|
function InboxPanel({
|
||||||
overview,
|
overview,
|
||||||
|
tasks,
|
||||||
locale,
|
locale,
|
||||||
|
onTaskAction,
|
||||||
|
taskActionKey,
|
||||||
t,
|
t,
|
||||||
}: {
|
}: {
|
||||||
overview: DashboardOverview;
|
overview: DashboardOverview;
|
||||||
|
tasks: DashboardTask[];
|
||||||
locale: Locale;
|
locale: Locale;
|
||||||
|
onTaskAction: (task: DashboardTask, action: DashboardTaskAction) => void;
|
||||||
|
taskActionKey: TaskActionKey | null;
|
||||||
t: Messages;
|
t: Messages;
|
||||||
}) {
|
}) {
|
||||||
const [filter, setFilter] = useState<InboxFilter>('all');
|
const [filter, setFilter] = useState<InboxFilter>('all');
|
||||||
@@ -672,6 +678,13 @@ function InboxPanel({
|
|||||||
<div className="inbox-list" aria-label={t.inbox.cardsAria}>
|
<div className="inbox-list" aria-label={t.inbox.cardsAria}>
|
||||||
{filteredItems.map((item) => {
|
{filteredItems.map((item) => {
|
||||||
const href = inboxTargetHref(item);
|
const href = inboxTargetHref(item);
|
||||||
|
const linkedTask =
|
||||||
|
item.source === 'scheduled-task' && item.taskId
|
||||||
|
? tasks.find((task) => task.id === item.taskId)
|
||||||
|
: undefined;
|
||||||
|
const linkedTaskActions = linkedTask
|
||||||
|
? taskActionsFor(linkedTask)
|
||||||
|
: [];
|
||||||
return (
|
return (
|
||||||
<article
|
<article
|
||||||
className={`inbox-card inbox-${item.severity}`}
|
className={`inbox-card inbox-${item.severity}`}
|
||||||
@@ -717,6 +730,25 @@ function InboxPanel({
|
|||||||
{item.taskId ? t.inbox.openTask : t.inbox.openRoom}
|
{item.taskId ? t.inbox.openTask : t.inbox.openRoom}
|
||||||
</a>
|
</a>
|
||||||
) : null}
|
) : null}
|
||||||
|
{linkedTask && linkedTaskActions.length > 0 ? (
|
||||||
|
<div className="task-actions inbox-actions">
|
||||||
|
{linkedTaskActions.map((action) => {
|
||||||
|
const actionKey: TaskActionKey = `${linkedTask.id}:${action}`;
|
||||||
|
const busy = taskActionKey === actionKey;
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={`task-action task-action-${action}`}
|
||||||
|
disabled={busy}
|
||||||
|
key={action}
|
||||||
|
onClick={() => onTaskAction(linkedTask, action)}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
{busy ? t.tasks.actions.busy : t.tasks.actions[action]}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</article>
|
</article>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -1459,7 +1491,16 @@ function App() {
|
|||||||
<h2>{t.panels.inbox}</h2>
|
<h2>{t.panels.inbox}</h2>
|
||||||
<span>{t.panels.inboxQueue}</span>
|
<span>{t.panels.inboxQueue}</span>
|
||||||
</div>
|
</div>
|
||||||
<InboxPanel locale={locale} overview={data.overview} t={t} />
|
<InboxPanel
|
||||||
|
locale={locale}
|
||||||
|
onTaskAction={(task, action) =>
|
||||||
|
void handleTaskAction(task, action)
|
||||||
|
}
|
||||||
|
overview={data.overview}
|
||||||
|
taskActionKey={taskActionKey}
|
||||||
|
tasks={data.tasks}
|
||||||
|
t={t}
|
||||||
|
/>
|
||||||
</section>
|
</section>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
|||||||
@@ -1000,6 +1000,10 @@ progress::-moz-progress-bar {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inbox-actions {
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.health-overview {
|
.health-overview {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
|||||||
Reference in New Issue
Block a user