mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-18 08:56:41 +00:00
fix(security): redact user-entered content from exportable logs
Replace task titles, project names, tag names, profile names, note content, and other user-entered data in log calls with internal IDs and structural metadata (counts, lengths, types). This prevents sensitive information from leaking into exported logs when users share them for bug reports. Addresses GHSA-jpwx-59x4-rprg.
This commit is contained in:
parent
4e41c567c0
commit
5772b3416c
22 changed files with 77 additions and 82 deletions
|
|
@ -92,7 +92,7 @@ export class CapacitorReminderService {
|
|||
|
||||
Log.log('📱 CapacitorReminderService.scheduleReminder called', {
|
||||
notificationId: options.notificationId,
|
||||
title: options.title.substring(0, 30),
|
||||
reminderId: options.reminderId,
|
||||
triggerAt: new Date(triggerAt).toISOString(),
|
||||
triggerInMs: triggerAt - now,
|
||||
triggerInMinutes: Math.round((triggerAt - now) / 1000 / 60),
|
||||
|
|
@ -126,7 +126,7 @@ export class CapacitorReminderService {
|
|||
|
||||
Log.log('✅ CapacitorReminderService: Android reminder scheduled successfully', {
|
||||
notificationId: options.notificationId,
|
||||
title: options.title,
|
||||
reminderId: options.reminderId,
|
||||
triggerAt: new Date(triggerAt).toISOString(),
|
||||
});
|
||||
return true;
|
||||
|
|
@ -181,7 +181,7 @@ export class CapacitorReminderService {
|
|||
|
||||
Log.log('CapacitorReminderService: iOS reminder scheduled', {
|
||||
notificationId: options.notificationId,
|
||||
title: options.title,
|
||||
reminderId: options.reminderId,
|
||||
triggerAt: new Date(triggerAt).toISOString(),
|
||||
});
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ if (IS_ANDROID_WEB_VIEW) {
|
|||
const pendingShare = androidInterface.getPendingShareData?.();
|
||||
if (pendingShare) {
|
||||
const parsed = JSON.parse(pendingShare);
|
||||
DroidLog.log('Pulled pending share data from SharedPreferences', parsed);
|
||||
DroidLog.log('Pulled pending share data from SharedPreferences');
|
||||
androidInterface.onShareWithAttachment$.next(parsed);
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,6 @@ export class AndroidForegroundTrackingEffects {
|
|||
if (currentTask) {
|
||||
DroidLog.log('Starting tracking service', {
|
||||
taskId: currentTask.id,
|
||||
title: currentTask.title,
|
||||
timeSpent: currentTask.timeSpent,
|
||||
});
|
||||
this._safeNativeCall(
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ export class AndroidEffects {
|
|||
const pendingShare = androidInterface.getPendingShareData?.();
|
||||
if (pendingShare) {
|
||||
const parsed = JSON.parse(pendingShare);
|
||||
DroidLog.log('Resume: found pending share data', parsed);
|
||||
DroidLog.log('Resume: found pending share data');
|
||||
androidInterface.onShareWithAttachment$.next(parsed);
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ export class IssuePanelCalendarAgendaComponent implements OnInit {
|
|||
throw new Error('Issue Provider and Search Result Type dont match');
|
||||
}
|
||||
|
||||
Log.log('Add issue', item);
|
||||
Log.log('Add issue', { issueType: item.issueType });
|
||||
|
||||
this._issueService.addTaskFromIssue({
|
||||
issueDataReduced: item.issueData,
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ export class IssueProviderTabComponent implements OnDestroy, AfterViewInit {
|
|||
throw new Error('Issue Provider and Search Result Type dont match');
|
||||
}
|
||||
|
||||
Log.log('Add issue', item);
|
||||
Log.log('Add issue', { issueType: item.issueType });
|
||||
|
||||
this._issueService.addTaskFromIssue({
|
||||
issueDataReduced: item.issueData,
|
||||
|
|
|
|||
|
|
@ -514,7 +514,10 @@ export class IssueService {
|
|||
related_to,
|
||||
...additionalFromProviderIssueService
|
||||
} = this._getAddTaskData(issueProviderKey, issueDataReduced);
|
||||
IssueLog.log({ title, related_to, additionalFromProviderIssueService });
|
||||
IssueLog.log({
|
||||
related_to,
|
||||
additionalKeys: Object.keys(additionalFromProviderIssueService),
|
||||
});
|
||||
|
||||
const getTaskDefaults = async (): Promise<Partial<TaskCopy>> => {
|
||||
const providerCfg = await this._issueProviderService
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ export class CaldavClientService {
|
|||
const todo = comp.getFirstSubcomponent('vtodo');
|
||||
|
||||
if (!todo) {
|
||||
IssueLog.log(task);
|
||||
IssueLog.log('No todo found for CalDAV task');
|
||||
throw new Error('No todo found for task');
|
||||
}
|
||||
|
||||
|
|
@ -410,7 +410,7 @@ export class CaldavClientService {
|
|||
const todo = comp.getFirstSubcomponent('vtodo');
|
||||
|
||||
if (!todo) {
|
||||
IssueLog.err('No todo found for task', task);
|
||||
IssueLog.err('No todo found for CalDAV task');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -130,9 +130,9 @@ export class ReminderCountdownEffects {
|
|||
|
||||
const nrOfAllBanners = dueTasks.length;
|
||||
Log.log({
|
||||
firstDueTask,
|
||||
firstDue,
|
||||
dueTasks,
|
||||
firstDueTaskId: firstDueTask?.id,
|
||||
firstDueRemindAt: firstDue.remindAt,
|
||||
dueTaskCount: dueTasks.length,
|
||||
});
|
||||
|
||||
this._bannerService.open({
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ export class AddTaskBarIssueSearchService {
|
|||
return item.taskId;
|
||||
} else if (item.taskId) {
|
||||
if (!item.projectId) {
|
||||
TaskLog.log(item);
|
||||
TaskLog.log('Weird add task case1', { taskId: item.taskId });
|
||||
throw new Error('Weird add task case1');
|
||||
}
|
||||
this._projectService.moveTaskToTodayList(item.taskId, item.projectId);
|
||||
|
|
|
|||
|
|
@ -200,14 +200,10 @@ export class TaskListComponent implements OnDestroy, AfterViewInit {
|
|||
const srcListData = ev.previousContainer.data;
|
||||
const targetListData = ev.container.data;
|
||||
const draggedTask = ev.item.data;
|
||||
TaskLog.log({
|
||||
ev,
|
||||
srcListData,
|
||||
targetListData,
|
||||
draggedTask,
|
||||
TaskLog.log('drop', {
|
||||
listId: this.listId(),
|
||||
listModelId: this.listModelId(),
|
||||
filteredTasks: this.filteredTasks(),
|
||||
taskCount: this.filteredTasks()?.length,
|
||||
});
|
||||
|
||||
if (this._scheduleExternalDragService.isCancelNextDrop()) {
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ export class TaskService {
|
|||
workContextId,
|
||||
});
|
||||
|
||||
TaskLog.log(task, additional);
|
||||
TaskLog.log('addTask', { taskId: task.id, workContextId, workContextType });
|
||||
|
||||
this._store.dispatch(
|
||||
TaskSharedActions.addTask({
|
||||
|
|
@ -750,7 +750,7 @@ export class TaskService {
|
|||
title: additional.title || '',
|
||||
additional: { dueDay: additional.dueDay || undefined, ...additional },
|
||||
});
|
||||
console.log(task);
|
||||
TaskLog.log('addSubTaskTo', { taskId: task.id, parentId });
|
||||
|
||||
this._store.dispatch(
|
||||
addSubTask({
|
||||
|
|
|
|||
|
|
@ -81,9 +81,7 @@ export class UserProfileService {
|
|||
);
|
||||
if (activeProfile) {
|
||||
this.activeProfile.set(activeProfile);
|
||||
Log.log(
|
||||
`UserProfileService: Active profile set to "${activeProfile.name}" (${activeProfile.id})`,
|
||||
);
|
||||
Log.log(`UserProfileService: Active profile set to ${activeProfile.id}`);
|
||||
} else {
|
||||
Log.warn(
|
||||
'UserProfileService: Active profile not found in metadata, using first profile',
|
||||
|
|
@ -143,7 +141,7 @@ export class UserProfileService {
|
|||
this._metadata.set(updatedMetadata);
|
||||
this.profiles.set(updatedProfiles);
|
||||
|
||||
Log.log(`UserProfileService: Created new profile "${name}" (${newProfile.id})`);
|
||||
Log.log(`UserProfileService: Created new profile ${newProfile.id}`);
|
||||
this._snackService.open({
|
||||
type: 'SUCCESS',
|
||||
msg: `Profile "${name}" created successfully`,
|
||||
|
|
@ -196,7 +194,7 @@ export class UserProfileService {
|
|||
}
|
||||
}
|
||||
|
||||
Log.log(`UserProfileService: Renamed profile ${profileId} to "${newName}"`);
|
||||
Log.log(`UserProfileService: Renamed profile ${profileId}`);
|
||||
this._snackService.open({
|
||||
type: 'SUCCESS',
|
||||
msg: `Profile renamed to "${newName}"`,
|
||||
|
|
@ -279,7 +277,7 @@ export class UserProfileService {
|
|||
}
|
||||
|
||||
Log.log(
|
||||
`UserProfileService: Switching from "${currentProfile.name}" to "${targetProfile.name}"`,
|
||||
`UserProfileService: Switching from ${currentProfile.id} to ${targetProfile.id}`,
|
||||
);
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ export class WorklogComponent implements AfterViewInit, OnDestroy {
|
|||
.filter((v) => !!v);
|
||||
}
|
||||
|
||||
Log.log('RESTORE', task, subTasks);
|
||||
Log.log('RESTORE', { taskId: task.id, subTaskCount: subTasks?.length });
|
||||
this._taskService.restoreTask(task, (subTasks || []) as Task[]);
|
||||
this._router.navigate(['/active/tasks']);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ export class LocalBackupService {
|
|||
)
|
||||
) {
|
||||
const backupData = await this.loadBackupElectron(backupMeta.path);
|
||||
Log.log('backupData', backupData);
|
||||
Log.log('backupData loaded from Electron backup');
|
||||
await this._importBackup(backupData);
|
||||
}
|
||||
|
||||
|
|
@ -124,9 +124,9 @@ export class LocalBackupService {
|
|||
)
|
||||
) {
|
||||
const backupData = await this.loadBackupAndroid();
|
||||
Log.log('backupData', backupData);
|
||||
Log.log('backupData loaded from Android, length: ' + backupData.length);
|
||||
const lineBreaksReplaced = backupData.replace(/\n/g, '\\n');
|
||||
Log.log('lineBreaksReplaced', lineBreaksReplaced);
|
||||
Log.log('lineBreaksReplaced, length: ' + lineBreaksReplaced.length);
|
||||
await this._importBackup(lineBreaksReplaced);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,13 +76,16 @@ class AdditionalLogErrorBase<T = unknown[]> extends Error {
|
|||
super(extractedMessage ?? 'Unknown error');
|
||||
|
||||
if (additional.length > 0) {
|
||||
OpLog.log(this.name, ...additional);
|
||||
try {
|
||||
// Sanitize before logging to avoid exposing tokens in logs
|
||||
// Sanitize before logging to avoid exposing tokens and user content in logs
|
||||
const sanitized = additional.map(sanitizeForLogging);
|
||||
OpLog.log('additional error log: ' + JSON.stringify(sanitized));
|
||||
OpLog.log(this.name + ' additional error log: ' + JSON.stringify(sanitized));
|
||||
} catch (e) {
|
||||
OpLog.log('additional error log not stringified: ', additional, e);
|
||||
OpLog.log(
|
||||
this.name +
|
||||
' additional error log not stringifiable: ' +
|
||||
(e instanceof Error ? e.message : 'unknown'),
|
||||
);
|
||||
}
|
||||
}
|
||||
this.additionalLog = additional as T;
|
||||
|
|
|
|||
|
|
@ -978,7 +978,7 @@ const _cleanupNonExistingTasksFromLists = (
|
|||
projectIds.forEach((pid) => {
|
||||
const projectItem = data.project.entities[pid];
|
||||
if (!projectItem) {
|
||||
OpLog.log(data.project);
|
||||
OpLog.log('Missing project entity for id: ' + pid);
|
||||
throw new Error('No project');
|
||||
}
|
||||
const origTaskIdsLen = projectItem.taskIds.length;
|
||||
|
|
@ -999,7 +999,7 @@ const _cleanupNonExistingTasksFromLists = (
|
|||
.map((id) => data.tag.entities[id])
|
||||
.forEach((tagItem) => {
|
||||
if (!tagItem) {
|
||||
OpLog.log(data.tag);
|
||||
OpLog.log('Missing tag entity');
|
||||
throw new Error('No tag');
|
||||
}
|
||||
const origLen = tagItem.taskIds.length;
|
||||
|
|
@ -1019,7 +1019,7 @@ const _cleanupNonExistingNotesFromLists = (
|
|||
projectIds.forEach((pid) => {
|
||||
const projectItem = data.project.entities[pid];
|
||||
if (!projectItem) {
|
||||
OpLog.log(data.project);
|
||||
OpLog.log('Missing project entity for id: ' + pid);
|
||||
throw new Error('No project');
|
||||
}
|
||||
const origLen = (projectItem as ProjectCopy).noteIds?.length ?? 0;
|
||||
|
|
@ -1047,7 +1047,7 @@ const _fixOrphanedNotes = (
|
|||
noteIds.forEach((nId) => {
|
||||
const note = data.note.entities[nId];
|
||||
if (!note) {
|
||||
OpLog.log(data.note);
|
||||
OpLog.log('Missing note entity for id: ' + nId);
|
||||
throw new Error('No note');
|
||||
}
|
||||
// missing project case
|
||||
|
|
@ -1097,7 +1097,7 @@ const _fixInconsistentProjectId = (
|
|||
.map((id) => data.project.entities[id])
|
||||
.forEach((projectItem) => {
|
||||
if (!projectItem) {
|
||||
OpLog.log(data.project);
|
||||
OpLog.log('Missing project entity');
|
||||
throw new Error('No project');
|
||||
}
|
||||
projectItem.taskIds.forEach((tid) => {
|
||||
|
|
@ -1149,7 +1149,7 @@ const _fixInconsistentTagId = (
|
|||
.map((id) => data.tag.entities[id])
|
||||
.forEach((tagItem) => {
|
||||
if (!tagItem) {
|
||||
OpLog.log(data.tag);
|
||||
OpLog.log('Missing tag entity');
|
||||
throw new Error('No tag');
|
||||
}
|
||||
tagItem.taskIds.forEach((tid) => {
|
||||
|
|
@ -1175,7 +1175,7 @@ const _setTaskProjectIdAccordingToParent = (
|
|||
.map((id) => data.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
OpLog.log(data.task);
|
||||
OpLog.log('Missing task entity');
|
||||
throw new Error('No task');
|
||||
}
|
||||
if (taskItem.subTaskIds) {
|
||||
|
|
@ -1198,7 +1198,7 @@ const _setTaskProjectIdAccordingToParent = (
|
|||
.map((id) => data.archiveYoung.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
OpLog.log(data.archiveYoung.task);
|
||||
OpLog.log('Missing archive task entity');
|
||||
throw new Error('No archive task');
|
||||
}
|
||||
if (taskItem.subTaskIds) {
|
||||
|
|
@ -1221,7 +1221,7 @@ const _setTaskProjectIdAccordingToParent = (
|
|||
.map((id) => data.archiveOld.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
OpLog.log(data.archiveOld.task);
|
||||
OpLog.log('Missing old archive task entity');
|
||||
throw new Error('No old archive task');
|
||||
}
|
||||
if (taskItem.subTaskIds) {
|
||||
|
|
@ -1252,7 +1252,7 @@ const _cleanupOrphanedSubTasks = (
|
|||
.map((id) => data.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
OpLog.log(data.task);
|
||||
OpLog.log('Missing task entity');
|
||||
throw new Error('No task');
|
||||
}
|
||||
|
||||
|
|
@ -1261,7 +1261,7 @@ const _cleanupOrphanedSubTasks = (
|
|||
while (i >= 0) {
|
||||
const sid = taskItem.subTaskIds[i];
|
||||
if (!data.task.entities[sid]) {
|
||||
OpLog.log('Delete orphaned sub task for ', taskItem);
|
||||
OpLog.log('Delete orphaned sub task ' + sid + ' for ' + taskItem.id);
|
||||
taskItem.subTaskIds.splice(i, 1);
|
||||
summary.relationshipsFixed++;
|
||||
}
|
||||
|
|
@ -1275,7 +1275,7 @@ const _cleanupOrphanedSubTasks = (
|
|||
.map((id) => data.archiveYoung.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
OpLog.log(data.archiveYoung.task);
|
||||
OpLog.log('Missing archive task entity');
|
||||
throw new Error('No archive task');
|
||||
}
|
||||
|
||||
|
|
@ -1284,7 +1284,7 @@ const _cleanupOrphanedSubTasks = (
|
|||
while (i >= 0) {
|
||||
const sid = taskItem.subTaskIds[i];
|
||||
if (!data.archiveYoung.task.entities[sid]) {
|
||||
OpLog.log('Delete orphaned archive sub task for ', taskItem);
|
||||
OpLog.log('Delete orphaned archive sub task ' + sid + ' for ' + taskItem.id);
|
||||
taskItem.subTaskIds.splice(i, 1);
|
||||
summary.relationshipsFixed++;
|
||||
}
|
||||
|
|
@ -1298,7 +1298,7 @@ const _cleanupOrphanedSubTasks = (
|
|||
.map((id) => data.archiveOld.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
OpLog.log(data.archiveOld.task);
|
||||
OpLog.log('Missing old archive task entity');
|
||||
throw new Error('No old archive task');
|
||||
}
|
||||
|
||||
|
|
@ -1307,7 +1307,9 @@ const _cleanupOrphanedSubTasks = (
|
|||
while (i >= 0) {
|
||||
const sid = taskItem.subTaskIds[i];
|
||||
if (!data.archiveOld.task.entities[sid]) {
|
||||
OpLog.log('Delete orphaned old archive sub task for ', taskItem);
|
||||
OpLog.log(
|
||||
'Delete orphaned old archive sub task ' + sid + ' for ' + taskItem.id,
|
||||
);
|
||||
taskItem.subTaskIds.splice(i, 1);
|
||||
summary.relationshipsFixed++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ export class SearchPageComponent implements OnInit {
|
|||
: tagMap.get(tagId);
|
||||
|
||||
if (!context) {
|
||||
Log.err(`Could not find context for task: ${task.title}`);
|
||||
Log.err(`Could not find context for task: ${task.id}`);
|
||||
context = { ...DEFAULT_TAG, icon: 'help_outline', color: 'black' };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -180,16 +180,13 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
}
|
||||
|
||||
async updateTask(taskId: string, updates: Partial<Task>): Promise<void> {
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} requested to update task ${taskId}:`,
|
||||
updates,
|
||||
);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to update task ${taskId}`);
|
||||
const taskCopyUpdates = taskDataToPartialTaskCopy(updates);
|
||||
return this._pluginBridge.updateTask(taskId, taskCopyUpdates);
|
||||
}
|
||||
|
||||
async addTask(taskData: PluginCreateTaskData): Promise<string> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to add task:`, taskData);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to add task`);
|
||||
return this._pluginBridge.addTask(taskData);
|
||||
}
|
||||
|
||||
|
|
@ -205,16 +202,13 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
}
|
||||
|
||||
async addProject(projectData: Partial<Project>): Promise<string> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to add project:`, projectData);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to add project`);
|
||||
const projectCopyData = projectDataToPartialProjectCopy(projectData);
|
||||
return this._pluginBridge.addProject(projectCopyData);
|
||||
}
|
||||
|
||||
async updateProject(projectId: string, updates: Partial<Project>): Promise<void> {
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} requested to update project ${projectId}:`,
|
||||
updates,
|
||||
);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to update project ${projectId}`);
|
||||
const projectCopyUpdates = projectDataToPartialProjectCopy(updates);
|
||||
return this._pluginBridge.updateProject(projectId, projectCopyUpdates);
|
||||
}
|
||||
|
|
@ -226,13 +220,13 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
}
|
||||
|
||||
async addTag(tagData: Partial<Tag>): Promise<string> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to add tag:`, tagData);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to add tag`);
|
||||
const tagCopyData = tagDataToPartialTagCopy(tagData);
|
||||
return this._pluginBridge.addTag(tagCopyData);
|
||||
}
|
||||
|
||||
async updateTag(tagId: string, updates: Partial<Tag>): Promise<void> {
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to update tag ${tagId}:`, updates);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to update tag ${tagId}`);
|
||||
const tagCopyUpdates = tagDataToPartialTagCopy(updates);
|
||||
return this._pluginBridge.updateTag(tagId, tagCopyUpdates);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -412,7 +412,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((result) => {
|
||||
PluginLog.log('PluginBridge: Dialog closed with result:', result);
|
||||
PluginLog.log('PluginBridge: Dialog closed');
|
||||
resolve();
|
||||
});
|
||||
} catch (error) {
|
||||
|
|
@ -531,7 +531,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
this._taskService.update(taskId, otherUpdates);
|
||||
}
|
||||
|
||||
PluginLog.log('PluginBridge: Task updated successfully', { taskId, updates });
|
||||
PluginLog.log('PluginBridge: Task updated successfully', { taskId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -595,7 +595,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
false, // isAddToBottom
|
||||
);
|
||||
|
||||
PluginLog.log('PluginBridge: Task added successfully', { taskId, taskData });
|
||||
PluginLog.log('PluginBridge: Task added successfully', { taskId });
|
||||
return taskId;
|
||||
}
|
||||
}
|
||||
|
|
@ -646,7 +646,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
async addProject(projectData: Partial<ProjectCopy>): Promise<string> {
|
||||
typia.assert<Partial<ProjectCopy>>(projectData);
|
||||
|
||||
PluginLog.log('PluginBridge: Project add', { projectData });
|
||||
PluginLog.log('PluginBridge: Project add');
|
||||
return this._projectService.add(projectData);
|
||||
}
|
||||
|
||||
|
|
@ -660,7 +660,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
// Update the project using ProjectService (ProjectCopy is compatible with Project)
|
||||
this._projectService.update(projectId, updates);
|
||||
|
||||
PluginLog.log('PluginBridge: Project updated successfully', { projectId, updates });
|
||||
PluginLog.log('PluginBridge: Project updated successfully', { projectId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -679,7 +679,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
// Add the tag using TagService (TagCopy is compatible with Tag)
|
||||
const tagId = this._tagService.addTag(tagData);
|
||||
PluginLog.log('PluginBridge: Tag added successfully', { tagId, tagData });
|
||||
PluginLog.log('PluginBridge: Tag added successfully', { tagId });
|
||||
return tagId;
|
||||
}
|
||||
|
||||
|
|
@ -692,7 +692,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
// Update the tag using TagService (TagCopy is compatible with Tag)
|
||||
this._tagService.updateTag(tagId, updates);
|
||||
PluginLog.log('PluginBridge: Tag updated successfully', { tagId, updates });
|
||||
PluginLog.log('PluginBridge: Tag updated successfully', { tagId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export class MentionDirective implements OnChanges {
|
|||
const itemValue = item[labelKey];
|
||||
|
||||
if (itemValue === undefined || itemValue === null) {
|
||||
Log.warn(`MentionDirective: item missing required property '${labelKey}'`, item);
|
||||
Log.warn(`MentionDirective: item missing required property '${labelKey}'`);
|
||||
return this.activeConfig?.triggerChar || '';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ export const isEntityStateConsistent = <T extends Dictionary<any>>(
|
|||
Object.keys(data.entities).length !== data.ids.length ||
|
||||
!arrayEquals(Object.keys(data.entities).sort(), [...data.ids].sort())
|
||||
) {
|
||||
Log.log(data);
|
||||
Log.log(
|
||||
`Inconsistent entity state "${additionalStr}": ids=${data?.ids?.length}, entities=${data?.entities ? Object.keys(data.entities).length : 0}`,
|
||||
);
|
||||
devError(`Inconsistent entity state "${additionalStr}"`);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -29,10 +31,9 @@ export const fixEntityStateConsistency = <T extends Dictionary<any>>(data: T): T
|
|||
Object.keys(data.entities).length !== data.ids.length ||
|
||||
!arrayEquals(Object.keys(data.entities).sort(), [...data.ids].sort())
|
||||
) {
|
||||
Log.err('FIXING ENTITY STATE', {
|
||||
...data,
|
||||
ids: Object.keys(data.entities),
|
||||
});
|
||||
Log.err(
|
||||
`FIXING ENTITY STATE: ids=${data?.ids?.length}, entities=${Object.keys(data.entities).length}`,
|
||||
);
|
||||
|
||||
return {
|
||||
...data,
|
||||
|
|
@ -52,10 +53,9 @@ export const fixEntityStateConsistencyOrError = <T extends Dictionary<any>>(
|
|||
Object.keys(data.entities).length !== data.ids.length ||
|
||||
!arrayEquals(Object.keys(data.entities).sort(), [...data.ids].sort())
|
||||
) {
|
||||
Log.log({
|
||||
...data,
|
||||
ids: Object.keys(data.entities),
|
||||
});
|
||||
Log.log(
|
||||
`Fixing entity state: ids=${data?.ids?.length}, entities=${Object.keys(data.entities).length}`,
|
||||
);
|
||||
|
||||
return {
|
||||
...data,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue