From 753c887bb90cb0650877e7221c26a6313ccc5737 Mon Sep 17 00:00:00 2001 From: Vladyslav Sitalo Date: Wed, 19 Feb 2020 20:31:22 -0800 Subject: [PATCH 1/2] Estimates from queries. Iteration 1 --- src/ts/contentScripts/estimates/index.ts | 54 ++++++++++++++++++++++++ src/ts/contentScripts/features.tsx | 2 + 2 files changed, 56 insertions(+) create mode 100644 src/ts/contentScripts/estimates/index.ts diff --git a/src/ts/contentScripts/estimates/index.ts b/src/ts/contentScripts/estimates/index.ts new file mode 100644 index 00000000..e57342a7 --- /dev/null +++ b/src/ts/contentScripts/estimates/index.ts @@ -0,0 +1,54 @@ +import {Roam, RoamNode} from '../../utils/roam'; +import {Feature, getSetting, Textarea} from '../../utils/settings'; +import {getActiveEditElement} from '../../utils/dom'; + + +// TODO: Input instead of textarea +const estimateProperty: Textarea = {type: 'textarea', id: 'estimate_property', label: 'Property to base estimates on'}; + +export const config: Feature = { + id: 'calculate-estimate', + name: 'Calculate estimate', + shortcuts: [ + { + id: 'calculate-estimate', label: 'Calculate estimate shortcut', initValue: 'ctl+m', placeholder: '', + onPress: calculateFirstSiblingTotal + } + ], + settings: [ + estimateProperty, + ] +}; + +function getParentElement() { + return getActiveEditElement()?.closest('.roam-block-container')?.parentElement; +} + +/** I'm still figuring out UX on this one. + * The current expectation is that you have to create a parent node, put a query as a child of it, + * then run this with cursor ina query sibling. + * Maybe I should create sibling? then you can do it from query node, which seems somewhat more intuitive + * but when your cursor is in the query node it's not rendered, which may be confusing + * + * or maybe flow - you select query node, then press shortcut, get estimate for it in new node below + * + */ +export async function calculateFirstSiblingTotal() { + const attributeName = await getSetting(config.id, estimateProperty.id) || 'pomodoro_estimate'; + const estimateRegex = new RegExp(`${attributeName}:\\s*(\\d+\\.?\\d*)`, 'g'); + + const queryNode = getParentElement()?.querySelector('.rm-reference-main') as HTMLElement; + const queryText = queryNode?.innerText; + console.log('Extracting estimate from ' + queryText); + + let total = 0; + + const nextMatch = () => estimateRegex.exec(queryText); + let match = nextMatch(); + while (match) { + total += parseFloat(match[1]); + match = nextMatch(); + } + + Roam.applyToCurrent(node => new RoamNode(`total_${attributeName}::${total}` + node.text, node.selection)) +} \ No newline at end of file diff --git a/src/ts/contentScripts/features.tsx b/src/ts/contentScripts/features.tsx index 2eb2d1f8..be76e307 100644 --- a/src/ts/contentScripts/features.tsx +++ b/src/ts/contentScripts/features.tsx @@ -4,6 +4,7 @@ import {config as incDec} from './inc-dec-value/index' import {config as customCss} from './custom-css/index' import {config as srs} from './srs/index' import {config as blockManipulation} from './block-manipulation' +import {config as estimate} from './estimates/index' import {filterAsync, mapAsync} from '../utils/async'; export const Features = { @@ -12,6 +13,7 @@ export const Features = { customCss, srs, blockManipulation, + estimate, ]), isActive: Settings.isActive, From 8ef7e58c724888ae3e2d460f30b1f255ff6ff6b2 Mon Sep 17 00:00:00 2001 From: Vladyslav Sitalo Date: Sun, 8 Mar 2020 20:04:55 -0700 Subject: [PATCH 2/2] Migrate Estimate to using new interface for settings --- src/ts/contentScripts/estimates/index.ts | 22 +++++++++++----------- src/ts/utils/settings.ts | 3 ++- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/ts/contentScripts/estimates/index.ts b/src/ts/contentScripts/estimates/index.ts index e57342a7..4e989b95 100644 --- a/src/ts/contentScripts/estimates/index.ts +++ b/src/ts/contentScripts/estimates/index.ts @@ -1,23 +1,23 @@ import {Roam, RoamNode} from '../../utils/roam'; -import {Feature, getSetting, Textarea} from '../../utils/settings'; +import {Feature, Settings, Shortcut, String} from '../../utils/settings'; import {getActiveEditElement} from '../../utils/dom'; - -// TODO: Input instead of textarea -const estimateProperty: Textarea = {type: 'textarea', id: 'estimate_property', label: 'Property to base estimates on'}; +const estimateProperty: String = {type: 'string', id: 'estimate_property', label: 'Property to base estimates on'}; export const config: Feature = { id: 'calculate-estimate', name: 'Calculate estimate', - shortcuts: [ + settings: [ { - id: 'calculate-estimate', label: 'Calculate estimate shortcut', initValue: 'ctl+m', placeholder: '', + type: 'shortcut', + id: 'calculate-estimate', + label: 'Calculate estimate shortcut', + initValue: 'ctrl+m', + placeholder: '', onPress: calculateFirstSiblingTotal - } - ], - settings: [ + } as Shortcut, estimateProperty, - ] + ], }; function getParentElement() { @@ -34,7 +34,7 @@ function getParentElement() { * */ export async function calculateFirstSiblingTotal() { - const attributeName = await getSetting(config.id, estimateProperty.id) || 'pomodoro_estimate'; + const attributeName = await Settings.get(config.id, estimateProperty.id, 'pomodoro_estimate'); const estimateRegex = new RegExp(`${attributeName}:\\s*(\\d+\\.?\\d*)`, 'g'); const queryNode = getParentElement()?.querySelector('.rm-reference-main') as HTMLElement; diff --git a/src/ts/utils/settings.ts b/src/ts/utils/settings.ts index 9e4da361..36e551d5 100644 --- a/src/ts/utils/settings.ts +++ b/src/ts/utils/settings.ts @@ -39,7 +39,8 @@ export interface Shortcut extends Setting { export const Settings = { - get: async (featureId: string, settingId: string) => (await getStateFromStorage())[featureId][settingId], + get: async (featureId: string, settingId: string, defaultValue?: string) => + (await getStateFromStorage())[featureId][settingId] || defaultValue, isActive: async (featureId: string) => (await getStateFromStorage())[featureId]?.active }