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 ErrorBoundary from "components/errorboundry";
|
||||||
import List from "components/tasklist/list";
|
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 (
|
return (
|
||||||
<div key={group.name} className="flex-1">
|
<div key={groupName} className="flex-1">
|
||||||
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{group.name}</h2>
|
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{groupName}</h2>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<List tasklist={group.tasklist} />
|
<List listDetail={groupTasks} listUpdate={listUpdate} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</div>
|
</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 (
|
return (
|
||||||
<li key={task.title}>
|
<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 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">
|
<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>
|
||||||
<div className="flex-1 flex items-center justify-between rounded-r-md ">
|
<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>
|
<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";
|
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 (
|
return (
|
||||||
<ul className="mt-3 flex flex-col">
|
<ul className="mt-3 flex flex-col">
|
||||||
{tasklist.map((task) => (
|
{tasks.map((task) => (
|
||||||
<Item key={task.title} task={task} />
|
<Item key={Object.values(task)[0]} taskDetail={task} taskUpdate={taskUpdate} />
|
||||||
))}
|
))}
|
||||||
</ul>
|
</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 { ColorContext } from "utils/contexts/color";
|
||||||
import { ThemeContext } from "utils/contexts/theme";
|
import { ThemeContext } from "utils/contexts/theme";
|
||||||
import { SettingsContext } from "utils/contexts/settings";
|
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 ErrorBoundary from "components/errorboundry";
|
||||||
import themes from "utils/styles/themes";
|
import themes from "utils/styles/themes";
|
||||||
import QuickLaunch from "components/quicklaunch";
|
import QuickLaunch from "components/quicklaunch";
|
||||||
@ -46,6 +46,7 @@ export async function getStaticProps() {
|
|||||||
const { providers, ...settings } = getSettings();
|
const { providers, ...settings } = getSettings();
|
||||||
|
|
||||||
const services = await servicesResponse();
|
const services = await servicesResponse();
|
||||||
|
const tasklist = await tasklistResponse();
|
||||||
const bookmarks = await bookmarksResponse();
|
const bookmarks = await bookmarksResponse();
|
||||||
const widgets = await widgetsResponse();
|
const widgets = await widgetsResponse();
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ export async function getStaticProps() {
|
|||||||
initialSettings: settings,
|
initialSettings: settings,
|
||||||
fallback: {
|
fallback: {
|
||||||
"/api/services": services,
|
"/api/services": services,
|
||||||
|
"/api/tasklist": tasklist,
|
||||||
"/api/bookmarks": bookmarks,
|
"/api/bookmarks": bookmarks,
|
||||||
"/api/widgets": widgets,
|
"/api/widgets": widgets,
|
||||||
"/api/hash": false,
|
"/api/hash": false,
|
||||||
@ -70,6 +72,7 @@ export async function getStaticProps() {
|
|||||||
initialSettings: {},
|
initialSettings: {},
|
||||||
fallback: {
|
fallback: {
|
||||||
"/api/services": [],
|
"/api/services": [],
|
||||||
|
"/api/tasklist": [],
|
||||||
"/api/bookmarks": [],
|
"/api/bookmarks": [],
|
||||||
"/api/widgets": [],
|
"/api/widgets": [],
|
||||||
"/api/hash": false,
|
"/api/hash": false,
|
||||||
@ -174,8 +177,8 @@ function Home({ initialSettings }) {
|
|||||||
}, [initialSettings, setSettings]);
|
}, [initialSettings, setSettings]);
|
||||||
|
|
||||||
const { data: services } = useSWR("/api/services");
|
const { data: services } = useSWR("/api/services");
|
||||||
const { data: bookmarks } = useSWR("/api/bookmarks");
|
|
||||||
const { data: tasklist } = useSWR("/api/tasklist");
|
const { data: tasklist } = useSWR("/api/tasklist");
|
||||||
|
const { data: bookmarks } = useSWR("/api/bookmarks");
|
||||||
const { data: widgets } = useSWR("/api/widgets");
|
const { data: widgets } = useSWR("/api/widgets");
|
||||||
|
|
||||||
const servicesAndBookmarks = [...services.map(sg => sg.services).flat(), ...bookmarks.map(bg => bg.bookmarks).flat()]
|
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);
|
document.removeEventListener('keydown', handleKeyDown);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const [taskList, setTaskList] = useState(tasklist)
|
||||||
|
const taskListUpdate = () => {
|
||||||
|
setTaskList(taskList)
|
||||||
|
fetch("/api/tasklistSave", {method: "POST", body: JSON.stringify(taskList)})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -296,10 +304,10 @@ function Home({ initialSettings }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{tasklist?.length > 0 && (
|
{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)}`}>
|
<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) => (
|
{taskList.map((group) => (
|
||||||
<TasklistGroup key={group.name} group={group} />
|
<TasklistGroup key={Object.keys(group)[0]} groupDetail={group} groupUpdate={taskListUpdate} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -54,19 +54,13 @@ export async function tasklistResponse() {
|
|||||||
const fileContents = substituteEnvironmentVars(rawFileContents);
|
const fileContents = substituteEnvironmentVars(rawFileContents);
|
||||||
const tasklist = yaml.load(fileContents);
|
const tasklist = yaml.load(fileContents);
|
||||||
|
|
||||||
if (!tasklist) return [];
|
return tasklist
|
||||||
|
}
|
||||||
|
|
||||||
// map easy to write YAML objects into easy to consume JS arrays
|
export async function tasklistPersist(taskState) {
|
||||||
const tasklistArray = tasklist.map((group) => ({
|
const tasklistYaml = path.join(process.cwd(), "config", "tasklist.yaml");
|
||||||
name: Object.keys(group)[0],
|
await fs.writeFile(tasklistYaml, yaml.dump(JSON.parse(taskState)));
|
||||||
tasklist: group[Object.keys(group)[0]].map((entries) => ({
|
return [taskState];
|
||||||
// id: Object.values(entries)[0].replaceAll(" ", "_"),
|
|
||||||
title: Object.values(entries)[0],
|
|
||||||
checked: Object.values(entries)[1],
|
|
||||||
})),
|
|
||||||
}));
|
|
||||||
|
|
||||||
return tasklistArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function widgetsResponse() {
|
export async function widgetsResponse() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user