feat: Store updated state in the source YAML file
This commit is contained in:
parent
d4c764e854
commit
f5f5721cf0
@ -1,12 +1,22 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import ErrorBoundary from "components/errorboundry";
|
||||
import List from "components/tasklist/list";
|
||||
|
||||
export default function TaskListGroup({ group }) {
|
||||
export default function TaskListGroup({groupDetail, groupUpdate}) {
|
||||
const [group, setGroup] = useState(groupDetail)
|
||||
const groupName = Object.keys(group)[0]
|
||||
const groupTasks = Object.values(group)[0]
|
||||
|
||||
const listUpdate = () => {
|
||||
setGroup(group)
|
||||
groupUpdate()
|
||||
}
|
||||
return (
|
||||
<div key={group.name} className="flex-1">
|
||||
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{group.name}</h2>
|
||||
<div key={groupName} className="flex-1">
|
||||
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{groupName}</h2>
|
||||
<ErrorBoundary>
|
||||
<List tasklist={group.tasklist} />
|
||||
<List listDetail={groupTasks} listUpdate={listUpdate} />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,9 +1,19 @@
|
||||
export default function Item({ task }) {
|
||||
import {useState} from "react";
|
||||
|
||||
export default function Item({taskDetail, taskUpdate}) {
|
||||
const [task, setTask] = useState(taskDetail)
|
||||
|
||||
const toggleComplete = () => {
|
||||
task.checked = !task.checked;
|
||||
setTask(task)
|
||||
taskUpdate()
|
||||
}
|
||||
|
||||
return (
|
||||
<li key={task.title}>
|
||||
<div className="flex block w-full text-left transition-all h-15 mb-3 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10">
|
||||
<div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md">
|
||||
<input type="checkbox" className="checkbox bg-theme-500/10 text-theme-200 dark:text-theme-700" id={task.title} defaultChecked={task.checked}/>
|
||||
<input type="checkbox" className="checkbox bg-theme-500/10 text-theme-200 dark:text-theme-700" id={task.title} defaultChecked={task.checked} onChange={toggleComplete}/>
|
||||
</div>
|
||||
<div className="flex-1 flex items-center justify-between rounded-r-md ">
|
||||
<div className="flex-1 grow pl-3 py-2 text-xs">{task.title}</div>
|
||||
|
||||
@ -1,10 +1,19 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import Item from "components/tasklist/item";
|
||||
|
||||
export default function List({ tasklist }) {
|
||||
export default function List({listDetail, listUpdate}) {
|
||||
const [tasks, setTasks] = useState(listDetail)
|
||||
|
||||
const taskUpdate = () => {
|
||||
setTasks(tasks)
|
||||
listUpdate()
|
||||
}
|
||||
|
||||
return (
|
||||
<ul className="mt-3 flex flex-col">
|
||||
{tasklist.map((task) => (
|
||||
<Item key={task.title} task={task} />
|
||||
{tasks.map((task) => (
|
||||
<Item key={Object.values(task)[0]} taskDetail={task} taskUpdate={taskUpdate} />
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
|
||||
5
src/pages/api/tasklistSave.js
Normal file
5
src/pages/api/tasklistSave.js
Normal file
@ -0,0 +1,5 @@
|
||||
import { tasklistPersist } from "utils/config/api-response";
|
||||
|
||||
export default async function handler(req, res) {
|
||||
res.send(await tasklistPersist(req.body));
|
||||
}
|
||||
@ -19,7 +19,7 @@ import { getSettings } from "utils/config/config";
|
||||
import { ColorContext } from "utils/contexts/color";
|
||||
import { ThemeContext } from "utils/contexts/theme";
|
||||
import { SettingsContext } from "utils/contexts/settings";
|
||||
import { bookmarksResponse, servicesResponse, widgetsResponse } from "utils/config/api-response";
|
||||
import { bookmarksResponse, servicesResponse, tasklistResponse, widgetsResponse } from "utils/config/api-response";
|
||||
import ErrorBoundary from "components/errorboundry";
|
||||
import themes from "utils/styles/themes";
|
||||
import QuickLaunch from "components/quicklaunch";
|
||||
@ -46,6 +46,7 @@ export async function getStaticProps() {
|
||||
const { providers, ...settings } = getSettings();
|
||||
|
||||
const services = await servicesResponse();
|
||||
const tasklist = await tasklistResponse();
|
||||
const bookmarks = await bookmarksResponse();
|
||||
const widgets = await widgetsResponse();
|
||||
|
||||
@ -54,6 +55,7 @@ export async function getStaticProps() {
|
||||
initialSettings: settings,
|
||||
fallback: {
|
||||
"/api/services": services,
|
||||
"/api/tasklist": tasklist,
|
||||
"/api/bookmarks": bookmarks,
|
||||
"/api/widgets": widgets,
|
||||
"/api/hash": false,
|
||||
@ -70,6 +72,7 @@ export async function getStaticProps() {
|
||||
initialSettings: {},
|
||||
fallback: {
|
||||
"/api/services": [],
|
||||
"/api/tasklist": [],
|
||||
"/api/bookmarks": [],
|
||||
"/api/widgets": [],
|
||||
"/api/hash": false,
|
||||
@ -174,8 +177,8 @@ function Home({ initialSettings }) {
|
||||
}, [initialSettings, setSettings]);
|
||||
|
||||
const { data: services } = useSWR("/api/services");
|
||||
const { data: bookmarks } = useSWR("/api/bookmarks");
|
||||
const { data: tasklist } = useSWR("/api/tasklist");
|
||||
const { data: bookmarks } = useSWR("/api/bookmarks");
|
||||
const { data: widgets } = useSWR("/api/widgets");
|
||||
|
||||
const servicesAndBookmarks = [...services.map(sg => sg.services).flat(), ...bookmarks.map(bg => bg.bookmarks).flat()]
|
||||
@ -229,6 +232,11 @@ function Home({ initialSettings }) {
|
||||
document.removeEventListener('keydown', handleKeyDown);
|
||||
}
|
||||
})
|
||||
const [taskList, setTaskList] = useState(tasklist)
|
||||
const taskListUpdate = () => {
|
||||
setTaskList(taskList)
|
||||
fetch("/api/tasklistSave", {method: "POST", body: JSON.stringify(taskList)})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -296,10 +304,10 @@ function Home({ initialSettings }) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tasklist?.length > 0 && (
|
||||
<div className={`grow flex flex-wrap pt-0 p-4 sm:p-8 gap-2 grid-cols-1 lg:grid-cols-2 lg:grid-cols-${Math.min(6, tasklist.length)}`}>
|
||||
{tasklist.map((group) => (
|
||||
<TasklistGroup key={group.name} group={group} />
|
||||
{taskList?.length > 0 && (
|
||||
<div className={`grow flex flex-wrap pt-0 p-4 sm:p-8 gap-2 grid-cols-1 lg:grid-cols-2 lg:grid-cols-${Math.min(6, taskList.length)}`}>
|
||||
{taskList.map((group) => (
|
||||
<TasklistGroup key={Object.keys(group)[0]} groupDetail={group} groupUpdate={taskListUpdate} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -54,19 +54,13 @@ export async function tasklistResponse() {
|
||||
const fileContents = substituteEnvironmentVars(rawFileContents);
|
||||
const tasklist = yaml.load(fileContents);
|
||||
|
||||
if (!tasklist) return [];
|
||||
return tasklist
|
||||
}
|
||||
|
||||
// map easy to write YAML objects into easy to consume JS arrays
|
||||
const tasklistArray = tasklist.map((group) => ({
|
||||
name: Object.keys(group)[0],
|
||||
tasklist: group[Object.keys(group)[0]].map((entries) => ({
|
||||
// id: Object.values(entries)[0].replaceAll(" ", "_"),
|
||||
title: Object.values(entries)[0],
|
||||
checked: Object.values(entries)[1],
|
||||
})),
|
||||
}));
|
||||
|
||||
return tasklistArray;
|
||||
export async function tasklistPersist(taskState) {
|
||||
const tasklistYaml = path.join(process.cwd(), "config", "tasklist.yaml");
|
||||
await fs.writeFile(tasklistYaml, yaml.dump(JSON.parse(taskState)));
|
||||
return [taskState];
|
||||
}
|
||||
|
||||
export async function widgetsResponse() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user