mirror of
https://github.com/akaswan/table-list.git
synced 2026-07-22 05:49:21 +00:00
Added basic task input
This commit is contained in:
parent
68cfbe1ff8
commit
b2d2e215c7
9 changed files with 554 additions and 201 deletions
15
package-lock.json
generated
15
package-lock.json
generated
|
|
@ -10,6 +10,8 @@
|
|||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide": "^0.469.0",
|
||||
"lucide-react": "^0.469.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
|
|
@ -1718,6 +1720,19 @@
|
|||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lucide": {
|
||||
"version": "0.469.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide/-/lucide-0.469.0.tgz",
|
||||
"integrity": "sha512-ZmMtOekJ6g1UFqTvV9aWbkk+u/QxpfDpgUrbNj8jJEK+CtBdHVQ4akCA0TcTyeOvnL8RWo271UzFTimBRT0gKw=="
|
||||
},
|
||||
"node_modules/lucide-react": {
|
||||
"version": "0.469.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.469.0.tgz",
|
||||
"integrity": "sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-react": "^0.469.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
}
|
||||
|
|
|
|||
191
src/main/components/App.tsx
Normal file
191
src/main/components/App.tsx
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { useTableContext } from "../views/TableView";
|
||||
import Table from "./Table";
|
||||
import TopBar from "./TopBar";
|
||||
import { format, addDays, startOfWeek, subDays } from "date-fns";
|
||||
|
||||
export interface Project {
|
||||
id: number;
|
||||
name: string;
|
||||
tasks: Task[];
|
||||
}
|
||||
|
||||
export interface Task {
|
||||
id: number;
|
||||
name: string;
|
||||
date: Date;
|
||||
parentProjectId: number;
|
||||
}
|
||||
|
||||
const getWeekDates = (date: Date) => {
|
||||
const startDate = startOfWeek(date, { weekStartsOn: 1 });
|
||||
const dates = Array.from({ length: 7 }, (_, i) => {
|
||||
return format(addDays(startDate, i), "yyyy-MM-dd");
|
||||
});
|
||||
return dates;
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const tableContext = useTableContext();
|
||||
|
||||
const [dates, setDates] = useState(getWeekDates(new Date()));
|
||||
|
||||
const [data, setData] = useState(() => tableContext!.loadData());
|
||||
|
||||
const [projects, setProjects] = useState(
|
||||
() => tableContext!.loadData().projects as Project[]
|
||||
);
|
||||
const [nextProjectId, setNextProjectId] = useState(
|
||||
() => tableContext!.loadData().nextProjectId as number
|
||||
);
|
||||
const [nextTaskId, setNextTaskId] = useState(
|
||||
() => tableContext!.loadData().nextProjectId as number
|
||||
);
|
||||
|
||||
const incrementDates = () => {
|
||||
setDates((prevDates) => {
|
||||
const newDates = getWeekDates(addDays(new Date(prevDates[0]), 8));
|
||||
return newDates;
|
||||
});
|
||||
};
|
||||
|
||||
const decrementDates = () => {
|
||||
setDates((prevDates) => {
|
||||
const newDates = getWeekDates(subDays(new Date(prevDates[0]), 8));
|
||||
return newDates;
|
||||
});
|
||||
};
|
||||
|
||||
const setDatesToThisWeek = () => {
|
||||
setDates((prevDates) => {
|
||||
const newDates = getWeekDates(new Date());
|
||||
return newDates;
|
||||
});
|
||||
};
|
||||
|
||||
const handleProjectNameChange = (id: number, newName: string) => {
|
||||
setProjects((prevProjects) => {
|
||||
const newProjects = prevProjects.map((project) =>
|
||||
project.id === id ? { ...project, name: newName } : project
|
||||
);
|
||||
saveSpecificData("projects", newProjects);
|
||||
return newProjects;
|
||||
});
|
||||
};
|
||||
|
||||
const removeProject = (id: number) => {
|
||||
setProjects((prevProjects) => {
|
||||
const newProjects = prevProjects.filter(
|
||||
(project) => project.id !== id
|
||||
);
|
||||
saveSpecificData("projects", newProjects);
|
||||
return newProjects;
|
||||
});
|
||||
};
|
||||
|
||||
const removeTask = (id: number) => {
|
||||
setProjects((prevProjects) => {
|
||||
const newProjects = prevProjects.map((project) => {
|
||||
const newTasks = project.tasks.filter((task) => task.id !== id);
|
||||
return { ...project, tasks: newTasks };
|
||||
});
|
||||
saveSpecificData("projects", newProjects);
|
||||
return newProjects;
|
||||
});
|
||||
};
|
||||
|
||||
const createNewProject = (
|
||||
newName: string,
|
||||
newProjectInputRef: React.RefObject<HTMLInputElement | null>
|
||||
) => {
|
||||
if (!newName.trim()) return;
|
||||
setProjects((prevProjects) => {
|
||||
const newProjects = [
|
||||
...prevProjects,
|
||||
{ id: nextProjectId, name: newName, tasks: [] },
|
||||
];
|
||||
|
||||
saveSpecificData("projects", newProjects);
|
||||
|
||||
return newProjects;
|
||||
});
|
||||
|
||||
setNextProjectId((prevId) => {
|
||||
const newId = prevId + 1;
|
||||
saveSpecificData("nextProjectId", newId);
|
||||
return newId;
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
if (newProjectInputRef.current) {
|
||||
newProjectInputRef.current.focus();
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const addTaskToProject = (project: Project, date: string) => {
|
||||
const newTask = {
|
||||
id: nextTaskId,
|
||||
name: "",
|
||||
date: new Date(date),
|
||||
parentProjectId: project.id,
|
||||
};
|
||||
|
||||
setProjects((prevProjects) => {
|
||||
const newProjects = prevProjects.map((p) => {
|
||||
if (p.id === project.id) {
|
||||
return { ...p, tasks: [...p.tasks, newTask] };
|
||||
}
|
||||
return p;
|
||||
});
|
||||
|
||||
saveSpecificData("projects", newProjects);
|
||||
|
||||
return newProjects;
|
||||
});
|
||||
|
||||
setNextTaskId((prevId) => {
|
||||
const newId = prevId + 1;
|
||||
saveSpecificData("nextTaskId", newId);
|
||||
return newId;
|
||||
});
|
||||
};
|
||||
|
||||
const saveSpecificData = (key: string, value: any): void => {
|
||||
setData((prevData: any) => {
|
||||
const newData = { ...prevData, [key]: value };
|
||||
return newData;
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (tableContext) {
|
||||
tableContext.saveData(data);
|
||||
} else {
|
||||
console.log("not exist");
|
||||
}
|
||||
}, [projects, nextProjectId]);
|
||||
|
||||
return (
|
||||
<div className="app-wrapper">
|
||||
<TopBar
|
||||
incrementDates={incrementDates}
|
||||
decrementDates={decrementDates}
|
||||
setDatesToThisWeek={setDatesToThisWeek}
|
||||
/>
|
||||
<Table
|
||||
projects={projects}
|
||||
nextProjectId={nextProjectId}
|
||||
handleProjectNameChange={handleProjectNameChange}
|
||||
createNewProject={createNewProject}
|
||||
dates={dates}
|
||||
addTaskToProject={addTaskToProject}
|
||||
removeProject={removeProject}
|
||||
removeTask={removeTask}
|
||||
nextTaskId={nextTaskId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
158
src/main/components/Table.tsx
Normal file
158
src/main/components/Table.tsx
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
import { format } from "date-fns";
|
||||
import { useEffect, useRef } from "react";
|
||||
import * as React from "react";
|
||||
import { Project } from "./App";
|
||||
import TaskCell from "./TaskCell";
|
||||
|
||||
interface TableProps {
|
||||
projects: Project[];
|
||||
nextProjectId: number;
|
||||
handleProjectNameChange: (id: number, newName: string) => void;
|
||||
createNewProject: (
|
||||
newName: string,
|
||||
newProjectInputRef: React.RefObject<HTMLInputElement | null>
|
||||
) => void;
|
||||
dates: string[];
|
||||
addTaskToProject: (project: Project, date: string) => void;
|
||||
removeProject: (id: number) => void;
|
||||
removeTask: (id: number) => void;
|
||||
nextTaskId: number;
|
||||
}
|
||||
|
||||
const Table: React.FC<TableProps> = ({
|
||||
projects,
|
||||
nextProjectId,
|
||||
handleProjectNameChange,
|
||||
createNewProject,
|
||||
dates,
|
||||
addTaskToProject,
|
||||
removeProject,
|
||||
removeTask,
|
||||
nextTaskId
|
||||
}) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const newProjectInputRef = useRef<HTMLInputElement | null>(null);
|
||||
const newTaskInputRef = useRef<HTMLInputElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
const containerWidth = containerRef.current?.clientWidth;
|
||||
if (containerWidth) {
|
||||
document.documentElement.style.setProperty(
|
||||
"--taskcell-enclosure-width",
|
||||
`${(containerWidth - 128) / 7}px`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const resizeObserver = new ResizeObserver(handleResize);
|
||||
if (containerRef.current) {
|
||||
resizeObserver.observe(containerRef.current);
|
||||
}
|
||||
|
||||
// Initial call to set the variable
|
||||
handleResize();
|
||||
|
||||
return () => {
|
||||
if (containerRef.current) {
|
||||
resizeObserver.unobserve(containerRef.current);
|
||||
}
|
||||
};
|
||||
}, [containerRef]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="table-container" ref={containerRef}>
|
||||
<table className="table headings-center">
|
||||
<thead className="table-header">
|
||||
<tr>
|
||||
<th>Projects</th>
|
||||
{dates.map((date) => (
|
||||
<th className="date" key={date}>{`${format(
|
||||
date,
|
||||
"EEEE"
|
||||
)} - ${format(date, "yyyy-MM-dd")}`}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{projects.map((project) => (
|
||||
<tr key={project.id}>
|
||||
<td key={project.id}>
|
||||
<input
|
||||
ref={
|
||||
project.id === nextProjectId - 1
|
||||
? newProjectInputRef
|
||||
: null
|
||||
}
|
||||
type="text"
|
||||
value={project.name}
|
||||
className="project-input"
|
||||
placeholder="New Project"
|
||||
onBlur={(e) => {if (e.target.value === "") removeProject(project.id)}}
|
||||
onChange={(e) =>
|
||||
handleProjectNameChange(
|
||||
project.id,
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
{dates.map((date, index) => (
|
||||
<td
|
||||
className="taskcell-enclosure"
|
||||
key={`${project.id}:${date}:${index}`}
|
||||
onClick={(e) => {
|
||||
if (e.target === e.currentTarget) {
|
||||
addTaskToProject(project, date);
|
||||
setTimeout(() => {
|
||||
if (newTaskInputRef.current) {
|
||||
newTaskInputRef.current.focus();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{project.tasks
|
||||
.filter(
|
||||
(task) =>
|
||||
new Date(
|
||||
task.date
|
||||
).toISOString() ===
|
||||
new Date(date).toISOString()
|
||||
)
|
||||
.map((task) => (
|
||||
<TaskCell
|
||||
task={task}
|
||||
removeTask={removeTask}
|
||||
key={task.id}
|
||||
inputRef={
|
||||
task.id === nextTaskId - 1
|
||||
? newTaskInputRef
|
||||
: null
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="new-project-container">
|
||||
<input
|
||||
type="text"
|
||||
className="project-input"
|
||||
placeholder="New Project"
|
||||
onChange={(e) => {
|
||||
createNewProject(e.target.value, newProjectInputRef);
|
||||
e.target.value = "";
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Table;
|
||||
61
src/main/components/TaskCell.tsx
Normal file
61
src/main/components/TaskCell.tsx
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import { Task } from "./App";
|
||||
|
||||
const transColor = (color: string, percent: number): string => {
|
||||
const num = parseInt(color.replace("#", ""), 16);
|
||||
const amt = Math.round(2.55 * percent);
|
||||
const R = (num >> 16) + amt;
|
||||
const B = ((num >> 8) & 0x00ff) + amt;
|
||||
const G = (num & 0x0000ff) + amt;
|
||||
return (
|
||||
"#" +
|
||||
(
|
||||
0x1000000 +
|
||||
(R < 255 ? (R < 1 ? 0 : R) : 255) * 0x10000 +
|
||||
(B < 255 ? (B < 1 ? 0 : B) : 255) * 0x100 +
|
||||
(G < 255 ? (G < 1 ? 0 : G) : 255)
|
||||
)
|
||||
.toString(16)
|
||||
.slice(1)
|
||||
);
|
||||
};
|
||||
|
||||
interface TaskCellProps {
|
||||
task: Task;
|
||||
removeTask: (id: number) => void;
|
||||
inputRef: React.RefObject<HTMLInputElement | null> | null;
|
||||
}
|
||||
|
||||
const TaskCell: React.FC<TaskCellProps> = ({task, removeTask, inputRef}) => {
|
||||
const color = "#35CC70";
|
||||
|
||||
document.documentElement.style.setProperty("--task-color", color);
|
||||
document.documentElement.style.setProperty(
|
||||
"--task-background",
|
||||
`${color}33`
|
||||
);
|
||||
document.documentElement.style.setProperty(
|
||||
"--dark-task-text-color",
|
||||
transColor(color, -40)
|
||||
);
|
||||
document.documentElement.style.setProperty(
|
||||
"--light-task-text-color",
|
||||
transColor(color, 25)
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="task-cell">
|
||||
<div className="task-cell-header">Apush</div>
|
||||
<div className="task-cell-content">
|
||||
<input
|
||||
placeholder="Task Name"
|
||||
onBlur={(e) => {
|
||||
if (e.target.value === "") removeTask(task.id);
|
||||
}}
|
||||
ref={inputRef}
|
||||
></input>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TaskCell;
|
||||
23
src/main/components/TopBar.tsx
Normal file
23
src/main/components/TopBar.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||
|
||||
interface TopBarProps {
|
||||
incrementDates: () => void;
|
||||
decrementDates: () => void;
|
||||
setDatesToThisWeek: () => void;
|
||||
}
|
||||
|
||||
const TopBar: React.FC<TopBarProps> = ({ incrementDates, decrementDates, setDatesToThisWeek }) => {
|
||||
return (
|
||||
<div className="top-bar">
|
||||
<div className="date-increment-container">
|
||||
<ChevronLeft onClick={decrementDates} className="date-increment left-increment" />
|
||||
<div onClick={setDatesToThisWeek} className="date-display">
|
||||
{new Date().toDateString()}
|
||||
</div>
|
||||
<ChevronRight onClick={incrementDates} className="date-increment right-increment" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TopBar;
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
// import "styles.css";
|
||||
import { format, addDays, startOfWeek } from "date-fns";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import * as React from "react";
|
||||
import { useTableContext } from "../views/TableView";
|
||||
|
||||
interface Project {
|
||||
id: number;
|
||||
name: string;
|
||||
tasks: Task[];
|
||||
}
|
||||
|
||||
interface Task {
|
||||
id: number;
|
||||
name: string;
|
||||
date: Date;
|
||||
parentProjectId: number;
|
||||
}
|
||||
|
||||
const getInitialDates = () => {
|
||||
const startDate = startOfWeek(new Date(), { weekStartsOn: 1 });
|
||||
const dates = Array.from({ length: 7 }, (_, i) => {
|
||||
return format(addDays(startDate, i), "yyyy-MM-dd");
|
||||
});
|
||||
return dates;
|
||||
};
|
||||
|
||||
const Table: React.FC = () => {
|
||||
const tableContext = useTableContext();
|
||||
|
||||
const [data, setData] = useState(() => tableContext!.loadData());
|
||||
|
||||
const [dates, setDates] = useState(getInitialDates);
|
||||
|
||||
const [projects, setProjects] = useState(
|
||||
() => tableContext!.loadData().projects as Project[]
|
||||
);
|
||||
const [nextProjectId, setNextProjectId] = useState(
|
||||
() => tableContext!.loadData().nextProjectId as number
|
||||
);
|
||||
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const newProjectInputRef = useRef<HTMLInputElement | null>(null);
|
||||
|
||||
const saveSpecificData = (key: string, value: any): void => {
|
||||
setData((prevData: any) => {
|
||||
const newData = { ...prevData, [key]: value };
|
||||
return newData;
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
const containerWidth = containerRef.current?.clientWidth;
|
||||
if (containerWidth) {
|
||||
document.documentElement.style.setProperty(
|
||||
"--taskcell-enclosure-width",
|
||||
`${(containerWidth - 128) / 7}px`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const resizeObserver = new ResizeObserver(handleResize);
|
||||
if (containerRef.current) {
|
||||
resizeObserver.observe(containerRef.current);
|
||||
}
|
||||
|
||||
// Initial call to set the variable
|
||||
handleResize();
|
||||
|
||||
return () => {
|
||||
if (containerRef.current) {
|
||||
resizeObserver.unobserve(containerRef.current);
|
||||
}
|
||||
};
|
||||
}, [containerRef]);
|
||||
|
||||
const handleProjectNameChange = (id: number, newName: string) => {
|
||||
if (!newName.trim()) {
|
||||
setProjects((prevProjects) => {
|
||||
const newProjects = prevProjects.filter(
|
||||
(project) => project.id !== id
|
||||
);
|
||||
saveSpecificData("projects", newProjects);
|
||||
return newProjects;
|
||||
});
|
||||
} else {
|
||||
setProjects((prevProjects) => {
|
||||
const newProjects = prevProjects.map((project) =>
|
||||
project.id === id ? { ...project, name: newName } : project
|
||||
);
|
||||
saveSpecificData("projects", newProjects);
|
||||
return newProjects;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const createNewProject = (newName: string) => {
|
||||
if (!newName.trim()) return;
|
||||
setProjects((prevProjects) => {
|
||||
const newProjects = [
|
||||
...prevProjects,
|
||||
{ id: nextProjectId, name: newName, tasks: [] },
|
||||
];
|
||||
|
||||
saveSpecificData("projects", newProjects);
|
||||
|
||||
return newProjects;
|
||||
});
|
||||
|
||||
setNextProjectId((prevId) => {
|
||||
const newId = prevId + 1;
|
||||
saveSpecificData("nextProjectId", newId);
|
||||
return newId;
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
if (newProjectInputRef.current) {
|
||||
newProjectInputRef.current.focus();
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (tableContext) {
|
||||
tableContext.saveData(data);
|
||||
} else {
|
||||
console.log("not exist");
|
||||
}
|
||||
}, [projects, nextProjectId]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="table-container" ref={containerRef}>
|
||||
<table className="table headings-center">
|
||||
<thead className="table-header">
|
||||
<tr>
|
||||
<th>Projects</th>
|
||||
{dates.map((date) => (
|
||||
<th className="date" key={date}>{`${format(
|
||||
date,
|
||||
"EEEE"
|
||||
)} - ${format(date, "yyyy-MM-dd")}`}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{projects.map((project) => (
|
||||
<tr key={project.id}>
|
||||
<td key={project.id}>
|
||||
<input
|
||||
ref={
|
||||
project.id === nextProjectId - 1
|
||||
? newProjectInputRef
|
||||
: null
|
||||
} // Attach ref to the newly created project
|
||||
type="text"
|
||||
value={project.name}
|
||||
className="project-input"
|
||||
placeholder="New Project"
|
||||
onChange={(e) =>
|
||||
handleProjectNameChange(
|
||||
project.id,
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
{dates.map((date, index) => (
|
||||
<td
|
||||
className="taskcell-enclosure"
|
||||
key={`${project.id}:${date}:${index}`}
|
||||
></td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="new-project-container">
|
||||
<input
|
||||
type="text"
|
||||
className="project-input"
|
||||
placeholder="New Project"
|
||||
onChange={(e) => {
|
||||
createNewProject(e.target.value);
|
||||
e.target.value = "";
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Table;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { createContext, useContext } from 'react';
|
||||
import { ItemView, WorkspaceLeaf, App } from 'obsidian';
|
||||
import { Root, createRoot } from 'react-dom/client';
|
||||
import Table from 'src/main/react/Table';
|
||||
import AppComponent from 'src/main/components/App';
|
||||
|
||||
export interface AppContext {
|
||||
app: App;
|
||||
|
|
@ -45,7 +45,7 @@ export class TableView extends ItemView {
|
|||
this.root = createRoot(this.containerEl.children[1]);
|
||||
this.root.render(
|
||||
<TableContext.Provider value={{app: this.app, saveData: this.saveData, loadData: this.loadData}}>
|
||||
<Table />
|
||||
<AppComponent />
|
||||
</TableContext.Provider>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
107
styles.css
107
styles.css
|
|
@ -1,4 +1,102 @@
|
|||
/* styles.css */
|
||||
/* App */
|
||||
.app-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Top Bar */
|
||||
.top-bar {
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.date-increment-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
.date-display {
|
||||
width: max-content;
|
||||
font-weight: bold !important;
|
||||
font-size: large !important;
|
||||
padding: 0px 24px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: var(--background-secondary);
|
||||
border-left: var(--border-width) solid var(--background-modifier-border);
|
||||
border-top: var(--border-width) solid var(--background-modifier-border);
|
||||
border-bottom: var(--border-width) solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.date-display:hover {
|
||||
background-color: var(--background-secondary-alt);
|
||||
}
|
||||
|
||||
.date-increment {
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
padding: 6px;
|
||||
border-left: var(--border-width) solid var(--background-modifier-border);
|
||||
border-top: var(--border-width) solid var(--background-modifier-border);
|
||||
border-bottom: var(--border-width) solid var(--background-modifier-border);
|
||||
background-color: var(--background-secondary);
|
||||
}
|
||||
|
||||
.date-increment:hover {
|
||||
background-color: var(--background-secondary-alt);
|
||||
}
|
||||
|
||||
.left-increment {
|
||||
border-top-left-radius: 6px;
|
||||
border-bottom-left-radius: 6px;
|
||||
}
|
||||
|
||||
.right-increment {
|
||||
border-top-right-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
border-right: var(--border-width) solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
/* Task Cell */
|
||||
|
||||
.task-cell {
|
||||
background: var(--task-background);
|
||||
opacity: 0.8;
|
||||
border-radius: 8px;
|
||||
padding: 4px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.task-cell-header {
|
||||
background: var(--task-background);
|
||||
border-radius: 4px;
|
||||
margin-bottom: 4px;
|
||||
color: var(--light-task-text-color);
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.task-cell-content input {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--light-task-text-color);
|
||||
margin-bottom: 4px;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.task-cell-content input::placeholder {
|
||||
color: var(--light-task-text-color);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Table */
|
||||
.table-container {
|
||||
border: var(--border-width) solid var(--background-modifier-border);
|
||||
border-top-left-radius: 8px;
|
||||
|
|
@ -38,9 +136,10 @@
|
|||
width: 128px;
|
||||
}
|
||||
.table td {
|
||||
padding: 12px 16px;
|
||||
padding: 8px;
|
||||
font-size: small;
|
||||
height: 68px;
|
||||
height: 80px;
|
||||
/* height: 128px; */
|
||||
border-top: var(--border-width) solid var(--background-modifier-border);
|
||||
}
|
||||
.taskcell-enclosure {
|
||||
|
|
@ -58,4 +157,4 @@
|
|||
border-left: var(--border-width) solid var(--background-modifier-border);
|
||||
width: var(--taskcell-enclosure-width);
|
||||
}
|
||||
/*# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3R5bGVzLmNzcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyogRGVmaW5lIGEgY3VzdG9tIGJvcmRlciBjb2xvciAqL1xyXG4udGFibGUtY29udGFpbmVyIHtcclxuICBib3JkZXI6IHZhcigtLWJvcmRlci13aWR0aCkgc29saWQgdmFyKC0tYmFja2dyb3VuZC1tb2RpZmllci1ib3JkZXIpOyAvKiBDdXN0b20gYm9yZGVyIGNvbG9yICovXHJcbiAgYm9yZGVyLXJhZGl1czogOHB4OyAvKiBSb3VuZGVkIGNvcm5lcnMgKi9cclxuICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gIG1heC13aWR0aDogMTAwJTtcclxuICAtLW9uZS1zZXZlbnRoLXdpZHRoOiAwcHg7XHJcbn1cclxuXHJcbi50YWJsZSB7XHJcbiAgd2lkdGg6IDEwMCU7XHJcbiAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTtcclxuICB0ZXh0LWFsaWduOiBsZWZ0O1xyXG59XHJcblxyXG4udGFibGUtaGVhZGVyIHtcclxuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1iYWNrZ3JvdW5kLXNlY29uZGFyeSk7XHJcbn1cclxuXHJcbi50YWJsZSB0aCB7XHJcbiAgcGFkZGluZzogMTJweCAxNnB4O1xyXG4gIGZvbnQtc2l6ZTogc21hbGw7XHJcbiAgZm9udC13ZWlnaHQ6IDUwMDtcclxufSBcclxuXHJcbi50b3AtbGVmdCB7XHJcbiAgd2lkdGg6IDEyOHB4O1xyXG59XHJcblxyXG4udGFibGUgdGQge1xyXG4gIHBhZGRpbmc6IDEycHggMTZweDtcclxuICBmb250LXNpemU6IHNtYWxsO1xyXG4gIGhlaWdodDogNjhweDtcclxuICBib3JkZXItdG9wOiB2YXIoLS1ib3JkZXItd2lkdGgpIHNvbGlkIHZhcigtLWJhY2tncm91bmQtbW9kaWZpZXItYm9yZGVyKTtcclxufVxyXG5cclxuLnRhc2tjZWxsLWVuY2xvc3VyZSB7XHJcbiAgYm9yZGVyLWxlZnQ6IHZhcigtLWJvcmRlci13aWR0aCkgc29saWQgdmFyKC0tYmFja2dyb3VuZC1tb2RpZmllci1ib3JkZXIpO1xyXG59XHJcblxyXG4ucHJvamVjdC1pbnB1dCB7XHJcbiAgYm9yZGVyOiBub25lICFpbXBvcnRhbnQ7XHJcbiAgd2lkdGg6IDEwMCU7XHJcbn1cclxuXHJcbi5kYXRlIHtcclxuICBib3JkZXItbGVmdDogdmFyKC0tYm9yZGVyLXdpZHRoKSBzb2xpZCB2YXIoLS1iYWNrZ3JvdW5kLW1vZGlmaWVyLWJvcmRlcik7IFxyXG4gIHdpZHRoOiB2YXIoLS10YXNrY2VsbC1lbmNsb3N1cmUtd2lkdGgpO1xyXG59Il0sCiAgIm1hcHBpbmdzIjogIjtBQUNBO0FBQ0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBR0Y7QUFDRTtBQUNBO0FBQ0E7QUFBQTtBQUdGO0FBQ0U7QUFBQTtBQUdGO0FBQ0U7QUFDQTtBQUNBO0FBQUE7QUFHRjtBQUNFO0FBQUE7QUFHRjtBQUNFO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFHRjtBQUNFO0FBQUE7QUFHRjtBQUNFO0FBQ0E7QUFBQTtBQUdGO0FBQ0U7QUFDQTtBQUFBOyIsCiAgIm5hbWVzIjogW10KfQo= */
|
||||
/*# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3R5bGVzLmNzcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyogRGVmaW5lIGEgY3VzdG9tIGJvcmRlciBjb2xvciAqL1xyXG4udGFibGUtY29udGFpbmVyIHtcclxuICBib3JkZXI6IHZhcigtLWJvcmRlci13aWR0aCkgc29saWQgdmFyKC0tYmFja2dyb3VuZC1tb2RpZmllci1ib3JkZXIpOyAvKiBDdXN0b20gYm9yZGVyIGNvbG9yICovXHJcbiAgYm9yZGVyLXJhZGl1czogOHB4OyAvKiBSb3VuZGVkIGNvcm5lcnMgKi9cclxuICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gIG1heC13aWR0aDogMTAwJTtcclxuICAtLW9uZS1zZXZlbnRoLXdpZHRoOiAwcHg7XHJcbn1cclxuXHJcbi50YWJsZSB7XHJcbiAgd2lkdGg6IDEwMCU7XHJcbiAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTtcclxuICB0ZXh0LWFsaWduOiBsZWZ0O1xyXG59XHJcblxyXG4udGFibGUtaGVhZGVyIHtcclxuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1iYWNrZ3JvdW5kLXNlY29uZGFyeSk7XHJcbn1cclxuXHJcbi50YWJsZSB0aCB7XHJcbiAgcGFkZGluZzogMTJweCAxNnB4O1xyXG4gIGZvbnQtc2l6ZTogc21hbGw7XHJcbiAgZm9udC13ZWlnaHQ6IDUwMDtcclxufSBcclxuXHJcbi50b3AtbGVmdCB7XHJcbiAgd2lkdGg6IDEyOHB4O1xyXG59XHJcblxyXG4udGFibGUgdGQge1xyXG4gIHBhZGRpbmc6IDEycHggMTZweDtcclxuICBmb250LXNpemU6IHNtYWxsO1xyXG4gIGhlaWdodDogNjhweDtcclxuICBib3JkZXItdG9wOiB2YXIoLS1ib3JkZXItd2lkdGgpIHNvbGlkIHZhcigtLWJhY2tncm91bmQtbW9kaWZpZXItYm9yZGVyKTtcclxufVxyXG5cclxuLnRhc2tjZWxsLWVuY2xvc3VyZSB7XHJcbiAgYm9yZGVyLWxlZnQ6IHZhcigtLWJvcmRlci13aWR0aCkgc29saWQgdmFyKC0tYmFja2dyb3VuZC1tb2RpZmllci1ib3JkZXIpO1xyXG59XHJcblxyXG4ucHJvamVjdC1pbnB1dCB7XHJcbiAgYm9yZGVyOiBub25lICFpbXBvcnRhbnQ7XHJcbiAgd2lkdGg6IDEwMCU7XHJcbn1cclxuXHJcbi5kYXRlIHtcclxuICBib3JkZXItbGVmdDogdmFyKC0tYm9yZGVyLXdpZHRoKSBzb2xpZCB2YXIoLS1iYWNrZ3JvdW5kLW1vZGlmaWVyLWJvcmRlcik75mdzIjogIjtBQUNBO0FBQ0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBR0Y7QUFDRTtBQUNBO0FBQ0E7QUFBQTtBQUdGO0FBQ0U7QUFBQTtBQUdGO0FBQ0U7QUFDQTtBQUNBO0FBQUE7QUFHRjtBQUNFO0FBQUE7QUFHRjtBQUNFO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFHRjtBQUNFO0FBQUE7QUFHRjtBQUNFO0FBQ0E7QUFBQTtBQUdGO0FBQ0U7QUFDQTtBQUFBOyIsCiAgIm5hbWVzIjogW10KfQo= */
|
||||
|
|
|
|||
Loading…
Reference in a new issue