/** @import * as TYPES from "./graph/types.ts" */ import * as FSHandle from "./store-directory-handle.js"; const {Div, DOM} = Gale({ Title:{ padding:"2rem", background: "blue", color:"white" }, Plain:{}, PartGroup:{ display: `flex`, flexWrap: `wrap` }, Part:{ border: `1px solid black`, borderRadius: `5px`, padding: `1rem` }, BlockScreen:{ position: "fixed", zIndex: "9999", top: "0", left: "0", width: "100%", height: "100%", background: "rgba(128, 128, 128, 0.5)" } }); async function PickHandle() { handle = await showDirectoryPicker(); await FSHandle.setDirectoryHandle(handle); await LoadHandleFiles(); } async function LoadHandleFiles() { console.log("fetching room.js", handle); if(handle) { try { const module = await import("./graph/room.js"+"?bust="+Math.random()); /** @type {Record} */ const read = module.default(); rooms.val = read; } catch(_e) { console.log("the handle exists, but the request failed. the service work must not be ready yet.") rooms.val = {}; } } else { console.log("no fs handle has been set, cannot get room graph") rooms.val = {}; } } /** @type {Van.State>} */ const rooms = van.state({}); let handle = await FSHandle.getDirectoryHandle(); await LoadHandleFiles(); /** @type {(path:string[], part:string, time:number, data:string)=>void} */ async function WRITE(path, part, time, data) { const fileHandle = await FSHandle.Dig(handle, path, true); if(fileHandle) { const file = await fileHandle.getFile(); const text = await file.text(); let json = {}; if(text) { json = JSON.parse(text); } let partProp = json[part]; if(!partProp) { partProp = []; json[part] = partProp; } partProp.push([time, data]); const writeable = await fileHandle.createWritable(); await writeable.write(JSON.stringify(json, null, 2)); await writeable.close(); } } /** @type {Van.State} */ const loggedIn = van.state(false); const blocking = van.state(false); /** @type {(room_id:string, graphParts:TYPES.GraphParts)=>HTMLElement} */ function Room(room_id, graphParts) { const rerender = van.state(0); blocking.val; return Div.Plain( Div.Plain("Users:"), Div.PartGroup( Object.entries(graphParts.User).map(([user_id, user])=>{ return ()=>{ //rerender.val; return Div.Part( DOM.div.Plain(user.name), ()=>{ return DOM.button.Plain( {onclick(){ loggedIn.val = (loggedIn.val == user) ? false : user; }}, loggedIn.val == user ? "this is me" : "impersonate" ) }, ) } }) ), Div.Plain("Passes:"), Div.PartGroup( Object.entries(graphParts.Pass).map(([pass_id, pass])=>{ return ()=>{ console.log("rerendering...", rerender.rawVal); rerender.val; return Div.Part( DOM.div.Plain(pass.name), ()=>{ return DOM.button.Plain( {async onclick(){ await pass[pass.live ? "dump" : "load"](); rerender.val++ }}, pass.live ? "Dump" : "Load" ) }, ) } }) ), Div.Plain("Parts"), Div.PartGroup( Object.entries(graphParts.Part).map(([part_id, part])=>{ return ()=>{ rerender.val; const work = [] for(const [pass, data] of part.pass) { work.push(Div.Part( DOM.h5(pass.name), DOM.p(data.time), data.work.map(([time, data, user])=>Div.Plain( DOM.span(time), " ", DOM.strong(data), )), Div.Plain( loggedIn.val ? DOM.button({onclick(){ if(loggedIn.val) { blocking.val = true; data.make(loggedIn.val, "NEW").then(()=>{ blocking.val = false; rerender.val++; }); } }}, "Add work!") : null ) )) } return Div.Part( DOM.h3(part.name), ...work, ); } }), ), Div.Plain("Desks"), Div.PartGroup( Object.entries(graphParts.Desk).map(([desk_id, desk])=>{ return ()=>{ rerender.val; /** @type {(part:TYPES.Part, index:number, pass:TYPES.Pass, dirty:number[])=>HTMLElement|null} */ const Iterator = (part, index, pass, dirty)=>{ const partPass = part.pass.get(pass); if(partPass) { const time = partPass.time; const latest = partPass.work.find(t=>t[0] == time); return Div.Plain( part.name, DOM.p( dirty.includes(index) ? "Dirty" : "Good!" ), Div.Part( time, " ", latest?.[1] || "" ) ); } return null; } const work = []; for(const [pass, dirty] of desk.pass) { work.push(Div.Part( DOM.h5(pass.name), Div.Part( DOM.h4("Need:"), desk.need.map((part, index)=>Iterator(part, index, pass, dirty.need)) ), Div.Part( DOM.h4("Make:"), desk.make.map((part, index)=>Iterator(part, index, pass, dirty.make)) ) )) } return Div.Part( DOM.h3(desk.name), work ) } }), ), ()=>{ return blocking.val ? Div.BlockScreen() : null } ) } function App() { return Div.Plain( DOM.button({onclick:PickHandle}, "Pick Directory"), Object.entries(rooms.val).map(([room_id, graphParts])=> Room(room_id, graphParts) ) ) } van.add(document.body, App);