feat: weekday task layout matches AnyDay — stacked icon column

Priority icon (top) + project icon (bottom) now rendered in a fixed
leading column before the checkbox, matching the AnyDay area layout.
Provider/sync icon always inline at end (removed absolute fallback).

v1.111.0
This commit is contained in:
mARTin-B78 2026-05-11 15:07:01 +02:00
parent cf504846da
commit b1e549dbfa
2 changed files with 28 additions and 47 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "my-weekly-todo-list", "name": "my-weekly-todo-list",
"version": "1.110.7", "version": "1.111.0",
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view", "description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@ -341,6 +341,31 @@ export function GridTaskBlock({
setEditingTaskId(task.id); setEditingTaskId(task.id);
}} }}
> >
{(() => {
const pb = showPriorityIcons ? getPriorityBadge(task, priorityStyle, 11) : null;
const hasProject = !!(showProjectIcons && task.project);
if (!pb && !hasProject) return null;
return (
<span style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "flex-start", flexShrink: 0, gap: "1px", paddingTop: "2px", opacity: task.completed && showTaskCheckboxes ? 0.5 : 1 }}>
{pb && <span title={pb.label} style={{ display: "inline-flex", alignItems: "center" }}>{pb.node}</span>}
{hasProject && (() => {
const rawIcon = task.project!.icon || "";
const normalised = rawIcon.startsWith("fa") && rawIcon.length > 2 && rawIcon[2] === rawIcon[2].toUpperCase()
? rawIcon.slice(2, 3).toLowerCase() + rawIcon.slice(3)
: rawIcon;
const found = allIcons.find(i => i.name === normalised || i.name === rawIcon);
if (found) {
return found.type === "fa"
? <FontAwesomeIcon icon={found.icon as IconDefinition} style={{ fontSize: "11px", color: task.project!.color || "#888" }} />
: <MdiIcon path={found.icon as string} size={0.5} color={task.project!.color || "#888"} style={{ display: "inline-block" }} />;
}
return task.project!.icon
? <span style={{ fontSize: "11px" }}>{task.project!.icon}</span>
: <FontAwesomeIcon icon={faFolder} style={{ fontSize: "11px", color: task.project!.color || "#888" }} />;
})()}
</span>
);
})()}
{showTaskCheckboxes && ( {showTaskCheckboxes && (
<input <input
type="checkbox" type="checkbox"
@ -353,30 +378,7 @@ export function GridTaskBlock({
/> />
)} )}
<span style={task.completed && showTaskCheckboxes ? { opacity: 0.5, flex: 1, display: "flex", alignItems: "center", flexWrap: "wrap", rowGap: "2px" } : { flex: 1, display: "flex", alignItems: "center", flexWrap: "wrap", rowGap: "2px" }}> <span style={task.completed && showTaskCheckboxes ? { opacity: 0.5, flex: 1, display: "flex", alignItems: "center", flexWrap: "wrap", rowGap: "2px" } : { flex: 1, display: "flex", alignItems: "center", flexWrap: "wrap", rowGap: "2px" }}>
{showPriorityIcons && (() => { <span style={{ marginRight: "4px" }}>{task.title}</span>
const pb = getPriorityBadge(task, priorityStyle, 11);
return pb ? (
<span title={pb.label} style={{ marginRight: "4px", display: "inline-flex", alignItems: "center", flexShrink: 0 }}>
{pb.node}
</span>
) : null;
})()}
<span style={{ marginRight: "4px" }}>{showProjectIcons && task.project && (() => {
const rawIcon = task.project!.icon || "";
const normalised = rawIcon.startsWith("fa") && rawIcon.length > 2 && rawIcon[2] === rawIcon[2].toUpperCase()
? rawIcon.slice(2, 3).toLowerCase() + rawIcon.slice(3)
: rawIcon;
const found = allIcons.find(i => i.name === normalised || i.name === rawIcon);
const iconStyle = { marginRight: "4px", verticalAlign: "middle" } as const;
if (found) {
return found.type === "fa"
? <FontAwesomeIcon icon={found.icon as IconDefinition} style={{ fontSize: "11px", ...iconStyle, color: task.project!.color || "#888" }} />
: <MdiIcon path={found.icon as string} size={0.5} color={task.project!.color || "#888"} style={{ ...iconStyle, display: "inline-block" }} />;
}
return task.project!.icon
? <span style={{ fontSize: "11px", ...iconStyle }}>{task.project!.icon}</span>
: <FontAwesomeIcon icon={faFolder} style={{ fontSize: "11px", ...iconStyle, color: task.project!.color || "#888" }} />;
})()}{task.title}</span>
{/* Subtask indicator */} {/* Subtask indicator */}
{task.subTasks && task.subTasks.length > 0 && (() => { {task.subTasks && task.subTasks.length > 0 && (() => {
const completed = task.subTasks.filter(s => s.completed).length; const completed = task.subTasks.filter(s => s.completed).length;
@ -507,7 +509,7 @@ export function GridTaskBlock({
</svg> </svg>
</span> </span>
)} )}
{weatherEnabled && (() => { {(() => {
const provider = task.externalProvider const provider = task.externalProvider
|| (task.externalId?.startsWith("synology::") ? "synology" : null); || (task.externalId?.startsWith("synology::") ? "synology" : null);
if (!provider) return null; if (!provider) return null;
@ -533,27 +535,6 @@ export function GridTaskBlock({
</span> </span>
)} )}
</div> </div>
{!weatherEnabled && (() => {
const provider = task.externalProvider
|| (task.externalId?.startsWith("synology::") ? "synology" : null);
if (!provider) return null;
const iconMap: Record<string, { icon: any; color: string; label: string }> = {
google: { icon: faGoogle, color: "#4285F4", label: "Google" },
outlook: { icon: faMicrosoft, color: "#0078D4", label: "Microsoft" },
apple: { icon: faApple, color: "#555", label: "Apple" },
synology: { icon: faServer, color: "#007AFF", label: "Synology" },
};
const info = iconMap[provider];
if (!info) return null;
return (
<span
aria-label={`Synced with ${info.label}`}
style={{ position: "absolute", top: "3px", right: "4px", display: "inline-flex", alignItems: "center", opacity: 0.45, zIndex: 2 }}
>
<FontAwesomeIcon icon={info.icon} aria-hidden="true" style={{ width: 10, height: 10, color: info.color }} />
</span>
);
})()}
<div <div
className="task-actions" className="task-actions"