From 449e357d6b7fbc991f3a049e244d53d2ca842cc6 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Sat, 30 Sep 2023 20:02:33 -0600 Subject: [PATCH 1/6] ui update, add debug panel --- src/components/DailyConfigComponent.tsx | 247 ++++++++++++++++-------- src/index.ts | 4 + 2 files changed, 169 insertions(+), 82 deletions(-) diff --git a/src/components/DailyConfigComponent.tsx b/src/components/DailyConfigComponent.tsx index 377cba2..bcc97a1 100644 --- a/src/components/DailyConfigComponent.tsx +++ b/src/components/DailyConfigComponent.tsx @@ -1,4 +1,13 @@ -import { Checkbox, InputGroup, Label, Switch } from "@blueprintjs/core"; +import { + Checkbox, + FormGroup, + InputGroup, + Label, + Switch, + Tab, + Tabs, + Text, +} from "@blueprintjs/core"; import { TimePicker } from "@blueprintjs/datetime"; import React, { useMemo, useState, useEffect } from "react"; import getDailyConfig from "../utils/getDailyConfig"; @@ -9,6 +18,7 @@ import localStorageSet from "roamjs-components/util/localStorageSet"; import nanoid from "nanoid"; const DailyConfig = () => { + // TODO refresh config so debug panel shows up to date info const config = useMemo(getDailyConfig, []); const [disabled, setDisabled] = useState(!config.enabled); const [onlyOnThisDevice, setOnlyOnThisDevice] = useState( @@ -51,91 +61,164 @@ const DailyConfig = () => { window.clearInterval(int); }; }, [setNow]); + return ( -
- { - const enabled = (e.target as HTMLInputElement).checked; - if (enabled) { - saveDailyConfig({ - "workflow name": workflowName || "Daily", - }); - scheduleNextDailyRun({ tomorrow: true }); - } else { - window.clearTimeout(getDailyConfig()["next-run-timeout"]); - saveDailyConfig({ "workflow name": "" }); - setWorkflowName(""); - } - setDisabled(!enabled); - }} - label={disabled ? "Disabled" : "Enabled"} - /> -
+ } + disabled={disabled} + /> + )} + {!disabled && ( + + + + + + + + + } + /> + )} + + { - saveDailyConfig({ - "workflow name": e.target.value, - }); - setWorkflowName(e.target.value); + const enabled = (e.target as HTMLInputElement).checked; + if (enabled) { + saveDailyConfig({ + "workflow name": workflowName || "Daily", + }); + scheduleNextDailyRun({ tomorrow: true }); + } else { + window.clearTimeout(getDailyConfig()["next-run-timeout"]); + saveDailyConfig({ "workflow name": "" }); + setWorkflowName(""); + } + setDisabled(!enabled); }} - disabled={disabled} - placeholder={"Daily"} - className={"w-full"} - /> - - - - {lastRun && - lastRun !== "01-01-1970" && - `Last ran daily workflow on page ${lastRun}.`} - - - {!!nextRun && - !disabled && - `Next run is in ${Math.floor( - nextRun / (60 * 60 * 1000) - )} hours, ${Math.floor( - (nextRun % (60 * 60 * 1000)) / (60 * 1000) - )} minutes, ${Math.floor((nextRun % (60 * 1000)) / 1000)} seconds.`} - - { - const enabled = (e.target as HTMLInputElement).checked; - if (enabled) { - const deviceId = localStorageGet("device") || nanoid(); - saveDailyConfig({ - device: deviceId, - }); - localStorageSet("device", deviceId); - } else { - saveDailyConfig({ device: "" }); - } - setOnlyOnThisDevice(enabled); - }} - label={"Only run on this device"} - disabled={disabled} - /> + ); }; diff --git a/src/index.ts b/src/index.ts index ad11669..0f0f01f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -103,6 +103,10 @@ export default runExtension(async ({ extensionAPI }) => { .roamjs-smartblock-menu { width: 300px; +} +.rm-settings-tabs .roamjs-daily-config-tabs .bp3-tab-list { + padding: 2px; + background: none; }`); const toggleCommandPalette = (flag: boolean) => { From ad8248a82db138ff6492495c949907301d0bbee0 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Tue, 3 Oct 2023 21:02:30 -0600 Subject: [PATCH 2/6] add local state, edit setTime, multiple others --- src/components/DailyConfigComponent.tsx | 128 +++++++++++++++--------- src/utils/saveDailyConfig.ts | 4 +- src/utils/scheduleNextDailyRun.ts | 10 +- 3 files changed, 89 insertions(+), 53 deletions(-) diff --git a/src/components/DailyConfigComponent.tsx b/src/components/DailyConfigComponent.tsx index bcc97a1..9e5df4d 100644 --- a/src/components/DailyConfigComponent.tsx +++ b/src/components/DailyConfigComponent.tsx @@ -1,6 +1,7 @@ import { Checkbox, FormGroup, + Icon, InputGroup, Label, Switch, @@ -18,17 +19,24 @@ import localStorageSet from "roamjs-components/util/localStorageSet"; import nanoid from "nanoid"; const DailyConfig = () => { - // TODO refresh config so debug panel shows up to date info const config = useMemo(getDailyConfig, []); - const [disabled, setDisabled] = useState(!config.enabled); + const [localConfig, setLocalConfig] = useState(config); + const { + enabled, + device, + time: setRunTime, + "workflow name": workflowName, + "last-run": lastRun, + "next-run": configNextRun, + } = localConfig; const [onlyOnThisDevice, setOnlyOnThisDevice] = useState( - !!config.device && config.device === localStorageGet("device") + !!device && device === localStorageGet("device") ); - const [workflowName, setWorkflowName] = useState(config["workflow name"]); + const defaultTime = useMemo(() => { const date = new Date(); - if (config && config["time"]) { - const [h, m] = config["time"].split(":").map(Number); + if (localConfig && setRunTime) { + const [h, m] = setRunTime.split(":").map(Number); date.setHours(h); date.setMinutes(m); } else { @@ -36,23 +44,26 @@ const DailyConfig = () => { date.setMinutes(0); } return date; - }, [config]); - const lastRun = config?.["last-run"]; + }, [localConfig]); + const [localTime, setLocalTime] = useState(defaultTime); const [now, setNow] = useState(new Date()); + const [isEditTime, setIsEditTime] = useState(false); const nextRun = useMemo(() => { - if (!config.enabled) return 0; - return config["next-run"] - now.valueOf(); - }, [now, config]); + if (!localConfig.enabled) return 0; + return configNextRun - now.valueOf(); + }, [now, localConfig]); // migrate old config useEffect(() => { - if (config["workflow name"] && !config["enabled"]) { + if (workflowName && !enabled) { saveDailyConfig({ enabled: true, }); - setDisabled(false); + setLocalConfig((prev) => ({ ...prev, enabled: true })); } }, [config]); + + // Set up an interval to periodically update the current time useEffect(() => { const int = window.setInterval(() => { setNow(new Date()); @@ -64,8 +75,8 @@ const DailyConfig = () => { return (
- - {!disabled && ( + + {enabled && ( { saveDailyConfig({ "workflow name": e.target.value, }); - setWorkflowName(e.target.value); + setLocalConfig((prev) => ({ + ...prev, + "workflow name": e.target.value, + })); + console.log(e.target.value); }} style={{ minWidth: "initial" }} placeholder={"Daily"} @@ -98,17 +113,35 @@ const DailyConfig = () => { style={{ alignItems: "center" }} inline={true} > - - saveDailyConfig({ - time: `${e.getHours()}:${e.getMinutes()}`, - }) - } - showArrowButtons - disabled={disabled} - className={"w-full user-select-none flex-1 text-center"} - /> +
+ setLocalTime(e)} + showArrowButtons + disabled={!isEditTime} + className={ + "user-select-none flex-1 text-center text-black" + } + /> + { + if (isEditTime) { + const newTime = `${localTime.getHours()}:${localTime.getMinutes()}`; + await saveDailyConfig({ + time: newTime, + }); + await scheduleNextDailyRun({ tomorrow: true }); + setLocalConfig(getDailyConfig()); + setIsEditTime(false); + } else { + setIsEditTime(true); + } + }} + className="cursor-pointer ml-2" + intent={isEditTime ? "success" : "none"} + /> +
{ } setOnlyOnThisDevice(enabled); }} - disabled={disabled} + disabled={!enabled} />
} - disabled={disabled} + disabled={!enabled} /> )} - {!disabled && ( + {enabled && ( { Last Run {lastRun && lastRun !== "01-01-1970" - ? `Last ran daily workflow on page ${lastRun}.` + ? `Last ran on page ${lastRun}` : "Last run data not available"} @@ -159,7 +192,7 @@ const DailyConfig = () => { Next Run {!!nextRun - ? `In ${Math.floor( + ? `${Math.floor( nextRun / (60 * 60 * 1000) )} hours, ${Math.floor( (nextRun % (60 * 60 * 1000)) / (60 * 1000) @@ -178,20 +211,16 @@ const DailyConfig = () => { - @@ -202,20 +231,29 @@ const DailyConfig = () => { { const enabled = (e.target as HTMLInputElement).checked; if (enabled) { saveDailyConfig({ + enabled: true, "workflow name": workflowName || "Daily", }); + setLocalConfig((prev) => ({ + ...prev, + enabled: true, + "workflow name": workflowName || "Daily", + })); scheduleNextDailyRun({ tomorrow: true }); } else { window.clearTimeout(getDailyConfig()["next-run-timeout"]); - saveDailyConfig({ "workflow name": "" }); - setWorkflowName(""); + saveDailyConfig({ "workflow name": "", enabled: false }); + setLocalConfig((prev) => ({ + ...prev, + "workflow name": "", + enabled: false, + })); } - setDisabled(!enabled); }} /> diff --git a/src/utils/saveDailyConfig.ts b/src/utils/saveDailyConfig.ts index fccce74..efba568 100644 --- a/src/utils/saveDailyConfig.ts +++ b/src/utils/saveDailyConfig.ts @@ -1,9 +1,9 @@ import getExtensionApi from "roamjs-components/util/extensionApiContext"; import getDailyConfig, { DailyConfig } from "./getDailyConfig"; -const saveDailyConfig = (config: Partial) => { +const saveDailyConfig = async (config: Partial) => { const currentConfig = getDailyConfig(); - getExtensionApi().settings.set("daily", { + return getExtensionApi().settings.set("daily", { ...currentConfig, ...config, }); diff --git a/src/utils/scheduleNextDailyRun.ts b/src/utils/scheduleNextDailyRun.ts index 3bae701..a1d65dc 100644 --- a/src/utils/scheduleNextDailyRun.ts +++ b/src/utils/scheduleNextDailyRun.ts @@ -57,7 +57,6 @@ export const runDaily = async () => { const todayUid = window.roamAlphaAPI.util.dateToPageUid(today); const latestDate = parseRoamDateUid(lastRun); - let saveLastRun = false; if (isBefore(startOfDay(latestDate), startOfDay(today))) { const availableWorkflows = getCleanCustomWorkflows(); const srcUid = availableWorkflows.find( @@ -80,7 +79,6 @@ export const runDaily = async () => { target: { uid: todayUid, isParent: true }, fromDaily: true, }); - saveLastRun = true; } else { renderToast({ id: "smartblocks-error", @@ -98,19 +96,19 @@ export const runDaily = async () => { scheduleNextDailyRun({ saveLastRun: true, tomorrow: true }); }; -const scheduleNextDailyRun = ( +const scheduleNextDailyRun = async ( args: { tomorrow?: boolean; saveLastRun?: boolean } = {} ) => { const today = new Date(); const triggerDay = args.tomorrow ? addDays(today, 1) : today; const triggerDate = addSeconds(getTriggerTime(triggerDay), 1); const ms = differenceInMilliseconds(triggerDate, today); - const timeout = window.setTimeout(() => { + const timeoutId = window.setTimeout(() => { runDaily(); }, ms); - saveDailyConfig({ + await saveDailyConfig({ "next-run": triggerDate.valueOf(), - "next-run-timeout": timeout, + "next-run-timeout": timeoutId, ...(args.saveLastRun ? { "last-run": window.roamAlphaAPI.util.dateToPageUid(today) } : {}), From c45c339c9ed2ecbeff2b5e0fa44eede3a9a5d890 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Fri, 13 Oct 2023 16:16:18 -0600 Subject: [PATCH 3/6] PR Feedback --- README.md | 2 +- src/components/DailyConfigComponent.tsx | 87 ++++++++++--------------- src/index.ts | 3 + src/utils/scheduleNextDailyRun.ts | 2 +- 4 files changed, 38 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index e12237a..63f7e24 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The following steps dive into all the features SmartBlocks has to offer in incre ## Demo -[![](docs/media/vargas-smartblocks-demo-thumbnail.gif)](https://www.loom.com/share/954d916643754027a3889fd5bf7f24dd) +[![](https://raw.githubusercontent.com/RoamJs/smartblocks/main/docs/media/vargas-smartblocks-demo-thumbnail.gif)](https://www.loom.com/share/954d916643754027a3889fd5bf7f24dd) diff --git a/src/components/DailyConfigComponent.tsx b/src/components/DailyConfigComponent.tsx index 9e5df4d..5c39fdc 100644 --- a/src/components/DailyConfigComponent.tsx +++ b/src/components/DailyConfigComponent.tsx @@ -1,3 +1,4 @@ +import React, { useMemo, useState, useEffect } from "react"; import { Checkbox, FormGroup, @@ -10,7 +11,6 @@ import { Text, } from "@blueprintjs/core"; import { TimePicker } from "@blueprintjs/datetime"; -import React, { useMemo, useState, useEffect } from "react"; import getDailyConfig from "../utils/getDailyConfig"; import saveDailyConfig from "../utils/saveDailyConfig"; import scheduleNextDailyRun from "../utils/scheduleNextDailyRun"; @@ -19,24 +19,27 @@ import localStorageSet from "roamjs-components/util/localStorageSet"; import nanoid from "nanoid"; const DailyConfig = () => { - const config = useMemo(getDailyConfig, []); - const [localConfig, setLocalConfig] = useState(config); + const initialConfig = useMemo(getDailyConfig, []); + const [localConfig, _setLocalConfig] = useState(initialConfig); + const setConfig = async (newConfig: { [key: string]: any }) => { + _setLocalConfig((prev) => ({ ...prev, ...newConfig })); + await saveDailyConfig(newConfig); + }; const { enabled, device, - time: setRunTime, + time: timeToRun, "workflow name": workflowName, "last-run": lastRun, "next-run": configNextRun, } = localConfig; - const [onlyOnThisDevice, setOnlyOnThisDevice] = useState( - !!device && device === localStorageGet("device") - ); - const defaultTime = useMemo(() => { + const [currentDevice, setCurrentDevice] = useState(localStorageGet("device")); + + const initialTimePicker = useMemo(() => { const date = new Date(); - if (localConfig && setRunTime) { - const [h, m] = setRunTime.split(":").map(Number); + if (localConfig && timeToRun) { + const [h, m] = timeToRun.split(":").map(Number); date.setHours(h); date.setMinutes(m); } else { @@ -45,7 +48,7 @@ const DailyConfig = () => { } return date; }, [localConfig]); - const [localTime, setLocalTime] = useState(defaultTime); + const [timePicker, setTimePicker] = useState(initialTimePicker); const [now, setNow] = useState(new Date()); const [isEditTime, setIsEditTime] = useState(false); const nextRun = useMemo(() => { @@ -56,12 +59,9 @@ const DailyConfig = () => { // migrate old config useEffect(() => { if (workflowName && !enabled) { - saveDailyConfig({ - enabled: true, - }); - setLocalConfig((prev) => ({ ...prev, enabled: true })); + setConfig({ enabled: true }); } - }, [config]); + }, [initialConfig]); // Set up an interval to periodically update the current time useEffect(() => { @@ -92,17 +92,10 @@ const DailyConfig = () => { id="roamjs-workflow-name" value={workflowName} onChange={(e) => { - saveDailyConfig({ - "workflow name": e.target.value, - }); - setLocalConfig((prev) => ({ - ...prev, - "workflow name": e.target.value, - })); - console.log(e.target.value); + setConfig({ "workflow name": e.target.value }); }} style={{ minWidth: "initial" }} - placeholder={"Daily"} + placeholder={"Enter workflow name"} /> @@ -115,24 +108,19 @@ const DailyConfig = () => { >
setLocalTime(e)} + value={timePicker} + onChange={(date) => setTimePicker(date)} showArrowButtons disabled={!isEditTime} - className={ - "user-select-none flex-1 text-center text-black" - } + className={"user-select-none flex-1 text-center"} /> { if (isEditTime) { - const newTime = `${localTime.getHours()}:${localTime.getMinutes()}`; - await saveDailyConfig({ - time: newTime, - }); + const newTime = `${timePicker.getHours()}:${timePicker.getMinutes()}`; + await setConfig({ time: newTime }); await scheduleNextDailyRun({ tomorrow: true }); - setLocalConfig(getDailyConfig()); setIsEditTime(false); } else { setIsEditTime(true); @@ -151,19 +139,17 @@ const DailyConfig = () => { > { const enabled = (e.target as HTMLInputElement).checked; if (enabled) { - const deviceId = localStorageGet("device") || nanoid(); - saveDailyConfig({ - device: deviceId, - }); + const deviceId = currentDevice || nanoid(); + setConfig({ device: deviceId }); localStorageSet("device", deviceId); + setCurrentDevice(deviceId); } else { - saveDailyConfig({ device: "" }); + setConfig({ device: "" }); } - setOnlyOnThisDevice(enabled); }} disabled={!enabled} /> @@ -217,7 +203,7 @@ const DailyConfig = () => {