mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-01-23 02:36:05 +00:00
refactor: replace console.* with Log methods throughout codebase
- Created migration script to replace console.log/info/error/warn/debug with Log methods - Replaced 584 console calls across 89 files: - console.log → Log.log (385 occurrences) - console.info → Log.info (4 occurrences) - console.error → Log.err (107 occurrences) - console.warn → Log.err (87 occurrences) - console.debug → Log.debug (1 occurrence) - Added appropriate import statements for Log - Removed unused Log imports from files with only commented-out usage - Fixed all linting errors All logging now goes through our centralized Log class which: - Records logs to history for export/download - Provides consistent log level filtering - Supports context-aware logging - Trade-off: Line numbers show log.ts instead of actual location
This commit is contained in:
parent
f9902d59e4
commit
97f96f2393
103 changed files with 860 additions and 566 deletions
171
scripts/migrate-console-to-log.ts
Executable file
171
scripts/migrate-console-to-log.ts
Executable file
|
|
@ -0,0 +1,171 @@
|
|||
#!/usr/bin/env ts-node
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as glob from 'glob';
|
||||
|
||||
interface Replacement {
|
||||
pattern: RegExp;
|
||||
replacement: string;
|
||||
logMethod: string;
|
||||
}
|
||||
|
||||
const replacements: Replacement[] = [
|
||||
{ pattern: /console\.log\(/g, replacement: 'Log.log(', logMethod: 'log' },
|
||||
{ pattern: /console\.info\(/g, replacement: 'Log.info(', logMethod: 'info' },
|
||||
{ pattern: /console\.error\(/g, replacement: 'Log.err(', logMethod: 'err' },
|
||||
{ pattern: /console\.warn\(/g, replacement: 'Log.err(', logMethod: 'err' },
|
||||
{ pattern: /console\.debug\(/g, replacement: 'Log.debug(', logMethod: 'debug' },
|
||||
];
|
||||
|
||||
// Files to exclude
|
||||
const excludePatterns = [
|
||||
'**/node_modules/**',
|
||||
'**/dist/**',
|
||||
'**/build/**',
|
||||
'**/*.spec.ts',
|
||||
'**/core/log.ts',
|
||||
'**/scripts/migrate-console-to-log.ts',
|
||||
'**/e2e/**',
|
||||
'**/coverage/**',
|
||||
'**/.angular/**',
|
||||
];
|
||||
|
||||
function calculateImportPath(filePath: string): string {
|
||||
const fileDir = path.dirname(filePath);
|
||||
const logPath = path.join(__dirname, '../src/app/core/log');
|
||||
let relativePath = path.relative(fileDir, logPath).replace(/\\/g, '/');
|
||||
|
||||
// Remove .ts extension if present
|
||||
relativePath = relativePath.replace(/\.ts$/, '');
|
||||
|
||||
// Ensure it starts with ./ or ../
|
||||
if (!relativePath.startsWith('.')) {
|
||||
relativePath = './' + relativePath;
|
||||
}
|
||||
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
function hasLogImport(content: string): boolean {
|
||||
return /import\s+{[^}]*\bLog\b[^}]*}\s+from\s+['"].*\/log['"]/.test(content);
|
||||
}
|
||||
|
||||
function addLogImport(content: string, importPath: string): string {
|
||||
// Find the last import statement
|
||||
const importRegex = /^import\s+.*?;$/gm;
|
||||
const imports = content.match(importRegex);
|
||||
|
||||
if (imports && imports.length > 0) {
|
||||
const lastImport = imports[imports.length - 1];
|
||||
const lastImportIndex = content.lastIndexOf(lastImport);
|
||||
const insertPosition = lastImportIndex + lastImport.length;
|
||||
|
||||
return (
|
||||
content.slice(0, insertPosition) +
|
||||
`\nimport { Log } from '${importPath}';` +
|
||||
content.slice(insertPosition)
|
||||
);
|
||||
} else {
|
||||
// No imports found, add at the beginning
|
||||
return `import { Log } from '${importPath}';\n\n` + content;
|
||||
}
|
||||
}
|
||||
|
||||
function processFile(filePath: string): boolean {
|
||||
try {
|
||||
let content = fs.readFileSync(filePath, 'utf8');
|
||||
const originalContent = content;
|
||||
let hasChanges = false;
|
||||
|
||||
// Check if file uses any console methods
|
||||
const usesConsole = replacements.some((r) => r.pattern.test(content));
|
||||
|
||||
if (!usesConsole) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Apply replacements
|
||||
for (const { pattern, replacement } of replacements) {
|
||||
if (pattern.test(content)) {
|
||||
content = content.replace(pattern, replacement);
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasChanges && !hasLogImport(content)) {
|
||||
const importPath = calculateImportPath(filePath);
|
||||
content = addLogImport(content, importPath);
|
||||
}
|
||||
|
||||
if (content !== originalContent) {
|
||||
fs.writeFileSync(filePath, content, 'utf8');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error(`Error processing ${filePath}:`, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log('Starting console to Log migration...\n');
|
||||
|
||||
// Find all TypeScript files
|
||||
const files = glob.sync('src/**/*.ts', {
|
||||
ignore: excludePatterns,
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
console.log(`Found ${files.length} TypeScript files to check\n`);
|
||||
|
||||
const modifiedFiles: string[] = [];
|
||||
const stats = {
|
||||
total: 0,
|
||||
log: 0,
|
||||
info: 0,
|
||||
error: 0,
|
||||
warn: 0,
|
||||
debug: 0,
|
||||
};
|
||||
|
||||
for (const file of files) {
|
||||
const content = fs.readFileSync(file, 'utf8');
|
||||
|
||||
// Count occurrences before processing
|
||||
stats.log += (content.match(/console\.log\(/g) || []).length;
|
||||
stats.info += (content.match(/console\.info\(/g) || []).length;
|
||||
stats.error += (content.match(/console\.error\(/g) || []).length;
|
||||
stats.warn += (content.match(/console\.warn\(/g) || []).length;
|
||||
stats.debug += (content.match(/console\.debug\(/g) || []).length;
|
||||
|
||||
if (processFile(file)) {
|
||||
modifiedFiles.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
stats.total = stats.log + stats.info + stats.error + stats.warn + stats.debug;
|
||||
|
||||
console.log('Migration complete!\n');
|
||||
console.log('Statistics:');
|
||||
console.log(` Total console calls found: ${stats.total}`);
|
||||
console.log(` - console.log: ${stats.log}`);
|
||||
console.log(` - console.info: ${stats.info}`);
|
||||
console.log(` - console.error: ${stats.error}`);
|
||||
console.log(` - console.warn: ${stats.warn}`);
|
||||
console.log(` - console.debug: ${stats.debug}`);
|
||||
console.log(`\nModified ${modifiedFiles.length} files:`);
|
||||
|
||||
modifiedFiles.forEach((file) => {
|
||||
console.log(` - ${path.relative(process.cwd(), file)}`);
|
||||
});
|
||||
|
||||
if (modifiedFiles.length === 0) {
|
||||
console.log(' No files needed modification.');
|
||||
}
|
||||
}
|
||||
|
||||
// Run the migration
|
||||
main();
|
||||
72
scripts/remove-unused-log-imports.ts
Normal file
72
scripts/remove-unused-log-imports.ts
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env ts-node
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const filesToFix = [
|
||||
'src/app/features/calendar-integration/is-calender-event-due.ts',
|
||||
'src/app/features/schedule/map-schedule-data/create-sorted-blocker-blocks.ts',
|
||||
'src/app/features/schedule/map-schedule-data/create-view-entries-for-day.ts',
|
||||
'src/app/features/tasks/short-syntax.ts',
|
||||
'src/app/features/tasks/task-detail-panel/task-detail-panel.component.ts',
|
||||
'src/app/imex/sync/sync-trigger.service.ts',
|
||||
'src/app/pfapi/api/encryption/encryption.ts',
|
||||
'src/app/ui/stuck/stuck.directive.ts',
|
||||
];
|
||||
|
||||
function removeUnusedLogImport(filePath: string): void {
|
||||
try {
|
||||
const fullPath = path.join(process.cwd(), filePath);
|
||||
let content = fs.readFileSync(fullPath, 'utf8');
|
||||
|
||||
// Check if Log is actually used in the file (excluding import statement and comments)
|
||||
const importRegex = /import\s+{[^}]*\bLog\b[^}]*}\s+from\s+['"][^'"]+['"]/g;
|
||||
let contentWithoutImports = content.replace(importRegex, '');
|
||||
|
||||
// Remove single line comments
|
||||
contentWithoutImports = contentWithoutImports.replace(/\/\/.*$/gm, '');
|
||||
// Remove multi-line comments
|
||||
contentWithoutImports = contentWithoutImports.replace(/\/\*[\s\S]*?\*\//g, '');
|
||||
|
||||
const isLogUsed = /\bLog\./g.test(contentWithoutImports);
|
||||
|
||||
if (!isLogUsed) {
|
||||
// Remove Log from imports
|
||||
content = content.replace(
|
||||
/import\s+{([^}]*)\bLog\b([^}]*)}\s+from\s+(['"][^'"]+['"])/g,
|
||||
(match, before, after, path) => {
|
||||
// Clean up the remaining imports
|
||||
const remainingImports = (before + after)
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s && s !== 'Log')
|
||||
.join(', ');
|
||||
|
||||
if (remainingImports) {
|
||||
return `import { ${remainingImports} } from ${path}`;
|
||||
} else {
|
||||
// If Log was the only import, remove the entire import line
|
||||
return '';
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Clean up any empty lines left by removed imports
|
||||
content = content.replace(/^\s*;\s*$/gm, ''); // Remove standalone semicolons
|
||||
content = content.replace(/\n\n+/g, '\n\n'); // Replace multiple newlines with double newline
|
||||
|
||||
fs.writeFileSync(fullPath, content, 'utf8');
|
||||
console.log(`Fixed: ${filePath}`);
|
||||
} else {
|
||||
console.log(`Skipped (Log is used): ${filePath}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error processing ${filePath}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Removing unused Log imports...\n');
|
||||
|
||||
filesToFix.forEach(removeUnusedLogImport);
|
||||
|
||||
console.log('\nDone!');
|
||||
|
|
@ -70,6 +70,7 @@ import { MarkdownPasteService } from './features/tasks/markdown-paste.service';
|
|||
import { TaskService } from './features/tasks/task.service';
|
||||
import { IpcRendererEvent } from 'electron';
|
||||
import { SyncSafetyBackupService } from './imex/sync/sync-safety-backup.service';
|
||||
import { Log } from './core/log';
|
||||
|
||||
const w = window as any;
|
||||
const productivityTip: string[] = w.productivityTips && w.productivityTips[w.randomIndex];
|
||||
|
|
@ -224,9 +225,9 @@ export class AppComponent implements OnDestroy {
|
|||
// Initialize plugin system
|
||||
try {
|
||||
await this._pluginService.initializePlugins();
|
||||
console.log('Plugin system initialized');
|
||||
Log.log('Plugin system initialized');
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize plugin system:', error);
|
||||
Log.err('Failed to initialize plugin system:', error);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
|
|
@ -248,7 +249,7 @@ export class AppComponent implements OnDestroy {
|
|||
msg: errMsg,
|
||||
type: 'ERROR',
|
||||
});
|
||||
console.error(data);
|
||||
Log.err(data);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -414,7 +415,7 @@ export class AppComponent implements OnDestroy {
|
|||
this.imexMetaService.setDataImportInProgress(true);
|
||||
|
||||
const legacyData = await this._persistenceLegacyService.loadComplete();
|
||||
console.log({ legacyData: legacyData });
|
||||
Log.log({ legacyData: legacyData });
|
||||
|
||||
alert(this._translateService.instant(T.MIGRATE.DETECTED_LEGACY));
|
||||
|
||||
|
|
@ -449,7 +450,7 @@ export class AppComponent implements OnDestroy {
|
|||
} catch (error) {
|
||||
// prevent any interaction with the app on after failure
|
||||
this.imexMetaService.setDataImportInProgress(true);
|
||||
console.error(error);
|
||||
Log.err(error);
|
||||
|
||||
try {
|
||||
alert(
|
||||
|
|
@ -537,21 +538,21 @@ export class AppComponent implements OnDestroy {
|
|||
if (!persisted) {
|
||||
return navigator.storage.persist().then((granted) => {
|
||||
if (granted) {
|
||||
console.log('Persistent store granted');
|
||||
Log.log('Persistent store granted');
|
||||
}
|
||||
// NOTE: we never execute for android web view, because it is always true
|
||||
else if (!IS_ANDROID_WEB_VIEW) {
|
||||
const msg = T.GLOBAL_SNACK.PERSISTENCE_DISALLOWED;
|
||||
console.warn('Persistence not allowed');
|
||||
Log.err('Persistence not allowed');
|
||||
this._snackService.open({ msg });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('Persistence already allowed');
|
||||
Log.log('Persistence already allowed');
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
Log.log(e);
|
||||
const err = e && e.toString ? e.toString() : 'UNKNOWN';
|
||||
const msg = T.GLOBAL_SNACK.PERSISTENCE_ERROR;
|
||||
this._snackService.open({
|
||||
|
|
@ -576,7 +577,7 @@ export class AppComponent implements OnDestroy {
|
|||
const usageInMib = Math.round(u / (1024 * 1024));
|
||||
const quotaInMib = Math.round(q / (1024 * 1024));
|
||||
const details = `${usageInMib} out of ${quotaInMib} MiB used (${percentUsed}%)`;
|
||||
console.log(details);
|
||||
Log.log(details);
|
||||
if (quotaInMib - usageInMib <= 333) {
|
||||
alert(
|
||||
`There is only very little disk space available (${
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { saveBeforeLastErrorActionLog } from '../../util/action-logger';
|
|||
import { error } from 'electron-log/renderer';
|
||||
import { PfapiService } from '../../pfapi/pfapi.service';
|
||||
import { CompleteBackup } from '../../pfapi/api';
|
||||
import { Log } from '../log';
|
||||
|
||||
let isErrorAlertShown = false;
|
||||
|
||||
|
|
@ -23,7 +24,7 @@ export class GlobalErrorHandler implements ErrorHandler {
|
|||
const errStr = typeof err === 'string' ? err : err.toString();
|
||||
// eslint-disable-next-line
|
||||
const simpleStack = err && err.stack;
|
||||
console.error('GLOBAL_ERROR_HANDLER', err);
|
||||
Log.err('GLOBAL_ERROR_HANDLER', err);
|
||||
|
||||
// if not our custom error handler we have a critical error on our hands
|
||||
if (!isHandledError(err) && !isErrorAlertShown) {
|
||||
|
|
@ -67,8 +68,8 @@ export class GlobalErrorHandler implements ErrorHandler {
|
|||
try {
|
||||
return await this.injector.get(PfapiService).pf.loadCompleteBackup(true);
|
||||
} catch (e) {
|
||||
console.warn('Cannot load user data for error modal');
|
||||
console.error(e);
|
||||
Log.err('Cannot load user data for error modal');
|
||||
Log.err(e);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { download } from '../../util/download';
|
|||
import { privacyExport } from '../../imex/file-imex/privacy-export';
|
||||
import { getAppVersionStr } from '../../util/get-app-version-str';
|
||||
import { CompleteBackup } from '../../pfapi/api';
|
||||
import { Log } from '../log';
|
||||
|
||||
let isWasErrorAlertCreated = false;
|
||||
|
||||
|
|
@ -48,7 +49,7 @@ const _getStacktrace = async (err: Error | any): Promise<string> => {
|
|||
.join('\n');
|
||||
});
|
||||
} else if (!isHandledError(err)) {
|
||||
console.warn('Error without stack', err);
|
||||
Log.err('Error without stack', err);
|
||||
}
|
||||
return Promise.resolve('');
|
||||
};
|
||||
|
|
@ -74,7 +75,7 @@ export const logAdvancedStacktrace = (
|
|||
}
|
||||
|
||||
const githubIssueLinks = document.getElementsByClassName('github-issue-urlX');
|
||||
console.log(githubIssueLinks);
|
||||
Log.log(githubIssueLinks);
|
||||
|
||||
if (githubIssueLinks) {
|
||||
const errEscaped = _cleanHtml(origErr as string);
|
||||
|
|
@ -144,7 +145,7 @@ export const createErrorAlert = (
|
|||
});
|
||||
innerWrapper.append(btnReload);
|
||||
|
||||
console.log(userData);
|
||||
Log.log(userData);
|
||||
|
||||
if (userData) {
|
||||
const btnExport = document.createElement('BUTTON');
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { BehaviorSubject, Observable } from 'rxjs';
|
|||
import { GlobalConfigService } from 'src/app/features/config/global-config.service';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
import { DEFAULT_GLOBAL_CONFIG } from 'src/app/features/config/default-global-config.const';
|
||||
import { Log } from '../log';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class LanguageService {
|
||||
|
|
@ -36,7 +37,7 @@ export class LanguageService {
|
|||
if (lng) {
|
||||
console.error('Invalid language code', lng);
|
||||
} else {
|
||||
console.warn('No language code provided');
|
||||
Log.err('No language code provided');
|
||||
}
|
||||
this.setFromBrowserLngIfAutoSwitchLng();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { androidInterface } from '../../features/android/android-interface';
|
||||
import { Log } from '../log';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -15,7 +16,7 @@ export class AndroidDbAdapterService {
|
|||
|
||||
async load(key: string): Promise<unknown> {
|
||||
const data = await androidInterface.loadFromDbWrapped(key);
|
||||
console.log('load', key, data);
|
||||
Log.log('load', key, data);
|
||||
|
||||
return typeof data === 'string'
|
||||
? JSON.parse((data as string).replace(/\n/g, '\\n'))
|
||||
|
|
@ -23,7 +24,7 @@ export class AndroidDbAdapterService {
|
|||
}
|
||||
|
||||
async save(key: string, data: unknown): Promise<unknown> {
|
||||
console.log('save', key, data);
|
||||
Log.log('save', key, data);
|
||||
return await androidInterface.saveToDbWrapped(key, JSON.stringify(data));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { T } from '../../t.const';
|
|||
import { IndexedDBAdapterService } from './indexed-db-adapter.service';
|
||||
import { DBAdapter } from './db-adapter.model';
|
||||
import { AndroidDbAdapterService } from './android-db-adapter.service';
|
||||
import { Log } from '../log';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -32,7 +33,7 @@ export class DatabaseService {
|
|||
try {
|
||||
return await this._adapter.load(key);
|
||||
} catch (e) {
|
||||
console.warn('DB Load Error: Last Params,', this._lastParams);
|
||||
Log.err('DB Load Error: Last Params,', this._lastParams);
|
||||
return this._errorHandler(e, this.load, [key]);
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +45,7 @@ export class DatabaseService {
|
|||
try {
|
||||
return await this._adapter.save(key, data);
|
||||
} catch (e) {
|
||||
console.warn('DB Save Error: Last Params,', this._lastParams);
|
||||
Log.err('DB Save Error: Last Params,', this._lastParams);
|
||||
return this._errorHandler(e, this.save, [key, data]);
|
||||
}
|
||||
}
|
||||
|
|
@ -54,7 +55,7 @@ export class DatabaseService {
|
|||
try {
|
||||
return await this._adapter.remove(key);
|
||||
} catch (e) {
|
||||
console.warn('DB Remove Error: Last Params,', this._lastParams);
|
||||
Log.err('DB Remove Error: Last Params,', this._lastParams);
|
||||
return this._errorHandler(e, this.remove, [key]);
|
||||
}
|
||||
}
|
||||
|
|
@ -64,7 +65,7 @@ export class DatabaseService {
|
|||
try {
|
||||
return await this._adapter.clearDatabase();
|
||||
} catch (e) {
|
||||
console.warn('DB Clear Error: Last Params,', this._lastParams);
|
||||
Log.err('DB Clear Error: Last Params,', this._lastParams);
|
||||
return this._errorHandler(e, this.clearDatabase, []);
|
||||
}
|
||||
}
|
||||
|
|
@ -73,9 +74,9 @@ export class DatabaseService {
|
|||
try {
|
||||
await this._adapter.init();
|
||||
} catch (e) {
|
||||
console.error('Database initialization failed');
|
||||
console.error('_lastParams', this._lastParams);
|
||||
console.error(e);
|
||||
Log.err('Database initialization failed');
|
||||
Log.err('_lastParams', this._lastParams);
|
||||
Log.err(e);
|
||||
alert('DB INIT Error');
|
||||
throw new Error(e as any);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { BehaviorSubject, Observable } from 'rxjs';
|
|||
import { filter, shareReplay, take } from 'rxjs/operators';
|
||||
import { DBSchema, openDB } from 'idb';
|
||||
import { DBAdapter } from './db-adapter.model';
|
||||
import { Log } from '../log';
|
||||
|
||||
const DB_NAME = 'SUP';
|
||||
const DB_MAIN_NAME = 'SUP_STORE';
|
||||
|
|
@ -70,23 +71,20 @@ export class IndexedDBAdapterService implements DBAdapter {
|
|||
const result = await (this._db as IDBPDatabase<MyDb>).get(DB_MAIN_NAME, key);
|
||||
return result;
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`[IndexedDB] Error loading key "${key}" from store "${DB_MAIN_NAME}":`,
|
||||
e,
|
||||
);
|
||||
Log.err(`[IndexedDB] Error loading key "${key}" from store "${DB_MAIN_NAME}":`, e);
|
||||
|
||||
if (e instanceof Error) {
|
||||
console.error('[IndexedDB] Error name:', e.name);
|
||||
console.error('[IndexedDB] Error message:', e.message);
|
||||
Log.err('[IndexedDB] Error name:', e.name);
|
||||
Log.err('[IndexedDB] Error message:', e.message);
|
||||
|
||||
// Log specific details for the large value error
|
||||
if (e.message && e.message.includes('Failed to read large IndexedDB value')) {
|
||||
console.error('[IndexedDB] CRITICAL: Large value read failure detected');
|
||||
console.error(
|
||||
Log.err('[IndexedDB] CRITICAL: Large value read failure detected');
|
||||
Log.err(
|
||||
'[IndexedDB] This indicates IndexedDB blob files are missing or corrupted',
|
||||
);
|
||||
console.error('[IndexedDB] Affected store:', DB_MAIN_NAME);
|
||||
console.error('[IndexedDB] Affected key:', key);
|
||||
Log.err('[IndexedDB] Affected store:', DB_MAIN_NAME);
|
||||
Log.err('[IndexedDB] Affected key:', key);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,10 +98,7 @@ export class IndexedDBAdapterService implements DBAdapter {
|
|||
try {
|
||||
return await (this._db as IDBPDatabase<MyDb>).put(DB_MAIN_NAME, data, key);
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`[IndexedDB] Error saving key "${key}" to store "${DB_MAIN_NAME}":`,
|
||||
e,
|
||||
);
|
||||
Log.err(`[IndexedDB] Error saving key "${key}" to store "${DB_MAIN_NAME}":`, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
@ -122,7 +117,7 @@ export class IndexedDBAdapterService implements DBAdapter {
|
|||
try {
|
||||
return await this._afterReady$.pipe(take(1)).toPromise();
|
||||
} catch (e) {
|
||||
console.warn('DB After Ready Error: Last Params');
|
||||
Log.err('DB After Ready Error: Last Params');
|
||||
throw new Error(e as string);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { LocalSyncMetaForProvider, LocalSyncMetaModel } from '../../imex/sync/sy
|
|||
import { LegacySyncProvider } from 'src/app/imex/sync/legacy-sync-provider.model';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { Log } from '../log';
|
||||
|
||||
const DEFAULT_LOCAL_SYNC_META: LocalSyncMetaModel = {
|
||||
[LegacySyncProvider.Dropbox]: {
|
||||
|
|
@ -46,7 +47,7 @@ export class PersistenceLocalService {
|
|||
r[LegacySyncProvider.LocalFile]
|
||||
) {
|
||||
if (environment.production) {
|
||||
console.log(r);
|
||||
Log.log(r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
|
@ -82,7 +83,7 @@ export class PersistenceLocalService {
|
|||
}
|
||||
|
||||
async updateLastSyncModelChange(lastSyncModelChange: number): Promise<unknown> {
|
||||
console.log(lastSyncModelChange);
|
||||
Log.log(lastSyncModelChange);
|
||||
console.trace();
|
||||
this.lastSnyModelChange$.next(lastSyncModelChange);
|
||||
return await this._databaseService.save(
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import { androidInterface } from '../../features/android/android-interface';
|
|||
import { HttpClient } from '@angular/common/http';
|
||||
import { LS } from '../persistence/storage-keys.const';
|
||||
import { CustomThemeService } from './custom-theme.service';
|
||||
import { Log } from '../log';
|
||||
|
||||
export type DarkModeCfg = 'dark' | 'light' | 'system';
|
||||
|
||||
|
|
@ -176,7 +177,7 @@ export class GlobalThemeService {
|
|||
);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(`Error loading icon: ${iconName} from ${url}`, error);
|
||||
Log.err(`Error loading icon: ${iconName} from ${url}`, error);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { IS_ANDROID_WEB_VIEW } from '../../util/is-android-web-view';
|
|||
import { nanoid } from 'nanoid';
|
||||
import { BehaviorSubject, merge, Observable, Subject } from 'rxjs';
|
||||
import { mapTo } from 'rxjs/operators';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
export interface AndroidInterface {
|
||||
getVersion?(): string;
|
||||
|
|
@ -123,5 +124,5 @@ if (IS_ANDROID_WEB_VIEW) {
|
|||
delete requestMap[rId];
|
||||
};
|
||||
|
||||
console.log('Android Web View interfaces initialized', androidInterface);
|
||||
Log.log('Android Web View interfaces initialized', androidInterface);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { LocalNotifications } from '@capacitor/local-notifications';
|
|||
import { SnackService } from '../../../core/snack/snack.service';
|
||||
import { IS_ANDROID_WEB_VIEW } from '../../../util/is-android-web-view';
|
||||
import { LocalNotificationSchema } from '@capacitor/local-notifications/dist/esm/definitions';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
// TODO send message to electron when current task changes here
|
||||
|
||||
|
|
@ -30,11 +31,11 @@ export class AndroidEffects {
|
|||
try {
|
||||
const checkResult = await LocalNotifications.checkPermissions();
|
||||
if (checkResult.display === 'denied') {
|
||||
console.log(await LocalNotifications.requestPermissions());
|
||||
console.log(await LocalNotifications.changeExactNotificationSetting());
|
||||
Log.log(await LocalNotifications.requestPermissions());
|
||||
Log.log(await LocalNotifications.changeExactNotificationSetting());
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Log.err(error);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: error?.toString() || 'Notifications not supported',
|
||||
|
|
@ -58,7 +59,7 @@ export class AndroidEffects {
|
|||
const checkResult = await LocalNotifications.checkPermissions();
|
||||
if (checkResult.display === 'granted') {
|
||||
const pendingNotifications = await LocalNotifications.getPending();
|
||||
console.log({ pendingNotifications });
|
||||
Log.log({ pendingNotifications });
|
||||
if (pendingNotifications.notifications.length > 0) {
|
||||
await LocalNotifications.cancel({
|
||||
notifications: pendingNotifications.notifications.map((n) => ({
|
||||
|
|
@ -90,7 +91,7 @@ export class AndroidEffects {
|
|||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Log.err(error);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: error?.toString() || 'Notifications not supported',
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import { selectCalendarProviders } from '../issue/store/issue-provider.selectors
|
|||
import { IssueProviderCalendar } from '../issue/issue.model';
|
||||
import { CalendarProviderCfg } from '../issue/providers/calendar/calendar.model';
|
||||
import { CORS_SKIP_EXTRA_HEADERS } from '../../app.constants';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
const ONE_MONTHS = 60 * 60 * 1000 * 24 * 31;
|
||||
|
||||
|
|
@ -75,7 +76,7 @@ export class CalendarIntegrationService {
|
|||
.pipe(distinctUntilChanged(fastArrayCompare)),
|
||||
this.skippedEventIds$.pipe(distinctUntilChanged(fastArrayCompare)),
|
||||
]).pipe(
|
||||
// tap((val) => console.log('selectAllCalendarTaskEventIds', val)),
|
||||
// tap((val) => Log.log('selectAllCalendarTaskEventIds', val)),
|
||||
map(([allCalendarTaskEventIds, skippedEventIds]) => {
|
||||
return resultForProviders.map(({ itemsForProvider, calProvider }) => {
|
||||
return {
|
||||
|
|
@ -90,7 +91,7 @@ export class CalendarIntegrationService {
|
|||
}),
|
||||
),
|
||||
),
|
||||
// tap((v) => console.log('icalEvents$ final', v)),
|
||||
// tap((v) => Log.log('icalEvents$ final', v)),
|
||||
tap((val) => {
|
||||
saveToRealLs(LS.CAL_EVENTS_CACHE, val);
|
||||
}),
|
||||
|
|
@ -104,7 +105,7 @@ export class CalendarIntegrationService {
|
|||
public readonly skippedEventIds$ = new BehaviorSubject<string[]>([]);
|
||||
|
||||
constructor() {
|
||||
// console.log(
|
||||
// Log.log(
|
||||
// localStorage.getItem(LS.CALENDER_EVENTS_LAST_SKIP_DAY),
|
||||
// localStorage.getItem(LS.CALENDER_EVENTS_SKIPPED_TODAY),
|
||||
// localStorage.getItem(LS.CAL_EVENTS_CACHE),
|
||||
|
|
@ -132,7 +133,7 @@ export class CalendarIntegrationService {
|
|||
.pipe(
|
||||
map((v) => !!v),
|
||||
catchError((err) => {
|
||||
console.error(err);
|
||||
Log.err(err);
|
||||
return of(false);
|
||||
}),
|
||||
)
|
||||
|
|
@ -155,7 +156,7 @@ export class CalendarIntegrationService {
|
|||
end = getEndOfDayTimestamp(),
|
||||
isForwardError = false,
|
||||
): Observable<CalendarIntegrationEvent[]> {
|
||||
// console.log('REQUEST EVENTS', calProvider, start, end);
|
||||
// Log.log('REQUEST EVENTS', calProvider, start, end);
|
||||
|
||||
return this._http
|
||||
.get(calProvider.icalUrl, {
|
||||
|
|
@ -174,7 +175,7 @@ export class CalendarIntegrationService {
|
|||
),
|
||||
),
|
||||
catchError((err) => {
|
||||
console.error(err);
|
||||
Log.err(err);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: T.F.CALENDARS.S.CAL_PROVIDER_ERROR,
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ export const isCalenderEventDue = (
|
|||
skippedEventIds: string[],
|
||||
now: number,
|
||||
): boolean => {
|
||||
// console.log(calEv);
|
||||
// console.log(calEv.start >= now - START_OFFSET, calEv.start, now - START_OFFSET);
|
||||
// console.log(
|
||||
// Log.log(calEv);
|
||||
// Log.log(calEv.start >= now - START_OFFSET, calEv.start, now - START_OFFSET);
|
||||
// Log.log(
|
||||
// calEv.start <= now + (calProvider.showBannerBeforeThreshold || 0),
|
||||
// calEv.start,
|
||||
// now + (calProvider.showBannerBeforeThreshold || 0),
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { IssueProviderCalendar } from '../../issue/issue.model';
|
|||
import { IssueService } from '../../issue/issue.service';
|
||||
import { isToday } from '../../../util/is-today.util';
|
||||
import { TaskService } from '../../tasks/task.service';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
const CHECK_TO_SHOW_INTERVAL = 60 * 1000;
|
||||
|
||||
|
|
@ -58,7 +59,7 @@ export class CalendarIntegrationEffects {
|
|||
activatedProviders.map((calProvider) =>
|
||||
timer(0, calProvider.checkUpdatesEvery).pipe(
|
||||
// timer(0, 10000).pipe(
|
||||
// tap(() => console.log('REQUEST CALENDAR', calProvider)),
|
||||
// tap(() => Log.log('REQUEST CALENDAR', calProvider)),
|
||||
switchMap(() =>
|
||||
this._calendarIntegrationService.requestEvents$(calProvider),
|
||||
),
|
||||
|
|
@ -103,7 +104,7 @@ export class CalendarIntegrationEffects {
|
|||
),
|
||||
);
|
||||
}),
|
||||
tap((a) => console.log('_____END___', a)),
|
||||
tap((a) => Log.log('_____END___', a)),
|
||||
),
|
||||
{ dispatch: false },
|
||||
);
|
||||
|
|
@ -123,11 +124,11 @@ export class CalendarIntegrationEffects {
|
|||
calProvider: IssueProviderCalendar,
|
||||
): void {
|
||||
const curVal = this._currentlyShownBanners$.getValue();
|
||||
console.log('addEvToShow', curVal, calEv);
|
||||
Log.log('addEvToShow', curVal, calEv);
|
||||
if (!curVal.map((val) => val.id).includes(calEv.id)) {
|
||||
const newBanners = [...curVal, { id: calEv.id, calEv, calProvider }];
|
||||
newBanners.sort((a, b) => a.calEv.start - b.calEv.start);
|
||||
console.log('UDATE _currentlyShownBanners$');
|
||||
Log.log('UDATE _currentlyShownBanners$');
|
||||
|
||||
this._currentlyShownBanners$.next(newBanners);
|
||||
}
|
||||
|
|
@ -162,7 +163,7 @@ export class CalendarIntegrationEffects {
|
|||
const isInPast = calEv.start < Date.now();
|
||||
|
||||
const nrOfAllBanners = allEvsToShow.length;
|
||||
console.log({ taskForEvent, allEvsToShow });
|
||||
Log.log({ taskForEvent, allEvsToShow });
|
||||
|
||||
this._bannerService.open({
|
||||
id: BannerId.CalendarEvent,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { MODEL_VERSION_KEY } from '../../app.constants';
|
|||
import { isMigrateModel } from '../../util/is-migrate-model';
|
||||
import { LegacySyncProvider } from '../../imex/sync/legacy-sync-provider.model';
|
||||
import { MODEL_VERSION } from '../../core/model-version';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
export const migrateGlobalConfigState = (
|
||||
globalConfigState: GlobalConfigState,
|
||||
|
|
@ -111,7 +112,7 @@ const _extendConfigDefaults = (config: GlobalConfigState): GlobalConfigState =>
|
|||
if (!newCfg[key].hasOwnProperty(entryKey)) {
|
||||
// @ts-ignore
|
||||
const defaultVal = DEFAULT_GLOBAL_CONFIG[key][entryKey];
|
||||
console.log('EXTEND globalConfig', key, entryKey, defaultVal);
|
||||
Log.log('EXTEND globalConfig', key, entryKey, defaultVal);
|
||||
// @ts-ignore
|
||||
newCfg[key] = { ...newCfg[key], [entryKey]: defaultVal };
|
||||
}
|
||||
|
|
@ -214,10 +215,7 @@ const _migrateSyncCfg = (config: GlobalConfigState): GlobalConfigState => {
|
|||
}
|
||||
|
||||
if (!config.sync.localFileSync || !config.sync.webDav) {
|
||||
console.warn(
|
||||
'sync config was missing some keys, reverting to default',
|
||||
config.sync,
|
||||
);
|
||||
Log.err('sync config was missing some keys, reverting to default', config.sync);
|
||||
return {
|
||||
...config,
|
||||
sync: {
|
||||
|
|
@ -233,7 +231,7 @@ const _migrateSyncCfg = (config: GlobalConfigState): GlobalConfigState => {
|
|||
// config.sync.localFileSync.syncFolderPath = getDir(
|
||||
// config.sync.localFileSync.syncFilePath,
|
||||
// );
|
||||
// console.log(
|
||||
// Log.log(
|
||||
// 'migrating new folder path localFileSync',
|
||||
// JSON.stringify(config.sync.localFileSync),
|
||||
// );
|
||||
|
|
@ -242,7 +240,7 @@ const _migrateSyncCfg = (config: GlobalConfigState): GlobalConfigState => {
|
|||
// }
|
||||
// if (!config.sync.webDav.syncFolderPath && config.sync.webDav.syncFilePath?.length) {
|
||||
// config.sync.webDav.syncFolderPath = getDir(config.sync.webDav.syncFilePath);
|
||||
// console.log('migrating new folder path webDav', JSON.stringify(config.sync.webDav));
|
||||
// Log.log('migrating new folder path webDav', JSON.stringify(config.sync.webDav));
|
||||
// // TODO add delete with next version
|
||||
// // delete config.sync.webDav.syncFilePath;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { getErrorTxt } from 'src/app/util/get-error-text';
|
|||
import { getWorklogStr } from '../../../util/get-work-log-str';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { standardListAnimation } from '../../../ui/animations/standard-list.ani';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'issue-panel-calendar-agenda',
|
||||
|
|
@ -113,7 +114,7 @@ export class IssuePanelCalendarAgendaComponent implements OnInit {
|
|||
.catch((e) => {
|
||||
this.isLoading.set(false);
|
||||
this._setAgendaItems([]);
|
||||
console.error(e);
|
||||
Log.err(e);
|
||||
this.error.set(getErrorTxt(e));
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ import { TranslatePipe } from '@ngx-translate/core';
|
|||
import { MatInput } from '@angular/material/input';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatProgressSpinner } from '@angular/material/progress-spinner';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'issue-provider-tab',
|
||||
|
|
@ -122,7 +123,7 @@ export class IssueProviderTabComponent implements OnDestroy, AfterViewInit {
|
|||
: of(null),
|
||||
),
|
||||
catchError(() => {
|
||||
console.error('Project not found for issueProvider');
|
||||
Log.err('Project not found for issueProvider');
|
||||
return of(null);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import { IssueServiceInterface } from './issue-service-interface';
|
|||
import { JiraCommonInterfacesService } from './providers/jira/jira-common-interfaces.service';
|
||||
import { GithubCommonInterfacesService } from './providers/github/github-common-interfaces.service';
|
||||
import { catchError, map, switchMap } from 'rxjs/operators';
|
||||
import { Log } from '../../core/log';
|
||||
import { GitlabCommonInterfacesService } from './providers/gitlab/gitlab-common-interfaces.service';
|
||||
import { CaldavCommonInterfacesService } from './providers/caldav/caldav-common-interfaces.service';
|
||||
import { OpenProjectCommonInterfacesService } from './providers/open-project/open-project-common-interfaces.service';
|
||||
|
|
@ -324,7 +325,7 @@ export class IssueService {
|
|||
|
||||
for (const pKey of Object.keys(tasksIssueIdsByIssueProviderKey)) {
|
||||
const providerKey = pKey as IssueProviderKey;
|
||||
console.log(
|
||||
Log.log(
|
||||
'POLLING CHANGES FOR ' + providerKey,
|
||||
tasksIssueIdsByIssueProviderKey[providerKey],
|
||||
);
|
||||
|
|
@ -426,7 +427,7 @@ export class IssueService {
|
|||
|
||||
const { title = null, ...additionalFromProviderIssueService } =
|
||||
this.ISSUE_SERVICE_MAP[issueProviderKey].getAddTaskData(issueDataReduced);
|
||||
console.log({ title, additionalFromProviderIssueService });
|
||||
Log.log({ title, additionalFromProviderIssueService });
|
||||
|
||||
const getProjectOrTagId = async (): Promise<Partial<TaskCopy>> => {
|
||||
const defaultProjectId = (
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import { T } from '../../../../t.const';
|
|||
import { catchError } from 'rxjs/operators';
|
||||
import { HANDLED_ERROR_PROP_STR } from '../../../../app.constants';
|
||||
import { throwHandledError } from '../../../../util/throw-handled-error';
|
||||
import { Log } from '../../../../core/log';
|
||||
|
||||
interface ClientCache {
|
||||
client: DavClient;
|
||||
|
|
@ -397,7 +398,7 @@ export class CaldavClientService {
|
|||
const todo = comp.getFirstSubcomponent('vtodo');
|
||||
|
||||
if (!todo) {
|
||||
console.warn('No todo found for task', task);
|
||||
Log.err('No todo found for task', task);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { IssueProviderCalendar } from '../../issue.model';
|
|||
import { CalendarProviderCfg } from './calendar.model';
|
||||
import { ISSUE_PROVIDER_FF_DEFAULT_PROJECT } from '../../common-issue-form-stuff.const';
|
||||
import { IS_ELECTRON } from '../../../../app.constants';
|
||||
import { Log } from '../../../../core/log';
|
||||
|
||||
export const DEFAULT_CALENDAR_CFG: CalendarProviderCfg = {
|
||||
isEnabled: false,
|
||||
|
|
@ -45,7 +46,7 @@ export const CALENDAR_FORM_CFG_NEW: ConfigFormSection<IssueProviderCalendar> = {
|
|||
key: 'checkUpdatesEvery',
|
||||
hooks: {
|
||||
onInit: (field) => {
|
||||
console.log(field?.formControl?.value);
|
||||
Log.log(field?.formControl?.value);
|
||||
if (!field?.formControl?.value) {
|
||||
field?.formControl?.setValue(2 * 60 * 60000);
|
||||
}
|
||||
|
|
@ -61,7 +62,7 @@ export const CALENDAR_FORM_CFG_NEW: ConfigFormSection<IssueProviderCalendar> = {
|
|||
key: 'showBannerBeforeThreshold',
|
||||
hooks: {
|
||||
onInit: (field) => {
|
||||
console.log(field?.formControl?.value);
|
||||
Log.log(field?.formControl?.value);
|
||||
if (!field?.formControl?.value && field?.formControl?.value !== null) {
|
||||
field?.formControl?.setValue(2 * 60 * 60000);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import { SearchResultItem } from '../../../issue.model';
|
|||
import { GITLAB_TYPE, ISSUE_PROVIDER_HUMANIZED } from '../../../issue.const';
|
||||
import { assertTruthy } from '../../../../../util/assert-truthy';
|
||||
import { handleIssueProviderHttpError$ } from '../../../handle-issue-provider-http-error';
|
||||
import { Log } from '../../../../../core/log';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -43,7 +44,7 @@ export class GitlabApiService {
|
|||
private _http = inject(HttpClient);
|
||||
|
||||
getById$(id: string, cfg: GitlabCfg): Observable<GitlabIssue> {
|
||||
console.log(this._issueApiLink(cfg, id));
|
||||
Log.log(this._issueApiLink(cfg, id));
|
||||
|
||||
return this._sendIssuePaginatedRequest$(
|
||||
{
|
||||
|
|
@ -307,7 +308,7 @@ export class GitlabApiService {
|
|||
responseType: params.responseType,
|
||||
},
|
||||
];
|
||||
console.log(allArgs);
|
||||
Log.log(allArgs);
|
||||
|
||||
const req = new HttpRequest(p.method, p.url, ...allArgs);
|
||||
|
||||
|
|
@ -325,7 +326,7 @@ export class GitlabApiService {
|
|||
}
|
||||
|
||||
private _issueApiLink(cfg: GitlabCfg, issueId: string): string {
|
||||
console.log(issueId);
|
||||
Log.log(issueId);
|
||||
const { projectIssueId } = getPartsFromGitlabIssueId(issueId);
|
||||
return `${this._apiLink(cfg)}/issues/${projectIssueId}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import { MsToStringPipe } from '../../../../../ui/duration/ms-to-string.pipe';
|
|||
import { SortPipe } from '../../../../../ui/pipes/sort.pipe';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { SnackService } from '../../../../../core/snack/snack.service';
|
||||
import { Log } from '../../../../../core/log';
|
||||
|
||||
interface JiraSubtaskWithUrl extends JiraSubtask {
|
||||
href: string;
|
||||
|
|
@ -102,7 +103,7 @@ export class JiraIssueContentComponent {
|
|||
}),
|
||||
).pipe(
|
||||
catchError((e) => {
|
||||
console.error(e);
|
||||
Log.err(e);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: 'Failed to load subtasks for Jira Issue',
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ import { DialogPromptComponent } from '../../../../ui/dialog-prompt/dialog-promp
|
|||
import { stripTrailing } from '../../../../util/strip-trailing';
|
||||
import { IS_ANDROID_WEB_VIEW } from '../../../../util/is-android-web-view';
|
||||
import { formatJiraDate } from '../../../../util/format-jira-date';
|
||||
import { Log } from '../../../../core/log';
|
||||
|
||||
const BLOCK_ACCESS_KEY = 'SUP_BLOCK_JIRA_ACCESS';
|
||||
const API_VERSION = 'latest';
|
||||
|
|
@ -149,7 +150,7 @@ export class JiraApiService {
|
|||
// switchMap((res) =>
|
||||
// res.length > 0 ? of(res) : this.issuePicker$(searchTerm, cfg),
|
||||
// ),
|
||||
tap((v) => console.log('AAAAA', v)),
|
||||
tap((v) => Log.log('AAAAA', v)),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -421,7 +422,7 @@ export class JiraApiService {
|
|||
}
|
||||
|
||||
if (this._isBlockAccess && !isForce) {
|
||||
console.error('Blocked Jira Access to prevent being shut out');
|
||||
Log.err('Blocked Jira Access to prevent being shut out');
|
||||
this._bannerService.open({
|
||||
id: BannerId.JiraUnblock,
|
||||
msg: T.F.JIRA.BANNER.BLOCK_ACCESS_MSG,
|
||||
|
|
@ -513,8 +514,8 @@ export class JiraApiService {
|
|||
}),
|
||||
).pipe(
|
||||
catchError((err) => {
|
||||
console.log(err);
|
||||
console.log(getErrorTxt(err));
|
||||
Log.log(err);
|
||||
Log.log(getErrorTxt(err));
|
||||
const errTxt = `Jira: ${getErrorTxt(err)}`;
|
||||
this._snackService.open({ type: 'ERROR', msg: errTxt });
|
||||
return throwError({ [HANDLED_ERROR_PROP_STR]: errTxt });
|
||||
|
|
@ -527,8 +528,8 @@ export class JiraApiService {
|
|||
this._globalProgressBarService.countUp(url);
|
||||
return fromPromise(promise).pipe(
|
||||
catchError((err) => {
|
||||
console.log(err);
|
||||
console.log(getErrorTxt(err));
|
||||
Log.log(err);
|
||||
Log.log(getErrorTxt(err));
|
||||
const errTxt = `Jira: ${getErrorTxt(err)}`;
|
||||
this._snackService.open({ type: 'ERROR', msg: errTxt });
|
||||
return throwError({ [HANDLED_ERROR_PROP_STR]: errTxt });
|
||||
|
|
@ -625,7 +626,7 @@ export class JiraApiService {
|
|||
jiraCfg,
|
||||
|
||||
timeoutId: window.setTimeout(() => {
|
||||
console.log('ERROR', 'Jira Request timed out', requestInit);
|
||||
Log.log('ERROR', 'Jira Request timed out', requestInit);
|
||||
this._blockAccess();
|
||||
// delete entry for promise
|
||||
this._snackService.open({
|
||||
|
|
@ -647,7 +648,7 @@ export class JiraApiService {
|
|||
|
||||
// resolve saved promise
|
||||
if (!res || res.error) {
|
||||
console.error('JIRA_RESPONSE_ERROR', res, currentRequest);
|
||||
Log.err('JIRA_RESPONSE_ERROR', res, currentRequest);
|
||||
// let msg =
|
||||
if (
|
||||
res?.error &&
|
||||
|
|
@ -661,15 +662,15 @@ export class JiraApiService {
|
|||
|
||||
currentRequest.reject(res);
|
||||
} else {
|
||||
// console.log('JIRA_RESPONSE', res);
|
||||
// Log.log('JIRA_RESPONSE', res);
|
||||
if (currentRequest.transform) {
|
||||
// data can be invalid, that's why we check
|
||||
try {
|
||||
currentRequest.resolve(currentRequest.transform(res, currentRequest.jiraCfg));
|
||||
} catch (e) {
|
||||
console.log(res);
|
||||
console.log(currentRequest);
|
||||
console.error(e);
|
||||
Log.log(res);
|
||||
Log.log(currentRequest);
|
||||
Log.err(e);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: T.F.JIRA.S.INVALID_RESPONSE,
|
||||
|
|
@ -682,7 +683,7 @@ export class JiraApiService {
|
|||
// delete entry for promise afterwards
|
||||
delete this._requestsLog[res.requestId];
|
||||
} else {
|
||||
console.warn('Jira: Response Request ID not existing', res && res.requestId);
|
||||
Log.err('Jira: Response Request ID not existing', res && res.requestId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -726,7 +727,7 @@ async function streamToJsonIfPossible(stream: ReadableStream): Promise<any> {
|
|||
try {
|
||||
return JSON.parse(text);
|
||||
} catch (e) {
|
||||
console.error('Jira: Could not parse response', text);
|
||||
Log.err('Jira: Could not parse response', text);
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,10 @@ import { IssueProviderKey, SearchResultItem } from '../../issue.model';
|
|||
import { TaskAttachment } from '../../../tasks/task-attachment/task-attachment.model';
|
||||
import { dedupeByKey } from '../../../../util/de-dupe-by-key';
|
||||
import { JIRA_TYPE } from '../../issue.const';
|
||||
import { Log } from '../../../../core/log';
|
||||
|
||||
export const mapToSearchResults = (res: any): SearchResultItem[] => {
|
||||
console.log(res);
|
||||
Log.log(res);
|
||||
|
||||
const issues = dedupeByKey(
|
||||
res.response.sections.map((sec: any) => sec.issues).flat(),
|
||||
|
|
@ -50,7 +51,7 @@ export const mapToSearchResults = (res: any): SearchResultItem[] => {
|
|||
};
|
||||
|
||||
export const mapToSearchResultsForJQL = (res: any): SearchResultItem[] => {
|
||||
console.log(res);
|
||||
Log.log(res);
|
||||
|
||||
const issues = dedupeByKey(res.response.issues, 'key').map((issue: any) => {
|
||||
return {
|
||||
|
|
@ -82,7 +83,7 @@ export const mapIssueResponse = (res: any, cfg: JiraCfg): JiraIssue =>
|
|||
export const mapIssue = (issue: JiraIssueOriginal, cfg: JiraCfg): JiraIssue => {
|
||||
const issueCopy = Object.assign({}, issue);
|
||||
const fields = issueCopy.fields;
|
||||
console.log(fields);
|
||||
Log.log(fields);
|
||||
|
||||
return {
|
||||
key: issueCopy.key,
|
||||
|
|
@ -113,7 +114,7 @@ export const mapIssue = (issue: JiraIssueOriginal, cfg: JiraCfg): JiraIssue => {
|
|||
};
|
||||
|
||||
const mapIssueLinks = (issueLinks: JiraOriginalIssueLink[]): JiraRelatedIssue[] => {
|
||||
console.log(issueLinks);
|
||||
Log.log(issueLinks);
|
||||
|
||||
return issueLinks.map((il) => {
|
||||
const isInwardIssue = !!il.inwardIssue;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ import { MatOption, MatSelect } from '@angular/material/select';
|
|||
import { formatLocalIsoWithoutSeconds } from '../../../../../../util/format-local-iso-without-seconds';
|
||||
import { formatDateYYYYMMDD } from '../../../../../../util/format-date-yyyy-mm-dd';
|
||||
import { msToIsoDuration } from '../../../../../../util/ms-to-iso-duration';
|
||||
import { Log } from '../../../../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'dialog-open-project-track-time',
|
||||
|
|
@ -152,7 +153,7 @@ export class DialogOpenProjectTrackTimeComponent implements OnDestroy {
|
|||
);
|
||||
|
||||
constructor() {
|
||||
this._issueProviderIdOnce$.subscribe((v) => console.log(`_issueProviderIdOnce$`, v));
|
||||
this._issueProviderIdOnce$.subscribe((v) => Log.log(`_issueProviderIdOnce$`, v));
|
||||
|
||||
this.timeSpent = this.data.task.timeSpent;
|
||||
this.workPackage = this.data.workPackage;
|
||||
|
|
@ -183,7 +184,7 @@ export class DialogOpenProjectTrackTimeComponent implements OnDestroy {
|
|||
}
|
||||
|
||||
async postTime(): Promise<void> {
|
||||
console.log({
|
||||
Log.log({
|
||||
wp: this.workPackage,
|
||||
started: this.started,
|
||||
timeSpent: this.timeSpent,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { IssueProvider } from '../issue.model';
|
|||
import { SnackService } from '../../../core/snack/snack.service';
|
||||
import { getErrorTxt } from '../../../util/get-error-text';
|
||||
import { DELAY_BEFORE_ISSUE_POLLING } from '../issue.const';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
@Injectable()
|
||||
export class PollToBacklogEffects {
|
||||
|
|
@ -79,7 +80,7 @@ export class PollToBacklogEffects {
|
|||
),
|
||||
),
|
||||
catchError((e) => {
|
||||
console.error(e);
|
||||
Log.err(e);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
// TODO translate
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { Log } from '../../core/log';
|
||||
|
||||
/*
|
||||
we want to match:
|
||||
- [x] task
|
||||
|
|
@ -25,8 +27,8 @@ export const isMarkdownChecklist = (text: string): boolean => {
|
|||
);
|
||||
return items.length === lines.length || items.length >= 2;
|
||||
} catch (e) {
|
||||
console.error('Checklist parsing failed');
|
||||
console.error(e);
|
||||
Log.err('Checklist parsing failed');
|
||||
Log.err(e);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
} from '../obstruction/store/obstruction.reducer';
|
||||
import { ObstructionState } from '../obstruction/obstruction.model';
|
||||
import { unique } from '../../../util/unique';
|
||||
import { Log } from '../../../core/log';
|
||||
import {
|
||||
selectAllSimpleCounters,
|
||||
selectSimpleCounterFeatureState,
|
||||
|
|
@ -159,7 +160,7 @@ export const selectImprovementCountsPieChartData = createSelector(
|
|||
chart.labels?.push(imp.title);
|
||||
chart.datasets[0].data.push(counts[id]);
|
||||
} else {
|
||||
console.warn('No improvement entity found');
|
||||
Log.err('No improvement entity found');
|
||||
}
|
||||
});
|
||||
return chart;
|
||||
|
|
@ -190,7 +191,7 @@ export const selectObstructionCountsPieChartData = createSelector(
|
|||
chart.labels?.push(obstr.title);
|
||||
chart.datasets[0].data.push(counts[id]);
|
||||
} else {
|
||||
console.warn('No obstruction entity found');
|
||||
Log.err('No obstruction entity found');
|
||||
}
|
||||
});
|
||||
return chart;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ import {
|
|||
import { MatSelect } from '@angular/material/select';
|
||||
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
|
||||
import { MatInput } from '@angular/material/input';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
const DEFAULT_TIME = '09:00';
|
||||
|
||||
|
|
@ -122,7 +123,7 @@ export class DialogScheduleTaskComponent implements AfterViewInit {
|
|||
reminder.remindAt,
|
||||
);
|
||||
} else {
|
||||
console.warn('No reminder found for task', this.data.task);
|
||||
Log.err('No reminder found for task', this.data.task);
|
||||
}
|
||||
// for tasks without anything scheduled
|
||||
} else if (!this.data.task.dueWithTime) {
|
||||
|
|
@ -184,10 +185,10 @@ export class DialogScheduleTaskComponent implements AfterViewInit {
|
|||
|
||||
onKeyDownOnCalendar(ev: KeyboardEvent): void {
|
||||
this._timeCheckVal = null;
|
||||
// console.log(ev.key, ev.keyCode);
|
||||
// Log.log(ev.key, ev.keyCode);
|
||||
if (ev.key === 'Enter' || ev.keyCode === 32) {
|
||||
this.isShowEnterMsg = true;
|
||||
// console.log(
|
||||
// Log.log(
|
||||
// 'check to submit',
|
||||
// this.selectedDate &&
|
||||
// new Date(this.selectedDate).getTime() ===
|
||||
|
|
@ -208,7 +209,7 @@ export class DialogScheduleTaskComponent implements AfterViewInit {
|
|||
}
|
||||
|
||||
onTimeKeyDown(ev: KeyboardEvent): void {
|
||||
// console.log('ev.key!', ev.key);
|
||||
// Log.log('ev.key!', ev.key);
|
||||
if (ev.key === 'Enter') {
|
||||
this.isShowEnterMsg = true;
|
||||
|
||||
|
|
@ -226,7 +227,7 @@ export class DialogScheduleTaskComponent implements AfterViewInit {
|
|||
}
|
||||
|
||||
dateSelected(newDate: Date): void {
|
||||
// console.log('dateSelected', typeof newDate, newDate, this.selectedDate);
|
||||
// Log.log('dateSelected', typeof newDate, newDate, this.selectedDate);
|
||||
// we do the timeout is there to make sure this happens after our click handler
|
||||
setTimeout(() => {
|
||||
this.selectedDate = new Date(newDate);
|
||||
|
|
@ -283,7 +284,7 @@ export class DialogScheduleTaskComponent implements AfterViewInit {
|
|||
}
|
||||
|
||||
onTimeFocus(): void {
|
||||
console.log('onTimeFocus');
|
||||
Log.log('onTimeFocus');
|
||||
if (!this.selectedTime && this.isInitValOnTimeFocus) {
|
||||
this.isInitValOnTimeFocus = false;
|
||||
|
||||
|
|
@ -303,7 +304,7 @@ export class DialogScheduleTaskComponent implements AfterViewInit {
|
|||
|
||||
async submit(): Promise<void> {
|
||||
if (!this.selectedDate) {
|
||||
console.warn('no selected date');
|
||||
Log.err('no selected date');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { selectTodayTaskIds } from '../work-context/store/work-context.selectors
|
|||
import { msToString } from '../../ui/duration/ms-to-string.pipe';
|
||||
import { getWorklogStr } from '../../util/get-work-log-str';
|
||||
import { selectAllTaskRepeatCfgs } from '../task-repeat-cfg/store/task-repeat-cfg.selectors';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -26,7 +27,7 @@ export class PlannerService {
|
|||
includedWeekDays$ = of([0, 1, 2, 3, 4, 5, 6]);
|
||||
|
||||
daysToShow$ = this._globalTrackingIntervalService.todayDateStr$.pipe(
|
||||
tap((val) => console.log('daysToShow$', val)),
|
||||
tap((val) => Log.log('daysToShow$', val)),
|
||||
switchMap(() => this.includedWeekDays$),
|
||||
map((includedWeekDays) => {
|
||||
const today = new Date().getTime();
|
||||
|
|
@ -74,8 +75,8 @@ export class PlannerService {
|
|||
),
|
||||
// for better performance
|
||||
// TODO better solution, gets called very often
|
||||
// tap((val) => console.log('days$', val)),
|
||||
// tap((val) => console.log('days$ SIs', val[0]?.scheduledIItems)),
|
||||
// tap((val) => Log.log('days$', val)),
|
||||
// tap((val) => Log.log('days$ SIs', val[0]?.scheduledIItems)),
|
||||
shareReplay(1),
|
||||
);
|
||||
tomorrow$ = this.days$.pipe(
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { loadAllData } from '../../../root-store/meta/load-all-data.action';
|
|||
import { unique } from '../../../util/unique';
|
||||
import { TaskSharedActions } from '../../../root-store/meta/task-shared.actions';
|
||||
import { getWorklogStr } from '../../../util/get-work-log-str';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
export const plannerFeatureKey = 'planner';
|
||||
|
||||
|
|
@ -139,7 +140,7 @@ export const plannerReducer = createReducer(
|
|||
// when moving a parent to the day, remove all sub-tasks
|
||||
.filter((id) => !action.task.subTaskIds.includes(id)),
|
||||
};
|
||||
console.log({ updateNextDay, updatePrevDay });
|
||||
Log.log({ updateNextDay, updatePrevDay });
|
||||
|
||||
return {
|
||||
...state,
|
||||
|
|
@ -174,7 +175,7 @@ export const plannerReducer = createReducer(
|
|||
}
|
||||
const toIndex = daysCopy[dayI].indexOf(action.toTaskId);
|
||||
if (toIndex > -1) {
|
||||
console.log('toIndex', toIndex);
|
||||
Log.log('toIndex', toIndex);
|
||||
const tidsForDay = [...daysCopy[dayI]];
|
||||
tidsForDay.splice(toIndex, 0, action.fromTask.id);
|
||||
daysCopy[dayI] = tidsForDay;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { isMigrateModel } from '../../util/is-migrate-model';
|
|||
import { WORK_CONTEXT_DEFAULT_THEME } from '../work-context/work-context.const';
|
||||
import { dirtyDeepCopy } from '../../util/dirtyDeepCopy';
|
||||
import { MODEL_VERSION } from '../../core/model-version';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
export const migrateProjectState = (projectState: ProjectState): ProjectState => {
|
||||
if (!isMigrateModel(projectState, MODEL_VERSION.PROJECT, 'Project')) {
|
||||
|
|
@ -77,7 +78,7 @@ const _fixIds = (projectState: ProjectState): ProjectState => {
|
|||
const allIds = Object.keys(projectState.entities);
|
||||
|
||||
if (!currentIds) {
|
||||
console.error('Project Ids not defined');
|
||||
Log.err('Project Ids not defined');
|
||||
console.log('Attempting to fix...');
|
||||
return {
|
||||
...projectState,
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ import {
|
|||
} from '../../note/store/note.actions';
|
||||
import { MODEL_VERSION } from '../../../core/model-version';
|
||||
import { INBOX_PROJECT } from '../project.const';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
export const PROJECT_FEATURE_NAME = 'projects';
|
||||
const WORK_CONTEXT_TYPE: WorkContextType = WorkContextType.PROJECT;
|
||||
|
|
@ -271,7 +272,7 @@ export const projectReducer = createReducer<ProjectState>(
|
|||
on(moveProjectTaskToBacklogList, (state, { taskId, newOrderedIds, workContextId }) => {
|
||||
const project = state.entities[workContextId] as Project;
|
||||
if (!project.isEnableBacklog) {
|
||||
console.warn('Project backlog is disabled');
|
||||
Log.err('Project backlog is disabled');
|
||||
return state;
|
||||
}
|
||||
const todaysTaskIdsBefore = project.taskIds;
|
||||
|
|
@ -461,7 +462,7 @@ export const projectReducer = createReducer<ProjectState>(
|
|||
on(moveProjectTaskToBacklogListAuto, (state, { taskId, projectId }) => {
|
||||
const project = state.entities[projectId] as Project;
|
||||
if (!project.isEnableBacklog) {
|
||||
console.warn('Project backlog is disabled');
|
||||
Log.err('Project backlog is disabled');
|
||||
return state;
|
||||
}
|
||||
const todaysTaskIdsBefore = project.taskIds;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import { devError } from '../../util/dev-error';
|
|||
import { Note } from '../note/note.model';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { PfapiService } from '../../pfapi/pfapi.service';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -49,10 +50,10 @@ export class ReminderService {
|
|||
private _reminders: Reminder[] = [];
|
||||
|
||||
constructor() {
|
||||
// this._triggerPauseAfterUpdate$.subscribe((v) => console.log('_triggerPauseAfterUpdate$', v));
|
||||
// this._pauseAfterUpdate$.subscribe((v) => console.log('_pauseAfterUpdate$', v));
|
||||
// this._onRemindersActive$.subscribe((v) => console.log('_onRemindersActive$', v));
|
||||
// this.onRemindersActive$.subscribe((v) => console.log('onRemindersActive$', v));
|
||||
// this._triggerPauseAfterUpdate$.subscribe((v) => Log.log('_triggerPauseAfterUpdate$', v));
|
||||
// this._pauseAfterUpdate$.subscribe((v) => Log.log('_pauseAfterUpdate$', v));
|
||||
// this._onRemindersActive$.subscribe((v) => Log.log('_onRemindersActive$', v));
|
||||
// this.onRemindersActive$.subscribe((v) => Log.log('onRemindersActive$', v));
|
||||
|
||||
if (typeof (Worker as any) === 'undefined') {
|
||||
throw new Error('No service workers supported :(');
|
||||
|
|
@ -78,7 +79,7 @@ export class ReminderService {
|
|||
}
|
||||
this._reminders = await this._loadFromDatabase();
|
||||
if (!Array.isArray(this._reminders)) {
|
||||
console.log(this._reminders);
|
||||
Log.log(this._reminders);
|
||||
devError('Something went wrong with the reminders');
|
||||
this._reminders = [];
|
||||
}
|
||||
|
|
@ -87,7 +88,7 @@ export class ReminderService {
|
|||
this._onReloadModel$.next(this._reminders);
|
||||
this._reminders$.next(this._reminders);
|
||||
if (environment.production) {
|
||||
console.log('loaded reminders from database', this._reminders);
|
||||
Log.log('loaded reminders from database', this._reminders);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -205,7 +206,7 @@ export class ReminderService {
|
|||
const remindersWithData: Reminder[] = (await Promise.all(
|
||||
reminders.map(async (reminder) => {
|
||||
const relatedModel = await this._getRelatedDataForReminder(reminder);
|
||||
// console.log('RelatedModel for Reminder', relatedModel);
|
||||
// Log.log('RelatedModel for Reminder', relatedModel);
|
||||
// only show when not currently syncing and related model still exists
|
||||
if (!relatedModel) {
|
||||
devError('No Reminder Related Data found, removing reminder...');
|
||||
|
|
@ -241,7 +242,7 @@ export class ReminderService {
|
|||
} else if (!this._isRemindersLoaded$.getValue()) {
|
||||
throw new Error('Reminders not loaded initially when trying to save model');
|
||||
}
|
||||
console.log('saveReminders', reminders);
|
||||
Log.log('saveReminders', reminders);
|
||||
await this._pfapiService.m.reminders.save(reminders, {
|
||||
isUpdateRevAndLastUpdate: true,
|
||||
});
|
||||
|
|
@ -254,7 +255,7 @@ export class ReminderService {
|
|||
}
|
||||
|
||||
private _handleError(err: any): void {
|
||||
console.error(err);
|
||||
Log.err(err);
|
||||
this._snackService.open({ type: 'ERROR', msg: T.F.REMINDER.S_REMINDER_ERR });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
import { ReminderCopy } from './reminder.model';
|
||||
import { lazySetInterval } from '../../../../electron/shared-with-frontend/lazy-set-interval';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
const CHECK_INTERVAL_DURATION = 10000;
|
||||
let cancelCheckInterval: (() => void) | undefined;
|
||||
|
||||
addEventListener('message', ({ data }) => {
|
||||
// console.log('REMINDER WORKER', data);
|
||||
// Log.log('REMINDER WORKER', data);
|
||||
reInitCheckInterval(data);
|
||||
});
|
||||
|
||||
|
|
@ -32,7 +33,7 @@ const reInitCheckInterval = (reminders: ReminderCopy[]): void => {
|
|||
[oldest];
|
||||
|
||||
postMessage(remindersToSend);
|
||||
console.log('Worker postMessage', remindersToSend);
|
||||
Log.log('Worker postMessage', remindersToSend);
|
||||
}
|
||||
}, CHECK_INTERVAL_DURATION);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import { msLeftToday } from '../../../util/ms-left-today';
|
|||
import { getTasksWithinAndBeyondBudget } from './get-tasks-within-and-beyond-budget';
|
||||
import { dateStrToUtcDate } from '../../../util/date-str-to-utc-date';
|
||||
import { selectTaskRepeatCfgsDueOnDayOnly } from '../../task-repeat-cfg/store/task-repeat-cfg.selectors';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
export const createScheduleDays = (
|
||||
nonScheduledTasks: TaskWithoutReminder[],
|
||||
|
|
@ -131,8 +132,8 @@ export const createScheduleDays = (
|
|||
) {
|
||||
viewEntriesPushedToNextDay.push(entry);
|
||||
} else {
|
||||
console.log('entry Start:', new Date(entry.start), { entry });
|
||||
console.warn('Entry start time after next day start', entry);
|
||||
Log.log('entry Start:', new Date(entry.start), { entry });
|
||||
Log.err('Entry start time after next day start', entry);
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
|
|
@ -149,7 +150,7 @@ export const createScheduleDays = (
|
|||
}
|
||||
});
|
||||
|
||||
// console.log({
|
||||
// Log.log({
|
||||
// dayDate,
|
||||
// startTime: dateStrToUtcDate(startTime),
|
||||
// viewEntriesPushedToNextDay,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import {
|
|||
ScheduleWorkStartEndCfg,
|
||||
} from '../schedule.model';
|
||||
import { selectTaskRepeatCfgsDueOnDayOnly } from '../../task-repeat-cfg/store/task-repeat-cfg.selectors';
|
||||
|
||||
const PROJECTION_DAYS: number = 30;
|
||||
|
||||
export const createSortedBlockerBlocks = (
|
||||
|
|
@ -40,7 +39,7 @@ export const createSortedBlockerBlocks = (
|
|||
|
||||
blockedBlocks = mergeBlocksRecursively(blockedBlocks);
|
||||
blockedBlocks.sort((a, b) => a.start - b.start);
|
||||
// console.log(
|
||||
// Log.log(
|
||||
// blockedBlocks.map(({ start, end }) => ({
|
||||
// // start,
|
||||
// // end,
|
||||
|
|
@ -48,7 +47,7 @@ export const createSortedBlockerBlocks = (
|
|||
// e: new Date(end),
|
||||
// })),
|
||||
// );
|
||||
// console.log(blockedBlocks);
|
||||
// Log.log(blockedBlocks);
|
||||
|
||||
return blockedBlocks;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import {
|
|||
import { createScheduleViewEntriesForNormalTasks } from './create-schedule-view-entries-for-normal-tasks';
|
||||
import { insertBlockedBlocksViewEntriesForSchedule } from './insert-blocked-blocks-view-entries-for-schedule';
|
||||
import { SCHEDULE_VIEW_TYPE_ORDER, SVEType } from '../schedule.const';
|
||||
|
||||
export const createViewEntriesForDay = (
|
||||
dayDate: string,
|
||||
initialStartTime: number,
|
||||
|
|
@ -77,7 +76,7 @@ export const createViewEntriesForDay = (
|
|||
// viewEntries.splice(currentIndex + 1, 1);
|
||||
// } else {
|
||||
// debug(viewEntries);
|
||||
// console.warn('View Entry for current not available');
|
||||
// Log.err('View Entry for current not available');
|
||||
// }
|
||||
// }
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import { IS_TOUCH_PRIMARY } from '../../../util/is-mouse-primary';
|
|||
import { DRAG_DELAY_FOR_TOUCH } from '../../../app.constants';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { ShortcutService } from '../../../core-ui/shortcut/shortcut.service';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
const D_HOURS = 24;
|
||||
const DRAG_CLONE_CLASS = 'drag-clone';
|
||||
|
|
@ -201,7 +202,7 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
if (targetEl !== this.prevDragOverEl) {
|
||||
console.log('dragMoved targetElChanged', targetEl);
|
||||
Log.log('dragMoved targetElChanged', targetEl);
|
||||
|
||||
if (this.prevDragOverEl) {
|
||||
this.prevDragOverEl.classList.remove(DRAG_OVER_CLASS);
|
||||
|
|
@ -222,7 +223,7 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
dragStarted(ev: CdkDragStart<ScheduleEvent>): void {
|
||||
console.log('dragStart', ev);
|
||||
Log.log('dragStart', ev);
|
||||
this.isDragging = this.isDraggingDelayed = true;
|
||||
this.containerExtraClass = IS_DRAGGING_CLASS + ' ' + ev.source.data.type;
|
||||
|
||||
|
|
@ -238,7 +239,7 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
dragReleased(ev: CdkDragRelease): void {
|
||||
console.log('dragReleased', {
|
||||
Log.log('dragReleased', {
|
||||
target: ev.event.target,
|
||||
source: ev.source.element.nativeElement,
|
||||
ev,
|
||||
|
|
@ -271,7 +272,7 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy {
|
|||
if (target.tagName.toLowerCase() === 'div' && target.classList.contains('col')) {
|
||||
const isMoveToEndOfDay = target.classList.contains('end-of-day');
|
||||
const targetDay = (target as any).day || target.getAttribute('data-day');
|
||||
console.log({ targetDay });
|
||||
Log.log({ targetDay });
|
||||
if (targetDay) {
|
||||
this._store.dispatch(
|
||||
PlannerActions.planTaskForDay({
|
||||
|
|
@ -284,7 +285,7 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy {
|
|||
} else if (target.tagName.toLowerCase() === 'schedule-event') {
|
||||
const sourceTaskId = ev.source.element.nativeElement.id.replace(T_ID_PREFIX, '');
|
||||
const targetTaskId = target.id.replace(T_ID_PREFIX, '');
|
||||
console.log(sourceTaskId === targetTaskId, sourceTaskId, targetTaskId);
|
||||
Log.log(sourceTaskId === targetTaskId, sourceTaskId, targetTaskId);
|
||||
|
||||
if (
|
||||
sourceTaskId &&
|
||||
|
|
@ -292,7 +293,7 @@ export class ScheduleWeekComponent implements OnInit, OnDestroy {
|
|||
targetTaskId &&
|
||||
sourceTaskId !== targetTaskId
|
||||
) {
|
||||
console.log('sourceTaskId', sourceTaskId, 'targetTaskId', targetTaskId);
|
||||
Log.log('sourceTaskId', sourceTaskId, 'targetTaskId', targetTaskId);
|
||||
this._store.dispatch(
|
||||
PlannerActions.moveBeforeTask({
|
||||
fromTask: ev.source.data.data,
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@ import { ShepherdService } from './shepherd.service';
|
|||
import Step from 'shepherd.js/src/types/step';
|
||||
import StepOptionsWhen = Step.StepOptionsWhen;
|
||||
import { TourId } from './shepherd-steps.const';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
export const waitForEl = (selector: string, cb: () => void): number => {
|
||||
const int = window.setInterval(() => {
|
||||
console.log('INT');
|
||||
Log.log('INT');
|
||||
|
||||
if (document.querySelector(selector)) {
|
||||
window.clearInterval(int);
|
||||
|
|
@ -41,7 +42,7 @@ export const nextOnObs = (
|
|||
.pipe(
|
||||
tap((v) => {
|
||||
if (debugTitle) {
|
||||
console.log('nextOnObs', v, debugTitle);
|
||||
Log.log('nextOnObs', v, debugTitle);
|
||||
}
|
||||
}),
|
||||
first(),
|
||||
|
|
@ -75,7 +76,7 @@ export const twoWayObs = (
|
|||
onDestroy$ = new Subject();
|
||||
fwd.obs.pipe(first(), takeUntil(onDestroy$)).subscribe((v) => {
|
||||
if (debugTitle) {
|
||||
console.log(debugTitle, 'fwd', v);
|
||||
Log.log(debugTitle, 'fwd', v);
|
||||
}
|
||||
fwd.cbAfter?.();
|
||||
shepherdService.next();
|
||||
|
|
@ -83,7 +84,7 @@ export const twoWayObs = (
|
|||
if (back) {
|
||||
back.obs.pipe(first(), takeUntil(onDestroy$)).subscribe((v) => {
|
||||
if (debugTitle) {
|
||||
console.log(debugTitle, 'back', v);
|
||||
Log.log(debugTitle, 'back', v);
|
||||
}
|
||||
back.cbAfter?.();
|
||||
if (back.backToId) {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||
import { PlannerService } from '../../planner/planner.service';
|
||||
import { selectAllTasksDueToday } from '../../planner/store/planner.selectors';
|
||||
import { TaskSharedActions } from '../../../root-store/meta/task-shared.actions';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
@Injectable()
|
||||
export class TagEffects {
|
||||
|
|
@ -174,7 +175,7 @@ export class TagEffects {
|
|||
),
|
||||
),
|
||||
filter(({ nullTasks }) => nullTasks.length > 0),
|
||||
tap((arg) => console.log('Error INFO Today:', arg)),
|
||||
tap((arg) => Log.log('Error INFO Today:', arg)),
|
||||
tap(({ activeId, allTasks }) => {
|
||||
const allIds = allTasks.map((t) => t && t.id);
|
||||
const r = confirm(
|
||||
|
|
@ -221,7 +222,7 @@ export class TagEffects {
|
|||
newTaskIds.some((id, i) => id !== todayTagTaskIds[i]);
|
||||
|
||||
if (isChanged && (tasksWithParentInListIds.length || dueNotInListIds.length)) {
|
||||
console.log('Preventing parent and subtask in today list', {
|
||||
Log.log('Preventing parent and subtask in today list', {
|
||||
isChanged,
|
||||
tasksWithParentInListIds,
|
||||
dueNotInListIds,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import { Update } from '@ngrx/entity';
|
|||
import { getDateTimeFromClockString } from '../../../util/get-date-time-from-clock-string';
|
||||
import { isToday } from '../../../util/is-today.util';
|
||||
import { TaskArchiveService } from '../../time-tracking/task-archive.service';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
@Injectable()
|
||||
export class TaskRepeatCfgEffects {
|
||||
|
|
@ -122,8 +123,8 @@ export class TaskRepeatCfgEffects {
|
|||
),
|
||||
tap(([isConfirm, completeCfg]) => {
|
||||
if (isConfirm) {
|
||||
console.log(changes);
|
||||
console.log(todayTasks, archiveTasks);
|
||||
Log.log(changes);
|
||||
Log.log(todayTasks, archiveTasks);
|
||||
// NOTE: keep in mind that it's very likely that there will be only one task for today
|
||||
// TODO update reminders if given
|
||||
todayTasks.forEach((task) =>
|
||||
|
|
@ -163,7 +164,7 @@ export class TaskRepeatCfgEffects {
|
|||
) {
|
||||
changesForArchiveTask.timeEstimate = changes.defaultEstimate;
|
||||
}
|
||||
console.log('updateArchiveTask', changesForArchiveTask);
|
||||
Log.log('updateArchiveTask', changesForArchiveTask);
|
||||
return { id: task.id, changes: changesForArchiveTask };
|
||||
});
|
||||
this._taskService.updateArchiveTasks(archiveUpdates);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import { T } from '../../../t.const';
|
|||
import { IssueService } from '../../issue/issue.service';
|
||||
import { assertTruthy } from '../../../util/assert-truthy';
|
||||
import { DEFAULT_PROJECT_COLOR } from '../../work-context/work-context.const';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -184,7 +185,7 @@ export class AddTaskBarService {
|
|||
return item.taskId;
|
||||
} else if (item.taskId) {
|
||||
if (!item.projectId) {
|
||||
console.log(item);
|
||||
Log.log(item);
|
||||
throw new Error('Weird add task case1');
|
||||
}
|
||||
this._projectService.moveTaskToTodayList(item.taskId, item.projectId);
|
||||
|
|
@ -204,7 +205,7 @@ export class AddTaskBarService {
|
|||
item.issueType,
|
||||
this._workContextService.activeWorkContextId as string,
|
||||
);
|
||||
console.log(res);
|
||||
Log.log(res);
|
||||
if (!res) {
|
||||
return await this._issueService.addTaskFromIssue({
|
||||
issueProviderKey: item.issueType,
|
||||
|
|
@ -305,7 +306,7 @@ export class AddTaskBarService {
|
|||
try {
|
||||
return !!task.title.toLowerCase().match(searchText.toLowerCase());
|
||||
} catch (e) {
|
||||
console.warn('RegEx Error', e);
|
||||
Log.err('RegEx Error', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { stringToMs } from '../../ui/duration/string-to-ms.pipe';
|
|||
import { Tag } from '../tag/tag.model';
|
||||
import { Project } from '../project/project.model';
|
||||
import { ShortSyntaxConfig } from '../config/global-config.model';
|
||||
|
||||
type ProjectChanges = {
|
||||
title?: string;
|
||||
projectId?: string;
|
||||
|
|
@ -285,15 +284,15 @@ const parseTagChanges = (task: Partial<TaskCopy>, allTags?: Tag[]): TagChanges =
|
|||
taskChanges.title = taskChanges.title.trim();
|
||||
}
|
||||
|
||||
// console.log(task.title);
|
||||
// console.log('newTagTitles', regexTagTitles);
|
||||
// console.log('newTagTitlesTrimmed', regexTagTitlesTrimmedAndFiltered);
|
||||
// console.log('allTags)', allTags.map(tag => `${tag.id}: ${tag.title}`));
|
||||
// console.log('task.tagIds', task.tagIds);
|
||||
// console.log('task.title', task.title);
|
||||
// Log.log(task.title);
|
||||
// Log.log('newTagTitles', regexTagTitles);
|
||||
// Log.log('newTagTitlesTrimmed', regexTagTitlesTrimmedAndFiltered);
|
||||
// Log.log('allTags)', allTags.map(tag => `${tag.id}: ${tag.title}`));
|
||||
// Log.log('task.tagIds', task.tagIds);
|
||||
// Log.log('task.title', task.title);
|
||||
}
|
||||
}
|
||||
// console.log(taskChanges);
|
||||
// Log.log(taskChanges);
|
||||
|
||||
return {
|
||||
taskChanges,
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ import { PlannerActions } from '../../planner/store/planner.actions';
|
|||
import { getWorklogStr } from '../../../util/get-work-log-str';
|
||||
import { TaskSharedActions } from '../../../root-store/meta/task-shared.actions';
|
||||
import { TimeTrackingActions } from '../../time-tracking/store/time-tracking.actions';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
export const TASK_FEATURE_NAME = 'tasks';
|
||||
|
||||
|
|
@ -280,14 +281,14 @@ export const taskReducer = createReducer<TaskState>(
|
|||
on(moveSubTaskUp, (state, { id, parentId }) => {
|
||||
const parentTask = state.entities[parentId];
|
||||
if (!parentTask) {
|
||||
console.warn(`Parent task ${parentId} not found`);
|
||||
Log.err(`Parent task ${parentId} not found`);
|
||||
return state;
|
||||
}
|
||||
const parentSubTaskIds = parentTask.subTaskIds;
|
||||
|
||||
// Check if the subtask is actually in the parent's subtask list
|
||||
if (!parentSubTaskIds.includes(id)) {
|
||||
console.warn(`Subtask ${id} not found in parent ${parentId} subtasks`);
|
||||
Log.err(`Subtask ${id} not found in parent ${parentId} subtasks`);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
@ -305,14 +306,14 @@ export const taskReducer = createReducer<TaskState>(
|
|||
on(moveSubTaskDown, (state, { id, parentId }) => {
|
||||
const parentTask = state.entities[parentId];
|
||||
if (!parentTask) {
|
||||
console.warn(`Parent task ${parentId} not found`);
|
||||
Log.err(`Parent task ${parentId} not found`);
|
||||
return state;
|
||||
}
|
||||
const parentSubTaskIds = parentTask.subTaskIds;
|
||||
|
||||
// Check if the subtask is actually in the parent's subtask list
|
||||
if (!parentSubTaskIds.includes(id)) {
|
||||
console.warn(`Subtask ${id} not found in parent ${parentId} subtasks`);
|
||||
Log.err(`Subtask ${id} not found in parent ${parentId} subtasks`);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
@ -330,14 +331,14 @@ export const taskReducer = createReducer<TaskState>(
|
|||
on(moveSubTaskToTop, (state, { id, parentId }) => {
|
||||
const parentTask = state.entities[parentId];
|
||||
if (!parentTask) {
|
||||
console.warn(`Parent task ${parentId} not found`);
|
||||
Log.err(`Parent task ${parentId} not found`);
|
||||
return state;
|
||||
}
|
||||
const parentSubTaskIds = parentTask.subTaskIds;
|
||||
|
||||
// Check if the subtask is actually in the parent's subtask list
|
||||
if (!parentSubTaskIds.includes(id)) {
|
||||
console.warn(`Subtask ${id} not found in parent ${parentId} subtasks`);
|
||||
Log.err(`Subtask ${id} not found in parent ${parentId} subtasks`);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
@ -355,14 +356,14 @@ export const taskReducer = createReducer<TaskState>(
|
|||
on(moveSubTaskToBottom, (state, { id, parentId }) => {
|
||||
const parentTask = state.entities[parentId];
|
||||
if (!parentTask) {
|
||||
console.warn(`Parent task ${parentId} not found`);
|
||||
Log.err(`Parent task ${parentId} not found`);
|
||||
return state;
|
||||
}
|
||||
const parentSubTaskIds = parentTask.subTaskIds;
|
||||
|
||||
// Check if the subtask is actually in the parent's subtask list
|
||||
if (!parentSubTaskIds.includes(id)) {
|
||||
console.warn(`Subtask ${id} not found in parent ${parentId} subtasks`);
|
||||
Log.err(`Subtask ${id} not found in parent ${parentId} subtasks`);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { calcTotalTimeSpent } from '../util/calc-total-time-spent';
|
|||
import { taskAdapter } from './task.adapter';
|
||||
import { filterOutId } from '../../../util/filter-out-id';
|
||||
import { Update } from '@ngrx/entity';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
export const getTaskById = (taskId: string, state: TaskState): Task => {
|
||||
if (!state.entities[taskId]) {
|
||||
|
|
@ -37,9 +38,7 @@ export const reCalcTimeSpentForParentIfParent = (
|
|||
if (parentId) {
|
||||
const parentTask = state.entities[parentId];
|
||||
if (!parentTask) {
|
||||
console.warn(
|
||||
`Parent task ${parentId} not found in reCalcTimeSpentForParentIfParent`,
|
||||
);
|
||||
Log.err(`Parent task ${parentId} not found in reCalcTimeSpentForParentIfParent`);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
@ -83,9 +82,7 @@ export const reCalcTimeEstimateForParentIfParent = (
|
|||
): TaskState => {
|
||||
const parentTask = state.entities[parentId];
|
||||
if (!parentTask) {
|
||||
console.warn(
|
||||
`Parent task ${parentId} not found in reCalcTimeEstimateForParentIfParent`,
|
||||
);
|
||||
Log.err(`Parent task ${parentId} not found in reCalcTimeEstimateForParentIfParent`);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
@ -97,9 +94,9 @@ export const reCalcTimeEstimateForParentIfParent = (
|
|||
return upd && upd.id === id ? { ...task, ...upd.changes } : task;
|
||||
})
|
||||
.filter((task): task is Task => !!task);
|
||||
// console.log(
|
||||
// Log.log(
|
||||
// subTasks.reduce((acc: number, st: Task) => {
|
||||
// console.log(
|
||||
// Log.log(
|
||||
// (st.isDone ? 0 : Math.max(0, st.timeEstimate - st.timeSpent)) / 60 / 1000,
|
||||
// );
|
||||
//
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ import { TaskSharedActions } from '../../../../root-store/meta/task-shared.actio
|
|||
import { selectTodayTagTaskIds } from '../../../tag/store/tag.reducer';
|
||||
import { isToday } from '../../../../util/is-today.util';
|
||||
import { MenuTouchFixDirective } from '../menu-touch-fix.directive';
|
||||
import { Log } from '../../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'task-context-menu-inner',
|
||||
|
|
@ -536,7 +537,7 @@ export class TaskContextMenuInnerComponent implements AfterViewInit {
|
|||
|
||||
private async _schedule(selectedDate: Date, isRemoveFromToday = false): Promise<void> {
|
||||
if (!selectedDate) {
|
||||
console.warn('no selected date');
|
||||
Log.err('no selected date');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,6 @@ import { MsToStringPipe } from '../../../ui/duration/ms-to-string.pipe';
|
|||
import { IssueIconPipe } from '../../issue/issue-icon/issue-icon.pipe';
|
||||
import { isToday } from '../../../util/is-today.util';
|
||||
import { getWorklogStr } from '../../../util/get-work-log-str';
|
||||
|
||||
interface IssueAndType {
|
||||
id?: string | number;
|
||||
type?: IssueProviderKey;
|
||||
|
|
@ -309,9 +308,9 @@ export class TaskDetailPanelComponent implements OnInit, AfterViewInit, OnDestro
|
|||
}
|
||||
});
|
||||
}
|
||||
// this.issueIdAndType$.subscribe((v) => console.log('issueIdAndType$', v));
|
||||
// this.issueDataTrigger$.subscribe((v) => console.log('issueDataTrigger$', v));
|
||||
// this.issueData$.subscribe((v) => console.log('issueData$', v));
|
||||
// this.issueIdAndType$.subscribe((v) => Log.log('issueIdAndType$', v));
|
||||
// this.issueDataTrigger$.subscribe((v) => Log.log('issueDataTrigger$', v));
|
||||
// this.issueData$.subscribe((v) => Log.log('issueData$', v));
|
||||
|
||||
// NOTE: check work-view component for more info
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import { MatIcon } from '@angular/material/icon';
|
|||
import { TaskComponent } from '../task/task.component';
|
||||
import { AsyncPipe } from '@angular/common';
|
||||
import { TaskViewCustomizerService } from '../../task-view-customizer/task-view-customizer.service';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
export type TaskListId = 'PARENT' | 'SUB';
|
||||
export type ListModelId = DropListModelSource | string;
|
||||
|
|
@ -131,7 +132,7 @@ export class TaskListComponent implements OnDestroy, AfterViewInit {
|
|||
// const targetModelId = drag.dropContainer.data.listModelId;
|
||||
const targetModelId = drop.data.listModelId;
|
||||
const isSubtask = !!task.parentId;
|
||||
// console.log(drag.data.id, { isSubtask, targetModelId, drag, drop });
|
||||
// Log.log(drag.data.id, { isSubtask, targetModelId, drag, drop });
|
||||
// return true;
|
||||
if (targetModelId === 'OVERDUE' || targetModelId === 'LATER_TODAY') {
|
||||
return false;
|
||||
|
|
@ -158,7 +159,7 @@ export class TaskListComponent implements OnDestroy, AfterViewInit {
|
|||
const srcListData = ev.previousContainer.data;
|
||||
const targetListData = ev.container.data;
|
||||
const draggedTask = ev.item.data;
|
||||
console.log({
|
||||
Log.log({
|
||||
ev,
|
||||
srcListData,
|
||||
targetListData,
|
||||
|
|
@ -220,7 +221,7 @@ export class TaskListComponent implements OnDestroy, AfterViewInit {
|
|||
...targetListData.filteredTasks.filter((t) => t.id !== draggedTask.id),
|
||||
draggedTask,
|
||||
];
|
||||
console.log(srcListData.listModelId, '=>', targetListData.listModelId, {
|
||||
Log.log(srcListData.listModelId, '=>', targetListData.listModelId, {
|
||||
targetTask,
|
||||
draggedTask,
|
||||
newIds,
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ import { TaskSharedActions } from '../../../root-store/meta/task-shared.actions'
|
|||
import { environment } from '../../../../environments/environment';
|
||||
import { TODAY_TAG } from '../../tag/tag.const';
|
||||
import { GlobalTrackingIntervalService } from '../../../core/global-tracking-interval/global-tracking-interval.service';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'task',
|
||||
|
|
@ -596,7 +597,7 @@ export class TaskComponent implements OnDestroy, AfterViewInit {
|
|||
focusTitleForEdit(): void {
|
||||
const taskTitleEditEl = this.taskTitleEditEl();
|
||||
if (!taskTitleEditEl || !taskTitleEditEl.textarea().nativeElement) {
|
||||
console.log(taskTitleEditEl);
|
||||
Log.log(taskTitleEditEl);
|
||||
throw new Error('No el');
|
||||
}
|
||||
taskTitleEditEl.textarea().nativeElement.focus();
|
||||
|
|
@ -710,7 +711,7 @@ export class TaskComponent implements OnDestroy, AfterViewInit {
|
|||
archiveInstances,
|
||||
targetProject,
|
||||
]) => {
|
||||
console.log({
|
||||
Log.log({
|
||||
reminderCfg,
|
||||
nonArchiveInstancesWithSubTasks,
|
||||
archiveInstances,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { SoundConfig } from '../../config/global-config.model';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
export const playDoneSound = (soundCfg: SoundConfig, nrOfDoneTasks: number = 0): void => {
|
||||
const speed = 1;
|
||||
|
|
@ -7,13 +8,13 @@ export const playDoneSound = (soundCfg: SoundConfig, nrOfDoneTasks: number = 0):
|
|||
const file = `${BASE}/${soundCfg.doneSound}`;
|
||||
// const speed = 0.5;
|
||||
// const a = new Audio('/assets/snd/done4.mp3');
|
||||
// console.log(a);
|
||||
// Log.log(a);
|
||||
// a.volume = .4;
|
||||
// a.playbackRate = 1.5;
|
||||
// (a as any).mozPreservesPitch = false;
|
||||
// (a as any).webkitPreservesPitch = false;
|
||||
// a.play();
|
||||
console.log(file);
|
||||
Log.log(file);
|
||||
|
||||
const pitchFactor = soundCfg.isIncreaseDoneSoundPitch
|
||||
? // prettier-ignore
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { UI_LOCAL_HELPER_DEFAULT } from './ui-helper.const';
|
|||
import { IS_ELECTRON } from '../../app.constants';
|
||||
import { fromEvent } from 'rxjs';
|
||||
import { throttleTime } from 'rxjs/operators';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class UiHelperService {
|
||||
|
|
@ -18,7 +19,7 @@ export class UiHelperService {
|
|||
|
||||
zoomTo(zoomFactor: number): void {
|
||||
if (Number.isNaN(zoomFactor)) {
|
||||
console.error('Invalid zoom factor', zoomFactor);
|
||||
Log.err('Invalid zoom factor', zoomFactor);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +29,7 @@ export class UiHelperService {
|
|||
|
||||
zoomBy(zoomBy: number): void {
|
||||
if (Number.isNaN(zoomBy)) {
|
||||
console.error('Invalid zoom factor', zoomBy);
|
||||
Log.err('Invalid zoom factor', zoomBy);
|
||||
return;
|
||||
}
|
||||
const currentZoom = window.ea.getZoomFactor();
|
||||
|
|
@ -49,7 +50,7 @@ export class UiHelperService {
|
|||
|
||||
window.ea.showOrFocus();
|
||||
} else {
|
||||
console.error('Cannot execute focus app window in browser');
|
||||
Log.err('Cannot execute focus app window in browser');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ import { TaskArchiveService } from '../time-tracking/task-archive.service';
|
|||
import { INBOX_PROJECT } from '../project/project.const';
|
||||
import { selectProjectById } from '../project/store/project.selectors';
|
||||
import { getWorklogStr } from '../../util/get-work-log-str';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -257,11 +258,11 @@ export class WorkContextService {
|
|||
);
|
||||
|
||||
todaysTasks$: Observable<TaskWithSubTasks[]> = this.todaysTaskIds$.pipe(
|
||||
// tap((taskIds: string[]) => console.log('[WorkContext] Today task IDs:', taskIds)),
|
||||
// tap((taskIds: string[]) => Log.log('[WorkContext] Today task IDs:', taskIds)),
|
||||
switchMap((taskIds: string[]) => this._getTasksByIds$(taskIds)),
|
||||
// TODO find out why this is triggered so often
|
||||
// tap((tasks: TaskWithSubTasks[]) =>
|
||||
// console.log('[WorkContext] Today tasks loaded:', tasks.length, 'tasks'),
|
||||
// Log.log('[WorkContext] Today tasks loaded:', tasks.length, 'tasks'),
|
||||
// ),
|
||||
// map(to => to.filter(t => !!t)),
|
||||
shareReplay(1),
|
||||
|
|
@ -645,7 +646,7 @@ export class WorkContextService {
|
|||
// we don't want a circular dependency that's why we do it here...
|
||||
private _getTasksByIds$(ids: string[]): Observable<TaskWithSubTasks[]> {
|
||||
if (!Array.isArray(ids)) {
|
||||
console.log({ ids });
|
||||
Log.log({ ids });
|
||||
throw new Error('Invalid param provided for getByIds$ :(');
|
||||
}
|
||||
return this._store$.select(selectTasksWithSubTasksByIds, { ids });
|
||||
|
|
@ -654,7 +655,7 @@ export class WorkContextService {
|
|||
// we don't want a circular dependency that's why we do it here...
|
||||
private _getNotesByIds$(ids: string[]): Observable<Note[]> {
|
||||
if (!Array.isArray(ids)) {
|
||||
console.log({ ids });
|
||||
Log.log({ ids });
|
||||
throw new Error('Invalid param provided for getByIds$ :(');
|
||||
}
|
||||
return this._store$.select(selectNotesById, { ids });
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { MatButtonModule } from '@angular/material/button';
|
|||
import { CommonModule } from '@angular/common'; // For *ngIf, etc.
|
||||
import { TranslateModule } from '@ngx-translate/core'; // For translate pipe
|
||||
import { T } from '../../t.const';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
export interface DialogConfirmUrlImportData {
|
||||
domain: string;
|
||||
|
|
@ -29,7 +30,7 @@ export class ConfirmUrlImportDialogComponent {
|
|||
|
||||
constructor() {
|
||||
if (!this.data || !this.data.domain) {
|
||||
console.error('ConfirmUrlImportDialogComponent: No URL provided in dialog data.');
|
||||
Log.err('ConfirmUrlImportDialogComponent: No URL provided in dialog data.');
|
||||
// Optionally close dialog or handle error, for now, it will show undefined in template
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { MatDialogModule } from '@angular/material/dialog'; // Import MatDialogM
|
|||
import { T } from '../../t.const';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { NgIf } from '@angular/common'; // For potential translations
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'dialog-import-from-url',
|
||||
|
|
@ -43,7 +44,7 @@ export class DialogImportFromUrlComponent {
|
|||
// Basic validation: show error or prevent closing if URL is empty
|
||||
// For now, we rely on the required attribute in HTML and button disable
|
||||
// Or handle with a snackbar if more sophisticated feedback is needed
|
||||
console.error('URL is required.');
|
||||
Log.err('URL is required.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import {
|
|||
ConfirmUrlImportDialogComponent,
|
||||
DialogConfirmUrlImportData,
|
||||
} from '../dialog-confirm-url-import/dialog-confirm-url-import.component';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'file-imex',
|
||||
|
|
@ -62,7 +63,7 @@ export class FileImexComponent implements OnInit {
|
|||
try {
|
||||
decodedUrl = decodeURIComponent(importUrlParam);
|
||||
} catch (e) {
|
||||
console.error('Error decoding importFromUrl parameter:', e);
|
||||
Log.err('Error decoding importFromUrl parameter:', e);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: T.FILE_IMEX.S_IMPORT_FROM_URL_ERR_DECODE,
|
||||
|
|
@ -134,7 +135,7 @@ export class FileImexComponent implements OnInit {
|
|||
await this._processAndImportData(textData);
|
||||
} catch (error) {
|
||||
// Handle network errors and HTTP errors
|
||||
console.error('Network error or HTTP error fetching from URL:', error);
|
||||
Log.err('Network error or HTTP error fetching from URL:', error);
|
||||
this._snackService.open({ type: 'ERROR', msg: T.FILE_IMEX.S_ERR_NETWORK });
|
||||
}
|
||||
}
|
||||
|
|
@ -183,7 +184,7 @@ export class FileImexComponent implements OnInit {
|
|||
// Optionally, add a success snackbar here if desired
|
||||
// this._snackService.open({ type: 'SUCCESS', msg: 'Data imported successfully!' });
|
||||
} catch (e) {
|
||||
console.error('Import process failed', e);
|
||||
Log.err('Import process failed', e);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: T.FILE_IMEX.S_ERR_IMPORT_FAILED,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { T } from '../../t.const';
|
|||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { AppDataCompleteNew } from '../../pfapi/pfapi-config';
|
||||
import { SnackService } from '../../core/snack/snack.service';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
const DEFAULT_BACKUP_INTERVAL = 5 * 60 * 1000;
|
||||
const ANDROID_DB_KEY = 'backup';
|
||||
|
|
@ -72,7 +73,7 @@ export class LocalBackupService {
|
|||
)
|
||||
) {
|
||||
const backupData = await this.loadBackupElectron(backupMeta.path);
|
||||
console.log('backupData', backupData);
|
||||
Log.log('backupData', backupData);
|
||||
await this._importBackup(backupData);
|
||||
}
|
||||
|
||||
|
|
@ -83,9 +84,9 @@ export class LocalBackupService {
|
|||
confirm(this._translateService.instant(T.CONFIRM.RESTORE_FILE_BACKUP_ANDROID))
|
||||
) {
|
||||
const backupData = await this.loadBackupAndroid();
|
||||
console.log('backupData', backupData);
|
||||
Log.log('backupData', backupData);
|
||||
const lineBreaksReplaced = backupData.replace(/\n/g, '\\n');
|
||||
console.log('lineBreaksReplaced', lineBreaksReplaced);
|
||||
Log.log('lineBreaksReplaced', lineBreaksReplaced);
|
||||
await this._importBackup(lineBreaksReplaced);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import { SyncWrapperService } from '../sync-wrapper.service';
|
|||
import { Subscription } from 'rxjs';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { SyncProviderId } from '../../../pfapi/api';
|
||||
import { SyncLog } from '../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'dialog-sync-initial-cfg',
|
||||
|
|
@ -82,7 +83,7 @@ export class DialogSyncInitialCfgComponent {
|
|||
if (!this.form.valid) {
|
||||
// Mark all fields as touched to show validation errors
|
||||
this.form.markAllAsTouched();
|
||||
console.warn('Sync form validation failed', this.form.errors);
|
||||
SyncLog.err('Sync form validation failed', this.form.errors);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { SyncConfig } from '../../features/config/global-config.model';
|
|||
import { switchMap, tap } from 'rxjs/operators';
|
||||
import { PrivateCfgByProviderId, SyncProviderId } from '../../pfapi/api';
|
||||
import { DEFAULT_GLOBAL_CONFIG } from '../../features/config/default-global-config.const';
|
||||
import { SyncLog } from '../../core/log';
|
||||
|
||||
const PROP_MAP_TO_FORM: Record<SyncProviderId, keyof SyncConfig | null> = {
|
||||
[SyncProviderId.LocalFile]: 'localFileSync',
|
||||
|
|
@ -76,7 +77,7 @@ export class SyncConfigService {
|
|||
|
||||
return of(result);
|
||||
}),
|
||||
tap((v) => console.log('syncSettingsForm$', v)),
|
||||
tap((v) => SyncLog.log('syncSettingsForm$', v)),
|
||||
);
|
||||
|
||||
async updateEncryptionPassword(
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import { takeUntil } from 'rxjs/operators';
|
|||
import { T } from '../../../t.const';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
|
||||
import { SyncLog } from '../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'sync-safety-backups',
|
||||
|
|
@ -57,7 +58,7 @@ export class SyncSafetyBackupsComponent implements OnInit, OnDestroy {
|
|||
const backups = await this._syncSafetyBackupService.getBackups();
|
||||
this.backups.set(backups);
|
||||
} catch (error) {
|
||||
console.error('Failed to load backups:', error);
|
||||
SyncLog.err('Failed to load backups:', error);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: 'Failed to load safety backups',
|
||||
|
|
@ -77,7 +78,7 @@ export class SyncSafetyBackupsComponent implements OnInit, OnDestroy {
|
|||
msg: T.F.SYNC.SAFETY_BACKUP.CREATED_SUCCESS,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to create manual backup:', error);
|
||||
SyncLog.err('Failed to create manual backup:', error);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: T.F.SYNC.SAFETY_BACKUP.CREATE_FAILED,
|
||||
|
|
@ -98,7 +99,7 @@ export class SyncSafetyBackupsComponent implements OnInit, OnDestroy {
|
|||
// Reload the page after restoration
|
||||
setTimeout(() => window.location.reload(), 1000);
|
||||
} catch (error) {
|
||||
console.error('Failed to restore backup:', error);
|
||||
SyncLog.err('Failed to restore backup:', error);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: error instanceof Error ? error.message : 'Failed to restore backup',
|
||||
|
|
@ -122,7 +123,7 @@ export class SyncSafetyBackupsComponent implements OnInit, OnDestroy {
|
|||
msg: T.F.SYNC.SAFETY_BACKUP.DELETED_SUCCESS,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to delete backup:', error);
|
||||
SyncLog.err('Failed to delete backup:', error);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: T.F.SYNC.SAFETY_BACKUP.DELETE_FAILED,
|
||||
|
|
@ -145,7 +146,7 @@ export class SyncSafetyBackupsComponent implements OnInit, OnDestroy {
|
|||
msg: T.F.SYNC.SAFETY_BACKUP.CLEARED_SUCCESS,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to clear backups:', error);
|
||||
SyncLog.err('Failed to clear backups:', error);
|
||||
this._snackService.open({
|
||||
type: 'ERROR',
|
||||
msg: T.F.SYNC.SAFETY_BACKUP.CLEAR_FAILED,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import { PfapiService } from '../../pfapi/pfapi.service';
|
|||
import { DataInitStateService } from '../../core/data-init/data-init-state.service';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { selectCurrentTaskId } from '../../features/tasks/store/task.selectors';
|
||||
import { SyncLog } from '../../core/log';
|
||||
|
||||
const MAX_WAIT_FOR_INITIAL_SYNC = 25000;
|
||||
const USER_INTERACTION_SYNC_CHECK_THROTTLE_TIME = 15 * 60 * 10000;
|
||||
|
|
@ -194,7 +195,7 @@ export class SyncTriggerService {
|
|||
);
|
||||
return merge(
|
||||
// once immediately
|
||||
_immediateSyncTrigger$.pipe(tap((v) => console.log('immediate sync trigger', v))),
|
||||
_immediateSyncTrigger$.pipe(tap((v) => SyncLog.log('immediate sync trigger', v))),
|
||||
|
||||
// and once we reset the sync interval for all other triggers
|
||||
// we do this to reset the audit time to avoid sync checks in short succession
|
||||
|
|
@ -205,8 +206,8 @@ export class SyncTriggerService {
|
|||
switchMap(() =>
|
||||
// NOTE: interval changes are only ever executed, if local data was changed
|
||||
this._onUpdateLocalDataTrigger$.pipe(
|
||||
// tap((ev) => console.log('__trigger_sync__', ev.appDataKey, ev)),
|
||||
// tap((ev) => console.log('__trigger_sync__', 'I_ON_UPDATE_LOCAL_DATA', ev)),
|
||||
// tap((ev) => Log.log('__trigger_sync__', ev.appDataKey, ev)),
|
||||
// tap((ev) => Log.log('__trigger_sync__', 'I_ON_UPDATE_LOCAL_DATA', ev)),
|
||||
auditTime(Math.max(syncInterval, SYNC_MIN_INTERVAL)),
|
||||
// tap((ev) => alert('__trigger_sync after auditTime__')),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import { DialogIncompleteSyncComponent } from './dialog-incomplete-sync/dialog-i
|
|||
import { DialogHandleDecryptErrorComponent } from './dialog-handle-decrypt-error/dialog-handle-decrypt-error.component';
|
||||
import { DialogIncoherentTimestampsErrorComponent } from './dialog-incoherent-timestamps-error/dialog-incoherent-timestamps-error.component';
|
||||
import { devError } from '../../util/dev-error';
|
||||
import { SyncLog } from '../../core/log';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -127,7 +128,7 @@ export class SyncWrapperService {
|
|||
return r.status;
|
||||
|
||||
case SyncStatus.Conflict:
|
||||
console.log('Sync conflict detected:', {
|
||||
SyncLog.log('Sync conflict detected:', {
|
||||
remote: r.conflictData?.remote.lastUpdate,
|
||||
local: r.conflictData?.local.lastUpdate,
|
||||
lastSync: r.conflictData?.local.lastSyncedUpdate,
|
||||
|
|
@ -135,7 +136,7 @@ export class SyncWrapperService {
|
|||
});
|
||||
|
||||
// Enhanced debugging for vector clock issues
|
||||
console.log('CONFLICT DEBUG - Vector Clock Analysis:', {
|
||||
SyncLog.log('CONFLICT DEBUG - Vector Clock Analysis:', {
|
||||
localVectorClock: r.conflictData?.local.vectorClock,
|
||||
remoteVectorClock: r.conflictData?.remote.vectorClock,
|
||||
localLastSyncedVectorClock: r.conflictData?.local.lastSyncedVectorClock,
|
||||
|
|
@ -147,21 +148,21 @@ export class SyncWrapperService {
|
|||
).toPromise();
|
||||
|
||||
if (res === 'USE_LOCAL') {
|
||||
console.log('User chose USE_LOCAL, calling uploadAll(true) with force');
|
||||
SyncLog.log('User chose USE_LOCAL, calling uploadAll(true) with force');
|
||||
// Use force upload to skip the meta file check and ensure lastUpdate is updated
|
||||
await this._pfapiService.pf.uploadAll(true);
|
||||
console.log('uploadAll(true) completed');
|
||||
SyncLog.log('uploadAll(true) completed');
|
||||
return SyncStatus.UpdateRemoteAll;
|
||||
} else if (res === 'USE_REMOTE') {
|
||||
await this._pfapiService.pf.downloadAll();
|
||||
await this._reInitAppAfterDataModelChange();
|
||||
}
|
||||
console.log({ res });
|
||||
SyncLog.log({ res });
|
||||
|
||||
return r.status;
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
SyncLog.err(error);
|
||||
|
||||
if (error instanceof AuthFailSPError) {
|
||||
this._snackService.open({
|
||||
|
|
@ -191,7 +192,7 @@ export class SyncWrapperService {
|
|||
error instanceof RevMismatchForModelError ||
|
||||
error instanceof NoRemoteModelFile
|
||||
) {
|
||||
console.log(error, Object.keys(error));
|
||||
SyncLog.log(error, Object.keys(error));
|
||||
const modelId = error.additionalLog;
|
||||
this._matDialog
|
||||
.open(DialogIncompleteSyncComponent, {
|
||||
|
|
@ -226,7 +227,7 @@ export class SyncWrapperService {
|
|||
return 'HANDLED_ERROR';
|
||||
} else if (error?.message === 'Sync already in progress') {
|
||||
// Silently ignore concurrent sync attempts
|
||||
console.log('Sync already in progress, skipping concurrent sync attempt');
|
||||
SyncLog.log('Sync already in progress, skipping concurrent sync attempt');
|
||||
return 'HANDLED_ERROR';
|
||||
} else {
|
||||
const errStr = getSyncErrorStr(error);
|
||||
|
|
@ -307,7 +308,7 @@ export class SyncWrapperService {
|
|||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
SyncLog.err(error);
|
||||
this._snackService.open({
|
||||
// TODO don't limit snack to dropbox
|
||||
msg: T.F.DROPBOX.S.UNABLE_TO_GENERATE_PKCE_CHALLENGE,
|
||||
|
|
@ -336,7 +337,7 @@ export class SyncWrapperService {
|
|||
}
|
||||
|
||||
private async _reInitAppAfterDataModelChange(): Promise<void> {
|
||||
console.log('Starting data re-initialization after sync...');
|
||||
SyncLog.log('Starting data re-initialization after sync...');
|
||||
|
||||
try {
|
||||
await Promise.all([
|
||||
|
|
@ -344,11 +345,11 @@ export class SyncWrapperService {
|
|||
this._reminderService.reloadFromDatabase(),
|
||||
]);
|
||||
|
||||
console.log('Data re-initialization complete');
|
||||
SyncLog.log('Data re-initialization complete');
|
||||
// Signal that data reload is complete
|
||||
this._dataReloadComplete$.next();
|
||||
} catch (error) {
|
||||
console.error('Error during data re-initialization:', error);
|
||||
SyncLog.err('Error during data re-initialization:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import { SyncWrapperService } from './sync-wrapper.service';
|
|||
import { getSyncErrorStr } from './get-sync-error-str';
|
||||
import { InitialPwaUpdateCheckService } from '../../core/initial-pwa-update-check.service';
|
||||
import { DataInitStateService } from '../../core/data-init/data-init-state.service';
|
||||
import { SyncLog } from '../../core/log';
|
||||
|
||||
@Injectable()
|
||||
export class SyncEffects {
|
||||
|
|
@ -72,7 +73,7 @@ export class SyncEffects {
|
|||
this._execBeforeCloseService.setDone(SYNC_BEFORE_CLOSE_ID);
|
||||
})
|
||||
.catch((e: unknown) => {
|
||||
console.error(e);
|
||||
SyncLog.err(e);
|
||||
this._snackService.open({
|
||||
msg: T.F.DROPBOX.S.SYNC_ERROR,
|
||||
type: 'ERROR',
|
||||
|
|
@ -132,7 +133,7 @@ export class SyncEffects {
|
|||
// this._wasJustEnabled$.pipe(take(1), mapTo('SYNC_DBX_AFTER_ENABLE')),
|
||||
),
|
||||
),
|
||||
tap((x) => console.log('sync(effect).....', x)),
|
||||
tap((x) => SyncLog.log('sync(effect).....', x)),
|
||||
withLatestFrom(isOnline$),
|
||||
// don't run multiple after each other when dialog is open
|
||||
exhaustMap(([trigger, isOnline]) => {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ import { createPluginShortcutFormItems } from '../../features/config/form-cfgs/p
|
|||
import { PluginService } from '../../plugins/plugin.service';
|
||||
import { PluginShortcutCfg } from '../../plugins/plugin-api.model';
|
||||
import { ThemeSelectorComponent } from '../../core/theme/theme-selector/theme-selector.component';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'config-page',
|
||||
|
|
@ -96,7 +97,7 @@ export class ConfigPageComponent implements OnInit, OnDestroy {
|
|||
};
|
||||
}),
|
||||
)
|
||||
.pipe(tap((v) => console.log('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXA', v)));
|
||||
.pipe(tap((v) => Log.log('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXA', v)));
|
||||
|
||||
private _subs: Subscription = new Subscription();
|
||||
|
||||
|
|
@ -131,7 +132,7 @@ export class ConfigPageComponent implements OnInit, OnDestroy {
|
|||
// Subscribe to plugin shortcuts changes for live updates
|
||||
this._subs.add(
|
||||
this._pluginBridgeService.shortcuts$.subscribe((shortcuts) => {
|
||||
console.log('Plugin shortcuts changed:', { shortcuts });
|
||||
Log.log('Plugin shortcuts changed:', { shortcuts });
|
||||
this._updateKeyboardFormWithPluginShortcuts(shortcuts);
|
||||
}),
|
||||
);
|
||||
|
|
@ -144,7 +145,7 @@ export class ConfigPageComponent implements OnInit, OnDestroy {
|
|||
);
|
||||
|
||||
if (keyboardFormIndex === -1) {
|
||||
console.warn('Keyboard form section not found');
|
||||
Log.err('Keyboard form section not found');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -172,9 +173,9 @@ export class ConfigPageComponent implements OnInit, OnDestroy {
|
|||
if (shortcuts.length > 0) {
|
||||
const pluginShortcutItems = createPluginShortcutFormItems(shortcuts);
|
||||
newItems = [...filteredItems, ...pluginShortcutItems];
|
||||
console.log(`Updated keyboard form with ${shortcuts.length} plugin shortcuts`);
|
||||
Log.log(`Updated keyboard form with ${shortcuts.length} plugin shortcuts`);
|
||||
} else {
|
||||
console.log('No plugin shortcuts to add to keyboard form');
|
||||
Log.log('No plugin shortcuts to add to keyboard form');
|
||||
}
|
||||
|
||||
// Create a new keyboard section object to trigger change detection
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { CompressError, DecompressError } from '../errors/errors';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
|
||||
export async function compressWithGzipToString(input: string): Promise<string> {
|
||||
|
|
@ -24,7 +25,7 @@ export async function compressWithGzipToString(input: string): Promise<string> {
|
|||
|
||||
return base64;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Log.err(error);
|
||||
throw new CompressError(error);
|
||||
}
|
||||
}
|
||||
|
|
@ -51,7 +52,7 @@ export async function decompressGzipFromString(
|
|||
// SyncLog.normal( 'Decompression stats', { decompressedLength: decoded.length });
|
||||
return decoded;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Log.err(error);
|
||||
throw new DecompressError(error);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { DatabaseAdapter } from './database-adapter.model';
|
||||
import { SyncLog } from '../../../core/log';
|
||||
import { devError } from '../../../util/dev-error';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
export class Database {
|
||||
private static readonly L = 'Database';
|
||||
|
|
@ -76,27 +77,27 @@ export class Database {
|
|||
async remove(key: string, isIgnoreDBLock = false): Promise<unknown> {
|
||||
this._lastParams = { a: 'remove', key };
|
||||
if (this._isLocked && !isIgnoreDBLock) {
|
||||
console.warn('Blocking write during lock');
|
||||
Log.err('Blocking write during lock');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
return await this._adapter.remove(key);
|
||||
} catch (e) {
|
||||
console.warn('DB Remove Error: Last Params,', this._lastParams);
|
||||
Log.err('DB Remove Error: Last Params,', this._lastParams);
|
||||
return this._errorHandler(e as Error, this.remove, [key]);
|
||||
}
|
||||
}
|
||||
|
||||
async clearDatabase(isIgnoreDBLock = false): Promise<unknown> {
|
||||
if (this._isLocked && !isIgnoreDBLock) {
|
||||
console.warn('Blocking write during lock');
|
||||
Log.err('Blocking write during lock');
|
||||
return;
|
||||
}
|
||||
this._lastParams = { a: 'clearDatabase' };
|
||||
try {
|
||||
return await this._adapter.clearDatabase();
|
||||
} catch (e) {
|
||||
console.warn('DB Clear Error: Last Params,', this._lastParams);
|
||||
Log.err('DB Clear Error: Last Params,', this._lastParams);
|
||||
return this._errorHandler(e as Error, this.clearDatabase, []);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,17 +86,17 @@ export async function decrypt(data: string, password: string): Promise<string> {
|
|||
// TESTING CODE
|
||||
// export const testCrypto = async (): Promise<void> => {
|
||||
// const enc = await encrypt('HAHAHHA', '1234');
|
||||
// console.log('enc', enc);
|
||||
// Log.log('enc', enc);
|
||||
// decrypt(enc, '1234')
|
||||
// .then((r) => {
|
||||
// console.log('YEAH', r);
|
||||
// Log.log('YEAH', r);
|
||||
// })
|
||||
// .catch((r) => {
|
||||
// console.log('NOOO', r);
|
||||
// Log.log('NOOO', r);
|
||||
// });
|
||||
//
|
||||
// const decrypted = await decrypt(enc, '1234');
|
||||
// console.log('decrypted', decrypted);
|
||||
// Log.log('decrypted', decrypted);
|
||||
// };
|
||||
//
|
||||
// testCrypto();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { IValidation } from 'typia';
|
||||
import { AllModelData } from '../pfapi.model';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
class AdditionalLogErrorBase<T = unknown[]> extends Error {
|
||||
additionalLog: T;
|
||||
|
|
@ -10,11 +11,11 @@ class AdditionalLogErrorBase<T = unknown[]> extends Error {
|
|||
|
||||
if (additional.length > 0) {
|
||||
// SyncLog.critical( this.name, ...additional);
|
||||
console.log(this.name, ...additional);
|
||||
Log.log(this.name, ...additional);
|
||||
try {
|
||||
console.log('additional error log: ' + JSON.stringify(additional));
|
||||
Log.log('additional error log: ' + JSON.stringify(additional));
|
||||
} catch (e) {
|
||||
console.log('additional error log not stringified: ', additional, e);
|
||||
Log.log('additional error log not stringified: ', additional, e);
|
||||
}
|
||||
}
|
||||
this.additionalLog = additional as T;
|
||||
|
|
@ -201,24 +202,24 @@ export class ModelValidationError extends Error {
|
|||
e?: unknown;
|
||||
}) {
|
||||
super('ModelValidationError');
|
||||
console.log(`ModelValidationError for model ${params.id}:`, params);
|
||||
Log.log(`ModelValidationError for model ${params.id}:`, params);
|
||||
|
||||
if (params.validationResult) {
|
||||
console.log('validation result: ', params.validationResult);
|
||||
Log.log('validation result: ', params.validationResult);
|
||||
|
||||
try {
|
||||
if ('errors' in params.validationResult) {
|
||||
const str = JSON.stringify(params.validationResult.errors);
|
||||
console.log('validation errors: ' + str);
|
||||
Log.log('validation errors: ' + str);
|
||||
this.additionalLog = `Model: ${params.id}, Errors: ${str.substring(0, 400)}`;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error stringifying validation errors:', e);
|
||||
Log.err('Error stringifying validation errors:', e);
|
||||
}
|
||||
}
|
||||
|
||||
if (params.e) {
|
||||
console.log('Additional error:', params.e);
|
||||
Log.log('Additional error:', params.e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -229,17 +230,17 @@ export class DataValidationFailedError extends Error {
|
|||
|
||||
constructor(validationResult: IValidation<AllModelData<any>>) {
|
||||
super('DataValidationFailedError');
|
||||
console.log('validation result: ', validationResult);
|
||||
Log.log('validation result: ', validationResult);
|
||||
|
||||
try {
|
||||
if ('errors' in validationResult) {
|
||||
const str = JSON.stringify(validationResult.errors);
|
||||
console.log('validation errors_: ' + str);
|
||||
Log.log('validation errors_: ' + str);
|
||||
this.additionalLog = str.substring(0, 400);
|
||||
}
|
||||
console.log('validation result_: ' + JSON.stringify(validationResult));
|
||||
Log.log('validation result_: ' + JSON.stringify(validationResult));
|
||||
} catch (e) {
|
||||
console.error('Failed to stringify validation errors:', e);
|
||||
Log.err('Failed to stringify validation errors:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import { promiseTimeout } from '../../util/promise-timeout';
|
|||
import { PFEventEmitter } from './util/events';
|
||||
import { MigrationService } from './migration/migration.service';
|
||||
import { IValidation } from 'typia';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
export class Pfapi<const MD extends ModelCfgs> {
|
||||
private static _wasInstanceCreated = false;
|
||||
|
|
@ -371,10 +372,10 @@ export class Pfapi<const MD extends ModelCfgs> {
|
|||
await this.tmpBackupService.save(await this.getAllSyncModelData());
|
||||
} catch (error) {
|
||||
SyncLog.critical(this.importAllSycModelData.name, error);
|
||||
console.warn(
|
||||
Log.err(
|
||||
'Could not create valid backup. Onwards on the highway throug the Danger Zone!',
|
||||
);
|
||||
console.error(error);
|
||||
Log.err(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -386,7 +387,7 @@ export class Pfapi<const MD extends ModelCfgs> {
|
|||
const modelData = data[modelId];
|
||||
const modelCtrl = this.m[modelId];
|
||||
if (!modelCtrl) {
|
||||
console.warn('ModelId without Ctrl', modelId, modelData);
|
||||
Log.err('ModelId without Ctrl', modelId, modelData);
|
||||
if (
|
||||
SKIPPED_MODEL_IDS.includes(modelId) ||
|
||||
isSkipLegacyWarnings ||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* eslint-disable */
|
||||
import { Capacitor, registerPlugin } from '@capacitor/core';
|
||||
import { Log } from '../../../../../../core/log';
|
||||
|
||||
// Define the plugin interface for SAF operations
|
||||
export interface SafPlugin {
|
||||
|
|
@ -70,7 +71,7 @@ export class SafService {
|
|||
const result = await SafBridge.checkUriPermission({ uri });
|
||||
return result.hasPermission;
|
||||
} catch (error) {
|
||||
console.error('Error checking SAF permission:', error);
|
||||
Log.err('Error checking SAF permission:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -109,7 +110,7 @@ export class SafService {
|
|||
const result = await SafBridge.checkFileExists({ uri, fileName });
|
||||
return result.exists;
|
||||
} catch (error) {
|
||||
console.error('Error checking file existence:', error);
|
||||
Log.err('Error checking file existence:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { SyncLog } from '../../../core/log';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
/**
|
||||
* Vector Clock implementation for distributed synchronization
|
||||
|
|
@ -124,15 +125,15 @@ export const compareVectorClocks = (
|
|||
): VectorClockComparison => {
|
||||
// Handle null/undefined cases
|
||||
if (isVectorClockEmpty(a) && isVectorClockEmpty(b)) {
|
||||
console.warn('BOTH VECTOR CLOCKS EMPTY!!!');
|
||||
Log.err('BOTH VECTOR CLOCKS EMPTY!!!');
|
||||
return VectorClockComparison.CONCURRENT;
|
||||
}
|
||||
if (isVectorClockEmpty(a)) {
|
||||
console.warn('EMPTY VECTOR CLOCK a !!!');
|
||||
Log.err('EMPTY VECTOR CLOCK a !!!');
|
||||
return VectorClockComparison.CONCURRENT;
|
||||
}
|
||||
if (isVectorClockEmpty(b)) {
|
||||
console.warn('EMPTY VECTOR CLOCK b !!!');
|
||||
Log.err('EMPTY VECTOR CLOCK b !!!');
|
||||
return VectorClockComparison.CONCURRENT;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,11 +17,12 @@ import {
|
|||
initialBoardsState,
|
||||
} from '../../features/boards/store/boards.reducer';
|
||||
import { DEFAULT_BOARD_CFG, DEFAULT_PANEL_CFG } from '../../features/boards/boards.const';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
export const crossModelMigration2: CrossModelMigrateFn = ((
|
||||
fullData: AppDataCompleteLegacy,
|
||||
): AppDataCompleteNew => {
|
||||
console.log('____________________Migrate2__________________');
|
||||
Log.log('____________________Migrate2__________________');
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { lastLocalSyncModelChange, lastArchiveUpdate, taskArchive, ...copy } = fullData;
|
||||
|
||||
|
|
@ -33,10 +34,10 @@ export const crossModelMigration2: CrossModelMigrateFn = ((
|
|||
Object.keys((fullData as any as AppDataCompleteNew).timeTracking.project).length
|
||||
) {
|
||||
// If time tracking is already migrated, return the original data
|
||||
console.warn('already migrated despite old model version!!!');
|
||||
Log.err('already migrated despite old model version!!!');
|
||||
return fullData as any as AppDataCompleteNew;
|
||||
}
|
||||
console.log(':::::::::::crossModelMigration2::::::::::::::');
|
||||
Log.log(':::::::::::crossModelMigration2::::::::::::::');
|
||||
|
||||
// Migrate project time tracking data
|
||||
const projectTimeTracking: TTWorkContextSessionMap = Object.keys(
|
||||
|
|
@ -126,7 +127,7 @@ export const crossModelMigration2: CrossModelMigrateFn = ((
|
|||
},
|
||||
{} as TTWorkContextSessionMap,
|
||||
);
|
||||
console.log('________________________________________________________', {
|
||||
Log.log('________________________________________________________', {
|
||||
copy,
|
||||
projectTimeTracking,
|
||||
tagTimeTracking,
|
||||
|
|
|
|||
|
|
@ -13,13 +13,14 @@ import {
|
|||
import { ProjectState } from '../../features/project/project.model';
|
||||
import { DEFAULT_GLOBAL_CONFIG } from '../../features/config/default-global-config.const';
|
||||
import { issueProviderInitialState } from '../../features/issue/store/issue-provider.reducer';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
const LEGACY_INBOX_PROJECT_ID = 'INBOX' as const;
|
||||
|
||||
export const crossModelMigration3: CrossModelMigrateFn = ((
|
||||
fullData: AppDataCompleteNew,
|
||||
): AppDataCompleteNew => {
|
||||
console.log('____________________Migrate3__________________');
|
||||
Log.log('____________________Migrate3__________________');
|
||||
const copy = fullData;
|
||||
|
||||
if (copy.planner) {
|
||||
|
|
@ -153,7 +154,7 @@ export const crossModelMigration3: CrossModelMigrateFn = ((
|
|||
}
|
||||
});
|
||||
|
||||
console.log(copy);
|
||||
Log.log(copy);
|
||||
return copy;
|
||||
}) as CrossModelMigrateFn;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ import { CrossModelMigrateFn } from '../api';
|
|||
import { TaskCopy } from '../../features/tasks/task.model';
|
||||
import { EntityState } from '@ngrx/entity';
|
||||
import { TODAY_TAG } from '../../features/tag/tag.const';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
export const crossModelMigration4: CrossModelMigrateFn = ((
|
||||
fullData: AppDataCompleteNew,
|
||||
): AppDataCompleteNew => {
|
||||
// throw new Error('Migration 4 is not implemented yet');
|
||||
console.log('____________________Migrate4__________________');
|
||||
Log.log('____________________Migrate4__________________');
|
||||
const copy = fullData;
|
||||
|
||||
if (!Array.isArray(copy.improvement.hiddenImprovementBannerItems)) {
|
||||
|
|
@ -22,7 +23,7 @@ export const crossModelMigration4: CrossModelMigrateFn = ((
|
|||
// @ts-ignore
|
||||
// copy.tag.entities[TODAY_TAG.id].taskIds = [];
|
||||
|
||||
console.log(copy);
|
||||
Log.log(copy);
|
||||
return copy;
|
||||
}) as CrossModelMigrateFn;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import { AppDataCompleteNew } from '../pfapi-config';
|
||||
import { CrossModelMigrateFn } from '../api';
|
||||
import { TODAY_TAG } from '../../features/tag/tag.const';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
export const crossModelMigration4_1: CrossModelMigrateFn = ((
|
||||
fullData: AppDataCompleteNew,
|
||||
): AppDataCompleteNew => {
|
||||
// throw new Error('Migration 4 is not implemented yet');
|
||||
console.log('____________________Migrate4.1__________________');
|
||||
Log.log('____________________Migrate4.1__________________');
|
||||
const copy = fullData;
|
||||
|
||||
Object.keys(copy.taskRepeatCfg.entities).forEach((id) => {
|
||||
|
|
@ -21,6 +22,6 @@ export const crossModelMigration4_1: CrossModelMigrateFn = ((
|
|||
// @ts-ignore
|
||||
// copy.tag.entities[TODAY_TAG.id].taskIds = [];
|
||||
|
||||
console.log(copy);
|
||||
Log.log(copy);
|
||||
return copy;
|
||||
}) as CrossModelMigrateFn;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import { CROSS_MODEL_MIGRATIONS } from './migrate/cross-model-migrations';
|
|||
import { appDataValidators, validateAllData } from './validate/validation-fn';
|
||||
import { fixEntityStateConsistency } from '../util/check-fix-entity-state-consistency';
|
||||
import { IValidation } from 'typia';
|
||||
import { Log } from '../core/log';
|
||||
import {
|
||||
initialPluginMetaDataState,
|
||||
initialPluginUserDataState,
|
||||
|
|
@ -268,7 +269,7 @@ export const PFAPI_CFG: PfapiBaseCfg<PfapiAllModelCfg> = {
|
|||
return r;
|
||||
},
|
||||
onDbError: (err) => {
|
||||
console.error(err);
|
||||
Log.err(err);
|
||||
alert('DB ERROR: ' + err);
|
||||
},
|
||||
repair: (data: any, errors: IValidation.IError[]) => {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import {
|
|||
import { fromPfapiEvent, pfapiEventAndInitialAfter } from './pfapi-helper';
|
||||
import { DataInitStateService } from '../core/data-init/data-init-state.service';
|
||||
import { GlobalProgressBarService } from '../core-ui/global-progress-bar/global-progress-bar.service';
|
||||
import { Log } from '../core/log';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -59,7 +60,7 @@ export class PfapiService {
|
|||
).pipe(
|
||||
shareReplay(1),
|
||||
distinctUntilChanged(),
|
||||
// tap((v) => console.log(`isSyncProviderEnabledAndReady$`, v)),
|
||||
// tap((v) => Log.log(`isSyncProviderEnabledAndReady$`, v)),
|
||||
);
|
||||
|
||||
public readonly currentProviderPrivateCfg$ = pfapiEventAndInitialAfter(
|
||||
|
|
@ -105,9 +106,9 @@ export class PfapiService {
|
|||
|
||||
constructor() {
|
||||
// TODO check why it gets triggered twice always
|
||||
// this.syncState$.subscribe((v) => console.log(`syncState$`, v));
|
||||
// this.syncState$.subscribe((v) => Log.log(`syncState$`, v));
|
||||
this.isSyncInProgress$.subscribe((v) => {
|
||||
// console.log('isSyncInProgress$', v);
|
||||
// Log.log('isSyncInProgress$', v);
|
||||
if (v) {
|
||||
this._globalProgressBarService.countUp('SYNC');
|
||||
} else {
|
||||
|
|
@ -127,7 +128,7 @@ export class PfapiService {
|
|||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
Log.err(e);
|
||||
alert('Unable to set sync provider. Please check your settings.');
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { AppDataCompleteNew } from '../pfapi-config';
|
||||
import { IValidation } from 'typia';
|
||||
import { DEFAULT_GLOBAL_CONFIG } from '../../features/config/default-global-config.const';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
export const autoFixTypiaErrors = (
|
||||
data: AppDataCompleteNew,
|
||||
|
|
@ -15,7 +16,7 @@ export const autoFixTypiaErrors = (
|
|||
const path = error.path.replace('$input.', '');
|
||||
const keys = parsePath(path);
|
||||
const value = getValueByPath(data, keys);
|
||||
console.warn('Auto-fixing error:', error, keys, value);
|
||||
Log.err('Auto-fixing error:', error, keys, value);
|
||||
|
||||
if (
|
||||
error.expected.includes('number') &&
|
||||
|
|
@ -24,7 +25,7 @@ export const autoFixTypiaErrors = (
|
|||
) {
|
||||
const parsedValue = parseFloat(value);
|
||||
setValueByPath(data, keys, parsedValue);
|
||||
console.warn(`Fixed: ${path} from string "${value}" to number ${parsedValue}`);
|
||||
Log.err(`Fixed: ${path} from string "${value}" to number ${parsedValue}`);
|
||||
} else if (keys[0] === 'globalConfig') {
|
||||
const defaultValue = getValueByPath(DEFAULT_GLOBAL_CONFIG, keys.slice(1));
|
||||
setValueByPath(data, keys, defaultValue);
|
||||
|
|
@ -33,29 +34,27 @@ export const autoFixTypiaErrors = (
|
|||
);
|
||||
} else if (error.expected.includes('undefined') && value === null) {
|
||||
setValueByPath(data, keys, undefined);
|
||||
console.warn(`Fixed: ${path} from null to undefined`);
|
||||
Log.err(`Fixed: ${path} from null to undefined`);
|
||||
} else if (error.expected.includes('null') && value === 'null') {
|
||||
setValueByPath(data, keys, null);
|
||||
console.warn(`Fixed: ${path} from string null to null`);
|
||||
Log.err(`Fixed: ${path} from string null to null`);
|
||||
} else if (error.expected.includes('undefined') && value === 'null') {
|
||||
setValueByPath(data, keys, undefined);
|
||||
console.warn(`Fixed: ${path} from string null to null`);
|
||||
Log.err(`Fixed: ${path} from string null to null`);
|
||||
} else if (error.expected.includes('null') && value === undefined) {
|
||||
setValueByPath(data, keys, null);
|
||||
console.warn(`Fixed: ${path} from undefined to null`);
|
||||
Log.err(`Fixed: ${path} from undefined to null`);
|
||||
} else if (error.expected.includes('boolean') && !value) {
|
||||
setValueByPath(data, keys, false);
|
||||
console.warn(`Fixed: ${path} to false (was ${value})`);
|
||||
Log.err(`Fixed: ${path} to false (was ${value})`);
|
||||
} else if (keys[0] === 'task' && error.expected.includes('number')) {
|
||||
// If the value is a string that can be parsed to a number, parse it
|
||||
if (typeof value === 'string' && !isNaN(parseFloat(value))) {
|
||||
setValueByPath(data, keys, parseFloat(value));
|
||||
console.warn(
|
||||
`Fixed: ${path} from string "${value}" to number ${parseFloat(value)}`,
|
||||
);
|
||||
Log.err(`Fixed: ${path} from string "${value}" to number ${parseFloat(value)}`);
|
||||
} else {
|
||||
setValueByPath(data, keys, 0);
|
||||
console.warn(`Fixed: ${path} to 0 (was ${value})`);
|
||||
Log.err(`Fixed: ${path} to 0 (was ${value})`);
|
||||
}
|
||||
} else if (
|
||||
keys[0] === 'simpleCounter' &&
|
||||
|
|
@ -67,7 +66,7 @@ export const autoFixTypiaErrors = (
|
|||
) {
|
||||
// Fix for issue #4593: simpleCounter countOnDay null value
|
||||
setValueByPath(data, keys, 0);
|
||||
console.warn(`Fixed: ${path} from null to 0 for simpleCounter`);
|
||||
Log.err(`Fixed: ${path} from null to 0 for simpleCounter`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -109,7 +108,7 @@ const setValueByPath = <T extends object>(
|
|||
value: any,
|
||||
): void => {
|
||||
if (!Array.isArray(path) || path.length === 0) return;
|
||||
console.warn('Auto-fixing error =>', path, value);
|
||||
Log.err('Auto-fixing error =>', path, value);
|
||||
|
||||
let current: any = obj;
|
||||
for (let i = 0; i < path.length - 1; i++) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import { AppDataCompleteNew } from '../pfapi-config';
|
|||
import { INBOX_PROJECT } from '../../features/project/project.const';
|
||||
import { autoFixTypiaErrors } from './auto-fix-typia-errors';
|
||||
import { IValidation } from 'typia';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
// TODO improve later
|
||||
const ENTITY_STATE_KEYS: (keyof AppDataCompleteLegacy)[] = ALL_ENTITY_MODEL_KEYS;
|
||||
|
|
@ -123,7 +124,7 @@ const _removeDuplicatesFromArchive = (data: AppDataCompleteNew): AppDataComplete
|
|||
}
|
||||
});
|
||||
if (duplicateIds.length > 0) {
|
||||
console.log(duplicateIds.length + ' duplicates removed from archive.');
|
||||
Log.log(duplicateIds.length + ' duplicates removed from archive.');
|
||||
}
|
||||
}
|
||||
return data;
|
||||
|
|
@ -153,7 +154,7 @@ const _moveArchivedSubTasksToUnarchivedParents = (
|
|||
.map((id: string) => taskArchiveState.entities[id] as TaskCopy)
|
||||
.filter((t: TaskCopy) => t.parentId && !taskArchiveState.ids.includes(t.parentId));
|
||||
|
||||
console.log('orphanArchivedSubTasks', orphanArchivedSubTasks);
|
||||
Log.log('orphanArchivedSubTasks', orphanArchivedSubTasks);
|
||||
orphanArchivedSubTasks.forEach((t: TaskCopy) => {
|
||||
// delete archived if duplicate
|
||||
if (taskState.ids.includes(t.id as string)) {
|
||||
|
|
@ -197,7 +198,7 @@ const _moveUnArchivedSubTasksToArchivedParents = (
|
|||
.map((id: string) => taskState.entities[id] as TaskCopy)
|
||||
.filter((t: TaskCopy) => t.parentId && !taskState.ids.includes(t.parentId));
|
||||
|
||||
console.log('orphanUnArchivedSubTasks', orphanUnArchivedSubTasks);
|
||||
Log.log('orphanUnArchivedSubTasks', orphanUnArchivedSubTasks);
|
||||
orphanUnArchivedSubTasks.forEach((t: TaskCopy) => {
|
||||
// delete un-archived if duplicate
|
||||
if (taskArchiveState.ids.includes(t.id as string)) {
|
||||
|
|
@ -275,9 +276,7 @@ const _removeMissingTasksFromListsOrRestoreFromArchive = (
|
|||
);
|
||||
|
||||
if (taskIdsToRestoreFromArchive.length > 0) {
|
||||
console.log(
|
||||
taskIdsToRestoreFromArchive.length + ' missing tasks restored from archive.',
|
||||
);
|
||||
Log.log(taskIdsToRestoreFromArchive.length + ' missing tasks restored from archive.');
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
|
@ -326,7 +325,7 @@ const _addOrphanedTasksToProjectLists = (
|
|||
});
|
||||
|
||||
if (orphanedTaskIds.length > 0) {
|
||||
console.log(orphanedTaskIds.length + ' orphaned tasks found & restored.');
|
||||
Log.log(orphanedTaskIds.length + ' orphaned tasks found & restored.');
|
||||
}
|
||||
|
||||
return data;
|
||||
|
|
@ -349,7 +348,7 @@ const _addInboxProjectIdIfNecessary = (data: AppDataCompleteNew): AppDataComplet
|
|||
taskIds.forEach((id) => {
|
||||
const t = task.entities[id] as TaskCopy;
|
||||
if (!t.projectId) {
|
||||
console.log('Set inbox project id for task ' + t.id);
|
||||
Log.log('Set inbox project id for task ' + t.id);
|
||||
// @ts-ignore
|
||||
data.project.entities[INBOX_PROJECT.id].taskIds = [
|
||||
...(data.project.entities[INBOX_PROJECT.id]!.taskIds as string[]),
|
||||
|
|
@ -364,13 +363,13 @@ const _addInboxProjectIdIfNecessary = (data: AppDataCompleteNew): AppDataComplet
|
|||
}
|
||||
});
|
||||
|
||||
console.log(taskArchiveIds);
|
||||
console.log(Object.keys(archiveYoung.task.entities));
|
||||
Log.log(taskArchiveIds);
|
||||
Log.log(Object.keys(archiveYoung.task.entities));
|
||||
|
||||
taskArchiveIds.forEach((id) => {
|
||||
const t = archiveYoung.task.entities[id] as TaskCopy;
|
||||
if (!t.projectId) {
|
||||
console.log('Set inbox project for missing project id from archive task ' + t.id);
|
||||
Log.log('Set inbox project for missing project id from archive task ' + t.id);
|
||||
t.projectId = INBOX_PROJECT.id;
|
||||
}
|
||||
// while we are at it, we also cleanup the today tag
|
||||
|
|
@ -406,19 +405,19 @@ const _removeNonExistentProjectIdsFromTasks = (
|
|||
taskIds.forEach((id) => {
|
||||
const t = task.entities[id] as TaskCopy;
|
||||
if (t.projectId && !projectIds.includes(t.projectId)) {
|
||||
console.log('Delete missing project id from task ' + t.projectId);
|
||||
Log.log('Delete missing project id from task ' + t.projectId);
|
||||
// @ts-ignore
|
||||
delete t.projectId;
|
||||
}
|
||||
});
|
||||
|
||||
console.log(taskArchiveIds);
|
||||
console.log(Object.keys(archiveYoung.task.entities));
|
||||
Log.log(taskArchiveIds);
|
||||
Log.log(Object.keys(archiveYoung.task.entities));
|
||||
|
||||
taskArchiveIds.forEach((id) => {
|
||||
const t = archiveYoung.task.entities[id] as TaskCopy;
|
||||
if (t.projectId && !projectIds.includes(t.projectId)) {
|
||||
console.log('Delete missing project id from archive task ' + t.projectId);
|
||||
Log.log('Delete missing project id from archive task ' + t.projectId);
|
||||
// @ts-ignore
|
||||
delete t.projectId;
|
||||
}
|
||||
|
|
@ -458,7 +457,7 @@ const _removeNonExistentTagsFromTasks = (
|
|||
(tagId) => !tagIds.includes(tagId) && tagId !== TODAY_TAG.id,
|
||||
);
|
||||
if (removedTags.length > 0) {
|
||||
console.log(
|
||||
Log.log(
|
||||
`Removing non-existent tags from task ${t.id}: ${removedTags.join(', ')}`,
|
||||
);
|
||||
removedCount += removedTags.length;
|
||||
|
|
@ -478,7 +477,7 @@ const _removeNonExistentTagsFromTasks = (
|
|||
(tagId) => !tagIds.includes(tagId) && tagId !== TODAY_TAG.id,
|
||||
);
|
||||
if (removedTags.length > 0) {
|
||||
console.log(
|
||||
Log.log(
|
||||
`Removing non-existent tags from archive task ${t.id}: ${removedTags.join(', ')}`,
|
||||
);
|
||||
removedCount += removedTags.length;
|
||||
|
|
@ -489,7 +488,7 @@ const _removeNonExistentTagsFromTasks = (
|
|||
});
|
||||
|
||||
if (removedCount > 0) {
|
||||
console.log(`Total non-existent tags removed from tasks: ${removedCount}`);
|
||||
Log.log(`Total non-existent tags removed from tasks: ${removedCount}`);
|
||||
}
|
||||
|
||||
return data;
|
||||
|
|
@ -504,7 +503,7 @@ const _removeNonExistentProjectIdsFromIssueProviders = (
|
|||
issueProviderIds.forEach((id) => {
|
||||
const t = issueProvider.entities[id] as IssueProvider;
|
||||
if (t.defaultProjectId && !projectIds.includes(t.defaultProjectId)) {
|
||||
console.log('Delete missing project id from issueProvider ' + t.defaultProjectId);
|
||||
Log.log('Delete missing project id from issueProvider ' + t.defaultProjectId);
|
||||
t.defaultProjectId = null;
|
||||
}
|
||||
});
|
||||
|
|
@ -522,18 +521,14 @@ const _removeNonExistentProjectIdsFromTaskRepeatCfg = (
|
|||
const repeatCfg = taskRepeatCfg.entities[id] as TaskRepeatCfgCopy;
|
||||
if (repeatCfg.projectId && !projectIds.includes(repeatCfg.projectId)) {
|
||||
if (repeatCfg.tagIds.length) {
|
||||
console.log(
|
||||
'Delete missing project id from task repeat cfg ' + repeatCfg.projectId,
|
||||
);
|
||||
Log.log('Delete missing project id from task repeat cfg ' + repeatCfg.projectId);
|
||||
repeatCfg.projectId = null;
|
||||
} else {
|
||||
taskRepeatCfg.ids = (taskRepeatCfg.ids as string[]).filter(
|
||||
(rid: string) => rid !== repeatCfg.id,
|
||||
);
|
||||
delete taskRepeatCfg.entities[repeatCfg.id];
|
||||
console.log(
|
||||
'Delete task repeat cfg with missing project id' + repeatCfg.projectId,
|
||||
);
|
||||
Log.log('Delete task repeat cfg with missing project id' + repeatCfg.projectId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -547,7 +542,7 @@ const _cleanupNonExistingTasksFromLists = (
|
|||
projectIds.forEach((pid) => {
|
||||
const projectItem = data.project.entities[pid];
|
||||
if (!projectItem) {
|
||||
console.log(data.project);
|
||||
Log.log(data.project);
|
||||
throw new Error('No project');
|
||||
}
|
||||
(projectItem as ProjectCopy).taskIds = projectItem.taskIds.filter(
|
||||
|
|
@ -562,7 +557,7 @@ const _cleanupNonExistingTasksFromLists = (
|
|||
.map((id) => data.tag.entities[id])
|
||||
.forEach((tagItem) => {
|
||||
if (!tagItem) {
|
||||
console.log(data.tag);
|
||||
Log.log(data.tag);
|
||||
throw new Error('No tag');
|
||||
}
|
||||
(tagItem as TagCopy).taskIds = tagItem.taskIds.filter(
|
||||
|
|
@ -579,7 +574,7 @@ const _cleanupNonExistingNotesFromLists = (
|
|||
projectIds.forEach((pid) => {
|
||||
const projectItem = data.project.entities[pid];
|
||||
if (!projectItem) {
|
||||
console.log(data.project);
|
||||
Log.log(data.project);
|
||||
throw new Error('No project');
|
||||
}
|
||||
(projectItem as ProjectCopy).noteIds = (projectItem as ProjectCopy).noteIds
|
||||
|
|
@ -600,7 +595,7 @@ const _fixOrphanedNotes = (data: AppDataCompleteNew): AppDataCompleteNew => {
|
|||
noteIds.forEach((nId) => {
|
||||
const note = data.note.entities[nId];
|
||||
if (!note) {
|
||||
console.log(data.note);
|
||||
Log.log(data.note);
|
||||
throw new Error('No note');
|
||||
}
|
||||
// missing project case
|
||||
|
|
@ -608,7 +603,7 @@ const _fixOrphanedNotes = (data: AppDataCompleteNew): AppDataCompleteNew => {
|
|||
if (data.project.entities[note.projectId]) {
|
||||
// @ts-ignore
|
||||
if (!data.project.entities[note.projectId]!.noteIds.includes(note.id)) {
|
||||
console.log(
|
||||
Log.log(
|
||||
'Add orphaned note back to project list ' + note.projectId + ' ' + note.id,
|
||||
);
|
||||
// @ts-ignore
|
||||
|
|
@ -618,7 +613,7 @@ const _fixOrphanedNotes = (data: AppDataCompleteNew): AppDataCompleteNew => {
|
|||
];
|
||||
}
|
||||
} else {
|
||||
console.log('Delete missing project id from note ' + note.id);
|
||||
Log.log('Delete missing project id from note ' + note.id);
|
||||
note.projectId = null;
|
||||
// @ts-ignore
|
||||
if (!data.note.todayOrder.includes(note.id)) {
|
||||
|
|
@ -627,7 +622,7 @@ const _fixOrphanedNotes = (data: AppDataCompleteNew): AppDataCompleteNew => {
|
|||
}
|
||||
} // orphaned note case
|
||||
else if (!data.note.todayOrder.includes(note.id)) {
|
||||
console.log('Add orphaned note to today list ' + note.id);
|
||||
Log.log('Add orphaned note to today list ' + note.id);
|
||||
// @ts-ignore
|
||||
if (!data.note.todayOrder.includes(note.id)) {
|
||||
data.note.todayOrder = [...data.note.todayOrder, note.id];
|
||||
|
|
@ -644,7 +639,7 @@ const _fixInconsistentProjectId = (data: AppDataCompleteNew): AppDataCompleteNew
|
|||
.map((id) => data.project.entities[id])
|
||||
.forEach((projectItem) => {
|
||||
if (!projectItem) {
|
||||
console.log(data.project);
|
||||
Log.log(data.project);
|
||||
throw new Error('No project');
|
||||
}
|
||||
projectItem.taskIds.forEach((tid) => {
|
||||
|
|
@ -689,7 +684,7 @@ const _fixInconsistentTagId = (data: AppDataCompleteNew): AppDataCompleteNew =>
|
|||
.map((id) => data.tag.entities[id])
|
||||
.forEach((tagItem) => {
|
||||
if (!tagItem) {
|
||||
console.log(data.tag);
|
||||
Log.log(data.tag);
|
||||
throw new Error('No tag');
|
||||
}
|
||||
tagItem.taskIds.forEach((tid) => {
|
||||
|
|
@ -713,7 +708,7 @@ const _setTaskProjectIdAccordingToParent = (
|
|||
.map((id) => data.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
console.log(data.task);
|
||||
Log.log(data.task);
|
||||
throw new Error('No task');
|
||||
}
|
||||
if (taskItem.subTaskIds) {
|
||||
|
|
@ -735,7 +730,7 @@ const _setTaskProjectIdAccordingToParent = (
|
|||
.map((id) => data.archiveYoung.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
console.log(data.archiveYoung.task);
|
||||
Log.log(data.archiveYoung.task);
|
||||
throw new Error('No archive task');
|
||||
}
|
||||
if (taskItem.subTaskIds) {
|
||||
|
|
@ -762,7 +757,7 @@ const _cleanupOrphanedSubTasks = (data: AppDataCompleteNew): AppDataCompleteNew
|
|||
.map((id) => data.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
console.log(data.task);
|
||||
Log.log(data.task);
|
||||
throw new Error('No task');
|
||||
}
|
||||
|
||||
|
|
@ -771,7 +766,7 @@ const _cleanupOrphanedSubTasks = (data: AppDataCompleteNew): AppDataCompleteNew
|
|||
while (i >= 0) {
|
||||
const sid = taskItem.subTaskIds[i];
|
||||
if (!data.task.entities[sid]) {
|
||||
console.log('Delete orphaned sub task for ', taskItem);
|
||||
Log.log('Delete orphaned sub task for ', taskItem);
|
||||
taskItem.subTaskIds.splice(i, 1);
|
||||
}
|
||||
i -= 1;
|
||||
|
|
@ -784,7 +779,7 @@ const _cleanupOrphanedSubTasks = (data: AppDataCompleteNew): AppDataCompleteNew
|
|||
.map((id) => data.archiveYoung.task.entities[id])
|
||||
.forEach((taskItem) => {
|
||||
if (!taskItem) {
|
||||
console.log(data.archiveYoung.task);
|
||||
Log.log(data.archiveYoung.task);
|
||||
throw new Error('No archive task');
|
||||
}
|
||||
|
||||
|
|
@ -793,7 +788,7 @@ const _cleanupOrphanedSubTasks = (data: AppDataCompleteNew): AppDataCompleteNew
|
|||
while (i >= 0) {
|
||||
const sid = taskItem.subTaskIds[i];
|
||||
if (!data.archiveYoung.task.entities[sid]) {
|
||||
console.log('Delete orphaned archive sub task for ', taskItem);
|
||||
Log.log('Delete orphaned archive sub task for ', taskItem);
|
||||
taskItem.subTaskIds.splice(i, 1);
|
||||
}
|
||||
i -= 1;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { devError } from '../../util/dev-error';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { AppDataCompleteNew } from '../pfapi-config';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
let errorCount = 0;
|
||||
let lastValidityError: string;
|
||||
|
|
@ -47,10 +48,10 @@ export const getLastValidityError = (): string | undefined => lastValidityError;
|
|||
|
||||
const _validityError = (errTxt: string, additionalInfo?: any): void => {
|
||||
if (additionalInfo) {
|
||||
console.log('Validity Error Info: ', additionalInfo);
|
||||
Log.log('Validity Error Info: ', additionalInfo);
|
||||
if (environment.production) {
|
||||
try {
|
||||
console.log('Validity Error Info string: ', JSON.stringify(additionalInfo));
|
||||
Log.log('Validity Error Info string: ', JSON.stringify(additionalInfo));
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
|
@ -58,9 +59,9 @@ const _validityError = (errTxt: string, additionalInfo?: any): void => {
|
|||
devError(errTxt);
|
||||
} else {
|
||||
if (errorCount === 4) {
|
||||
console.warn('too many validity errors, only logging from now on');
|
||||
Log.err('too many validity errors, only logging from now on');
|
||||
}
|
||||
console.error(errTxt);
|
||||
Log.err(errTxt);
|
||||
}
|
||||
lastValidityError = errTxt;
|
||||
errorCount++;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { ObstructionState } from '../../features/metric/obstruction/obstruction.
|
|||
import { GlobalConfigState } from '../../features/config/global-config.model';
|
||||
import { AppDataCompleteNew } from '../pfapi-config';
|
||||
import { ValidationResult } from '../api/pfapi.model';
|
||||
import { Log } from '../../core/log';
|
||||
import {
|
||||
PluginUserDataState,
|
||||
PluginMetaDataState,
|
||||
|
|
@ -110,7 +111,7 @@ export const appDataValidators: {
|
|||
const validateArchiveModel = <R>(d: ArchiveModel | R): ValidationResult<ArchiveModel> => {
|
||||
const r = _validateArchive(d);
|
||||
if (!r.success) {
|
||||
console.log('Validation failed', (r as any)?.errors, r.data);
|
||||
Log.log('Validation failed', (r as any)?.errors, r.data);
|
||||
}
|
||||
if (!isEntityStateConsistent((d as ArchiveModel).task)) {
|
||||
return {
|
||||
|
|
@ -135,7 +136,7 @@ const _wrapValidate = <R>(
|
|||
isEntityCheck = false,
|
||||
): ValidationResult<R> => {
|
||||
if (!result.success) {
|
||||
console.log('Validation failed', (result as any)?.errors, result, d);
|
||||
Log.log('Validation failed', (result as any)?.errors, result, d);
|
||||
}
|
||||
if (isEntityCheck && !isEntityStateConsistent(d as any)) {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import {
|
|||
PluginManifest,
|
||||
} from '@super-productivity/plugin-api';
|
||||
import { PluginBridgeService } from './plugin-bridge.service';
|
||||
import { Log } from '../core/log';
|
||||
import {
|
||||
taskCopyToTaskData,
|
||||
projectCopyToProjectData,
|
||||
|
|
@ -66,7 +67,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
}
|
||||
|
||||
pluginHooks.get(hook)!.push(fn);
|
||||
console.log(`Plugin ${this._pluginId} registered hook: ${hook}`);
|
||||
Log.log(`Plugin ${this._pluginId} registered hook: ${hook}`);
|
||||
|
||||
// Register hook with bridge
|
||||
this._pluginBridge.registerHook(this._pluginId, hook, fn);
|
||||
|
|
@ -74,14 +75,14 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
|
||||
registerHeaderButton(headerBtnCfg: PluginHeaderBtnCfg): void {
|
||||
this._headerButtons.push({ ...headerBtnCfg, pluginId: this._pluginId });
|
||||
console.log(`Plugin ${this._pluginId} registered header button`, headerBtnCfg);
|
||||
Log.log(`Plugin ${this._pluginId} registered header button`, headerBtnCfg);
|
||||
this._pluginBridge.registerHeaderButton(headerBtnCfg);
|
||||
}
|
||||
|
||||
registerMenuEntry(menuEntryCfg: Omit<PluginMenuEntryCfg, 'pluginId'>): void {
|
||||
const fullMenuEntry = { ...menuEntryCfg, pluginId: this._pluginId };
|
||||
this._menuEntries.push(fullMenuEntry);
|
||||
console.log(`Plugin ${this._pluginId} registered menu entry`, menuEntryCfg);
|
||||
Log.log(`Plugin ${this._pluginId} registered menu entry`, menuEntryCfg);
|
||||
this._pluginBridge.registerMenuEntry(menuEntryCfg);
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +100,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
};
|
||||
|
||||
this._shortcuts.push(shortcut);
|
||||
console.log(`Plugin ${this._pluginId} registered shortcut`, shortcutCfg);
|
||||
Log.log(`Plugin ${this._pluginId} registered shortcut`, shortcutCfg);
|
||||
|
||||
// Register shortcut with bridge
|
||||
this._pluginBridge.registerShortcut(shortcut);
|
||||
|
|
@ -109,58 +110,58 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
sidePanelBtnCfg: Omit<PluginSidePanelBtnCfg, 'pluginId'>,
|
||||
): void {
|
||||
this._sidePanelButtons.push({ ...sidePanelBtnCfg, pluginId: this._pluginId });
|
||||
console.log(`Plugin ${this._pluginId} registered side panel button`, sidePanelBtnCfg);
|
||||
Log.log(`Plugin ${this._pluginId} registered side panel button`, sidePanelBtnCfg);
|
||||
this._pluginBridge.registerSidePanelButton(sidePanelBtnCfg);
|
||||
}
|
||||
|
||||
showIndexHtmlAsView(): void {
|
||||
console.log(`Plugin ${this._pluginId} requested to show index.html`);
|
||||
Log.log(`Plugin ${this._pluginId} requested to show index.html`);
|
||||
return this._pluginBridge.showIndexHtmlAsView(this._pluginId);
|
||||
}
|
||||
|
||||
async getTasks(): Promise<Task[]> {
|
||||
console.log(`Plugin ${this._pluginId} requested all tasks`);
|
||||
Log.log(`Plugin ${this._pluginId} requested all tasks`);
|
||||
const tasks = await this._pluginBridge.getTasks();
|
||||
return tasks.map(taskCopyToTaskData);
|
||||
}
|
||||
|
||||
async getArchivedTasks(): Promise<Task[]> {
|
||||
console.log(`Plugin ${this._pluginId} requested archived tasks`);
|
||||
Log.log(`Plugin ${this._pluginId} requested archived tasks`);
|
||||
const tasks = await this._pluginBridge.getArchivedTasks();
|
||||
return tasks.map(taskCopyToTaskData);
|
||||
}
|
||||
|
||||
async getCurrentContextTasks(): Promise<Task[]> {
|
||||
console.log(`Plugin ${this._pluginId} requested current context tasks`);
|
||||
Log.log(`Plugin ${this._pluginId} requested current context tasks`);
|
||||
const tasks = await this._pluginBridge.getCurrentContextTasks();
|
||||
return tasks.map(taskCopyToTaskData);
|
||||
}
|
||||
|
||||
async updateTask(taskId: string, updates: Partial<Task>): Promise<void> {
|
||||
console.log(`Plugin ${this._pluginId} requested to update task ${taskId}:`, updates);
|
||||
Log.log(`Plugin ${this._pluginId} requested to update task ${taskId}:`, updates);
|
||||
const taskCopyUpdates = taskDataToPartialTaskCopy(updates);
|
||||
return this._pluginBridge.updateTask(taskId, taskCopyUpdates);
|
||||
}
|
||||
|
||||
async addTask(taskData: PluginCreateTaskData): Promise<string> {
|
||||
console.log(`Plugin ${this._pluginId} requested to add task:`, taskData);
|
||||
Log.log(`Plugin ${this._pluginId} requested to add task:`, taskData);
|
||||
return this._pluginBridge.addTask(taskData);
|
||||
}
|
||||
|
||||
async getAllProjects(): Promise<Project[]> {
|
||||
console.log(`Plugin ${this._pluginId} requested all projects`);
|
||||
Log.log(`Plugin ${this._pluginId} requested all projects`);
|
||||
const projects = await this._pluginBridge.getAllProjects();
|
||||
return projects.map(projectCopyToProjectData);
|
||||
}
|
||||
|
||||
async addProject(projectData: Partial<Project>): Promise<string> {
|
||||
console.log(`Plugin ${this._pluginId} requested to add project:`, projectData);
|
||||
Log.log(`Plugin ${this._pluginId} requested to add project:`, projectData);
|
||||
const projectCopyData = projectDataToPartialProjectCopy(projectData);
|
||||
return this._pluginBridge.addProject(projectCopyData);
|
||||
}
|
||||
|
||||
async updateProject(projectId: string, updates: Partial<Project>): Promise<void> {
|
||||
console.log(
|
||||
Log.log(
|
||||
`Plugin ${this._pluginId} requested to update project ${projectId}:`,
|
||||
updates,
|
||||
);
|
||||
|
|
@ -169,19 +170,19 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
}
|
||||
|
||||
async getAllTags(): Promise<Tag[]> {
|
||||
console.log(`Plugin ${this._pluginId} requested all tags`);
|
||||
Log.log(`Plugin ${this._pluginId} requested all tags`);
|
||||
const tags = await this._pluginBridge.getAllTags();
|
||||
return tags.map(tagCopyToTagData);
|
||||
}
|
||||
|
||||
async addTag(tagData: Partial<Tag>): Promise<string> {
|
||||
console.log(`Plugin ${this._pluginId} requested to add tag:`, tagData);
|
||||
Log.log(`Plugin ${this._pluginId} requested to add tag:`, tagData);
|
||||
const tagCopyData = tagDataToPartialTagCopy(tagData);
|
||||
return this._pluginBridge.addTag(tagCopyData);
|
||||
}
|
||||
|
||||
async updateTag(tagId: string, updates: Partial<Tag>): Promise<void> {
|
||||
console.log(`Plugin ${this._pluginId} requested to update tag ${tagId}:`, updates);
|
||||
Log.log(`Plugin ${this._pluginId} requested to update tag ${tagId}:`, updates);
|
||||
const tagCopyUpdates = tagDataToPartialTagCopy(updates);
|
||||
return this._pluginBridge.updateTag(tagId, tagCopyUpdates);
|
||||
}
|
||||
|
|
@ -191,7 +192,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
contextId: string,
|
||||
contextType: 'project' | 'task',
|
||||
): Promise<void> {
|
||||
console.log(
|
||||
Log.log(
|
||||
`Plugin ${this._pluginId} requested to reorder tasks in ${contextType} ${contextId}:`,
|
||||
taskIds,
|
||||
);
|
||||
|
|
@ -203,27 +204,27 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
}
|
||||
|
||||
async notify(notifyCfg: NotifyCfg): Promise<void> {
|
||||
console.log(`Plugin ${this._pluginId} requested notification:`, notifyCfg);
|
||||
Log.log(`Plugin ${this._pluginId} requested notification:`, notifyCfg);
|
||||
return this._pluginBridge.notify(notifyCfg);
|
||||
}
|
||||
|
||||
persistDataSynced(dataStr: string): Promise<void> {
|
||||
console.log(`Plugin ${this._pluginId} requested to persist data:`, dataStr);
|
||||
Log.log(`Plugin ${this._pluginId} requested to persist data:`, dataStr);
|
||||
return this._pluginBridge.persistDataSynced(dataStr);
|
||||
}
|
||||
|
||||
loadSyncedData(): Promise<string | null> {
|
||||
console.log(`Plugin ${this._pluginId} requested to load persisted data:`);
|
||||
Log.log(`Plugin ${this._pluginId} requested to load persisted data:`);
|
||||
return this._pluginBridge.loadPersistedData();
|
||||
}
|
||||
|
||||
async openDialog(dialogCfg: DialogCfg): Promise<void> {
|
||||
console.log(`Plugin ${this._pluginId} requested to open dialog:`, dialogCfg);
|
||||
Log.log(`Plugin ${this._pluginId} requested to open dialog:`, dialogCfg);
|
||||
return this._pluginBridge.openDialog(dialogCfg);
|
||||
}
|
||||
|
||||
async triggerSync(): Promise<void> {
|
||||
console.log(`Plugin ${this._pluginId} requested to trigger sync`);
|
||||
Log.log(`Plugin ${this._pluginId} requested to trigger sync`);
|
||||
return this._pluginBridge.triggerSync();
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +234,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
*/
|
||||
onMessage(handler: (message: any) => Promise<any>): void {
|
||||
this._messageHandler = handler;
|
||||
console.log(`Plugin ${this._pluginId} registered message handler`);
|
||||
Log.log(`Plugin ${this._pluginId} registered message handler`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -265,7 +266,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
* Execute an NgRx action if it's in the allowed list
|
||||
*/
|
||||
dispatchAction(action: any): void {
|
||||
console.log(`Plugin ${this._pluginId} requested to execute action:`, action);
|
||||
Log.log(`Plugin ${this._pluginId} requested to execute action:`, action);
|
||||
return this._pluginBridge.dispatchAction(action);
|
||||
}
|
||||
|
||||
|
|
@ -274,7 +275,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
* Called when the plugin is being unloaded
|
||||
*/
|
||||
cleanup(): void {
|
||||
console.log(`Cleaning up PluginAPI for plugin ${this._pluginId}`);
|
||||
Log.log(`Cleaning up PluginAPI for plugin ${this._pluginId}`);
|
||||
|
||||
// Clear all hook handlers
|
||||
this._hookHandlers.clear();
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import { isAllowedPluginAction } from './allowed-plugin-actions.const';
|
|||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { T } from '../t.const';
|
||||
import { SyncWrapperService } from '../imex/sync/sync-wrapper.service';
|
||||
import { Log } from '../core/log';
|
||||
|
||||
/**
|
||||
* PluginBridge acts as an intermediary layer between plugins and the main application services.
|
||||
|
|
@ -119,7 +120,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
duration: 5000, // 5 seconds default duration
|
||||
});
|
||||
|
||||
console.log('PluginBridge: Notification sent successfully', notifyCfg);
|
||||
Log.log('PluginBridge: Notification sent successfully', notifyCfg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -142,11 +143,11 @@ export class PluginBridgeService implements OnDestroy {
|
|||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((result) => {
|
||||
console.log('PluginBridge: Dialog closed with result:', result);
|
||||
Log.log('PluginBridge: Dialog closed with result:', result);
|
||||
resolve();
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('PluginBridge: Failed to open dialog:', error);
|
||||
Log.err('PluginBridge: Failed to open dialog:', error);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
|
|
@ -163,7 +164,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
this._translateService.instant(T.PLUGINS.NO_PLUGIN_ID_PROVIDED_FOR_HTML),
|
||||
);
|
||||
}
|
||||
console.log('PluginBridge: Navigating to plugin index view', {
|
||||
Log.log('PluginBridge: Navigating to plugin index view', {
|
||||
pluginId: targetPluginId,
|
||||
});
|
||||
// Navigate to the plugin index route
|
||||
|
|
@ -194,12 +195,12 @@ export class PluginBridgeService implements OnDestroy {
|
|||
return task as TaskCopy;
|
||||
});
|
||||
|
||||
console.log('PluginBridge: Retrieved archived tasks', {
|
||||
Log.log('PluginBridge: Retrieved archived tasks', {
|
||||
count: archivedTasks.length,
|
||||
});
|
||||
return archivedTasks;
|
||||
} catch (error) {
|
||||
console.error('PluginBridge: Failed to load archived tasks:', error);
|
||||
Log.err('PluginBridge: Failed to load archived tasks:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
@ -231,7 +232,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
// Update the task using TaskService (TaskCopy is compatible with Task)
|
||||
this._taskService.update(taskId, updates);
|
||||
|
||||
console.log('PluginBridge: Task updated successfully', { taskId, updates });
|
||||
Log.log('PluginBridge: Task updated successfully', { taskId, updates });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -269,7 +270,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
}),
|
||||
);
|
||||
|
||||
console.log('PluginBridge: Subtask added successfully', {
|
||||
Log.log('PluginBridge: Subtask added successfully', {
|
||||
taskId: task.id,
|
||||
taskData,
|
||||
});
|
||||
|
|
@ -292,7 +293,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
false, // isAddToBottom
|
||||
);
|
||||
|
||||
console.log('PluginBridge: Task added successfully', { taskId, taskData });
|
||||
Log.log('PluginBridge: Task added successfully', { taskId, taskData });
|
||||
return taskId;
|
||||
}
|
||||
}
|
||||
|
|
@ -311,7 +312,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
async addProject(projectData: Partial<ProjectCopy>): Promise<string> {
|
||||
typia.assert<Partial<ProjectCopy>>(projectData);
|
||||
|
||||
console.log('PluginBridge: Project add', { projectData });
|
||||
Log.log('PluginBridge: Project add', { projectData });
|
||||
return this._projectService.add(projectData);
|
||||
}
|
||||
|
||||
|
|
@ -325,7 +326,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
// Update the project using ProjectService (ProjectCopy is compatible with Project)
|
||||
this._projectService.update(projectId, updates);
|
||||
|
||||
console.log('PluginBridge: Project updated successfully', { projectId, updates });
|
||||
Log.log('PluginBridge: Project updated successfully', { projectId, updates });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -344,7 +345,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
// Add the tag using TagService (TagCopy is compatible with Tag)
|
||||
const tagId = this._tagService.addTag(tagData);
|
||||
console.log('PluginBridge: Tag added successfully', { tagId, tagData });
|
||||
Log.log('PluginBridge: Tag added successfully', { tagId, tagData });
|
||||
return tagId;
|
||||
}
|
||||
|
||||
|
|
@ -357,7 +358,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
// Update the tag using TagService (TagCopy is compatible with Tag)
|
||||
this._tagService.updateTag(tagId, updates);
|
||||
console.log('PluginBridge: Tag updated successfully', { tagId, updates });
|
||||
Log.log('PluginBridge: Tag updated successfully', { tagId, updates });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -400,7 +401,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
allTasks?.filter((t) => t.projectId === contextId && !t.parentId) || [];
|
||||
const taskIdsInProject = tasksInProject.map((t) => t.id);
|
||||
|
||||
console.log('PluginBridge: Validating task reorder', {
|
||||
Log.log('PluginBridge: Validating task reorder', {
|
||||
requestedTaskIds: taskIds,
|
||||
projectTaskIds: allProjectTaskIds,
|
||||
actualTasksInProject: taskIdsInProject,
|
||||
|
|
@ -426,7 +427,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
// Note: This assumes all tasks are in the regular list, not backlog
|
||||
this._projectService.update(contextId, { taskIds });
|
||||
|
||||
console.log('PluginBridge: Project tasks reordered successfully', {
|
||||
Log.log('PluginBridge: Project tasks reordered successfully', {
|
||||
projectId: contextId,
|
||||
newOrder: taskIds,
|
||||
});
|
||||
|
|
@ -460,7 +461,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
// Update the task with new subtask order
|
||||
this._taskService.update(contextId, { subTaskIds: taskIds });
|
||||
|
||||
console.log('PluginBridge: Subtasks reordered successfully', {
|
||||
Log.log('PluginBridge: Subtasks reordered successfully', {
|
||||
parentTaskId: contextId,
|
||||
newOrder: taskIds,
|
||||
});
|
||||
|
|
@ -484,11 +485,11 @@ export class PluginBridgeService implements OnDestroy {
|
|||
this._currentPluginId,
|
||||
dataStr,
|
||||
);
|
||||
console.log('PluginBridge: Plugin data persisted successfully', {
|
||||
Log.log('PluginBridge: Plugin data persisted successfully', {
|
||||
pluginId: this._currentPluginId,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('PluginBridge: Failed to persist plugin data:', error);
|
||||
Log.err('PluginBridge: Failed to persist plugin data:', error);
|
||||
throw new Error(this._translateService.instant(T.PLUGINS.UNABLE_TO_PERSIST_DATA));
|
||||
}
|
||||
}
|
||||
|
|
@ -508,7 +509,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
this._currentPluginId,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('PluginBridge: Failed to get persisted plugin data:', error);
|
||||
Log.err('PluginBridge: Failed to get persisted plugin data:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -522,11 +523,11 @@ export class PluginBridgeService implements OnDestroy {
|
|||
}
|
||||
|
||||
try {
|
||||
console.log('PluginBridge: Triggering sync for plugin', this._currentPluginId);
|
||||
Log.log('PluginBridge: Triggering sync for plugin', this._currentPluginId);
|
||||
await this._syncWrapperService.sync();
|
||||
console.log('PluginBridge: Sync completed successfully');
|
||||
Log.log('PluginBridge: Sync completed successfully');
|
||||
} catch (error) {
|
||||
console.error('PluginBridge: Sync failed:', error);
|
||||
Log.err('PluginBridge: Sync failed:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -554,7 +555,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
this._removePluginSidePanelButtons(pluginId);
|
||||
this.unregisterPluginShortcuts(pluginId);
|
||||
|
||||
console.log('PluginBridge: All hooks unregistered for plugin', { pluginId });
|
||||
Log.log('PluginBridge: All hooks unregistered for plugin', { pluginId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -576,7 +577,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
const currentButtons = this._headerButtons$.value;
|
||||
this._headerButtons$.next([...currentButtons, newButton]);
|
||||
|
||||
console.log('PluginBridge: Header button registered', {
|
||||
Log.log('PluginBridge: Header button registered', {
|
||||
pluginId: this._currentPluginId,
|
||||
headerBtnCfg,
|
||||
});
|
||||
|
|
@ -621,7 +622,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
);
|
||||
|
||||
if (isDuplicate) {
|
||||
console.warn('PluginBridge: Duplicate menu entry detected, skipping registration', {
|
||||
Log.err('PluginBridge: Duplicate menu entry detected, skipping registration', {
|
||||
pluginId: this._currentPluginId,
|
||||
label: menuEntryCfg.label,
|
||||
});
|
||||
|
|
@ -630,7 +631,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
this._menuEntries$.next([...currentEntries, newMenuEntry]);
|
||||
|
||||
console.log('PluginBridge: Menu entry registered', {
|
||||
Log.log('PluginBridge: Menu entry registered', {
|
||||
pluginId: this._currentPluginId,
|
||||
menuEntryCfg,
|
||||
});
|
||||
|
|
@ -646,7 +647,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
);
|
||||
this._headerButtons$.next(filteredButtons);
|
||||
|
||||
console.log('PluginBridge: Header buttons removed for plugin', { pluginId });
|
||||
Log.log('PluginBridge: Header buttons removed for plugin', { pluginId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -657,7 +658,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
const filteredEntries = currentEntries.filter((entry) => entry.pluginId !== pluginId);
|
||||
this._menuEntries$.next(filteredEntries);
|
||||
|
||||
console.log('PluginBridge: Menu entries removed for plugin', { pluginId });
|
||||
Log.log('PluginBridge: Menu entries removed for plugin', { pluginId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -697,7 +698,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
);
|
||||
|
||||
if (isDuplicate) {
|
||||
console.warn(
|
||||
Log.err(
|
||||
'PluginBridge: Duplicate side panel button detected, skipping registration',
|
||||
{
|
||||
pluginId: this._currentPluginId,
|
||||
|
|
@ -709,7 +710,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
this._sidePanelButtons$.next([...currentButtons, newButton]);
|
||||
|
||||
console.log('PluginBridge: Side panel button registered', {
|
||||
Log.log('PluginBridge: Side panel button registered', {
|
||||
pluginId: this._currentPluginId,
|
||||
sidePanelBtnCfg,
|
||||
});
|
||||
|
|
@ -725,7 +726,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
);
|
||||
this._sidePanelButtons$.next(filteredButtons);
|
||||
|
||||
console.log('PluginBridge: Side panel buttons removed for plugin', { pluginId });
|
||||
Log.log('PluginBridge: Side panel buttons removed for plugin', { pluginId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -746,7 +747,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
const currentShortcuts = this.shortcuts$.value;
|
||||
this.shortcuts$.next([...currentShortcuts, shortcutWithPluginId]);
|
||||
|
||||
console.log('PluginBridge: Shortcut registered', {
|
||||
Log.log('PluginBridge: Shortcut registered', {
|
||||
pluginId: this._currentPluginId,
|
||||
shortcut: shortcutWithPluginId,
|
||||
});
|
||||
|
|
@ -762,12 +763,10 @@ export class PluginBridgeService implements OnDestroy {
|
|||
if (shortcut) {
|
||||
try {
|
||||
await Promise.resolve(shortcut.onExec());
|
||||
console.log(
|
||||
`Executed shortcut "${shortcut.label}" from plugin ${shortcut.pluginId}`,
|
||||
);
|
||||
Log.log(`Executed shortcut "${shortcut.label}" from plugin ${shortcut.pluginId}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Failed to execute shortcut "${shortcut.label}":`, error);
|
||||
Log.err(`Failed to execute shortcut "${shortcut.label}":`, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -786,7 +785,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
if (filteredShortcuts.length !== currentShortcuts.length) {
|
||||
this.shortcuts$.next(filteredShortcuts);
|
||||
console.log(
|
||||
Log.log(
|
||||
`Unregistered ${currentShortcuts.length - filteredShortcuts.length} shortcuts for plugin ${pluginId}`,
|
||||
);
|
||||
}
|
||||
|
|
@ -864,9 +863,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
// Check if the action is in the allowed list
|
||||
if (!isAllowedPluginAction(action)) {
|
||||
console.error(
|
||||
`PluginBridge: Action type '${action.type}' is not allowed for plugins`,
|
||||
);
|
||||
Log.err(`PluginBridge: Action type '${action.type}' is not allowed for plugins`);
|
||||
throw new Error(
|
||||
this._translateService.instant(T.PLUGINS.ACTION_TYPE_NOT_ALLOWED, {
|
||||
actionType: action.type,
|
||||
|
|
@ -876,7 +873,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
// Dispatch the action
|
||||
this._store.dispatch(action);
|
||||
console.log(`PluginBridge: Dispatched action for plugin ${this._currentPluginId}`, {
|
||||
Log.log(`PluginBridge: Dispatched action for plugin ${this._currentPluginId}`, {
|
||||
actionType: action.type,
|
||||
payload: action,
|
||||
});
|
||||
|
|
@ -929,7 +926,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('PluginBridge: Failed to execute Node.js script:', error);
|
||||
Log.err('PluginBridge: Failed to execute Node.js script:', error);
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
|
|
@ -955,7 +952,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
* Clean up all resources when service is destroyed
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
console.log('PluginBridgeService: Cleaning up resources');
|
||||
Log.log('PluginBridgeService: Cleaning up resources');
|
||||
|
||||
// Complete all BehaviorSubjects
|
||||
this._headerButtons$.complete();
|
||||
|
|
@ -963,6 +960,6 @@ export class PluginBridgeService implements OnDestroy {
|
|||
this.shortcuts$.complete();
|
||||
this._sidePanelButtons$.complete();
|
||||
|
||||
console.log('PluginBridgeService: Cleanup complete');
|
||||
Log.log('PluginBridgeService: Cleanup complete');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Log } from '../core/log';
|
||||
|
||||
export interface CachedPlugin {
|
||||
id: string;
|
||||
|
|
@ -64,19 +65,18 @@ export class PluginCacheService {
|
|||
};
|
||||
const totalSizeKB = Object.values(sizes).reduce((sum, size) => sum + size, 0);
|
||||
|
||||
console.log(`[PluginCache] Storing plugin "${pluginId}":`);
|
||||
console.log(`[PluginCache] - Manifest: ${sizes.manifest.toFixed(2)}KB`);
|
||||
console.log(`[PluginCache] - Code: ${sizes.code.toFixed(2)}KB`);
|
||||
if (indexHtml)
|
||||
console.log(`[PluginCache] - IndexHtml: ${sizes.indexHtml.toFixed(2)}KB`);
|
||||
if (icon) console.log(`[PluginCache] - Icon: ${sizes.icon.toFixed(2)}KB`);
|
||||
console.log(
|
||||
Log.log(`[PluginCache] Storing plugin "${pluginId}":`);
|
||||
Log.log(`[PluginCache] - Manifest: ${sizes.manifest.toFixed(2)}KB`);
|
||||
Log.log(`[PluginCache] - Code: ${sizes.code.toFixed(2)}KB`);
|
||||
if (indexHtml) Log.log(`[PluginCache] - IndexHtml: ${sizes.indexHtml.toFixed(2)}KB`);
|
||||
if (icon) Log.log(`[PluginCache] - Icon: ${sizes.icon.toFixed(2)}KB`);
|
||||
Log.log(
|
||||
`[PluginCache] - Total size: ${totalSizeKB.toFixed(2)}KB (${(totalSizeKB / 1024).toFixed(2)}MB)`,
|
||||
);
|
||||
|
||||
if (totalSizeKB > 1024) {
|
||||
// Warn if plugin is larger than 1MB
|
||||
console.warn(
|
||||
Log.err(
|
||||
`[PluginCache] Large plugin detected: "${pluginId}" is ${(totalSizeKB / 1024).toFixed(2)}MB`,
|
||||
);
|
||||
}
|
||||
|
|
@ -97,14 +97,11 @@ export class PluginCacheService {
|
|||
return new Promise((resolve, reject) => {
|
||||
const request = store.put(plugin);
|
||||
request.onsuccess = () => {
|
||||
console.log(`[PluginCache] Successfully stored plugin "${pluginId}"`);
|
||||
Log.log(`[PluginCache] Successfully stored plugin "${pluginId}"`);
|
||||
resolve();
|
||||
};
|
||||
request.onerror = () => {
|
||||
console.error(
|
||||
`[PluginCache] Failed to store plugin "${pluginId}":`,
|
||||
request.error,
|
||||
);
|
||||
Log.err(`[PluginCache] Failed to store plugin "${pluginId}":`, request.error);
|
||||
reject(new Error(`Failed to store plugin ${pluginId}`));
|
||||
};
|
||||
});
|
||||
|
|
@ -114,7 +111,7 @@ export class PluginCacheService {
|
|||
* Get a plugin from the cache
|
||||
*/
|
||||
async getPlugin(pluginId: string): Promise<CachedPlugin | null> {
|
||||
console.log(`[PluginCache] Loading plugin "${pluginId}"`);
|
||||
Log.log(`[PluginCache] Loading plugin "${pluginId}"`);
|
||||
const db = await this._getDB();
|
||||
const transaction = db.transaction([this.STORE_NAME], 'readonly');
|
||||
const store = transaction.objectStore(this.STORE_NAME);
|
||||
|
|
@ -145,7 +142,7 @@ export class PluginCacheService {
|
|||
* Get all cached plugins
|
||||
*/
|
||||
async getAllPlugins(): Promise<CachedPlugin[]> {
|
||||
console.log('[PluginCache] Loading all plugins from cache');
|
||||
Log.log('[PluginCache] Loading all plugins from cache');
|
||||
const db = await this._getDB();
|
||||
const transaction = db.transaction([this.STORE_NAME], 'readonly');
|
||||
const store = transaction.objectStore(this.STORE_NAME);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Hooks, PluginHookHandler } from './plugin-api.model';
|
||||
import { Log } from '../core/log';
|
||||
|
||||
/**
|
||||
* Simplified plugin hooks service following KISS principles.
|
||||
|
|
@ -36,7 +37,7 @@ export class PluginHooksService {
|
|||
try {
|
||||
await handler(payload);
|
||||
} catch (error) {
|
||||
console.error(`Plugin ${pluginId} ${hook} handler error:`, error);
|
||||
Log.err(`Plugin ${pluginId} ${hook} handler error:`, error);
|
||||
// Continue with other handlers
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { PluginManifest } from './plugin-api.model';
|
|||
import { PluginCacheService } from './plugin-cache.service';
|
||||
// KISS: No size checks in loader - trust the browser's limits
|
||||
import { validatePluginManifest } from './util/validate-manifest.util';
|
||||
import { Log } from '../core/log';
|
||||
|
||||
interface PluginAssets {
|
||||
manifest: PluginManifest;
|
||||
|
|
@ -69,7 +70,7 @@ export class PluginLoaderService {
|
|||
.pipe(first())
|
||||
.toPromise();
|
||||
} catch (e) {
|
||||
console.warn(`No index.html for plugin ${manifest.id}`);
|
||||
Log.err(`No index.html for plugin ${manifest.id}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ export class PluginLoaderService {
|
|||
.pipe(first())
|
||||
.toPromise();
|
||||
} catch (e) {
|
||||
console.warn(`No icon for plugin ${manifest.id}`);
|
||||
Log.err(`No icon for plugin ${manifest.id}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { inject, Injectable } from '@angular/core';
|
||||
import { PfapiService } from '../pfapi/pfapi.service';
|
||||
import { PluginMetadata, PluginMetaDataState } from './plugin-persistence.model';
|
||||
import { Log } from '../core/log';
|
||||
|
||||
/**
|
||||
* Service for persisting plugin metadata using pfapi.
|
||||
|
|
@ -27,7 +28,7 @@ export class PluginMetaPersistenceService {
|
|||
|
||||
// Deep compare the states
|
||||
if (this._isDataEqual(currentState, newState)) {
|
||||
console.log('PluginMetaPersistenceService: No changes detected, skipping write');
|
||||
Log.log('PluginMetaPersistenceService: No changes detected, skipping write');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -35,7 +36,7 @@ export class PluginMetaPersistenceService {
|
|||
await this._pfapiService.pf.m.pluginMetadata.save(newState, {
|
||||
isUpdateRevAndLastUpdate: true,
|
||||
});
|
||||
console.log('PluginMetaPersistenceService: Data updated');
|
||||
Log.log('PluginMetaPersistenceService: Data updated');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { PluginSecurityService } from './plugin-security';
|
|||
import { SnackService } from '../core/snack/snack.service';
|
||||
import { IS_ELECTRON } from '../app.constants';
|
||||
import { PluginCleanupService } from './plugin-cleanup.service';
|
||||
import { Log } from '../core/log';
|
||||
|
||||
/**
|
||||
* Simplified plugin runner following KISS principles.
|
||||
|
|
@ -58,7 +59,7 @@ export class PluginRunner {
|
|||
|
||||
// Show warnings if any
|
||||
if (analysis.warnings.length > 0) {
|
||||
console.warn(`Plugin ${manifest.id} warnings:`, analysis.warnings);
|
||||
Log.err(`Plugin ${manifest.id} warnings:`, analysis.warnings);
|
||||
this._snackService.open({
|
||||
msg: `Plugin "${manifest.name}" has warnings: ${analysis.warnings[0]}`,
|
||||
type: 'CUSTOM',
|
||||
|
|
@ -68,7 +69,7 @@ export class PluginRunner {
|
|||
|
||||
// Log info for transparency
|
||||
if (analysis.info.length > 0) {
|
||||
console.info(`Plugin ${manifest.id} info:`, analysis.info);
|
||||
Log.info(`Plugin ${manifest.id} info:`, analysis.info);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -101,13 +102,13 @@ export class PluginRunner {
|
|||
} catch (error) {
|
||||
pluginInstance.error =
|
||||
error instanceof Error ? error.message : 'Failed to load plugin';
|
||||
console.error(`Plugin ${manifest.id} error:`, error);
|
||||
Log.err(`Plugin ${manifest.id} error:`, error);
|
||||
}
|
||||
|
||||
this._loadedPlugins.set(manifest.id, pluginInstance);
|
||||
return pluginInstance;
|
||||
} catch (error) {
|
||||
console.error(`Failed to load plugin ${manifest.id}:`, error);
|
||||
Log.err(`Failed to load plugin ${manifest.id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import { PluginLoaderService } from './plugin-loader.service';
|
|||
import { validatePluginManifest } from './util/validate-manifest.util';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { T } from '../t.const';
|
||||
import { Log } from '../core/log';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -66,11 +67,11 @@ export class PluginService implements OnDestroy {
|
|||
|
||||
async initializePlugins(): Promise<void> {
|
||||
if (this._isInitialized) {
|
||||
console.warn(this._translateService.instant(T.PLUGINS.ALREADY_INITIALIZED));
|
||||
Log.err(this._translateService.instant(T.PLUGINS.ALREADY_INITIALIZED));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Initializing plugin system...');
|
||||
Log.log('Initializing plugin system...');
|
||||
|
||||
try {
|
||||
// Only load manifests, not the actual plugin code
|
||||
|
|
@ -81,9 +82,9 @@ export class PluginService implements OnDestroy {
|
|||
await this._loadEnabledPlugins();
|
||||
|
||||
this._isInitialized = true;
|
||||
console.log('Plugin system initialized successfully');
|
||||
Log.log('Plugin system initialized successfully');
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize plugin system:', error);
|
||||
Log.err('Failed to initialize plugin system:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -131,13 +132,13 @@ export class PluginService implements OnDestroy {
|
|||
}
|
||||
} catch (e) {
|
||||
// Icon is optional - silently ignore 404s and other errors
|
||||
console.debug(
|
||||
Log.debug(
|
||||
`Icon not found for plugin ${manifest.id}: ${path}/${manifest.icon || 'icon.svg'}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Failed to discover plugin at ${path}:`, error);
|
||||
Log.err(`Failed to discover plugin at ${path}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,13 +187,13 @@ export class PluginService implements OnDestroy {
|
|||
this._pluginIcons.set(cachedPlugin.id, cachedPlugin.icon);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Failed to discover cached plugin ${cachedPlugin.id}:`, error);
|
||||
Log.err(`Failed to discover cached plugin ${cachedPlugin.id}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
this._updatePluginStates();
|
||||
} catch (error) {
|
||||
console.error('Failed to discover cached plugins:', error);
|
||||
Log.err('Failed to discover cached plugins:', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -202,11 +203,11 @@ export class PluginService implements OnDestroy {
|
|||
(state) => state.isEnabled,
|
||||
);
|
||||
|
||||
console.log(`Loading ${pluginsToLoad.length} enabled plugins...`);
|
||||
Log.log(`Loading ${pluginsToLoad.length} enabled plugins...`);
|
||||
|
||||
// Log which plugins are being loaded
|
||||
for (const state of pluginsToLoad) {
|
||||
console.log(
|
||||
Log.log(
|
||||
`Loading plugin: ${state.manifest.id} (enabled: ${state.isEnabled}, hooks: ${state.manifest.hooks?.length || 0}, sidePanel: ${state.manifest.sidePanel})`,
|
||||
);
|
||||
}
|
||||
|
|
@ -227,7 +228,7 @@ export class PluginService implements OnDestroy {
|
|||
async activatePlugin(pluginId: string): Promise<PluginInstance | null> {
|
||||
const state = this._pluginStates.get(pluginId);
|
||||
if (!state) {
|
||||
console.error(`Plugin ${pluginId} not found`);
|
||||
Log.err(`Plugin ${pluginId} not found`);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -258,7 +259,7 @@ export class PluginService implements OnDestroy {
|
|||
this._updatePluginStates();
|
||||
|
||||
try {
|
||||
console.log(`Activating plugin: ${pluginId}`);
|
||||
Log.log(`Activating plugin: ${pluginId}`);
|
||||
const instance = await this._loadPluginLazy(state);
|
||||
|
||||
state.status = 'loaded';
|
||||
|
|
@ -272,7 +273,7 @@ export class PluginService implements OnDestroy {
|
|||
|
||||
return instance;
|
||||
} catch (error) {
|
||||
console.error(`Failed to activate plugin ${pluginId}:`, error);
|
||||
Log.err(`Failed to activate plugin ${pluginId}:`, error);
|
||||
state.status = 'error';
|
||||
state.error = error instanceof Error ? error.message : String(error);
|
||||
this._updatePluginStates();
|
||||
|
|
@ -310,7 +311,7 @@ export class PluginService implements OnDestroy {
|
|||
|
||||
const promises = cachedPlugins.map(async (cachedPlugin) => {
|
||||
try {
|
||||
console.log(`Loading cached plugin: ${cachedPlugin.id}`);
|
||||
Log.log(`Loading cached plugin: ${cachedPlugin.id}`);
|
||||
// Set the path for reload functionality
|
||||
this._pluginPaths.set(cachedPlugin.id, `uploaded://${cachedPlugin.id}`);
|
||||
|
||||
|
|
@ -318,14 +319,14 @@ export class PluginService implements OnDestroy {
|
|||
await this._loadUploadedPlugin(cachedPlugin.id);
|
||||
// The plugin instance is already added to _loadedPlugins in _loadUploadedPlugin if loaded successfully
|
||||
} catch (error) {
|
||||
console.error(`Failed to load cached plugin ${cachedPlugin.id}:`, error);
|
||||
Log.err(`Failed to load cached plugin ${cachedPlugin.id}:`, error);
|
||||
// Continue loading other plugins even if one fails
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.allSettled(promises);
|
||||
} catch (error) {
|
||||
console.error('Failed to load cached plugins:', error);
|
||||
Log.err('Failed to load cached plugins:', error);
|
||||
// Don't throw - this shouldn't prevent other plugins from loading
|
||||
}
|
||||
}
|
||||
|
|
@ -350,9 +351,9 @@ export class PluginService implements OnDestroy {
|
|||
if (pluginInstance.manifest && pluginInstance.manifest.id) {
|
||||
this._pluginPaths.set(pluginInstance.manifest.id, pluginPath);
|
||||
}
|
||||
console.log(`${type} plugin loaded successfully from ${pluginPath}`);
|
||||
Log.log(`${type} plugin loaded successfully from ${pluginPath}`);
|
||||
} catch (error) {
|
||||
console.error(`Failed to load ${type} plugin from ${pluginPath}:`, error);
|
||||
Log.err(`Failed to load ${type} plugin from ${pluginPath}:`, error);
|
||||
// Continue loading other plugins even if one fails
|
||||
}
|
||||
});
|
||||
|
|
@ -401,9 +402,7 @@ export class PluginService implements OnDestroy {
|
|||
error: this._translateService.instant(T.PLUGINS.NODE_ONLY_DESKTOP),
|
||||
};
|
||||
this._pluginPaths.set(manifest.id, pluginPath); // Store the path for potential reload
|
||||
console.log(
|
||||
`Plugin ${manifest.id} requires desktop version, creating placeholder`,
|
||||
);
|
||||
Log.log(`Plugin ${manifest.id} requires desktop version, creating placeholder`);
|
||||
return placeholderInstance;
|
||||
}
|
||||
|
||||
|
|
@ -421,10 +420,10 @@ export class PluginService implements OnDestroy {
|
|||
// Analyze plugin code (informational only - KISS approach)
|
||||
const codeAnalysis = this._pluginSecurity.analyzePluginCode(pluginCode, manifest);
|
||||
if (codeAnalysis.warnings.length > 0) {
|
||||
console.warn(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
Log.err(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
}
|
||||
if (codeAnalysis.info.length > 0) {
|
||||
console.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
Log.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
}
|
||||
|
||||
// If plugin is disabled, create a placeholder instance without loading code
|
||||
|
|
@ -436,7 +435,7 @@ export class PluginService implements OnDestroy {
|
|||
error: undefined,
|
||||
};
|
||||
this._pluginPaths.set(manifest.id, pluginPath); // Store the path for potential reload
|
||||
console.log(`Plugin ${manifest.id} is disabled, skipping load`);
|
||||
Log.log(`Plugin ${manifest.id} is disabled, skipping load`);
|
||||
return placeholderInstance;
|
||||
}
|
||||
|
||||
|
|
@ -466,14 +465,14 @@ export class PluginService implements OnDestroy {
|
|||
// The enabled state will be persisted later when user explicitly enables/disables plugins
|
||||
this._ensurePluginEnabledInMemory(manifest.id);
|
||||
|
||||
console.log(`Plugin ${manifest.id} loaded successfully`);
|
||||
Log.log(`Plugin ${manifest.id} loaded successfully`);
|
||||
} else {
|
||||
console.error(`Plugin ${manifest.id} failed to load:`, pluginInstance.error);
|
||||
Log.err(`Plugin ${manifest.id} failed to load:`, pluginInstance.error);
|
||||
}
|
||||
|
||||
return pluginInstance;
|
||||
} catch (error) {
|
||||
console.error(`Failed to load plugin from ${pluginPath}:`, error);
|
||||
Log.err(`Failed to load plugin from ${pluginPath}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -618,7 +617,7 @@ export class PluginService implements OnDestroy {
|
|||
// Check if plugin exists in states
|
||||
const state = this._pluginStates.get(pluginId);
|
||||
if (!state) {
|
||||
console.warn(`Plugin ${pluginId} not found`);
|
||||
Log.err(`Plugin ${pluginId} not found`);
|
||||
this._activeSidePanelPlugin$.next(null);
|
||||
return;
|
||||
}
|
||||
|
|
@ -635,11 +634,11 @@ export class PluginService implements OnDestroy {
|
|||
if (instance) {
|
||||
this._activeSidePanelPlugin$.next(instance);
|
||||
} else {
|
||||
console.warn(`Failed to activate plugin ${pluginId}`);
|
||||
Log.err(`Failed to activate plugin ${pluginId}`);
|
||||
this._activeSidePanelPlugin$.next(null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error activating plugin ${pluginId}:`, error);
|
||||
Log.err(`Error activating plugin ${pluginId}:`, error);
|
||||
this._activeSidePanelPlugin$.next(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -702,7 +701,7 @@ export class PluginService implements OnDestroy {
|
|||
}
|
||||
|
||||
async loadPluginFromZip(file: File): Promise<PluginInstance> {
|
||||
console.log(`Starting plugin load from ZIP: ${file.name}`);
|
||||
Log.log(`Starting plugin load from ZIP: ${file.name}`);
|
||||
|
||||
// Import fflate dynamically for better bundle size
|
||||
const { unzip } = await import('fflate');
|
||||
|
|
@ -740,7 +739,7 @@ export class PluginService implements OnDestroy {
|
|||
});
|
||||
},
|
||||
);
|
||||
console.log({ extractedFiles });
|
||||
Log.log({ extractedFiles });
|
||||
|
||||
// Find and extract manifest.json
|
||||
if (!extractedFiles['manifest.json']) {
|
||||
|
|
@ -821,7 +820,7 @@ export class PluginService implements OnDestroy {
|
|||
iconContent = new TextDecoder().decode(iconBytes);
|
||||
// Basic SVG validation
|
||||
if (!iconContent.includes('<svg') || !iconContent.includes('</svg>')) {
|
||||
console.warn(`Plugin icon ${manifest.icon} does not appear to be a valid SVG`);
|
||||
Log.err(`Plugin icon ${manifest.icon} does not appear to be a valid SVG`);
|
||||
iconContent = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -829,10 +828,10 @@ export class PluginService implements OnDestroy {
|
|||
// Analyze plugin code (informational only - KISS approach)
|
||||
const codeAnalysis = this._pluginSecurity.analyzePluginCode(pluginCode, manifest);
|
||||
if (codeAnalysis.warnings.length > 0) {
|
||||
console.warn(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
Log.err(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
}
|
||||
if (codeAnalysis.info.length > 0) {
|
||||
console.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
Log.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
}
|
||||
|
||||
// Check if plugin is enabled (default to true for new uploads)
|
||||
|
|
@ -897,7 +896,7 @@ export class PluginService implements OnDestroy {
|
|||
this._pluginStates.set(manifest.id, state);
|
||||
this._updatePluginStates();
|
||||
|
||||
console.log(
|
||||
Log.log(
|
||||
`Uploaded plugin ${manifest.id} requires desktop version, creating placeholder`,
|
||||
);
|
||||
return placeholderInstance;
|
||||
|
|
@ -935,7 +934,7 @@ export class PluginService implements OnDestroy {
|
|||
this._pluginStates.set(manifest.id, state);
|
||||
this._updatePluginStates();
|
||||
|
||||
console.log(`Uploaded plugin ${manifest.id} is disabled, skipping load`);
|
||||
Log.log(`Uploaded plugin ${manifest.id} is disabled, skipping load`);
|
||||
return placeholderInstance;
|
||||
}
|
||||
|
||||
|
|
@ -974,12 +973,9 @@ export class PluginService implements OnDestroy {
|
|||
this._pluginStates.set(manifest.id, state);
|
||||
this._updatePluginStates();
|
||||
|
||||
console.log(`Uploaded plugin ${manifest.id} loaded successfully`);
|
||||
Log.log(`Uploaded plugin ${manifest.id} loaded successfully`);
|
||||
} else {
|
||||
console.error(
|
||||
`Uploaded plugin ${manifest.id} failed to load:`,
|
||||
pluginInstance.error,
|
||||
);
|
||||
Log.err(`Uploaded plugin ${manifest.id} failed to load:`, pluginInstance.error);
|
||||
|
||||
// Add failed plugin to states as well
|
||||
const state: PluginState = {
|
||||
|
|
@ -997,7 +993,7 @@ export class PluginService implements OnDestroy {
|
|||
|
||||
return pluginInstance;
|
||||
} catch (error) {
|
||||
console.error('Failed to load plugin from ZIP:', error);
|
||||
Log.err('Failed to load plugin from ZIP:', error);
|
||||
|
||||
// Create error instance for UI display
|
||||
const errorInstance: PluginInstance = {
|
||||
|
|
@ -1071,7 +1067,7 @@ export class PluginService implements OnDestroy {
|
|||
this._pluginStates.delete(pluginId);
|
||||
this._updatePluginStates();
|
||||
|
||||
console.log(`Uploaded plugin ${pluginId} removed completely`);
|
||||
Log.log(`Uploaded plugin ${pluginId} removed completely`);
|
||||
}
|
||||
|
||||
unloadPlugin(pluginId: string): boolean {
|
||||
|
|
@ -1110,7 +1106,7 @@ export class PluginService implements OnDestroy {
|
|||
// In lazy loading mode, unload and re-activate
|
||||
const state = this._pluginStates.get(pluginId);
|
||||
if (!state) {
|
||||
console.error(`Cannot reload plugin ${pluginId}: not found`);
|
||||
Log.err(`Cannot reload plugin ${pluginId}: not found`);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1150,10 +1146,10 @@ export class PluginService implements OnDestroy {
|
|||
// Analyze plugin code (informational only - KISS approach)
|
||||
const codeAnalysis = this._pluginSecurity.analyzePluginCode(pluginCode, manifest);
|
||||
if (codeAnalysis.warnings.length > 0) {
|
||||
console.warn(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
Log.err(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
}
|
||||
if (codeAnalysis.info.length > 0) {
|
||||
console.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
Log.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
}
|
||||
|
||||
// Check if plugin is enabled
|
||||
|
|
@ -1169,7 +1165,7 @@ export class PluginService implements OnDestroy {
|
|||
isEnabled: false,
|
||||
error: undefined,
|
||||
};
|
||||
console.log(`Uploaded plugin ${manifest.id} is disabled, skipping reload`);
|
||||
Log.log(`Uploaded plugin ${manifest.id} is disabled, skipping reload`);
|
||||
return placeholderInstance;
|
||||
}
|
||||
|
||||
|
|
@ -1193,17 +1189,14 @@ export class PluginService implements OnDestroy {
|
|||
// Replace existing instance
|
||||
this._loadedPlugins[existingIndex] = pluginInstance;
|
||||
}
|
||||
console.log(`Uploaded plugin ${manifest.id} reloaded successfully`);
|
||||
Log.log(`Uploaded plugin ${manifest.id} reloaded successfully`);
|
||||
} else {
|
||||
console.error(
|
||||
`Uploaded plugin ${manifest.id} failed to reload:`,
|
||||
pluginInstance.error,
|
||||
);
|
||||
Log.err(`Uploaded plugin ${manifest.id} failed to reload:`, pluginInstance.error);
|
||||
}
|
||||
|
||||
return pluginInstance;
|
||||
} catch (error) {
|
||||
console.error(`Failed to reload uploaded plugin ${pluginId}:`, error);
|
||||
Log.err(`Failed to reload uploaded plugin ${pluginId}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -1219,7 +1212,7 @@ export class PluginService implements OnDestroy {
|
|||
|
||||
// Only check consent in Electron environment
|
||||
if (!IS_ELECTRON) {
|
||||
console.warn(
|
||||
Log.err(
|
||||
`Plugin ${manifest.id} requires nodeExecution permission which is not available in web environment`,
|
||||
);
|
||||
return false;
|
||||
|
|
@ -1276,13 +1269,13 @@ export class PluginService implements OnDestroy {
|
|||
private _ensurePluginEnabledInMemory(pluginId: string): void {
|
||||
// We only need to track this in memory for startup purposes
|
||||
// The actual persistence will happen when user explicitly enables/disables plugins
|
||||
console.log(
|
||||
Log.log(
|
||||
`Plugin ${pluginId} marked as enabled in memory (no pfapi write during startup)`,
|
||||
);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
console.log('PluginService: Cleaning up all resources');
|
||||
Log.log('PluginService: Cleaning up all resources');
|
||||
|
||||
// Complete the side panel subject
|
||||
this._activeSidePanelPlugin$.complete();
|
||||
|
|
@ -1293,7 +1286,7 @@ export class PluginService implements OnDestroy {
|
|||
try {
|
||||
this.unloadPlugin(pluginId);
|
||||
} catch (error) {
|
||||
console.error(`Error unloading plugin ${pluginId} during cleanup:`, error);
|
||||
Log.err(`Error unloading plugin ${pluginId} during cleanup:`, error);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -1309,6 +1302,6 @@ export class PluginService implements OnDestroy {
|
|||
// Clear loader caches
|
||||
this._pluginLoader.clearAllCaches();
|
||||
|
||||
console.log('PluginService: Cleanup complete');
|
||||
Log.log('PluginService: Cleanup complete');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import {
|
|||
} from '@angular/material/card';
|
||||
import { TranslateService, TranslatePipe } from '@ngx-translate/core';
|
||||
import { T } from '../../../t.const';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'plugin-index',
|
||||
|
|
@ -102,7 +103,7 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
try {
|
||||
await this._loadPluginIndex(this.directPluginId);
|
||||
} catch (err) {
|
||||
console.error('Failed to load plugin index:', err);
|
||||
Log.err('Failed to load plugin index:', err);
|
||||
this.error.set(
|
||||
err instanceof Error
|
||||
? err.message
|
||||
|
|
@ -116,7 +117,7 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
// Subscribe to route parameter changes to handle navigation between plugins
|
||||
this._routeSubscription = this._route.paramMap.subscribe(async (params) => {
|
||||
const newPluginId = params.get('pluginId');
|
||||
console.log(
|
||||
Log.log(
|
||||
'Route paramMap changed, newPluginId:',
|
||||
newPluginId,
|
||||
'currentPluginId:',
|
||||
|
|
@ -131,13 +132,11 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
|
||||
// Skip if it's the same plugin (prevent unnecessary reloads)
|
||||
if (this.pluginId() === newPluginId) {
|
||||
console.log('Same plugin ID, skipping reload');
|
||||
Log.log('Same plugin ID, skipping reload');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Navigating from plugin "${this.pluginId()}" to plugin "${newPluginId}"`,
|
||||
);
|
||||
Log.log(`Navigating from plugin "${this.pluginId()}" to plugin "${newPluginId}"`);
|
||||
|
||||
// Clean up previous iframe communication BEFORE setting new plugin ID
|
||||
this._cleanupIframeCommunication();
|
||||
|
|
@ -153,7 +152,7 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
try {
|
||||
await this._loadPluginIndex(newPluginId);
|
||||
} catch (err) {
|
||||
console.error('Failed to load plugin index:', err);
|
||||
Log.err('Failed to load plugin index:', err);
|
||||
this.error.set(
|
||||
err instanceof Error
|
||||
? err.message
|
||||
|
|
@ -171,7 +170,7 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
try {
|
||||
await this._pluginService.initializePlugins();
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize plugin system:', error);
|
||||
Log.err('Failed to initialize plugin system:', error);
|
||||
throw new Error(
|
||||
this._translateService.instant(T.PLUGINS.PLUGIN_SYSTEM_FAILED_INIT),
|
||||
);
|
||||
|
|
@ -191,12 +190,12 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
private async _loadPluginIndex(pluginId: string): Promise<void> {
|
||||
console.log(`Loading plugin index for: ${pluginId}`);
|
||||
Log.log(`Loading plugin index for: ${pluginId}`);
|
||||
|
||||
// Get the plugin index.html content
|
||||
const indexContent = this._pluginService.getPluginIndexHtml(pluginId);
|
||||
if (!indexContent) {
|
||||
console.warn(`No index.html content found for plugin: ${pluginId}`);
|
||||
Log.err(`No index.html content found for plugin: ${pluginId}`);
|
||||
// Try to get the plugin instance to check if it should have an index.html
|
||||
const plugins = await this._pluginService.getAllPlugins();
|
||||
const plugin = plugins.find((p) => p.manifest.id === pluginId);
|
||||
|
|
@ -245,30 +244,30 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
|
||||
// Create safe URL and set iframe source
|
||||
const safeUrl = this._sanitizer.bypassSecurityTrustResourceUrl(iframeUrl);
|
||||
console.log(
|
||||
Log.log(
|
||||
`Setting iframe src for plugin ${pluginId}:`,
|
||||
iframeUrl.substring(0, 100) + '...',
|
||||
);
|
||||
this.iframeSrc.set(safeUrl);
|
||||
this.isLoading.set(false);
|
||||
console.log(`Plugin ${pluginId} iframe src set, loading complete`);
|
||||
Log.log(`Plugin ${pluginId} iframe src set, loading complete`);
|
||||
}
|
||||
|
||||
private _cleanupIframeCommunication(): void {
|
||||
const currentPluginId = this.pluginId();
|
||||
console.log(`Cleaning up iframe communication for plugin: ${currentPluginId}`);
|
||||
Log.log(`Cleaning up iframe communication for plugin: ${currentPluginId}`);
|
||||
|
||||
// Remove message listener
|
||||
if (this._messageListener) {
|
||||
window.removeEventListener('message', this._messageListener);
|
||||
this._messageListener = undefined;
|
||||
console.log(`Removed message listener for plugin: ${currentPluginId}`);
|
||||
Log.log(`Removed message listener for plugin: ${currentPluginId}`);
|
||||
}
|
||||
|
||||
// Clear iframe reference from cleanup service (but don't remove from DOM)
|
||||
if (currentPluginId) {
|
||||
this._cleanupService.cleanupPlugin(currentPluginId);
|
||||
console.log(`Cleaned up plugin references for: ${currentPluginId}`);
|
||||
Log.log(`Cleaned up plugin references for: ${currentPluginId}`);
|
||||
}
|
||||
|
||||
// Set iframe to empty data URL to stop execution but keep iframe in DOM
|
||||
|
|
@ -277,11 +276,11 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
'data:text/html,<html><body></body></html>',
|
||||
),
|
||||
);
|
||||
console.log(`Set iframe to empty data URL for plugin: ${currentPluginId}`);
|
||||
Log.log(`Set iframe to empty data URL for plugin: ${currentPluginId}`);
|
||||
}
|
||||
|
||||
onIframeLoad(): void {
|
||||
console.log('Plugin iframe loaded for plugin:', this.pluginId());
|
||||
Log.log('Plugin iframe loaded for plugin:', this.pluginId());
|
||||
|
||||
// Register iframe with cleanup service
|
||||
if (this.iframeRef?.nativeElement && this.pluginId()) {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import { PluginIconComponent } from '../plugin-icon/plugin-icon.component';
|
|||
import { IS_ELECTRON } from '../../../app.constants';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { DestroyRef } from '@angular/core';
|
||||
import { Log } from '../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'plugin-management',
|
||||
|
|
@ -138,7 +139,7 @@ export class PluginManagementComponent implements OnInit {
|
|||
}
|
||||
|
||||
private async enablePlugin(plugin: PluginInstance): Promise<void> {
|
||||
console.log('Enabling plugin:', plugin.manifest.id);
|
||||
Log.log('Enabling plugin:', plugin.manifest.id);
|
||||
|
||||
try {
|
||||
// Check if plugin requires Node.js execution consent
|
||||
|
|
@ -146,7 +147,7 @@ export class PluginManagementComponent implements OnInit {
|
|||
plugin.manifest,
|
||||
);
|
||||
if (!hasConsent) {
|
||||
console.log(
|
||||
Log.log(
|
||||
'User denied Node.js execution permission for plugin:',
|
||||
plugin.manifest.id,
|
||||
);
|
||||
|
|
@ -164,18 +165,18 @@ export class PluginManagementComponent implements OnInit {
|
|||
// Activate the plugin (lazy load if needed)
|
||||
const instance = await this._pluginService.activatePlugin(plugin.manifest.id);
|
||||
if (instance) {
|
||||
console.log('Plugin activated successfully:', plugin.manifest.id);
|
||||
Log.log('Plugin activated successfully:', plugin.manifest.id);
|
||||
}
|
||||
|
||||
// Refresh UI
|
||||
await this.loadPlugins();
|
||||
} catch (error) {
|
||||
console.error('Failed to enable plugin:', error);
|
||||
Log.err('Failed to enable plugin:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private async disablePlugin(plugin: PluginInstance): Promise<void> {
|
||||
console.log('Disabling plugin:', plugin.manifest.id);
|
||||
Log.log('Disabling plugin:', plugin.manifest.id);
|
||||
|
||||
try {
|
||||
// Set plugin as disabled in persistence
|
||||
|
|
@ -194,22 +195,22 @@ export class PluginManagementComponent implements OnInit {
|
|||
// Reload plugins to get the updated state from the service
|
||||
await this.loadPlugins();
|
||||
} catch (error) {
|
||||
console.error('Failed to disable plugin:', error);
|
||||
Log.err('Failed to disable plugin:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async reloadPlugin(plugin: PluginInstance): Promise<void> {
|
||||
console.log('Reloading plugin:', plugin.manifest.id);
|
||||
Log.log('Reloading plugin:', plugin.manifest.id);
|
||||
|
||||
try {
|
||||
const success = await this._pluginService.reloadPlugin(plugin.manifest.id);
|
||||
if (success) {
|
||||
console.log('Plugin reloaded successfully:', plugin.manifest.id);
|
||||
Log.log('Plugin reloaded successfully:', plugin.manifest.id);
|
||||
} else {
|
||||
console.error('Failed to reload plugin:', plugin.manifest.id);
|
||||
Log.err('Failed to reload plugin:', plugin.manifest.id);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to reload plugin:', error);
|
||||
Log.err('Failed to reload plugin:', error);
|
||||
}
|
||||
|
||||
// Refresh the UI
|
||||
|
|
@ -298,7 +299,7 @@ export class PluginManagementComponent implements OnInit {
|
|||
// Clear the input
|
||||
input.value = '';
|
||||
} catch (error) {
|
||||
console.error('Failed to load plugin from ZIP:', error);
|
||||
Log.err('Failed to load plugin from ZIP:', error);
|
||||
this.uploadError.set(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
|
|
@ -317,9 +318,9 @@ export class PluginManagementComponent implements OnInit {
|
|||
await this._pluginCacheService.clearCache();
|
||||
await this.loadPlugins(); // Refresh the plugin list
|
||||
|
||||
console.log('Plugin cache cleared successfully');
|
||||
Log.log('Plugin cache cleared successfully');
|
||||
} catch (error) {
|
||||
console.error('Failed to clear plugin cache:', error);
|
||||
Log.err('Failed to clear plugin cache:', error);
|
||||
this.uploadError.set(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
|
|
@ -357,9 +358,9 @@ export class PluginManagementComponent implements OnInit {
|
|||
await this._pluginService.removeUploadedPlugin(plugin.manifest.id);
|
||||
await this.loadPlugins(); // Refresh the plugin list
|
||||
|
||||
console.log(`Plugin ${plugin.manifest.id} removed successfully`);
|
||||
Log.log(`Plugin ${plugin.manifest.id} removed successfully`);
|
||||
} catch (error) {
|
||||
console.error('Failed to remove plugin:', error);
|
||||
Log.err('Failed to remove plugin:', error);
|
||||
this.uploadError.set(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { BreakpointObserver } from '@angular/cdk/layout';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
/**
|
||||
* Component that renders side panel buttons for plugins in the main header.
|
||||
|
|
@ -132,21 +133,21 @@ export class PluginSidePanelBtnsComponent {
|
|||
});
|
||||
|
||||
onButtonClick(button: PluginSidePanelBtnCfg): void {
|
||||
console.log('Side panel button clicked:', button.pluginId, button.label);
|
||||
Log.log('Side panel button clicked:', button.pluginId, button.label);
|
||||
|
||||
// Prevent action if not in work view
|
||||
if (!this.isWorkView()) {
|
||||
console.log('Not in work view, ignoring click');
|
||||
Log.log('Not in work view, ignoring click');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Dispatching togglePluginPanel action for:', button.pluginId);
|
||||
Log.log('Dispatching togglePluginPanel action for:', button.pluginId);
|
||||
// Dispatch action to toggle the plugin panel
|
||||
this._store.dispatch(togglePluginPanel(button.pluginId));
|
||||
|
||||
// Call the original onClick handler if provided
|
||||
if (button.onClick) {
|
||||
console.log('Calling plugin onClick handler for:', button.pluginId);
|
||||
Log.log('Calling plugin onClick handler for:', button.pluginId);
|
||||
button.onClick();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { PluginBridgeService } from '../plugin-bridge.service';
|
||||
import { PluginBaseCfg, PluginManifest } from '../plugin-api.model';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
/**
|
||||
* Simplified plugin iframe utilities following KISS principles.
|
||||
|
|
@ -149,7 +150,7 @@ export const createPluginApiScript = (config: PluginIframeConfig): string => {
|
|||
try {
|
||||
handler(data.payload);
|
||||
} catch (error) {
|
||||
console.error('Hook handler error:', error);
|
||||
Log.err('Hook handler error:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -371,7 +372,7 @@ export const handlePluginMessage = async (
|
|||
// Special handling for registerHook - it needs pluginId as first parameter
|
||||
if (args.length >= 2) {
|
||||
const [hook, handlerPlaceholder] = args;
|
||||
console.log('Plugin iframe registerHook:', {
|
||||
Log.log('Plugin iframe registerHook:', {
|
||||
hook,
|
||||
handlerPlaceholder,
|
||||
pluginId: config.pluginId,
|
||||
|
|
@ -523,6 +524,6 @@ export const handlePluginMessage = async (
|
|||
|
||||
// Handle plugin ready
|
||||
if (data.type === 'plugin-ready' && data.pluginId === config.pluginId) {
|
||||
console.log(`Plugin ${config.pluginId} is ready`);
|
||||
Log.log(`Plugin ${config.pluginId} is ready`);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { StringToMsPipe } from './string-to-ms.pipe';
|
|||
import { MsToStringPipe } from './ms-to-string.pipe';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { T } from 'src/app/t.const';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
@Directive({
|
||||
selector: 'input[inputDuration]',
|
||||
|
|
@ -160,7 +161,7 @@ export class InputDurationDirective implements ControlValueAccessor, Validator,
|
|||
this._previousMsValue = this._msValue;
|
||||
} catch (err) {
|
||||
// If parsing fails, set to null
|
||||
console.error('Error parsing duration:', err);
|
||||
Log.err('Error parsing duration:', err);
|
||||
this._msValue = null;
|
||||
this._onChange(null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { AfterViewInit, Directive, ElementRef, OnDestroy, inject } from '@angular/core';
|
||||
|
||||
const DEFAULT_PINNED_CLASS = 'is-stuck';
|
||||
|
||||
@Directive({
|
||||
|
|
@ -17,8 +16,8 @@ export class StuckDirective implements AfterViewInit, OnDestroy {
|
|||
// ([e]) => e.target.classList.toggle(DEFAULT_PINNED_CLASS, e.intersectionRatio < 1),
|
||||
([e]) => {
|
||||
e.target.classList.toggle(DEFAULT_PINNED_CLASS, !e.isIntersecting);
|
||||
// console.log(e.boundingClientRect.top, e);
|
||||
// console.log('top', e.boundingClientRect.top < 0, e.isIntersecting);
|
||||
// Log.log(e.boundingClientRect.top, e);
|
||||
// Log.log('top', e.boundingClientRect.top < 0, e.isIntersecting);
|
||||
// if (e.boundingClientRect.top < 0) {
|
||||
// e.target.classList.toggle(DEFAULT_PINNED_CLASS, e.isIntersecting);
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|||
import { T } from 'src/app/t.const';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { IS_ANDROID_WEB_VIEW } from '../../util/is-android-web-view';
|
||||
import { Log } from '../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'task-title',
|
||||
|
|
@ -31,7 +32,7 @@ export class TaskTitleComponent {
|
|||
if (!this.isFocused && this.tmpValue !== this.lastExternalValue) {
|
||||
// NOTE: this works because set value is called after this, for non-short syntax only changes
|
||||
this.tmpValue = this.lastExternalValue;
|
||||
console.log('new tmp', this.tmpValue);
|
||||
Log.log('new tmp', this.tmpValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +65,7 @@ export class TaskTitleComponent {
|
|||
el.selectionStart = el.selectionEnd = el.value.length;
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
Log.err(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +89,7 @@ export class TaskTitleComponent {
|
|||
onTextInput(ev: Event): void {
|
||||
// TODO not really clear if this is needed. was apparently added to prevent the android web view enter key from submitting
|
||||
if (IS_ANDROID_WEB_VIEW && (ev as InputEvent)?.data?.slice(-1) === '\n') {
|
||||
console.log('android enter key press');
|
||||
Log.log('android enter key press');
|
||||
this._forceBlur();
|
||||
ev.preventDefault();
|
||||
setTimeout(() => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { devError } from './dev-error';
|
||||
import { arrayEquals } from './array-equals';
|
||||
import { Dictionary } from '@ngrx/entity';
|
||||
import { Log } from '../core/log';
|
||||
|
||||
export const isEntityStateConsistent = <T extends Dictionary<any>>(
|
||||
data: T,
|
||||
|
|
@ -13,7 +14,7 @@ export const isEntityStateConsistent = <T extends Dictionary<any>>(
|
|||
Object.keys(data.entities).length !== data.ids.length ||
|
||||
!arrayEquals(Object.keys(data.entities).sort(), [...data.ids].sort())
|
||||
) {
|
||||
console.log(data);
|
||||
Log.log(data);
|
||||
devError(`Inconsistent entity state "${additionalStr}"`);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -22,7 +23,7 @@ export const isEntityStateConsistent = <T extends Dictionary<any>>(
|
|||
|
||||
export const fixEntityStateConsistency = <T extends Dictionary<any>>(data: T): T => {
|
||||
if (Object.keys(data.entities).length !== data.ids.length) {
|
||||
console.warn('FIXING ENTITY STATE', {
|
||||
Log.err('FIXING ENTITY STATE', {
|
||||
...data,
|
||||
ids: Object.keys(data.entities),
|
||||
});
|
||||
|
|
@ -39,7 +40,7 @@ export const fixEntityStateConsistencyOrError = <T extends Dictionary<any>>(
|
|||
data: T,
|
||||
): T => {
|
||||
if (Object.keys(data.entities).length !== data.ids.length) {
|
||||
console.log({
|
||||
Log.log({
|
||||
...data,
|
||||
ids: Object.keys(data.entities),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Observable, Subject } from 'rxjs';
|
||||
import { IS_ELECTRON } from '../app.constants';
|
||||
import { devError } from './dev-error';
|
||||
import { Log } from '../core/log';
|
||||
|
||||
const handlerMap: { [key: string]: Observable<any> } = {};
|
||||
|
||||
|
|
@ -11,19 +12,19 @@ export const ipcEvent$ = (evName: string): Observable<unknown[]> => {
|
|||
|
||||
const subject = new Subject<unknown[]>();
|
||||
if (handlerMap[evName]) {
|
||||
console.log(handlerMap);
|
||||
Log.log(handlerMap);
|
||||
devError(`ipcEvent$[${evName}] should only ever be registered once`);
|
||||
return handlerMap[evName];
|
||||
}
|
||||
handlerMap[evName] = subject;
|
||||
|
||||
const handler: (...args: any[]) => void = (...args): void => {
|
||||
console.log('ipcEvent$ trigger', evName);
|
||||
Log.log('ipcEvent$ trigger', evName);
|
||||
subject.next([...args]);
|
||||
};
|
||||
|
||||
if (!window.ea) {
|
||||
console.error('window.ea is not available. Make sure the preload script is loaded.');
|
||||
Log.err('window.ea is not available. Make sure the preload script is loaded.');
|
||||
return subject;
|
||||
}
|
||||
|
||||
|
|
@ -32,7 +33,7 @@ export const ipcEvent$ = (evName: string): Observable<unknown[]> => {
|
|||
return subject;
|
||||
// return subject.pipe(
|
||||
// // finalize(() => {
|
||||
// // console.log('FINALIZE', evName);
|
||||
// // Log.log('FINALIZE', evName);
|
||||
// // // NOTE doesn't work due to the different contexts
|
||||
// // // window.ea.off(evName, handler);
|
||||
// // devError(`ipcEvent$[${evName}] observables live forever`);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue