Files
TimeTracker/app/static/typing-utils.js
T
Dries Peeters 1ebfbf39de refactor: comprehensive code quality, security, and performance improvements
Performance:
- Fix N+1 queries in reports.py with joinedload for TimeEntry.project,
  TimeEntry.user, TimeEntry.task, and Project.client across 6 query locations
- Replace per-task time_entries loops with batch UPDATE queries in tasks.py
- Use efficient subquery for favorite project IDs in projects.py

Architecture:
- Add get_by_id() and get_by_name() methods to ProjectService and ClientService
- Route project/client lookups through service layer in timer.py, projects.py,
  and clients.py instead of direct Model.query calls

Security:
- Add sanitize_input() with length limits to form inputs in clients.py,
  projects.py, timer.py, issues.py, and auth.py
- Add email format validation for client creation
- Warn at startup when SECRET_KEY uses the default value or is too short
  in ProductionConfig
- Replace 7 bare except: pass clauses with specific exception types
  (OSError, IOError, TypeError, ValueError) in admin.py, settings.py,
  and invoice.py

Authorization:
- Migrate all @admin_required decorators to @admin_or_permission_required()
  with granular permissions (manage_roles, manage_kanban, manage_webhooks,
  manage_api_tokens, manage_integrations, access_admin) across permissions.py,
  kanban.py, webhooks.py, and admin.py (28 routes total)

Frontend:
- Remove 40+ console.log debug statements across 18 JS files
- Replace 42 inline onclick/onchange handlers in base.html with delegated
  event listeners using data-dropdown and data-no-propagation attributes
- Migrate 6 inline handlers in time_entries_overview.html to addEventListener
- Extract shared typing detection into typing-utils.js, eliminating 5
  duplicate isTyping() implementations across keyboard shortcut files
- Add missing aria-label attributes to icon-only buttons

Dependencies:
- Migrate from pytz to stdlib zoneinfo (Python 3.9+) across all 6 files
  that used pytz; replace pytz with tzdata in requirements.txt
- Separate dev/test dependencies into requirements-dev.txt
- Configure RotatingFileHandler (10MB, 5 backups) for app and JSON logs

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-06 07:56:23 +01:00

61 lines
1.7 KiB
JavaScript

/**
* Shared typing detection utility.
*
* Determines whether the user is currently focused on an input element
* (input, textarea, select, contenteditable, or rich text editor) so that
* keyboard shortcuts can be suppressed while the user is typing.
*
* Usage:
* if (window.TimeTracker.isTyping(event)) return;
*/
(function () {
'use strict';
var EDITOR_SELECTORS = [
'.toastui-editor',
'.toastui-editor-contents',
'.ProseMirror',
'.CodeMirror',
'.ql-editor',
'.tox-edit-area',
'.note-editable',
'[contenteditable="true"]',
'.toastui-editor-ww-container',
'.toastui-editor-md-container',
'.gjs-frame' // GrapesJS editor
];
/**
* Check whether the event target is an input-like element.
*
* @param {Event|KeyboardEvent} ev - The DOM event to inspect.
* @returns {boolean} true if the user is typing in a form field or editor.
*/
function isTyping(ev) {
var target = ev && ev.target;
if (!target) return false;
var tag = (target.tagName || '').toLowerCase();
// Standard form fields
if (tag === 'input' || tag === 'textarea' || tag === 'select' || target.isContentEditable) {
return true;
}
// Rich text / code editors
if (target.closest) {
for (var i = 0; i < EDITOR_SELECTORS.length; i++) {
if (target.closest(EDITOR_SELECTORS[i])) {
return true;
}
}
}
return false;
}
// Expose on a shared namespace
window.TimeTracker = window.TimeTracker || {};
window.TimeTracker.isTyping = isTyping;
})();