* fix(time-log): await report filters before executing the query
getFilterTimeLogQuery became async (it awaits
ManagedEmployeeService.canManageEmployees), but five report methods still
invoked it inside a synchronous TypeORM `where()` callback without awaiting
it. Whenever the manager check was reached, the callback returned before any
`andWhere` ran, so getMany() built the SQL with no WHERE clause at all:
tenant, organization, employee and date filters were all dropped.
Call the helper directly with `await` before getMany(), as getTimeLogs and
getWeeklyReport already do. The synchronous paths (CHANGE_SELECTED_EMPLOYEE,
onlyMe, no employeeIds) build the same SQL as before, since no clause existed
prior to the call.
Affected: getDailyReportCharts, getDailyReport, getOwedAmountReport,
getOwedAmountReportCharts, getTimeLimit.
The spec drives every report method through a query-builder double that
mirrors TypeORM's synchronous `where(callback)` semantics and asserts the
scoping clauses are present when the query executes. It fails on the
previous code for the five methods above and passes for the admin and
onlyMe paths on both versions.
* fix(timesheet): await the filter helper before executing the query
getFilterTimesheetQuery is declared async and was invoked inside a
synchronous `where()` callback without being awaited in getTimeSheetCount
and getTimeSheets. It contains no await today, so the clauses still land
before the query runs, but the first await added to it would silently drop
every filter, exactly what happened in the time-log reports.
Call it directly with `await`, matching the time-log service, and cover both
methods with a spec asserting the tenant and organization clauses are
present at execution time.
* chore: ignore the local graphify output
graphify-out/ holds the locally generated knowledge graph used to navigate
the codebase. Its graph.json alone weighs over 100 MB, so it must never be
committed.
* test(time-tracking): share the query-builder double and make the timesheet guard real
Review follow-up on the two new specs.
The recording SelectQueryBuilder double, the RequestContext spies and the
executed-clause helper were duplicated between the time-log and timesheet
specs (SonarCloud: 26% duplicated new lines). They now live once in
time-tracking/testing/, which the lib build excludes and the spec tsconfig
includes.
The timesheet spec passed with or without the direct await, because
getFilterTimesheetQuery has no awaited operation today. It now suspends the
helper through a spy before delegating to the real implementation, the way
the first await added to it would, so restoring the previous
where(callback) call makes both tests fail with an empty clause list. The
afterEach lets a dangling helper settle while the context mocks are still
in place, so that regression fails on the assertions instead of crashing
the worker.
Also rewords a comment that used a word outside the cspell dictionary.
* fix(timesheet): drop the stray optional chaining on request
getTimeSheets read `request?.relations` while every other access in the
method, including the one right after it, dereferences `request` directly
(DeepScan INSUFFICIENT_NULL_CHECK). The parameter is required by the
signature, so the optional chaining was the inconsistent part.
* test(time-tracking): evaluate Brackets in the query-builder double
Review follow-up. The double stored a `Brackets` without running its
factory, so the predicates inside the brackets and their parameters were
never recorded: the specs checked that a bracketed clause was attached but
not what it contained.
The double now runs the factory against a nested builder as soon as the
brackets are added, the way `QueryBuilder.getWhereCondition` does, and
`executedFilters` flattens the nested predicates in after their brackets.
The time-log spec asserts both startedAt predicates and the formatted
startDate/endDate parameters; the timesheet spec asserts the object-literal
predicate with the Between range and the employee id a caller without
CHANGE_SELECTED_EMPLOYEE is narrowed to.
* chore: upgrade angular dependencies version from v19.2.10 to v19.2.17
* chore: upgrade @angular/material and other deps related to angular version
* Delete migrations.json
* Update .gitignore
---------
Co-authored-by: Ruslan Konviser <evereq@gmail.com>
* feat: Modify existing auth tools to work with session-based authentication
* fix: add requested changes from AI bots
* fix: add suggestions from AI bots
* fix: add suggestions from AI bots
* fix: add suggestions from AI bots
* fix: add suggestions from AI bots
* fix: add suggestions from AI bots
* fix: exclude certificates directory and update transport layers
* fix: add suggestions review from AI bots
* feat: improve request logging and monitoring for production
* fix: enhance security measures for production deployment
* fix: add suggestions from AI bots
* Potential fix for code scanning alert no. 297: Unvalidated dynamic method call
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
* fix: add suggestions from AI bot
* fix: fix typos spelling
* Update .gitignore
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: add suggestions from AI bots
* fix: add suggestions from AI bot
* Update .env.docker
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* Update .env.sample
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* feat(videos-ui): add camshots state management and service
Add Akita store, effects, queries, and actions for managing camshot state.
Implement Angular service to fetch camshots from the API endpoint.
Define camshot model interface and class.
* refactor(videos-ui): simplify camshot query and model usage
Update CamshotQuery to directly use ICamshot interface instead of the Camshot class for camshots and camshot observables. This change enhances type safety and reduces unnecessary object instantiation, streamlining the state management for camshots.
* feat(videos-ui): add components for camshot list
Implement UI components for displaying a list of camshots.
Includes:
- camshot-list component (main container)
- camshot-item component (individual item)
- camshot-item-skeleton component (loading placeholder)
Uses Angular's @defer with 'on viewport' trigger for lazy loading individual camshot items and a minimum placeholder duration.
* refactor(videos-ui/camshots): refactor camshot list data flow
Refactor CamshotListComponent to consume camshots data from the
CamshotQuery observable instead of using an input property.
Refactor CamshotItemComponent to define its action buttons internally
based on the camshot's state (e.g., deleted status) and emit specific
events for each action (view, download, recover, delete, hard delete).
Remove the actions input from CamshotItemComponent.
Add CamshotItemComponent, CamshotItemSkeletonComponent, and
CamshotListComponent to the video-ui module declarations as they are
no longer standalone.
* feat(videos-ui): add camshots tab to video detail page
Display camshots associated with the video's time slot in a new tab on the video detail page.
Implement infinite scroll pagination for the camshot list to efficiently load camshots.
Refactor camshot list component to accept the time slot ID as input and manage its own data fetching and state based on the provided ID.
* feat(videos-ui): improve list display and loading
Introduce deferred loading for video and camshot lists on the detail page to
improve initial page load performance using Angular's @defer syntax.
Redesign the camshot item display by changing action buttons to a popover
menu accessed via an icon and updating the layout and styling of the
thumbnail, title, and meta information.
Adjust the initial and reset skip value in the camshot list component
to fix a potential pagination issue.
* refactor(camshot): restructure item skeleton html and style appearance
Restructure the HTML elements of the camshot item skeleton (e.g.,
using divs instead of semantic tags) to provide better hooks for
styling. Update the SCSS to apply new styles and refine the pulsing
animation colors and layout. Add overflow styling to the camshot
list container.
* refactor(video-detail): improve list loading and infinite scroll
Update camshot and similar video lists on the video detail page to:
- Display more informative 'Loading...' messages using ngx-no-data-message.
- Rename 'Videos' tab to 'Similars'.
- Prevent fetching camshots when timeSlotId is not available.
- Enable infinite scroll pagination for camshots only after the
initial data has loaded and timeSlotId is present.
- Remove unused console.log.
- Add minor styling to tab links.
* feat(camshot-item): emit full camshot object from item actions
Change camshot item action outputs to emit the full ICamshot object
instead of just the ID. Update output event emitter types and
button action callbacks to reflect this change.
* refactor(camshot-item): replace static button labels with i18n keys
Prepare the component for internationalization by using localization keys
instead of hardcoded strings for button labels.
* feat(videos-ui/camshot): add view, delete and restore functionality
Implement actions, effects, store updates, and service methods
for managing individual camshots.
Adds the ability to view, soft delete, hard delete, and restore
camshots from the UI.
Updates the camshot item component to emit events for these actions
and adds a delete confirmation dialog in the list component.
* feat(camshot): add loading state to actions and list deleted
Implement loading state feedback for action buttons in the UI.
Introduce an `ActionButton` class to standardize button properties and include a `loading` observable. Update camshot item component to use this class and bind the loading state of delete and recover actions to the respective query states (`deleting$`, `restoring$`). Update the action button component template to display a spinner based on the loading state.
Modify the `ListCamshotQueryHandler` to include deleted camshots (`withDeleted: true`) in the results, enabling recovery and hard delete actions from the list view. Refine the logic for filtering camshots by the current employee's uploads.
Includes minor UI updates: change recover icon to `refresh-outline` and soft delete button status to `danger`.
* feat(camshot): add downloading state for camshot item
Expose a downloading state observable via the query and add it to the camshot item component to show a loading indicator during download.
* feat(camshot): implement soft-deleted camshot recovery
Add backend endpoint, CQRS command, and handler to recover soft-deleted
camshot entities.
A new PATCH /plugins/camshots/:id endpoint is added to the CamshotController
to trigger the recovery command. The RecoverCamshotCommand and its handler
utilize the softRecover method in the CamshotService to restore the entity.
The DeleteCamshotCommandHandler is updated to correctly query for soft-deleted
entities using `withDeleted: true` when handling deletion commands,
particularly for forceDelete operations.
UI changes in the videos-ui plugin add event handlers and actions
(`onRecover`, `onHardDelete`) for the camshot list component to interact
with the new recovery and updated hard delete logic.
* feat(videos-ui/camshots): add camshot download feature
Implement the download camshot feature.
Adds a new action and effect to handle adding camshots to the download queue service.
Connects the download functionality to the camshot list component.
Updates modal titles for clarity and adds styling for no data message.
* feat(videos-ui/camshot): add dialog to view camshots
Implement a modal dialog component for viewing camshot images.
Replaces the console log action when clicking "view" on a camshot with opening
this new viewer dialog.
The viewer includes basic controls like zooming, loading state, and error
handling.
Updated the camshot query to include the 'uploadedBy' relation for displaying
the uploader's name in the viewer metadata.
Updated the camshot model to include the 'uploadedBy' property.
Includes necessary Angular NgOptimizedImage import for performance.
* feat(camshot-viewer): enhance image viewer with pan, drag, and ui updates
Implement image pan and drag functionality when the image is zoomed.
Redesign the user interface with floating header, updated loading/error states, floating zoom controls, and hoverable metadata.
Improve overall layout, styling, and responsiveness of the viewer dialog.
* fix(soundshot): remove IsUrl validator from file url
* feat(videos-ui/soundshot): add soundshot state management
Add Akita state management slice for soundshots, including:
- Actions for fetch, delete, restore, download
- Effects to handle actions and update store
- Query to select state data
- Store to hold soundshot state
- Service to interact with soundshot API
- Model definition
* feat(videos-ui): add sounshots list and player
Implement feature to display and play sounshots.
- Add `SounshotListComponent` with infinite scroll.
- Create `SounshotPlayerComponent` for audio playback.
- Introduce `SounshotPlayerSkeletonComponent` for loading states.
- Integrate list into video detail page with a new tab.
Includes updates to Codacy configuration, Codacy CLI script,
.gitignore, and .vscode/settings.json.
* feat(videos-ui/soundshot-player): add interactive player controls
Implement play/pause, seeking, and volume control for soundshots.
Display track duration and file size.
Refactor component logic using Angular signals and update template/styles.
Remove outdated spec file and Codacy configuration.
* style(soundshot-player): remove max width from player
Allow the player component to take up the full width of its container.
* refactor(soundshot-skeleton): restructure player skeleton
Rewrite the HTML and SCSS for the soundshot player skeleton
component.
Simplifies the layout structure and updates the animation
style. Also changes the background color variable.
* feat(soundshot-player): add cover image and update layout
Add a cover image element to the soundshot player component.
Adjust the layout to display the cover image alongside the soundshot
title and metadata on wider screens. Maintain a stacked layout on
smaller screens.
* style(soundshot-skeleton): improve skeleton layout and animation
Add a placeholder for the cover image to the soundshot player skeleton.
Refactor the layout of the title and meta information to accommodate
the new cover.
Apply the skeleton loading animation consistently to all significant
elements within the skeleton (cover, title, meta items, controls,
progress, time, volume).
* feat(soundshot-player): add actions popover
Add a popover with action buttons to the soundshot player component.
Include download, delete, and conditionally recover/hard delete actions based on the soundshot status.
Allows users to perform actions directly from the player UI.
* style(soundshot-player): update styling and layout
Adopt CSS variable for border radius for consistency.
Change align-items to flex-start in soundshot info.
Add transition for smoother visual updates.
Add specific styles for the actions element.
* feat(soundshot-player): emit player button action events and add loading state
Replace placeholder console.log actions for player buttons with EventEmitter
outputs. This allows parent components to handle the corresponding actions
such as download, recover, soft delete, and hard delete.
Add loading state indication to buttons based on query status for improved
user experience.
* feat(videos-ui): implement soundshot actions
Implement download, recover, soft delete, and hard delete actions for soundshots.
Add event handlers in the soundshot list component to dispatch corresponding
actions. Use confirmation modals for delete and hard delete operations.
Add visual styling to indicate deleted soundshots in the player component.
* fix(soundshot): include soft-deleted entities in delete lookup
When handling the delete command, the service needs to locate the
soundshot entity even if it has been previously soft-deleted.
Using `findOneByOptions` with `{ withDeleted: true }` ensures the
lookup finds the entity regardless of its soft-delete status.
* feat(soundshot/query): include deleted soundshots
Modify the query handler to pass `withDeleted: true` to the
pagination service, ensuring soft-deleted soundshots are
included in the results.
* feat(videos-ui): add toast notifications for restore and delete
Add toast notifications for camshot and soundshot restore and delete
operations.
These toasts inform the user about the status of the operation,
including when it starts, succeeds, or fails. This provides clearer
feedback than just updating the UI state.
* style(soundshot-player): reduce deleted background opacity
* feat(soundshot): add soundshot recovery endpoint and command
Implement command, handler, and controller endpoint to allow soft-recovering
a previously deleted soundshot record.
* feat(soundshot): allow filtering soundshots
Update GetSoundshotsQueryDTO to accept a generic FindOptionsWhere for the
where clause. This removes the previous limitation requiring
TenantOrganizationBaseDTO and a custom transformation.
Utilize the where clause in the soundshot list component to filter by
timeSlotId.
* refactor(soundshot): remove ValidateNested import
* fix(camshot): correctly apply filters to camshot query
When listing camshots, ensure that users without the
CHANGE_SELECTED_EMPLOYEE permission are correctly filtered by
their uploadedById. If a user lacks this permission and does
not have a current employee ID, return an empty result set
immediately to prevent unauthorized data exposure or query errors.
Also, ensure that the dynamically built 'where' clause (from
permissions or date filters) is correctly merged with any base
'where' conditions provided in the query parameters.
Update internal comments for accuracy.
* fix(videos): refine list query filtering and permissions
Add stricter checks in the list videos query handler:
- Ensure `employeeIds` filter is only applied for users
with the `CHANGE_SELECTED_EMPLOYEE` permission.
- Return empty result if user lacks permission and
current employee ID is missing.
- Include soft-deleted records in the query results.
Also update a comment in the list camshot query handler.
* refactor(videos): refactor video count query handler with validation
Add explicit validation for required query options (organizationId,
tenantId) to ensure the handler receives necessary parameters.
Refactor the handler by extracting validation and where condition
building logic into separate private methods. This improves code
structure, readability, and testability.
Enhance JSDoc comments to better explain the handler's purpose,
parameters, and behavior.
* chore(videos-ui): correct sounshot typo in soundshot components
Update component names, selectors, and file paths from "sounshot" to "soundshot" to fix consistent misspelling. This affects the soundshot list, player, and skeleton components and their imports.
* chore(cspell): ignore rules directory
* chore: ignore .codacy directory in spell check
* fix(video-detail-page): update similar tab title
* fix(camshot): correct recover camshot handler filename and import
Correct a typo in the filename for the recover camshot command handler and update the corresponding import path.
* fix(camshot): improve message for camshot recovery not found
Provide more detailed reasons when camshot recovery fails due
to not found or other issues.
* fix(video-detail-page): fix soundshot loading message status
Change the status of the placeholder message displayed while
soundshots are loading from danger to info. Danger status is misleading
for a simple loading state; info status better reflects the ongoing
process.
* fix(video-detail-page): correct loading message and status
Update the loading message from 'Loading camshots...' to
'Loading similar videos...' to accurately reflect the content.
Change the status from 'danger' to 'info' as the loading state
is not a critical error.
* style(camshot-list): clean up formatting
* fix: incorrect grammar in description
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix(soundshot-player): improve seek function robustness
Add checks to ensure the audio player and progress bar elements
are available before attempting to calculate the seek position.
Also add a check for zero width on the progress bar.
Wrap the seek operation in a try/catch block to gracefully handle
potential errors during playback updates.
Include console warnings/errors for debugging missing elements
or failed seek operations.
* fix: Duplicate 'nbButton' attribute on lines 2 and 5. Remove one instance.
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: property 'border-radius-top-left' is invalid
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: no feedback shown when isAdded is false. User should be notified if download queue addition fails
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: command should implement ICommand interface from @nestjs/cqrs to follow CQRS pattern
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* feat(soundshot): return recovered soundshot from patch
Return the updated soundshot object after recovery.
This allows the client to immediately use the refreshed state of the
soundshot without needing a subsequent GET request.
BREAKING CHANGE: The PATCH /soundshots/:id endpoint now returns the
recovered soundshot object instead of nothing.
* fix: API description has a typo 'UUID, version UUID the plugin ID'
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* chore: remove sensitive nx cloud access token
Remove the hardcoded token from nx.json.
Environment variables or secrets management
should be used instead.
* style(camshot): fix formatting and API description typo
Correct constructor formatting in CamshotController and RecoverCamshotCommand. Update API description to remove redundancy in the recover camshot operation.
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* feat(plugin-soundshot): add plugin package
Includes basic Nx configuration, package.json, tsconfig files, and a placeholder NestJS module for the new plugin.
* feat(soundshot): add soundshot plugin
Implement the soundshot feature including entity, services, and API endpoints
for managing short audio recordings.
This change introduces:
- Soundshot entity definition with relations and file storage details.
- DTOs for creating, deleting, and counting soundshots.
- CQRS commands and queries for soundshot operations (create, delete, list,
get, count).
- Service layer with file upload preparation, validation, and interaction
with storage providers.
- Controller with REST endpoints for soundshot CRUD and listing.
- TypeORM subscriber to manage file lifecycle (generate URL on insert,
delete file on remove).
- Updated plugin structure with dedicated module and entry point.
* feat(soundshot): increase soundshot size limit
Update the maximum allowed size for a soundshot file from 5MB
to 100MB to accommodate larger or higher quality audio
recordings.
* docs(soundshot): update file examples and patterns to webm
Update the FileDTO within the soundshot plugin to use .webm file examples and patterns instead of .png.
This change aligns the DTO descriptions and expected file formats with the typical use case for soundshots, which are expected to handle audio or video content rather than static images.
* feat(soundshot): add plugin
Integrate Soundshot plugin into the API application by adding it to the list
of available plugins.
Refactor query handlers within the soundshot plugin package.
Rename camshot-related handlers to soundshot handlers and update the exported
list of handlers.
* feat(soundshot): add media detail fields and rename title
Rename the main identifying field from `title` to `name` across contracts,
entity, and DTOs for improved clarity.
Introduce `channels` and `rate` fields to the soundshot entity and contract
to store audio media specific details.
Update the creation process to allow setting the `name` explicitly via the
`CreateSoundshotDTO` instead of deriving it from the uploaded file name.
Removed explicit `size` mapping in the creation handler.
Relaxed MIME type validation in the file DTO to permit any `/webm` subtype.
* chore(soundshot): adjust delete soundshot command type format
Update the static type string to follow the [Plugin] Action pattern.
* refactor(soundshot): make soundshot delete error messages more specific
Include tenant and soundshot IDs in error messages thrown during
soundshot deletion.
This provides more context for debugging when the requested
resource is missing or the required IDs are not provided.
* feat(soundshot): add dedicated soundshot query dto with filters
Introduce GetSoundshotsQueryDTO to handle specific query parameters
for listing soundshots, including date range, time zone, and employee
IDs.
This replaces the generic BaseQueryDTO in the soundshot list endpoint
for improved type safety and clarity of available filters.
Update findById endpoint to use FindOptionsQueryDTO.
* feat(soundshot): add soundshot plugin package
Add package metadata, dependencies, build scripts, and initial README
documentation for the soundshot plugin.
This plugin provides functionality to upload and manage sound shots.
* build: include soundshot plugin
Update package dependencies, build scripts, and Dockerfiles to
integrate the soundshot plugin. Also add relevant terms to the
spellcheck dictionary.
* feat(database): add soundshots table
* refactor(soundshot): make repository injectable
Add Injectable decorator to allow the repository to be injected
by the NestJS framework.
* fix: doc comment mentions 'image file' but this is for audio files
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* feat(soundshot): add uploader fields to soundshot model
Add `uploadedById` and `uploadedBy` properties to the `ISoundshot`
interface to track which employee uploaded a soundshot.
* docs(soundshot): update comments for entity properties
Correct comments for `channels` and `rate` properties by removing inaccurate reference to bytes.
Remove outdated note about maximum duration limit from `duration` property comment.
* chore: configure codacy and update gitignore
Add .codacy/codacy.yaml to specify analysis runtimes and tools.
Update .gitignore to exclude .cursor directory and specific AI rule files.
Improve JSDoc for the rate property in the Soundshot entity.
* refactor(soundshot): use injected file storage provider
Replace direct instantiation of `FileStorage` with the injected
`this.fileStorage` instance within the prepare method.
This aligns the service with dependency injection patterns and
improves testability.
* style(soundshot): apply formatting and fix comment
Apply minor formatting to constructor and correct comment
to reference the correct property `recordedAt` instead of `valueDate`.
* build(server-api): remove duplicate posthog plugin reference from package files
* docs(soundshot): clarify channels validation message
Update the validation message for the 'channels' field in the Soundshot
entity to provide clearer context regarding audio channels (mono/stereo).
Also applies minor code formatting.
* refactor(soundshot): use spread syntax for merging query params
* fix(soundshot): re-throw error in subscriber beforeInsert
Ensure that errors occurring during URL generation in the `beforeInsert`
hook are propagated correctly.
* refactor(soundshot): use service to get file storage provider for cleanup
Obtain the file storage provider instance from the injected
SoundshotService during error cleanup instead of creating a new
FileStorage instance.
This ensures consistency and avoids unnecessary object creation.
Also update getFileStorageProviderInstance in service to allow
retrieving the current provider without explicitly setting the enum.
* feat(soundshot): add url validation to file dto
* docs(soundshot): clarify soundshot channels property description
Update JSDoc comment and validation message for the channels property to explicitly state it represents the number of audio channels.
* fix(soundshot): fix soundshot query where property documentation
The 'where' property in the GetSoundshotsQueryDTO was documented
with @ApiProperty, incorrectly implying it was required. This change
uses @ApiPropertyOptional to correctly reflect its optional status.
* chore(cspell): add runtimes to dictionary
* docs(soundshot): mark startDate and endDate as optional in count dto
Update @ApiProperty to @ApiPropertyOptional and make type definition explicit using '?'. This aligns documentation and type hints with the @IsOptional validation already in place.
* refactor(soundshot): clarify date types in count soundshot dto
The startDate and endDate fields are already validated as ISO 8601
strings using the @IsISO8601 decorator. Update the type annotation to
reflect this expected format and remove the redundant 'Date' type from
the union.
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: remove duplicated translation
* feat: copy gauzy translation
* fix: http loader factory import
* fix: exclude duplicated translations from root
* fix: separate factory from login component
* feat: add ngx translate congiguration
* feat: set language in header with language interceptor
* feat: add listerner on preferred language change
* feat: add user to akita store
* feat: create language service
* feat: create language selector
* feat: add translations
* feat: add new translations
* fix: hebrew translation
* feat: add new translation
* feat: improve language selector
* feat: handle prefered language
* feat: add default language to store
* feat: translate about page
* refactor: translation for login page
* feat: translate splash screen
* feat: move the hanlder to app entry
* feat: add new translations
* feat: add translations to setup window
* feat: add new translations
* feat: caching languages
* fix: update language only if it change
* feat: add new translations
* feat: add translation to settings windows
* fix: subcribe to observable
* fix: humanize timer interval options
* fix: cspell splelling
* feat: add new translations
* feat: applied translations to time tracker component
* feat: translate login page for fr and es
* fix: all translations
* feat: add new translation
* feat: use instant service's method instantly
* fix: translation on pages
* fix: translation on time tracker page
* fix: update table column's titles in real time
* feat: no need to duplicate translations
* feat: copy translation files from gauzy to desktop app
* feat: add preferred language handler and default global variable.
* feat: add language interceptor to desktop app module
* fix: deferred smartable's loading
* feat: handle language change from gauzy to settings and hide language selector for desktop
* feat: handle electron process on language change
* feat: improve language initializer factory
* feat: no need to duplicate translations
* feat: add new translations
* feat: improve language selector
* feat: add translation to server dashboard
* feat: applied selector improvement
* feat: create language selector service
* fix: notify changes to settings page on setup.