mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-18 00:46:45 +00:00
Merge pull request #5459 from Mustache-Games/conflicts-resolved
feat(plugins): add simple counter API methods for plugins
This commit is contained in:
commit
2706c73db2
2 changed files with 344 additions and 133 deletions
|
|
@ -260,7 +260,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
return this._boundMethods.loadPersistedData();
|
||||
}
|
||||
|
||||
async getConfig<T>(): Promise<T> {
|
||||
async getConfig(): Promise<any> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested configuration`);
|
||||
return this._boundMethods.getConfig();
|
||||
}
|
||||
|
|
@ -324,7 +324,27 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set a simple counter value for today
|
||||
* Gets all simple counters as { [key: string]: number }.
|
||||
*/
|
||||
async getAllCounters(): Promise<{ [key: string]: number }> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested all simple counters`);
|
||||
return this._pluginBridge.getAllCounters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single simple counter value (undefined if unset).
|
||||
* @param id The counter id (e.g., 'daily-commits').
|
||||
*/
|
||||
async getCounter(id: string): Promise<number | null> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested counter value for id: ${id}`);
|
||||
const value = await this._pluginBridge.getCounter(id);
|
||||
return value ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a simple counter value.
|
||||
* @param id The counter id.
|
||||
* @param value The numeric value.
|
||||
*/
|
||||
async setCounter(id: string, value: number): Promise<void> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to set counter ${id} to ${value}`);
|
||||
|
|
@ -332,47 +352,123 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a simple counter value for today
|
||||
* Increments a simple counter (default +1).
|
||||
* @param id The counter id.
|
||||
* @param incrementBy Increment amount (default: 1).
|
||||
*/
|
||||
async getCounter(id: string): Promise<number | null> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to get counter ${id}`);
|
||||
return this._pluginBridge.getCounter(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment a simple counter value for today
|
||||
*/
|
||||
async incrementCounter(id: string, incrementBy: number = 1): Promise<number> {
|
||||
async incrementCounter(id: string, incrementBy = 1): Promise<number> {
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} requested to increment counter ${id} by ${incrementBy}`,
|
||||
);
|
||||
return this._pluginBridge.incrementCounter(id, incrementBy);
|
||||
const newValue = await this._pluginBridge.incrementCounter(id, incrementBy);
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement a simple counter value for today
|
||||
* Decrements a simple counter (floors at 0, default -1).
|
||||
* @param id The counter id.
|
||||
* @param decrementBy Decrement amount (default: 1).
|
||||
*/
|
||||
async decrementCounter(id: string, decrementBy: number = 1): Promise<number> {
|
||||
async decrementCounter(id: string, decrementBy = 1): Promise<number> {
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} requested to decrement counter ${id} by ${decrementBy}`,
|
||||
);
|
||||
return this._pluginBridge.decrementCounter(id, decrementBy);
|
||||
const newValue = await this._pluginBridge.decrementCounter(id, decrementBy);
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a simple counter
|
||||
* Deletes a simple counter.
|
||||
* @param id The counter ID.
|
||||
*/
|
||||
async deleteCounter(id: string): Promise<void> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to delete counter ${id}`);
|
||||
return this._pluginBridge.deleteCounter(id);
|
||||
return this._pluginBridge.deleteSimpleCounter(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all simple counters with their values for today
|
||||
* Gets all simple counters as SimpleCounter[].
|
||||
*/
|
||||
async getAllCounters(): Promise<{ [id: string]: number }> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to get all counters`);
|
||||
return this._pluginBridge.getAllCounters();
|
||||
async getAllSimpleCounters(): Promise<any[]> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested all simple counters (full model)`);
|
||||
return this._pluginBridge.getAllSimpleCounters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single simple counter by ID.
|
||||
* @param id The counter ID.
|
||||
*/
|
||||
async getSimpleCounter(id: string): Promise<any | undefined> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested simple counter ${id}`);
|
||||
return this._pluginBridge.getSimpleCounter(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a simple counter (partial).
|
||||
* @param id The counter ID.
|
||||
* @param updates Partial updates.
|
||||
*/
|
||||
async updateSimpleCounter(id: string, updates: Partial<any>): Promise<void> {
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} requested to update simple counter ${id}`,
|
||||
updates,
|
||||
);
|
||||
return this._pluginBridge.updateSimpleCounter(id, updates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles a simple counter's isOn state.
|
||||
* @param id The counter ID.
|
||||
*/
|
||||
async toggleSimpleCounter(id: string): Promise<void> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to toggle simple counter ${id}`);
|
||||
return this._pluginBridge.toggleSimpleCounter(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a simple counter's isEnabled state.
|
||||
* @param id The counter ID.
|
||||
* @param isEnabled Enabled state.
|
||||
*/
|
||||
async setSimpleCounterEnabled(id: string, isEnabled: boolean): Promise<void> {
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} requested to set simple counter ${id} enabled: ${isEnabled}`,
|
||||
);
|
||||
return this._pluginBridge.setSimpleCounterEnabled(id, isEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a simple counter.
|
||||
* @param id The counter ID.
|
||||
*/
|
||||
async deleteSimpleCounter(id: string): Promise<void> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to delete simple counter ${id}`);
|
||||
return this._pluginBridge.deleteSimpleCounter(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a simple counter value for today.
|
||||
* @param id The counter ID.
|
||||
* @param value The numeric value.
|
||||
*/
|
||||
async setSimpleCounterToday(id: string, value: number): Promise<void> {
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} requested to set simple counter ${id} today to ${value}`,
|
||||
);
|
||||
return this._pluginBridge.setSimpleCounterToday(id, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a simple counter value for a specific date.
|
||||
* @param id The counter ID.
|
||||
* @param date The date (`YYYY-MM-DD`).
|
||||
* @param value The numeric value.
|
||||
*/
|
||||
async setSimpleCounterDate(id: string, date: string, value: number): Promise<void> {
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} requested to set simple counter ${id} on ${date} to ${value}`,
|
||||
);
|
||||
return this._pluginBridge.setSimpleCounterDate(id, date, value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import { WorkContextService } from '../features/work-context/work-context.servic
|
|||
import { ProjectService } from '../features/project/project.service';
|
||||
import { TagService } from '../features/tag/tag.service';
|
||||
import typia from 'typia';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { first, take, map } from 'rxjs/operators';
|
||||
import { selectTaskByIdWithSubTaskData } from '../features/tasks/store/task.selectors';
|
||||
import { PluginUserPersistenceService } from './plugin-user-persistence.service';
|
||||
import { PluginConfigService } from './plugin-config.service';
|
||||
|
|
@ -50,7 +50,16 @@ import { Log, PluginLog } from '../core/log';
|
|||
import { TaskCopy } from '../features/tasks/task.model';
|
||||
import { ProjectCopy } from '../features/project/project.model';
|
||||
import { TagCopy } from '../features/tag/tag.model';
|
||||
import { SimpleCounterService } from '../features/simple-counter/simple-counter.service';
|
||||
|
||||
// New imports for simple counters
|
||||
import { selectAllSimpleCounters } from '../features/simple-counter/store/simple-counter.reducer';
|
||||
import { SimpleCounter } from '../features/simple-counter/simple-counter.model';
|
||||
import {
|
||||
upsertSimpleCounter,
|
||||
updateSimpleCounter,
|
||||
deleteSimpleCounter,
|
||||
toggleSimpleCounterCounter,
|
||||
} from '../features/simple-counter/store/simple-counter.actions';
|
||||
|
||||
/**
|
||||
* PluginBridge acts as an intermediary layer between plugins and the main application services.
|
||||
|
|
@ -80,7 +89,6 @@ export class PluginBridgeService implements OnDestroy {
|
|||
private _injector = inject(Injector);
|
||||
private _translateService = inject(TranslateService);
|
||||
private _syncWrapperService = inject(SyncWrapperService);
|
||||
private _simpleCounterService = inject(SimpleCounterService);
|
||||
|
||||
// Track header buttons registered by plugins
|
||||
private readonly _headerButtons = signal<PluginHeaderBtnCfg[]>([]);
|
||||
|
|
@ -112,7 +120,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
): {
|
||||
persistDataSynced: (dataStr: string) => Promise<void>;
|
||||
loadPersistedData: () => Promise<string | null>;
|
||||
getConfig: <T>() => Promise<T>;
|
||||
getConfig: () => Promise<any>;
|
||||
registerHeaderButton: (cfg: PluginHeaderBtnCfg) => void;
|
||||
registerMenuEntry: (cfg: Omit<PluginMenuEntryCfg, 'pluginId'>) => void;
|
||||
registerSidePanelButton: (cfg: Omit<PluginSidePanelBtnCfg, 'pluginId'>) => void;
|
||||
|
|
@ -123,6 +131,19 @@ export class PluginBridgeService implements OnDestroy {
|
|||
executeNodeScript: (
|
||||
request: PluginNodeScriptRequest,
|
||||
) => Promise<PluginNodeScriptResult>;
|
||||
getAllCounters: () => Promise<{ [key: string]: number }>;
|
||||
getCounter: (id: string) => Promise<number | null>;
|
||||
setCounter: (id: string, value: number) => Promise<void>;
|
||||
incrementCounter: (id: string, incrementBy?: number) => Promise<number>;
|
||||
decrementCounter: (id: string, decrementBy?: number) => Promise<number>;
|
||||
getAllSimpleCounters: () => Promise<SimpleCounter[]>;
|
||||
getSimpleCounter: (id: string) => Promise<SimpleCounter | undefined>;
|
||||
updateSimpleCounter: (id: string, updates: Partial<SimpleCounter>) => Promise<void>;
|
||||
toggleSimpleCounter: (id: string) => Promise<void>;
|
||||
setSimpleCounterEnabled: (id: string, isEnabled: boolean) => Promise<void>;
|
||||
deleteSimpleCounter: (id: string) => Promise<void>;
|
||||
setSimpleCounterToday: (id: string, value: number) => Promise<void>;
|
||||
setSimpleCounterDate: (id: string, date: string, value: number) => Promise<void>;
|
||||
log: ReturnType<typeof Log.withContext>;
|
||||
} {
|
||||
return {
|
||||
|
|
@ -154,6 +175,29 @@ export class PluginBridgeService implements OnDestroy {
|
|||
executeNodeScript: (request: PluginNodeScriptRequest) =>
|
||||
this._executeNodeScript(pluginId, manifest || null, request),
|
||||
|
||||
// Basic counter methods (existing)
|
||||
getAllCounters: () => this.getAllCounters(),
|
||||
getCounter: (id: string) => this.getCounter(id),
|
||||
setCounter: (id: string, value: number) => this.setCounter(id, value),
|
||||
incrementCounter: (id: string, incrementBy = 1) =>
|
||||
this.incrementCounter(id, incrementBy),
|
||||
decrementCounter: (id: string, decrementBy = 1) =>
|
||||
this.decrementCounter(id, decrementBy),
|
||||
|
||||
// Full SimpleCounter methods (new)
|
||||
getAllSimpleCounters: () => this.getAllSimpleCounters(),
|
||||
getSimpleCounter: (id: string) => this.getSimpleCounter(id),
|
||||
updateSimpleCounter: (id: string, updates: Partial<SimpleCounter>) =>
|
||||
this.updateSimpleCounter(id, updates),
|
||||
toggleSimpleCounter: (id: string) => this.toggleSimpleCounter(id),
|
||||
setSimpleCounterEnabled: (id: string, isEnabled: boolean) =>
|
||||
this.setSimpleCounterEnabled(id, isEnabled),
|
||||
deleteSimpleCounter: (id: string) => this.deleteSimpleCounter(id),
|
||||
setSimpleCounterToday: (id: string, value: number) =>
|
||||
this.setSimpleCounterToday(id, value),
|
||||
setSimpleCounterDate: (id: string, date: string, value: number) =>
|
||||
this.setSimpleCounterDate(id, date, value),
|
||||
|
||||
// Logging
|
||||
log: Log.withContext(`${pluginId}`),
|
||||
};
|
||||
|
|
@ -448,113 +492,6 @@ export class PluginBridgeService implements OnDestroy {
|
|||
PluginLog.log('PluginBridge: Tag updated successfully', { tagId, updates });
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a simple counter value for today
|
||||
*/
|
||||
async setCounter(id: string, value: number): Promise<void> {
|
||||
typia.assert<string>(id);
|
||||
typia.assert<number>(value);
|
||||
|
||||
this._simpleCounterService.setCounterToday(id, value);
|
||||
PluginLog.log('PluginBridge: Counter set successfully', { id, value });
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a simple counter value for today
|
||||
*/
|
||||
async getCounter(id: string): Promise<number | null> {
|
||||
typia.assert<string>(id);
|
||||
|
||||
const counter = await this._simpleCounterService.simpleCounters$
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
const simpleCounter = counter?.find((c) => c.id === id);
|
||||
|
||||
if (!simpleCounter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const dateService = this._injector.get(
|
||||
await import('../core/date/date.service').then((m) => m.DateService),
|
||||
);
|
||||
const today = dateService.todayStr();
|
||||
return simpleCounter.countOnDay[today] || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment a simple counter value for today
|
||||
*/
|
||||
async incrementCounter(id: string, incrementBy: number = 1): Promise<number> {
|
||||
typia.assert<string>(id);
|
||||
typia.assert<number>(incrementBy);
|
||||
|
||||
this._simpleCounterService.increaseCounterToday(id, incrementBy);
|
||||
|
||||
// Get the new value
|
||||
const newValue = await this.getCounter(id);
|
||||
PluginLog.log('PluginBridge: Counter incremented successfully', {
|
||||
id,
|
||||
incrementBy,
|
||||
newValue,
|
||||
});
|
||||
return newValue ?? incrementBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement a simple counter value for today
|
||||
*/
|
||||
async decrementCounter(id: string, decrementBy: number = 1): Promise<number> {
|
||||
typia.assert<string>(id);
|
||||
typia.assert<number>(decrementBy);
|
||||
|
||||
this._simpleCounterService.decreaseCounterToday(id, decrementBy);
|
||||
|
||||
// Get the new value
|
||||
const newValue = await this.getCounter(id);
|
||||
PluginLog.log('PluginBridge: Counter decremented successfully', {
|
||||
id,
|
||||
decrementBy,
|
||||
newValue,
|
||||
});
|
||||
return newValue ?? -decrementBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a simple counter
|
||||
*/
|
||||
async deleteCounter(id: string): Promise<void> {
|
||||
typia.assert<string>(id);
|
||||
|
||||
this._simpleCounterService.deleteSimpleCounter(id);
|
||||
PluginLog.log('PluginBridge: Counter deleted successfully', { id });
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all simple counters with their values for today
|
||||
*/
|
||||
async getAllCounters(): Promise<{ [id: string]: number }> {
|
||||
const counters = await this._simpleCounterService.simpleCounters$
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
if (!counters) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const dateService = this._injector.get(
|
||||
await import('../core/date/date.service').then((m) => m.DateService),
|
||||
);
|
||||
const today = dateService.todayStr();
|
||||
|
||||
const result: { [id: string]: number } = {};
|
||||
counters.forEach((counter) => {
|
||||
result[counter.id] = counter.countOnDay[today] || 0;
|
||||
});
|
||||
|
||||
PluginLog.log('PluginBridge: Retrieved all counters', result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder tasks in a project or parent task
|
||||
* @param taskIds - Array of task IDs in the new order
|
||||
|
|
@ -1211,6 +1148,184 @@ export class PluginBridgeService implements OnDestroy {
|
|||
handler(this._isWindowFocused);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all simple counters as { [key: string]: number }.
|
||||
*/
|
||||
async getAllCounters(): Promise<{ [key: string]: number }> {
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
const countersArray = await this._store
|
||||
.select(selectAllSimpleCounters)
|
||||
.pipe(
|
||||
take(1),
|
||||
map((counters: SimpleCounter[]) =>
|
||||
counters.reduce(
|
||||
(acc, c) => ({ ...acc, [c.id]: c.countOnDay?.[today] ?? 0 }),
|
||||
{} as { [key: string]: number },
|
||||
),
|
||||
),
|
||||
)
|
||||
.toPromise();
|
||||
return countersArray || {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single simple counter value (undefined if unset).
|
||||
* @param key The counter key (e.g., 'daily-commits').
|
||||
*/
|
||||
async getCounter(id: string): Promise<number | null> {
|
||||
typia.assert<string>(id);
|
||||
// Allow uppercase, lowercase, numbers, hyphens, underscores
|
||||
if (!/^[A-Za-z0-9_-]+$/.test(id)) {
|
||||
throw new Error('Invalid counter key: must be alphanumeric with hyphens');
|
||||
}
|
||||
const counters = await this.getAllCounters();
|
||||
return counters[id] ?? null;
|
||||
}
|
||||
|
||||
async setCounter(id: string, value: number): Promise<void> {
|
||||
typia.assert<string>(id);
|
||||
typia.assert<number>(value);
|
||||
// Allow uppercase, lowercase, numbers, hyphens, underscores
|
||||
if (!/^[A-Za-z0-9_-]+$/.test(id)) {
|
||||
throw new Error('Invalid counter key: must be alphanumeric with hyphens');
|
||||
}
|
||||
if (typeof value !== 'number' || !isFinite(value) || value < 0) {
|
||||
throw new Error('Invalid counter value: must be a non-negative number');
|
||||
}
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
// Upsert the counter (creates if not exists)
|
||||
this._store.dispatch(
|
||||
upsertSimpleCounter({
|
||||
simpleCounter: {
|
||||
id: id,
|
||||
//title: id,
|
||||
//isEnabled: true,
|
||||
//icon: null,
|
||||
//type: 'ClickCounter',
|
||||
countOnDay: { [today]: value },
|
||||
//isOn: false,
|
||||
} as SimpleCounter,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async incrementCounter(id: string, incrementBy = 1): Promise<number> {
|
||||
typia.assert<string>(id);
|
||||
typia.assert<number>(incrementBy);
|
||||
if (typeof incrementBy !== 'number' || !isFinite(incrementBy) || incrementBy <= 0) {
|
||||
throw new Error('Invalid increment amount: must be a positive number');
|
||||
}
|
||||
const current = (await this.getCounter(id)) ?? 0;
|
||||
const newValue = current + incrementBy;
|
||||
await this.setCounter(id, newValue);
|
||||
return newValue;
|
||||
}
|
||||
|
||||
async decrementCounter(id: string, decrementBy = 1): Promise<number> {
|
||||
typia.assert<string>(id);
|
||||
typia.assert<number>(decrementBy);
|
||||
if (typeof decrementBy !== 'number' || !isFinite(decrementBy) || decrementBy <= 0) {
|
||||
throw new Error('Invalid decrement amount: must be a positive number');
|
||||
}
|
||||
const current = (await this.getCounter(id)) ?? 0;
|
||||
const newValue = Math.max(0, current - decrementBy);
|
||||
await this.setCounter(id, Math.max(0, newValue));
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all simple counters as SimpleCounter[].
|
||||
*/
|
||||
async getAllSimpleCounters(): Promise<SimpleCounter[]> {
|
||||
return this._store.select(selectAllSimpleCounters).pipe(take(1)).toPromise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single simple counter by ID.
|
||||
* @param id The counter ID.
|
||||
*/
|
||||
async getSimpleCounter(id: string): Promise<SimpleCounter | undefined> {
|
||||
const all = await this.getAllSimpleCounters();
|
||||
return all.find((c) => c.id === id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a simple counter (partial).
|
||||
* @param id The counter ID.
|
||||
* @param updates Partial updates.
|
||||
*/
|
||||
async updateSimpleCounter(id: string, updates: Partial<SimpleCounter>): Promise<void> {
|
||||
this._store.dispatch(
|
||||
updateSimpleCounter({
|
||||
simpleCounter: { id, changes: updates },
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles a simple counter's isOn state.
|
||||
* @param id The counter ID.
|
||||
*/
|
||||
async toggleSimpleCounter(id: string): Promise<void> {
|
||||
const counter = await this.getSimpleCounter(id);
|
||||
if (!counter) {
|
||||
throw new Error(`Counter ${id} not found`);
|
||||
}
|
||||
this._store.dispatch(toggleSimpleCounterCounter({ id }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a simple counter's isEnabled state.
|
||||
* @param id The counter ID.
|
||||
* @param isEnabled Enabled state.
|
||||
*/
|
||||
async setSimpleCounterEnabled(id: string, isEnabled: boolean): Promise<void> {
|
||||
return this.updateSimpleCounter(id, { isEnabled });
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a simple counter.
|
||||
* @param id The counter ID.
|
||||
*/
|
||||
async deleteSimpleCounter(id: string): Promise<void> {
|
||||
this._store.dispatch(deleteSimpleCounter({ id }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a simple counter value for today.
|
||||
* @param id The counter ID.
|
||||
* @param value The numeric value.
|
||||
*/
|
||||
async setSimpleCounterToday(id: string, value: number): Promise<void> {
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
return this.setSimpleCounterDate(id, today, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a simple counter value for a specific date.
|
||||
* @param id The counter ID.
|
||||
* @param date The date (`YYYY-MM-DD`).
|
||||
* @param value The numeric value.
|
||||
*/
|
||||
async setSimpleCounterDate(id: string, date: string, value: number): Promise<void> {
|
||||
if (!date.match(/^\d{4}-\d{2}-\d{2}$/)) {
|
||||
throw new Error('Invalid date format: use YYYY-MM-DD');
|
||||
}
|
||||
const dateObj = new Date(date);
|
||||
if (isNaN(dateObj.getTime())) {
|
||||
throw new Error('Invalid date: must be valid YYYY-MM-DD');
|
||||
}
|
||||
const counter = await this.getSimpleCounter(id);
|
||||
if (!counter) {
|
||||
throw new Error(`Counter ${id} not found`);
|
||||
}
|
||||
if (typeof value !== 'number' || !isFinite(value) || value < 0) {
|
||||
throw new Error('Invalid counter value: must be a non-negative number');
|
||||
}
|
||||
const newCountOnDay = { ...counter.countOnDay, [date]: value };
|
||||
return this.updateSimpleCounter(id, { countOnDay: newCountOnDay });
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up all resources when service is destroyed
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue