[chore] Migrate desktop apps standalone (#9417)

* refactor(desktop-ui): convert components and directives to standalone

Migrate numerous components, directives, and pipes within the desktop
UI library to Angular's standalone architecture. This update involves:
- Removing 'standalone: false' from component and directive decorators.
- Adding necessary dependencies to the 'imports' array of individual
standalone components.
- Moving declarations from NgModule metadata to the 'imports' array.
- Updating test suites to use 'imports' instead of 'declarations' for
standalone components.

* refactor: remove redundant modules in favor of standalone components

Clean up the codebase by removing several intermediate Angular modules,
including DesktopDirectiveModule, NoDataMessageModule, and
PaginationModule. Components and directives are now imported directly
into consuming modules, streamlining the dependency structure and
supporting the transition to standalone components.

* refactor(ui): migrate templates to angular control flow syntax

Update various components to use the new @if and @for control flow
syntax instead of *ngIf and *ngFor structural directives. This change
also removes unnecessary NgIf and NgFor imports from the component
metadata.

* perf(desktop-ui): use loadComponent for lazy loading routes

Replace static component imports with dynamic imports using the
loadComponent property in routing configurations. This optimization
enables lazy loading for these components, which helps reduce the
initial bundle size and improves the application's startup time.

* refactor: streamline component imports and remove unused modules

* refactor(desktop-ui-lib): update component imports and clean up modules

Add PipeModule to various recap components to provide necessary pipes.
Remove several standalone components from NgModule declarations and
exports as they are now managed via lazy loading or direct component
imports. Clean up and reorder imports across affected files for
consistency.

* refactor(time-tracker): remove form value accessor and clean up imports

Remove the NG_VALUE_ACCESSOR implementation and provider from the
TimeTrackerComponent. Clean up redundant component references in
TimeTrackerModule and reorganize imports for better maintainability.

* refactor(desktop-timer): migrate to standalone application architecture

Migrate the desktop-timer application from a module-based architecture
to a standalone application architecture using Angular's
bootstrapApplication API.
- Delete AppModule and move its logic to main.ts.
- Update AppRoutingModule to use loadComponent for route-level lazy
loading of components from @gauzy/desktop-ui-lib.
- Refactor RecapModule and SettingsModule to remove unnecessary
component declarations and exports.
- Consolidate application providers and third-party module
initializations in the bootstrap process.

* refactor(desktop-timer): convert AppComponent to standalone and simplify refresh

Convert the root AppComponent to a standalone component and add the
RouterOutlet to its imports. Simplify the initialization logic by
removing manual token checks before starting the token refresh service.

* refactor(desktop-ui-lib): replace LanguageModule with TranslateModule

Replace the internal LanguageModule with TranslateModule from
@ngx-translate/core in the recap and task-table modules. Additionally,
import PipeModule in GauzyFiltersComponent to ensure required pipes are
available.

* refactor(desktop): migrate to standalone bootstrapping

Remove AppModule and transition to the bootstrapApplication API in
main.ts. This includes moving all providers and imported modules from
the deleted app.module.ts into the bootstrap configuration, and
replacing BrowserAnimationsModule with provideAnimations.

* refactor(desktop): implement lazy loading and standalone component

Update the routing configuration to use lazy loading for all component
routes in app-routing.module.ts. Refactor AppComponent to support
standalone imports and simplify the token refresh service
initialization logic.

* refactor(agent): migrate to standalone bootstrap api

Remove the AppModule and use the bootstrapApplication function to
initialize the app. Convert AppComponent to a standalone component and
consolidate providers and module configurations in main.ts.

* perf(agent): use lazy loading for routes and simplify token refresh

Implement lazy loading for all routes in the agent application using the
`loadComponent` syntax. This improves the initial bundle size and
startup performance by loading component code only when needed.
Additionally, simplify the initialization of the token refresh service
in `AppComponent` by removing the manual check for existing tokens,
allowing the service to handle its own internal state logic.

* style(server): fix indentation in app component spec

Correct the whitespace and indentation in the app component specification
file to align with the project's formatting standards.

* refactor: migrate server applications to standalone bootstrapping

Remove AppModule from both server and server-api applications and
transition to the Angular standalone bootstrap API. Provider
configurations are moved to main.ts using bootstrapApplication and
importProvidersFrom.

* perf(routing): use lazy loading for desktop ui components

Replace static component imports with dynamic imports using the
loadComponent property in both server and server-api routing modules.
This optimization reduces the initial bundle size and improves
application startup performance by loading components from the
@gauzy/desktop-ui-lib only when needed.

* refactor(app): update component to use standalone imports for RouterOutlet

* refactor(routing): update auth routes to use consistent lazy loading and guards

* feat(build): add quick build script for mac agent

* refactor(routing): add AuthGuard to server-dashboard route for enhanced security

* feat(desktop): initialize TranslateModule in bootstrap process

Configure the ngx-translate TranslateModule within the application bootstrap logic. This setup includes the HttpLoaderFactory and HttpClient dependencies to enable internationalization support.

* build(gauzy): add nebular default theme styles

Include the @nebular/theme prebuilt default CSS file in the project
styles configuration to ensure UI components render correctly.

* refactor(apps): simplify bootstrap process and update providers

Streamline the bootstrap process for server and server-api applications
by removing unused Nebular and feature modules. Configure the
TranslateModule with HttpLoaderFactory and add Store to the application
providers. Additionally, remove the AuthConnectionGuard from routing
configurations and update global style paths in project.json.
This commit is contained in:
Kifungo A
2026-02-05 21:00:29 +01:00
committed by GitHub
parent 8377491a56
commit fb004513c7
211 changed files with 2120 additions and 2239 deletions
+13 -23
View File
@@ -1,28 +1,17 @@
import { NgModule } from '@angular/core';
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
import {
AboutComponent,
AgentDashboardComponent,
AlwaysOnComponent,
AuthConnectionGuard,
ScreenCaptureComponent,
ServerDownPage,
SettingsComponent,
SetupComponent,
SplashScreenComponent,
UpdaterComponent
} from '@gauzy/desktop-ui-lib';
import { AuthConnectionGuard, AuthGuard } from '@gauzy/desktop-ui-lib';
import { AppModuleGuard } from './app.module.guards';
const routes: Routes = [
{
path: 'setup',
component: SetupComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SetupComponent)
},
{
path: 'auth',
loadChildren: () => import('@gauzy/desktop-ui-lib').then((m) => m.authRoutes),
canActivate: [AppModuleGuard]
canActivate: [AppModuleGuard],
loadChildren: () => import('@gauzy/desktop-ui-lib').then((m) => m.AuthModule)
},
{
path: 'plugins',
@@ -31,36 +20,37 @@ const routes: Routes = [
},
{
path: 'settings',
component: SettingsComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SettingsComponent)
},
{
path: 'updater',
component: UpdaterComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.UpdaterComponent)
},
{
path: 'splash-screen',
component: SplashScreenComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SplashScreenComponent)
},
{
path: 'server-down',
component: ServerDownPage
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.ServerDownPage)
},
{
path: 'always-on',
component: AlwaysOnComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.AlwaysOnComponent)
},
{
path: 'about',
component: AboutComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.AboutComponent)
},
{
path: 'server-dashboard',
component: AgentDashboardComponent,
canActivate: [AppModuleGuard, AuthConnectionGuard, AuthGuard],
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.AgentDashboardComponent),
loadChildren: () => import('@gauzy/desktop-ui-lib').then((m) => m.agentDashboardRoutes)
},
{
path: 'screen-capture',
component: ScreenCaptureComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.ScreenCaptureComponent)
}
];
+3 -7
View File
@@ -1,4 +1,5 @@
import { AfterViewInit, Component, HostBinding, NgZone, OnDestroy, OnInit, Renderer2 } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import {
ActivityWatchElectronService,
AuthStrategy,
@@ -19,7 +20,7 @@ import { AppService } from './app.service';
selector: 'agent-root',
template: '<router-outlet></router-outlet>',
styleUrls: ['./app.component.scss'],
standalone: false
imports: [RouterOutlet]
})
export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
@HostBinding('class.login-small-height') isLoginPage = false;
@@ -48,13 +49,8 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
this.checkAuthValidation();
const nebularLinkMedia = document.querySelector('link[media="print"]');
if (nebularLinkMedia) this._renderer.setAttribute(nebularLinkMedia, 'media', 'all');
this.electronService.ipcRenderer.send('app_is_init');
// Start token refresh timer if user is authenticated
if (this.store.token && this.store.refreshToken) {
this.tokenRefreshService.start();
}
this.tokenRefreshService.start();
}
ngOnDestroy(): void {
-219
View File
@@ -1,219 +0,0 @@
import { HTTP_INTERCEPTORS, HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { APP_INITIALIZER, ErrorHandler, Injector, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Router } from '@angular/router';
import {
APIInterceptor,
AboutModule,
AgentDashboardModule,
AlwaysOnModule,
AuthGuard,
AuthModule,
AuthService,
AuthStrategy,
DEFAULT_TIMEOUT,
ElectronService,
ErrorHandlerService,
GAUZY_ENV,
HttpLoaderFactory,
ImageViewerModule,
LanguageInterceptor,
LanguageModule,
LoggerService,
NgxDesktopThemeModule,
NgxLoginModule,
NoAuthGuard,
OrganizationInterceptor,
RefreshTokenInterceptor,
ScreenCaptureModule,
ServerConnectionService,
ServerDashboardModule,
ServerDownModule,
ServerErrorInterceptor,
SettingsModule,
SetupModule,
SplashScreenModule,
Store,
TenantInterceptor,
TimeoutInterceptor,
TokenInterceptor,
UnauthorizedInterceptor,
UpdaterModule,
serverConnectionFactory
} from '@gauzy/desktop-ui-lib';
import { environment as gauzyEnvironment } from '@gauzy/ui-config';
import {
NbButtonModule,
NbCardModule,
NbDatepickerModule,
NbDialogModule,
NbDialogService,
NbLayoutModule,
NbSidebarModule,
NbSidebarService,
NbThemeModule,
NbToastrModule
} from '@nebular/theme';
import { NgSelectModule } from '@ng-select/ng-select';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import * as Sentry from '@sentry/angular';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AppModuleGuard } from './app.module.guards';
import { AppService } from './app.service';
import { initializeSentry } from './sentry';
/**
* Initializes Sentry based on the environment configuration.
* If a valid Sentry DSN is provided, Sentry is initialized with the specified configuration.
* If the DSN is set to 'DOCKER_SENTRY_DSN', a warning is logged indicating that the environment
* is running inside Docker without a Sentry DSN.
*/
if (environment.SENTRY_DSN) {
if (environment.SENTRY_DSN === 'DOCKER_SENTRY_DSN') {
console.warn('You are running inside Docker but does not have SENTRY_DSN env set');
} else {
console.log(`Enabling Sentry with DSN: ${environment.SENTRY_DSN}`);
initializeSentry();
}
}
@NgModule({
declarations: [AppComponent],
bootstrap: [AppComponent],
exports: [],
imports: [
NbLayoutModule,
AuthModule,
NbDialogModule.forRoot(),
NbToastrModule.forRoot(),
NbCardModule,
NbButtonModule,
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
NbThemeModule,
NbSidebarModule.forRoot(),
NgxDesktopThemeModule,
NgxLoginModule,
SetupModule,
SettingsModule,
UpdaterModule,
ServerDashboardModule,
ScreenCaptureModule,
ImageViewerModule,
NgSelectModule,
SplashScreenModule,
ServerDownModule,
TranslateModule.forRoot({
extend: true,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
LanguageModule.forRoot(),
NbDatepickerModule.forRoot(),
AboutModule,
AgentDashboardModule,
AlwaysOnModule
],
providers: [
AppService,
NbDialogService,
NbSidebarService,
AuthGuard,
NoAuthGuard,
AppModuleGuard,
AuthStrategy,
AuthService,
ServerConnectionService,
ElectronService,
LoggerService,
Store,
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: RefreshTokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TenantInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: OrganizationInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: APIInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: LanguageInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TimeoutInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: UnauthorizedInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: ServerErrorInterceptor,
multi: true
},
{
provide: ErrorHandler,
useClass: ErrorHandlerService
},
{
provide: APP_INITIALIZER,
useFactory: serverConnectionFactory,
deps: [ServerConnectionService, Store, Router, Injector],
multi: true
},
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: true
})
},
{
provide: Sentry.TraceService,
deps: [Router]
},
{
provide: APP_INITIALIZER,
useFactory: () => () => {},
deps: [Sentry.TraceService],
multi: true
},
{ provide: DEFAULT_TIMEOUT, useValue: 80000 },
{
provide: GAUZY_ENV,
useValue: {
...gauzyEnvironment,
...environment
}
},
provideHttpClient(withInterceptorsFromDi())
]
})
export class AppModule {}
+209 -9
View File
@@ -1,9 +1,67 @@
import { enableProdMode } from '@angular/core';
import { platformBrowser } from '@angular/platform-browser';
import { HTTP_INTERCEPTORS, HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { APP_INITIALIZER, ErrorHandler, Injector, enableProdMode, importProvidersFrom } from '@angular/core';
import { BrowserModule, bootstrapApplication } from '@angular/platform-browser';
import { provideAnimations } from '@angular/platform-browser/animations';
import { Router } from '@angular/router';
import { akitaConfig, enableAkitaProdMode, persistState } from '@datorama/akita';
import { AppModule } from './app/app.module';
import {
APIInterceptor,
AboutModule,
AgentDashboardModule,
AlwaysOnModule,
AuthGuard,
AuthModule,
AuthService,
AuthStrategy,
DEFAULT_TIMEOUT,
ElectronService,
ErrorHandlerService,
GAUZY_ENV,
HttpLoaderFactory,
ImageViewerModule,
LanguageInterceptor,
LanguageModule,
LoggerService,
NgxDesktopThemeModule,
NgxLoginModule,
NoAuthGuard,
OrganizationInterceptor,
RefreshTokenInterceptor,
ServerConnectionService,
ServerDashboardModule,
ServerDownModule,
ServerErrorInterceptor,
SettingsModule,
SetupModule,
SplashScreenModule,
Store,
TenantInterceptor,
TimeoutInterceptor,
TokenInterceptor,
UnauthorizedInterceptor,
serverConnectionFactory
} from '@gauzy/desktop-ui-lib';
import { environment as gauzyEnvironment } from '@gauzy/ui-config';
import {
NbButtonModule,
NbCardModule,
NbDatepickerModule,
NbDialogModule,
NbDialogService,
NbLayoutModule,
NbSidebarModule,
NbSidebarService,
NbThemeModule,
NbToastrModule
} from '@nebular/theme';
import { NgSelectModule } from '@ng-select/ng-select';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import * as Sentry from '@sentry/angular';
import { AppRoutingModule } from './app/app-routing.module';
import { AppComponent } from './app/app.component';
import { AppModuleGuard } from './app/app.module.guards';
import { AppService } from './app/app.service';
import { initializeSentry } from './app/sentry';
import { environment } from './environments/environment';
if (environment.production) {
@@ -11,6 +69,21 @@ if (environment.production) {
enableAkitaProdMode();
}
/**
* Initializes Sentry based on the environment configuration.
* If a valid Sentry DSN is provided, Sentry is initialized with the specified configuration.
* If the DSN is set to 'DOCKER_SENTRY_DSN', a warning is logged indicating that the environment
* is running inside Docker without a Sentry DSN.
*/
if (environment.SENTRY_DSN) {
if (environment.SENTRY_DSN === 'DOCKER_SENTRY_DSN') {
console.warn('You are running inside Docker but does not have SENTRY_DSN env set');
} else {
console.log(`Enabling Sentry with DSN: ${environment.SENTRY_DSN}`);
initializeSentry();
}
}
persistState({
key: '_gauzyStore'
});
@@ -19,9 +92,136 @@ akitaConfig({
resettable: true
});
platformBrowser()
.bootstrapModule(AppModule, {
preserveWhitespaces: false
})
bootstrapApplication(AppComponent, {
providers: [
importProvidersFrom(
NbLayoutModule,
AuthModule,
NbDialogModule.forRoot(),
NbToastrModule.forRoot(),
NbCardModule,
NbButtonModule,
BrowserModule,
AppRoutingModule,
NbThemeModule,
NbSidebarModule.forRoot(),
NgxDesktopThemeModule,
NgxLoginModule,
SetupModule,
SettingsModule,
ServerDashboardModule,
ImageViewerModule,
NgSelectModule,
SplashScreenModule,
ServerDownModule,
TranslateModule.forRoot({
extend: true,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
LanguageModule.forRoot(),
NbDatepickerModule.forRoot(),
AboutModule,
AgentDashboardModule,
AlwaysOnModule
),
AppService,
NbDialogService,
NbSidebarService,
AuthGuard,
NoAuthGuard,
AppModuleGuard,
AuthStrategy,
AuthService,
ServerConnectionService,
ElectronService,
LoggerService,
Store,
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: RefreshTokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TenantInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: OrganizationInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: APIInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: LanguageInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TimeoutInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: UnauthorizedInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: ServerErrorInterceptor,
multi: true
},
{
provide: ErrorHandler,
useClass: ErrorHandlerService
},
{
provide: APP_INITIALIZER,
useFactory: serverConnectionFactory,
deps: [ServerConnectionService, Store, Router, Injector],
multi: true
},
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: true
})
},
{
provide: Sentry.TraceService,
deps: [Router]
},
{
provide: APP_INITIALIZER,
useFactory: () => () => {},
deps: [Sentry.TraceService],
multi: true
},
{ provide: DEFAULT_TIMEOUT, useValue: 80000 },
{
provide: GAUZY_ENV,
useValue: {
...gauzyEnvironment,
...environment
}
},
provideHttpClient(withInterceptorsFromDi()),
provideAnimations()
]
})
.then(() => console.log(`Bootstrap Success!`))
.catch((error) => console.error(error));
@@ -1,50 +1,41 @@
import { NgModule } from '@angular/core';
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
import {
AboutComponent,
AlwaysOnComponent,
AUTH_CONNECTION_GUARD_CONFIG,
AuthConnectionGuard,
AuthGuard,
DEFAULT_AUTH_CONNECTION_GUARD_CONFIG,
ImageViewerComponent,
ScreenCaptureComponent,
ServerDownPage,
SettingsComponent,
SetupComponent,
SplashScreenComponent,
TimeTrackerComponent,
UpdaterComponent
DEFAULT_AUTH_CONNECTION_GUARD_CONFIG
} from '@gauzy/desktop-ui-lib';
import { AppModuleGuard } from './app.module.guards';
const routes: Routes = [
{
path: 'setup',
component: SetupComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SetupComponent)
},
{
path: 'auth',
loadChildren: () => import('@gauzy/desktop-ui-lib').then((m) => m.AuthModule),
canActivate: [AppModuleGuard, AuthConnectionGuard]
canActivate: [AppModuleGuard, AuthConnectionGuard],
loadChildren: () => import('@gauzy/desktop-ui-lib').then((m) => m.AuthModule)
},
{
path: 'time-tracker',
component: TimeTrackerComponent,
canActivate: [AppModuleGuard, AuthGuard, AuthConnectionGuard],
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.TimeTrackerComponent),
loadChildren: () => import('@gauzy/desktop-ui-lib').then((m) => m.RecapModule)
},
{
path: 'screen-capture',
component: ScreenCaptureComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.ScreenCaptureComponent)
},
{
path: 'always-on',
component: AlwaysOnComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.AlwaysOnComponent)
},
{
path: 'settings',
component: SettingsComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SettingsComponent)
},
{
path: 'plugins',
@@ -53,29 +44,29 @@ const routes: Routes = [
},
{
path: 'updater',
component: UpdaterComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.UpdaterComponent)
},
{
path: 'viewer',
component: ImageViewerComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.ImageViewerComponent)
},
{
path: 'splash-screen',
component: SplashScreenComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SplashScreenComponent)
},
{
path: 'server-down',
component: ServerDownPage
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.ServerDownPage)
},
{
path: '',
component: TimeTrackerComponent,
canActivate: [AppModuleGuard, AuthGuard, AuthConnectionGuard],
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.TimeTrackerComponent),
loadChildren: () => import('@gauzy/desktop-ui-lib').then((m) => m.RecapModule)
},
{
path: 'about',
component: AboutComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.AboutComponent)
}
];
@@ -96,4 +87,4 @@ const config: ExtraOptions = {
}
]
})
export class AppRoutingModule { }
export class AppRoutingModule {}
+4 -6
View File
@@ -1,4 +1,5 @@
import { AfterViewInit, Component, NgZone, OnInit, Renderer2 } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import {
ActivityWatchElectronService,
AuthStrategy,
@@ -19,7 +20,7 @@ import { AppService } from './app.service';
selector: 'gauzy-root',
template: '<router-outlet></router-outlet>',
styleUrls: ['./app.component.scss'],
standalone: false
imports: [RouterOutlet]
})
export class AppComponent implements OnInit, AfterViewInit {
constructor(
@@ -43,11 +44,8 @@ export class AppComponent implements OnInit, AfterViewInit {
if (nebularLinkMedia) this._renderer.setAttribute(nebularLinkMedia, 'media', 'all');
this.electronService.ipcRenderer.send('app_is_init');
// Start token refresh timer if user is authenticated
if (this.store.token && this.store.refreshToken) {
this.tokenRefreshService.start();
}
// Start token refresh timer if we have a token and refresh token
this.tokenRefreshService.start();
}
ngAfterViewInit(): void {
-228
View File
@@ -1,228 +0,0 @@
import { HTTP_INTERCEPTORS, HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { ErrorHandler, Injector, NgModule, inject, provideAppInitializer } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Router } from '@angular/router';
import {
APIInterceptor,
AboutModule,
ActivityWatchInterceptor,
ActivityWatchModule,
AlwaysOnModule,
AuthGuard,
AuthModule,
AuthService,
AuthStrategy,
DEFAULT_TIMEOUT,
ElectronService,
ErrorHandlerService,
GAUZY_ENV,
HttpLoaderFactory,
ImageViewerModule,
LanguageInterceptor,
LanguageModule,
LoggerService,
NgxDesktopThemeModule,
NgxLoginModule,
NoAuthGuard,
OrganizationInterceptor,
PluginsModule,
RecapModule,
RefreshTokenInterceptor,
ScreenCaptureModule,
ServerConnectionService,
ServerDownModule,
ServerErrorInterceptor,
SettingsModule,
SetupModule,
SplashScreenModule,
Store,
TaskTableModule,
TenantInterceptor,
TimeTrackerModule,
TimeoutInterceptor,
TokenInterceptor,
UnauthorizedInterceptor,
UpdaterModule,
serverConnectionFactory
} from '@gauzy/desktop-ui-lib';
import { environment as gauzyEnvironment } from '@gauzy/ui-config';
import {
NbButtonModule,
NbCardModule,
NbDatepickerModule,
NbDialogModule,
NbDialogService,
NbLayoutModule,
NbThemeModule,
NbToastrModule
} from '@nebular/theme';
import { NgSelectModule } from '@ng-select/ng-select';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import * as Sentry from '@sentry/angular';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AppModuleGuard } from './app.module.guards';
import { AppService } from './app.service';
import { initializeSentry } from './sentry';
/**
* Initializes Sentry based on the environment configuration.
* If a valid Sentry DSN is provided, Sentry is initialized with the specified configuration.
* If the DSN is set to 'DOCKER_SENTRY_DSN', a warning is logged indicating that the environment
* is running inside Docker without a Sentry DSN.
*/
if (environment.SENTRY_DSN) {
if (environment.SENTRY_DSN === 'DOCKER_SENTRY_DSN') {
console.warn('You are running inside Docker but does not have SENTRY_DSN env set');
} else {
console.log(`Enabling Sentry with DSN: ${environment.SENTRY_DSN}`);
initializeSentry();
}
}
@NgModule({
declarations: [AppComponent],
bootstrap: [AppComponent],
exports: [],
imports: [
NbLayoutModule,
AuthModule,
NbDialogModule.forRoot(),
NbToastrModule.forRoot(),
NbCardModule,
NbButtonModule,
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
NbThemeModule,
NgxDesktopThemeModule,
NgxLoginModule,
SetupModule,
TimeTrackerModule,
ScreenCaptureModule,
SettingsModule,
UpdaterModule,
ImageViewerModule,
NgSelectModule,
SplashScreenModule,
ServerDownModule,
AlwaysOnModule,
TranslateModule.forRoot({
extend: true,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
LanguageModule.forRoot(),
NbDatepickerModule.forRoot(),
AboutModule,
ActivityWatchModule,
RecapModule,
TaskTableModule,
PluginsModule
],
providers: [
AppService,
NbDialogService,
AuthGuard,
NoAuthGuard,
AppModuleGuard,
AuthStrategy,
AuthService,
ServerConnectionService,
ElectronService,
LoggerService,
Store,
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TenantInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: ActivityWatchInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: OrganizationInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: APIInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: LanguageInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TimeoutInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: RefreshTokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: UnauthorizedInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: ServerErrorInterceptor,
multi: true
},
{
provide: ErrorHandler,
useClass: ErrorHandlerService
},
provideAppInitializer(() => {
const initializerFn = serverConnectionFactory(
inject(ServerConnectionService),
inject(Store),
inject(Router),
inject(Injector)
);
return initializerFn();
}),
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: true
})
},
{
provide: Sentry.TraceService,
deps: [Router]
},
provideAppInitializer(() => {
const initializerFn = ((trace: Sentry.TraceService) => () => {})(inject(Sentry.TraceService));
return initializerFn();
}),
{ provide: DEFAULT_TIMEOUT, useValue: 80000 },
{
provide: GAUZY_ENV,
useValue: {
...gauzyEnvironment,
...environment
}
},
provideHttpClient(withInterceptorsFromDi())
]
})
export class AppModule {}
+219 -8
View File
@@ -1,8 +1,76 @@
import { enableProdMode } from '@angular/core';
import { platformBrowser } from '@angular/platform-browser';
import { HTTP_INTERCEPTORS, HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import {
enableProdMode,
ErrorHandler,
importProvidersFrom,
inject,
Injector,
provideAppInitializer
} from '@angular/core';
import { bootstrapApplication, BrowserModule } from '@angular/platform-browser';
import { provideAnimations } from '@angular/platform-browser/animations';
import { Router } from '@angular/router';
import { akitaConfig, enableAkitaProdMode, persistState } from '@datorama/akita';
import { AppModule } from './app/app.module';
import {
AboutModule,
ActivityWatchInterceptor,
ActivityWatchModule,
AlwaysOnModule,
APIInterceptor,
AuthGuard,
AuthModule,
AuthService,
AuthStrategy,
DEFAULT_TIMEOUT,
ElectronService,
ErrorHandlerService,
GAUZY_ENV,
HttpLoaderFactory,
ImageViewerModule,
LanguageInterceptor,
LanguageModule,
LoggerService,
NgxDesktopThemeModule,
NgxLoginModule,
NoAuthGuard,
OrganizationInterceptor,
PluginsModule,
RecapModule,
RefreshTokenInterceptor,
serverConnectionFactory,
ServerConnectionService,
ServerDownModule,
ServerErrorInterceptor,
SettingsModule,
SetupModule,
SplashScreenModule,
Store,
TaskTableModule,
TenantInterceptor,
TimeoutInterceptor,
TimeTrackerModule,
TokenInterceptor,
UnauthorizedInterceptor
} from '@gauzy/desktop-ui-lib';
import { environment as gauzyEnvironment } from '@gauzy/ui-config';
import {
NbButtonModule,
NbCardModule,
NbDatepickerModule,
NbDialogModule,
NbDialogService,
NbLayoutModule,
NbThemeModule,
NbToastrModule
} from '@nebular/theme';
import { NgSelectModule } from '@ng-select/ng-select';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import * as Sentry from '@sentry/angular';
import { AppRoutingModule } from './app/app-routing.module';
import { AppComponent } from './app/app.component';
import { AppModuleGuard } from './app/app.module.guards';
import { AppService } from './app/app.service';
import { initializeSentry } from './app/sentry';
import { environment } from './environments/environment';
if (environment.production) {
@@ -10,6 +78,15 @@ if (environment.production) {
enableAkitaProdMode();
}
if (environment.SENTRY_DSN) {
if (environment.SENTRY_DSN === 'DOCKER_SENTRY_DSN') {
console.warn('You are running inside Docker but does not have SENTRY_DSN env set');
} else {
console.log(`Enabling Sentry with DSN: ${environment.SENTRY_DSN}`);
initializeSentry();
}
}
persistState({
key: '_gauzyStore'
});
@@ -18,9 +95,143 @@ akitaConfig({
resettable: true
});
platformBrowser()
.bootstrapModule(AppModule, {
preserveWhitespaces: false
})
bootstrapApplication(AppComponent, {
providers: [
importProvidersFrom(
NbLayoutModule,
AuthModule,
NbDialogModule.forRoot(),
NbToastrModule.forRoot(),
NbCardModule,
NbButtonModule,
BrowserModule,
AppRoutingModule,
NbThemeModule,
NgxDesktopThemeModule,
NgxLoginModule,
SetupModule,
TimeTrackerModule,
SettingsModule,
ImageViewerModule,
NgSelectModule,
SplashScreenModule,
ServerDownModule,
AlwaysOnModule,
TranslateModule.forRoot({
extend: true,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
LanguageModule.forRoot(),
NbDatepickerModule.forRoot(),
AboutModule,
ActivityWatchModule,
RecapModule,
TaskTableModule,
PluginsModule
),
AppService,
NbDialogService,
AuthGuard,
NoAuthGuard,
AppModuleGuard,
AuthStrategy,
AuthService,
ServerConnectionService,
ElectronService,
LoggerService,
Store,
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TenantInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: ActivityWatchInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: OrganizationInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: APIInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: LanguageInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TimeoutInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: RefreshTokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: UnauthorizedInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: ServerErrorInterceptor,
multi: true
},
{
provide: ErrorHandler,
useClass: ErrorHandlerService
},
provideAppInitializer(() => {
const initializerFn = serverConnectionFactory(
inject(ServerConnectionService),
inject(Store),
inject(Router),
inject(Injector)
);
return initializerFn();
}),
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: true
})
},
{
provide: Sentry.TraceService,
deps: [Router]
},
provideAppInitializer(() => {
const initializerFn = ((trace: Sentry.TraceService) => () => {})(inject(Sentry.TraceService));
return initializerFn();
}),
{ provide: DEFAULT_TIMEOUT, useValue: 80000 },
{
provide: GAUZY_ENV,
useValue: {
...gauzyEnvironment,
...environment
}
},
provideHttpClient(withInterceptorsFromDi()),
provideAnimations()
]
})
.then(() => console.log(`Bootstrap Success!`))
.catch((error) => console.error(error));
+11 -22
View File
@@ -1,35 +1,24 @@
import { NgModule } from '@angular/core';
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
import {
AboutComponent,
AlwaysOnComponent,
AuthConnectionGuard,
ImageViewerComponent,
ScreenCaptureComponent,
SettingsComponent,
SetupComponent,
SplashScreenComponent,
TimeTrackerComponent,
UpdaterComponent
} from '@gauzy/desktop-ui-lib';
import { AuthConnectionGuard } from '@gauzy/desktop-ui-lib';
const routes: Routes = [
{
path: '',
component: TimeTrackerComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.TimeTrackerComponent)
},
{
path: 'setup',
component: SetupComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SetupComponent)
},
{
path: 'time-tracker',
component: TimeTrackerComponent,
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.TimeTrackerComponent),
loadChildren: () => import('@gauzy/desktop-ui-lib').then((m) => m.recapRoutes)
},
{
path: 'screen-capture',
component: ScreenCaptureComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.ScreenCaptureComponent)
},
{
path: 'plugins',
@@ -38,27 +27,27 @@ const routes: Routes = [
},
{
path: 'settings',
component: SettingsComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SettingsComponent)
},
{
path: 'updater',
component: UpdaterComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.UpdaterComponent)
},
{
path: 'viewer',
component: ImageViewerComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.ImageViewerComponent)
},
{
path: 'about',
component: AboutComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.AboutComponent)
},
{
path: 'splash-screen',
component: SplashScreenComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SplashScreenComponent)
},
{
path: 'always-on',
component: AlwaysOnComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.AlwaysOnComponent)
}
];
+3 -6
View File
@@ -1,4 +1,5 @@
import { AfterViewInit, Component, NgZone, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import {
ActivityWatchElectronService,
ElectronService,
@@ -11,7 +12,7 @@ import { AppService } from './app.service';
@Component({
selector: 'gauzy-root',
template: '<router-outlet></router-outlet>',
standalone: false
imports: [RouterOutlet]
})
export class AppComponent implements OnInit, AfterViewInit {
public title: string;
@@ -36,11 +37,7 @@ export class AppComponent implements OnInit, AfterViewInit {
this._electronService.ipcRenderer.send('app_is_init');
this._isInitialized = true;
}
// Start token refresh timer if user is authenticated
if (this._store.token && this._store.refreshToken) {
this.tokenRefreshService.start();
}
this.tokenRefreshService.start();
}
ngAfterViewInit(): void {
-194
View File
@@ -1,194 +0,0 @@
import { HTTP_INTERCEPTORS, HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { ErrorHandler, inject, NgModule, provideAppInitializer } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Router, RouterModule } from '@angular/router';
import {
AboutModule,
ActivityWatchInterceptor,
AlwaysOnModule,
APIInterceptor,
AuthGuard,
AuthService,
AuthStrategy,
DEFAULT_TIMEOUT,
ElectronService,
ErrorHandlerService,
GAUZY_ENV,
HttpLoaderFactory,
ImageViewerModule,
LanguageInterceptor,
LanguageModule,
LoggerService,
NgxDesktopThemeModule,
NoAuthGuard,
OrganizationInterceptor,
PluginsModule,
RecapModule,
RefreshTokenInterceptor,
ScreenCaptureModule,
ServerErrorInterceptor,
SettingsModule,
SetupModule,
Store,
TenantInterceptor,
TimeoutInterceptor,
TimeTrackerModule,
TokenInterceptor,
UpdaterModule
} from '@gauzy/desktop-ui-lib';
import { environment as gauzyEnvironment } from '@gauzy/ui-config';
import {
NbButtonModule,
NbCardModule,
NbDatepickerModule,
NbDialogModule,
NbDialogService,
NbLayoutModule,
NbThemeModule,
NbToastrModule
} from '@nebular/theme';
import * as Sentry from '@sentry/angular';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AppService } from './app.service';
import { initializeSentry } from './sentry';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
/**
* Initializes Sentry based on the environment configuration.
* If a valid Sentry DSN is provided, Sentry is initialized with the specified configuration.
* If the DSN is set to 'DOCKER_SENTRY_DSN', a warning is logged indicating that the environment
* is running inside Docker without a Sentry DSN.
*/
if (environment.SENTRY_DSN) {
if (environment.SENTRY_DSN === 'DOCKER_SENTRY_DSN') {
console.warn('You are running inside Docker but does not have SENTRY_DSN env set');
} else {
console.log(`Enabling Sentry with DSN: ${environment.SENTRY_DSN}`);
initializeSentry();
}
}
@NgModule({
declarations: [AppComponent],
imports: [
NbLayoutModule,
NbDialogModule.forRoot(),
NbToastrModule.forRoot(),
NbCardModule,
NbButtonModule,
BrowserModule,
BrowserAnimationsModule,
RouterModule,
AppRoutingModule,
NbThemeModule,
NgxDesktopThemeModule,
SetupModule,
TimeTrackerModule,
ScreenCaptureModule,
SettingsModule,
UpdaterModule,
ImageViewerModule,
NbDatepickerModule.forRoot(),
TranslateModule.forRoot({
extend: true,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
LanguageModule.forRoot(),
AboutModule,
AlwaysOnModule,
RecapModule,
PluginsModule
],
providers: [
AppService,
NbDialogService,
ElectronService,
LoggerService,
AuthGuard,
NoAuthGuard,
AuthStrategy,
AuthService,
Store,
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: RefreshTokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TenantInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: OrganizationInterceptor,
multi: true
},
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: true
})
},
{
provide: Sentry.TraceService,
deps: [Router]
},
provideAppInitializer(() => {
const initializerFn = ((trace: Sentry.TraceService) => () => { })(inject(Sentry.TraceService));
return initializerFn();
}),
{
provide: ErrorHandler,
useClass: ErrorHandlerService
},
{
provide: HTTP_INTERCEPTORS,
useClass: ServerErrorInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: ActivityWatchInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: APIInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: LanguageInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TimeoutInterceptor,
multi: true
},
{ provide: DEFAULT_TIMEOUT, useValue: 80000 },
{
provide: GAUZY_ENV,
useValue: {
...gauzyEnvironment,
...environment
}
},
provideHttpClient(withInterceptorsFromDi())
],
bootstrap: [AppComponent]
})
export class AppModule { }
+186 -6
View File
@@ -1,7 +1,59 @@
import { enableProdMode } from '@angular/core';
import { platformBrowser } from '@angular/platform-browser';
import { enableProdMode, ErrorHandler, importProvidersFrom, inject, provideAppInitializer } from '@angular/core';
import { bootstrapApplication, BrowserModule } from '@angular/platform-browser';
import { akitaConfig, enableAkitaProdMode, persistState } from '@datorama/akita';
import { AppModule } from './app/app.module';
import { HTTP_INTERCEPTORS, HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { provideAnimations } from '@angular/platform-browser/animations';
import { Router, RouterModule } from '@angular/router';
import {
AboutModule,
ActivityWatchInterceptor,
AlwaysOnModule,
APIInterceptor,
AuthGuard,
AuthService,
AuthStrategy,
DEFAULT_TIMEOUT,
ElectronService,
ErrorHandlerService,
GAUZY_ENV,
HttpLoaderFactory,
ImageViewerModule,
LanguageInterceptor,
LanguageModule,
LoggerService,
NgxDesktopThemeModule,
NoAuthGuard,
OrganizationInterceptor,
PluginsModule,
RecapModule,
RefreshTokenInterceptor,
ServerErrorInterceptor,
SettingsModule,
SetupModule,
Store,
TenantInterceptor,
TimeoutInterceptor,
TimeTrackerModule,
TokenInterceptor
} from '@gauzy/desktop-ui-lib';
import { environment as gauzyEnvironment } from '@gauzy/ui-config';
import {
NbButtonModule,
NbCardModule,
NbDatepickerModule,
NbDialogModule,
NbDialogService,
NbLayoutModule,
NbThemeModule,
NbToastrModule
} from '@nebular/theme';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import * as Sentry from '@sentry/angular';
import { AppRoutingModule } from './app/app-routing.module';
import { AppComponent } from './app/app.component';
import { AppService } from './app/app.service';
import { initializeSentry } from './app/sentry';
import { environment } from './environments/environment';
if (environment.production) {
@@ -9,6 +61,21 @@ if (environment.production) {
enableAkitaProdMode();
}
/**
* Initializes Sentry based on the environment configuration.
* If a valid Sentry DSN is provided, Sentry is initialized with the specified configuration.
* If the DSN is set to 'DOCKER_SENTRY_DSN', a warning is logged indicating that the environment
* is running inside Docker without a Sentry DSN.
*/
if (environment.SENTRY_DSN) {
if (environment.SENTRY_DSN === 'DOCKER_SENTRY_DSN') {
console.warn('You are running inside Docker but does not have SENTRY_DSN env set');
} else {
console.log(`Enabling Sentry with DSN: ${environment.SENTRY_DSN}`);
initializeSentry();
}
}
persistState({
key: '_gauzyStore'
});
@@ -17,6 +84,119 @@ akitaConfig({
resettable: true
});
platformBrowser()
.bootstrapModule(AppModule)
.catch((error) => console.error(error));
bootstrapApplication(AppComponent, {
providers: [
importProvidersFrom(
NbLayoutModule,
NbDialogModule.forRoot(),
NbToastrModule.forRoot(),
NbCardModule,
NbButtonModule,
BrowserModule,
RouterModule,
AppRoutingModule,
NbThemeModule,
NgxDesktopThemeModule,
SetupModule,
TimeTrackerModule,
SettingsModule,
ImageViewerModule,
TranslateModule.forRoot({
extend: true,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
NbDatepickerModule.forRoot(),
LanguageModule.forRoot(),
AboutModule,
AlwaysOnModule,
RecapModule,
PluginsModule
),
AppService,
NbDialogService,
ElectronService,
LoggerService,
AuthGuard,
NoAuthGuard,
AuthStrategy,
AuthService,
Store,
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: RefreshTokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TenantInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: OrganizationInterceptor,
multi: true
},
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: true
})
},
{
provide: Sentry.TraceService,
deps: [Router]
},
provideAppInitializer(() => {
const initializerFn = ((trace: Sentry.TraceService) => () => {})(inject(Sentry.TraceService));
return initializerFn();
}),
{
provide: ErrorHandler,
useClass: ErrorHandlerService
},
{
provide: HTTP_INTERCEPTORS,
useClass: ServerErrorInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: ActivityWatchInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: APIInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: LanguageInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TimeoutInterceptor,
multi: true
},
{ provide: DEFAULT_TIMEOUT, useValue: 80000 },
{
provide: GAUZY_ENV,
useValue: {
...gauzyEnvironment,
...environment
}
},
provideHttpClient(withInterceptorsFromDi()),
provideAnimations()
]
}).catch((error) => console.error(error));
+1
View File
@@ -200,6 +200,7 @@
}
],
"styles": [
"node_modules/@nebular/theme/styles/prebuilt/default.css",
"node_modules/bootstrap/dist/css/bootstrap.css",
"node_modules/typeface-exo/index.css",
"node_modules/roboto-fontface/css/roboto/roboto-fontface.css",
+2 -2
View File
@@ -48,9 +48,9 @@
"node_modules/socicon/css/socicon.css",
"node_modules/@ali-hm/angular-tree-component/css/angular-tree-component.css",
"node_modules/leaflet/dist/leaflet.css",
"apps/server-api/src/styles.css",
"node_modules/@ng-select/ng-select/themes/default.theme.css",
"apps/server-api/src/assets/styles/styles.scss",
"node_modules/@ng-select/ng-select/themes/default.theme.css"
"packages/ui-core/static/styles/styles.scss"
],
"scripts": [],
"allowedCommonJsDependencies": [
+7 -17
View File
@@ -1,48 +1,38 @@
import { NgModule } from '@angular/core';
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
import {
AboutComponent,
AuthConnectionGuard,
ServerDashboardComponent,
SettingsComponent,
SetupComponent,
SplashScreenComponent,
UpdaterComponent
} from '@gauzy/desktop-ui-lib';
const routes: Routes = [
{
path: '',
component: SetupComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SetupComponent)
},
{
path: 'setup',
component: SetupComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SetupComponent)
},
{
path: 'plugins',
canActivate: [AuthConnectionGuard],
loadChildren: () => import('@gauzy/desktop-ui-lib').then((m) => m.PluginRoutingModule)
},
{
path: 'settings',
component: SettingsComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SettingsComponent)
},
{
path: 'updater',
component: UpdaterComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.UpdaterComponent)
},
{
path: 'server-dashboard',
component: ServerDashboardComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.ServerDashboardComponent)
},
{
path: 'about',
component: AboutComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.AboutComponent)
},
{
path: 'splash-screen',
component: SplashScreenComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SplashScreenComponent)
}
];
+4 -3
View File
@@ -1,10 +1,11 @@
import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { LanguageElectronService } from '@gauzy/desktop-ui-lib';
@Component({
selector: 'gauzy-root',
template: '<router-outlet></router-outlet>',
standalone: false
selector: 'gauzy-root',
template: '<router-outlet></router-outlet>',
imports: [RouterOutlet]
})
export class AppComponent implements OnInit {
constructor(private readonly languageElectronService: LanguageElectronService) {}
-101
View File
@@ -1,101 +0,0 @@
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { ErrorHandler, NgModule, inject, provideAppInitializer } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Router, RouterModule } from '@angular/router';
import {
AboutModule,
ElectronService,
GAUZY_ENV,
LanguageModule,
LoggerService,
NgxDesktopThemeModule,
PluginsModule,
ServerDashboardModule,
SettingsModule,
SetupModule,
UpdaterModule
} from '@gauzy/desktop-ui-lib';
import { environment as gauzyEnvironment } from '@gauzy/ui-config';
import {
NbButtonModule,
NbCardModule,
NbDialogModule,
NbDialogService,
NbLayoutModule,
NbMenuModule,
NbSidebarModule,
NbThemeModule,
NbToastrModule
} from '@nebular/theme';
import * as Sentry from '@sentry/angular';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AppService } from './app.service';
import { initializeSentry } from './sentry';
if (environment.SENTRY_DSN) {
if (environment.SENTRY_DSN === 'DOCKER_SENTRY_DSN') {
console.warn('You are running inside Docker but does not have SENTRY_DSN env set');
} else {
console.log(`Enabling Sentry with DSN: ${environment.SENTRY_DSN}`);
initializeSentry();
}
}
@NgModule({
declarations: [AppComponent],
bootstrap: [AppComponent],
imports: [
NbLayoutModule,
NbDialogModule.forRoot(),
NbToastrModule.forRoot(),
NbCardModule,
NbButtonModule,
BrowserModule,
BrowserAnimationsModule,
RouterModule,
AppRoutingModule,
NbThemeModule,
NgxDesktopThemeModule,
NbMenuModule.forRoot(),
NbSidebarModule.forRoot(),
SetupModule,
SettingsModule,
UpdaterModule,
ServerDashboardModule,
AboutModule,
LanguageModule.forRoot(),
PluginsModule
],
providers: [
AppService,
NbDialogService,
ElectronService,
LoggerService,
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: true
})
},
{
provide: Sentry.TraceService,
deps: [Router]
},
provideAppInitializer(() => {
const initializerFn = ((trace: Sentry.TraceService) => () => {})(inject(Sentry.TraceService));
return initializerFn();
}),
{
provide: GAUZY_ENV,
useValue: {
...gauzyEnvironment,
...environment
}
},
provideHttpClient(withInterceptorsFromDi())
]
})
export class AppModule {}
+85 -6
View File
@@ -1,12 +1,91 @@
import { enableProdMode } from '@angular/core';
import { platformBrowser } from '@angular/platform-browser';
import { AppModule } from './app/app.module';
import { enableProdMode, ErrorHandler, importProvidersFrom, inject, provideAppInitializer } from '@angular/core';
import { bootstrapApplication, BrowserModule } from '@angular/platform-browser';
import { HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { provideAnimations } from '@angular/platform-browser/animations';
import { Router, RouterModule } from '@angular/router';
import {
ElectronService,
GAUZY_ENV,
HttpLoaderFactory,
LanguageModule,
LoggerService,
NgxDesktopThemeModule,
Store
} from '@gauzy/desktop-ui-lib';
import { environment as gauzyEnvironment } from '@gauzy/ui-config';
import { NbTablerIconsModule } from '@gauzy/ui-core/theme';
import { NbDialogModule, NbDialogService, NbMenuModule, NbSidebarModule, NbToastrModule } from '@nebular/theme';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import * as Sentry from '@sentry/angular';
import { AppRoutingModule } from './app/app-routing.module';
import { AppComponent } from './app/app.component';
import { AppService } from './app/app.service';
import { initializeSentry } from './app/sentry';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowser()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
if (environment.SENTRY_DSN) {
if (environment.SENTRY_DSN === 'DOCKER_SENTRY_DSN') {
console.warn('You are running inside Docker but does not have SENTRY_DSN env set');
} else {
console.log(`Enabling Sentry with DSN: ${environment.SENTRY_DSN}`);
initializeSentry();
}
}
bootstrapApplication(AppComponent, {
providers: [
importProvidersFrom(
NbDialogModule.forRoot(),
NbToastrModule.forRoot(),
BrowserModule,
RouterModule,
AppRoutingModule,
NbMenuModule.forRoot(),
NbSidebarModule.forRoot(),
LanguageModule.forRoot(),
NgxDesktopThemeModule,
NbTablerIconsModule,
TranslateModule.forRoot({
extend: true,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
),
AppService,
NbDialogService,
ElectronService,
LoggerService,
Store,
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: true
})
},
{
provide: Sentry.TraceService,
deps: [Router]
},
provideAppInitializer(() => {
const initializerFn = ((trace: Sentry.TraceService) => () => {})(inject(Sentry.TraceService));
return initializerFn();
}),
{
provide: GAUZY_ENV,
useValue: {
...gauzyEnvironment,
...environment
}
},
provideHttpClient(withInterceptorsFromDi()),
provideAnimations()
]
}).catch((err) => console.error(err));
-1
View File
@@ -1 +0,0 @@
/* You can add global styles to this file, and also import other style files */
-1
View File
@@ -48,7 +48,6 @@
"node_modules/socicon/css/socicon.css",
"node_modules/@ali-hm/angular-tree-component/css/angular-tree-component.css",
"node_modules/leaflet/dist/leaflet.css",
"apps/server/src/styles.css",
"apps/server/src/assets/styles/styles.scss",
"node_modules/@ng-select/ng-select/themes/default.theme.css"
],
+7 -17
View File
@@ -1,48 +1,38 @@
import { NgModule } from '@angular/core';
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
import {
AboutComponent,
AuthConnectionGuard,
ServerDashboardComponent,
SettingsComponent,
SetupComponent,
SplashScreenComponent,
UpdaterComponent
} from '@gauzy/desktop-ui-lib';
const routes: Routes = [
{
path: '',
component: SetupComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SetupComponent)
},
{
path: 'setup',
component: SetupComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SetupComponent)
},
{
path: 'plugins',
canActivate: [AuthConnectionGuard],
loadChildren: () => import('@gauzy/desktop-ui-lib').then((m) => m.PluginRoutingModule)
},
{
path: 'settings',
component: SettingsComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SettingsComponent)
},
{
path: 'updater',
component: UpdaterComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.UpdaterComponent)
},
{
path: 'server-dashboard',
component: ServerDashboardComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.ServerDashboardComponent)
},
{
path: 'about',
component: AboutComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.AboutComponent)
},
{
path: 'splash-screen',
component: SplashScreenComponent
loadComponent: () => import('@gauzy/desktop-ui-lib').then((m) => m.SplashScreenComponent)
}
];
+3 -3
View File
@@ -5,9 +5,9 @@ import { RouterTestingModule } from '@angular/router/testing';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [AppComponent]
}).compileComponents();
imports: [RouterTestingModule],
declarations: [AppComponent]
}).compileComponents();
}));
it('should create the app', () => {
+4 -3
View File
@@ -1,10 +1,11 @@
import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { LanguageElectronService } from '@gauzy/desktop-ui-lib';
@Component({
selector: 'gauzy-root',
template: '<router-outlet></router-outlet>',
standalone: false
selector: 'gauzy-root',
template: '<router-outlet></router-outlet>',
imports: [RouterOutlet]
})
export class AppComponent implements OnInit {
constructor(private readonly languageElectronService: LanguageElectronService) {}
-101
View File
@@ -1,101 +0,0 @@
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { ErrorHandler, NgModule, inject, provideAppInitializer } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Router, RouterModule } from '@angular/router';
import {
AboutModule,
ElectronService,
GAUZY_ENV,
LanguageModule,
LoggerService,
NgxDesktopThemeModule,
PluginsModule,
ServerDashboardModule,
SettingsModule,
SetupModule,
UpdaterModule
} from '@gauzy/desktop-ui-lib';
import { environment as gauzyEnvironment } from '@gauzy/ui-config';
import {
NbButtonModule,
NbCardModule,
NbDialogModule,
NbDialogService,
NbLayoutModule,
NbMenuModule,
NbSidebarModule,
NbThemeModule,
NbToastrModule
} from '@nebular/theme';
import * as Sentry from '@sentry/angular';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AppService } from './app.service';
import { initializeSentry } from './sentry';
if (environment.SENTRY_DSN) {
if (environment.SENTRY_DSN === 'DOCKER_SENTRY_DSN') {
console.warn('You are running inside Docker but does not have SENTRY_DSN env set');
} else {
console.log(`Enabling Sentry with DSN: ${environment.SENTRY_DSN}`);
initializeSentry();
}
}
@NgModule({
declarations: [AppComponent],
bootstrap: [AppComponent],
imports: [
NbLayoutModule,
NbDialogModule.forRoot(),
NbToastrModule.forRoot(),
NbCardModule,
NbButtonModule,
BrowserModule,
BrowserAnimationsModule,
RouterModule,
AppRoutingModule,
NbThemeModule,
NgxDesktopThemeModule,
NbMenuModule.forRoot(),
NbSidebarModule.forRoot(),
SetupModule,
SettingsModule,
UpdaterModule,
ServerDashboardModule,
AboutModule,
LanguageModule.forRoot(),
PluginsModule
],
providers: [
AppService,
NbDialogService,
ElectronService,
LoggerService,
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: true
})
},
{
provide: Sentry.TraceService,
deps: [Router]
},
provideAppInitializer(() => {
const initializerFn = ((trace: Sentry.TraceService) => () => {})(inject(Sentry.TraceService));
return initializerFn();
}),
{
provide: GAUZY_ENV,
useValue: {
...gauzyEnvironment,
...environment
}
},
provideHttpClient(withInterceptorsFromDi())
]
})
export class AppModule {}
+85 -6
View File
@@ -1,12 +1,91 @@
import { enableProdMode } from '@angular/core';
import { platformBrowser } from '@angular/platform-browser';
import { AppModule } from './app/app.module';
import { enableProdMode, ErrorHandler, importProvidersFrom, inject, provideAppInitializer } from '@angular/core';
import { bootstrapApplication, BrowserModule } from '@angular/platform-browser';
import { HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { provideAnimations } from '@angular/platform-browser/animations';
import { Router, RouterModule } from '@angular/router';
import {
ElectronService,
GAUZY_ENV,
HttpLoaderFactory,
LanguageModule,
LoggerService,
NgxDesktopThemeModule,
Store
} from '@gauzy/desktop-ui-lib';
import { environment as gauzyEnvironment } from '@gauzy/ui-config';
import { NbTablerIconsModule } from '@gauzy/ui-core/theme';
import { NbDialogModule, NbDialogService, NbMenuModule, NbSidebarModule, NbToastrModule } from '@nebular/theme';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import * as Sentry from '@sentry/angular';
import { AppRoutingModule } from './app/app-routing.module';
import { AppComponent } from './app/app.component';
import { AppService } from './app/app.service';
import { initializeSentry } from './app/sentry';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowser()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
if (environment.SENTRY_DSN) {
if (environment.SENTRY_DSN === 'DOCKER_SENTRY_DSN') {
console.warn('You are running inside Docker but does not have SENTRY_DSN env set');
} else {
console.log(`Enabling Sentry with DSN: ${environment.SENTRY_DSN}`);
initializeSentry();
}
}
bootstrapApplication(AppComponent, {
providers: [
importProvidersFrom(
NbDialogModule.forRoot(),
NbToastrModule.forRoot(),
BrowserModule,
RouterModule,
AppRoutingModule,
NbMenuModule.forRoot(),
NbSidebarModule.forRoot(),
LanguageModule.forRoot(),
NgxDesktopThemeModule,
NbTablerIconsModule,
TranslateModule.forRoot({
extend: true,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
),
AppService,
NbDialogService,
ElectronService,
LoggerService,
Store,
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: true
})
},
{
provide: Sentry.TraceService,
deps: [Router]
},
provideAppInitializer(() => {
const initializerFn = ((trace: Sentry.TraceService) => () => {})(inject(Sentry.TraceService));
return initializerFn();
}),
{
provide: GAUZY_ENV,
useValue: {
...gauzyEnvironment,
...environment
}
},
provideHttpClient(withInterceptorsFromDi()),
provideAnimations()
]
}).catch((err) => console.error(err));
-1
View File
@@ -1 +0,0 @@
/* You can add global styles to this file, and also import other style files */
+1
View File
@@ -433,6 +433,7 @@
"build:agent:linux:release:gh:x64": "yarn run pack --desktop=agent --arch=x64 --platform=linux && cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=30000 yarn run build:agent && npm config set cache .cache && yarn electron-builder -c.electronVersion=38.2.2 build --linux --x64 --publish=always --project dist/apps/agent",
"build:agent:linux:release:gh:arm64": "yarn run pack --desktop=agent --arch=arm64 --platform=linux && cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=30000 yarn run build:agent && npm config set cache .cache && yarn electron-builder -c.electronVersion=38.2.2 build --linux --arm64 --publish=always --project dist/apps/agent",
"build:agent:mac": "yarn run build:agent && npm config set cache .cache && yarn electron-builder -c.electronVersion=38.2.2 build --mac --project dist/apps/agent",
"build:agent:mac:quick": "yarn run build:agent:mac -c.mac.identity=null",
"build:agent:mac:release": "yarn run build:agent && npm config set cache .cache && yarn electron-builder -c.electronVersion=38.2.2 build --mac --publish=always --project dist/apps/agent",
"copy-assets-agent": "copyfiles -f apps/desktop/src/assets/snapshot-sound.wav dist/apps/agent/data/sound/",
"build:mcp-server": "yarn nx build mcp-server",
+4 -4
View File
@@ -9,11 +9,11 @@ export * from './lib/always-on/always-on.component';
export * from './lib/always-on/always-on.module';
export * from './lib/auth';
export * from './lib/constants';
export * from './lib/desktop-ui-lib.module';
export * from './lib/dialogs/about/about.component';
export * from './lib/dialogs/about/about.module';
export * from './lib/dialogs/alert/alert.component';
export * from './lib/dialogs/alert/alert.module';
export * from './lib/electron/services';
export * from './lib/image-viewer/image-viewer.component';
export * from './lib/image-viewer/image-viewer.module';
@@ -33,7 +33,7 @@ export * from './lib/recap/recap-routing.module';
export * from './lib/recap/recap.module';
export * from './lib/recap/weekly/features/weekly-recap/weekly-recap.component';
export * from './lib/screen-capture/screen-capture.component';
export * from './lib/screen-capture/screen-capture.module';
export * from './lib/server-connection.factory';
export * from './lib/server-dashboard/server-dashboard.component';
export * from './lib/server-dashboard/server-dashboard.module';
@@ -60,7 +60,7 @@ export * from './lib/time-tracker/time-tracker.component';
export * from './lib/time-tracker/time-tracker.module';
export * from './lib/time-tracker/time-tracker.service';
export * from './lib/updater/updater.component';
export * from './lib/updater/updater.module';
/**
* Auth Module
@@ -3,11 +3,10 @@ import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
import { StatusMapper } from '../../../shared/utils/queue-status-mapper.util';
@Component({
selector: 'app-status-badge',
templateUrl: './status-render.html',
styleUrls: ['./status-render.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
selector: 'app-status-badge',
templateUrl: './status-render.html',
styleUrls: ['./status-render.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class StatusBadgeComponent {
@Input() value: string;
@@ -1,63 +1,67 @@
<nb-card>
<nb-card-header class="d-flex justify-content-between align-items-center">
<h6>Queue Item Details</h6>
<button nbButton ghost size="small" (click)="close()">
<nb-icon icon="close-outline"></nb-icon>
</button>
</nb-card-header>
<nb-card-header class="d-flex justify-content-between align-items-center">
<h6>Queue Item Details</h6>
<button nbButton ghost size="small" (click)="close()">
<nb-icon icon="close-outline"></nb-icon>
</button>
</nb-card-header>
<nb-card-body>
<div class="detail-section">
<div class="detail-row">
<span class="detail-label">ID:</span>
<span class="detail-value">{{ data.id || 'N/A' }}</span>
</div>
<nb-card-body>
<div class="detail-section">
<div class="detail-row">
<span class="detail-label">ID:</span>
<span class="detail-value">{{ data.id || 'N/A' }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Queue ID:</span>
<span class="detail-value">{{ data.queue_id || 'N/A' }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Queue ID:</span>
<span class="detail-value">{{ data.queue_id || 'N/A' }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Queue:</span>
<span class="detail-value">{{ data.queue || 'N/A' }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Queue:</span>
<span class="detail-value">{{ data.queue || 'N/A' }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Status:</span>
<span [class]="'status-chip status-' + getStatusClass(data.status)">
{{ data.status || 'N/A' }}
</span>
</div>
<div class="detail-row">
<span class="detail-label">Status:</span>
<span [class]="'status-chip status-' + getStatusClass(data.status)">
{{ data.status || 'N/A' }}
</span>
</div>
<div class="detail-row">
<span class="detail-label">Attempts:</span>
<span class="detail-value">{{ data.attempts || 0 }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Attempts:</span>
<span class="detail-value">{{ data.attempts || 0 }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Priority:</span>
<span class="detail-value">{{ data.priority || 0 }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Priority:</span>
<span class="detail-value">{{ data.priority || 0 }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Created At:</span>
<span class="detail-value">{{ getFormattedDate(data.created_at) }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Created At:</span>
<span class="detail-value">{{ getFormattedDate(data.created_at) }}</span>
</div>
<div class="detail-row" *ngIf="data.last_error">
<span class="detail-label">Last Error:</span>
<span class="detail-value error-text">{{ data.last_error }}</span>
</div>
@if (data.last_error) {
<div class="detail-row">
<span class="detail-label">Last Error:</span>
<span class="detail-value error-text">{{ data.last_error }}</span>
</div>
}
<div class="detail-row full-width" *ngIf="data.data">
<span class="detail-label">Data:</span>
<pre class="data-json">{{ getFormattedData() }}</pre>
</div>
</div>
</nb-card-body>
@if (data.data) {
<div class="detail-row full-width">
<span class="detail-label">Data:</span>
<pre class="data-json">{{ getFormattedData() }}</pre>
</div>
}
</div>
</nb-card-body>
<nb-card-footer class="text-right">
<button nbButton status="basic" (click)="close()">Close</button>
</nb-card-footer>
<nb-card-footer class="text-right">
<button nbButton status="basic" (click)="close()">Close</button>
</nb-card-footer>
</nb-card>
@@ -1,13 +1,14 @@
import { Component, Input } from '@angular/core';
import { NbDialogRef } from '@nebular/theme';
import { NbDialogRef, NbCardModule, NbButtonModule, NbIconModule } from '@nebular/theme';
import { QueueItem } from '../../models/logs.models';
import { StatusMapper } from '../../../shared/utils/queue-status-mapper.util';
@Component({
selector: 'app-activity-sync-detail-modal',
templateUrl: './activity-sync-detail-modal.component.html',
styleUrls: ['./activity-sync-detail-modal.component.scss'],
standalone: false
selector: 'app-activity-sync-detail-modal',
templateUrl: './activity-sync-detail-modal.component.html',
styleUrls: ['./activity-sync-detail-modal.component.scss'],
imports: [NbCardModule, NbButtonModule, NbIconModule]
})
export class ActivitySyncDetailModalComponent {
@Input() data: QueueItem;
@@ -19,26 +19,26 @@
</nb-card>
<ng-template #tableView>
<div class="row grow">
<div class="col-12 custom-table">
<div class="table-scroll-container grow" style="max-height: calc(100vh - 145px);">
<ng-container *ngIf="loading$ | async">
<div class="smart-table" [nbSpinner]="true" nbSpinnerSize="small"></div>
</ng-container>
<angular2-smart-table
#smartTable
[settings]="smartTableSettings"
[source]="smartTableSource"
style="cursor: pointer"
(userRowSelect)="onRowClick($event)"
>
</angular2-smart-table>
</div>
</div>
<ng-template #noTask>
<div class="no-data col-12">
<ngx-no-data-message [message]="'SM_TABLE.NO_DATA.TASK' | translate"> </ngx-no-data-message>
</div>
</ng-template>
</div>
<div class="row grow">
<div class="col-12 custom-table">
<div class="table-scroll-container grow" style="max-height: calc(100vh - 145px);">
@if (loading$ | async) {
<div class="smart-table" [nbSpinner]="true" nbSpinnerSize="small"></div>
}
<angular2-smart-table
#smartTable
[settings]="smartTableSettings"
[source]="smartTableSource"
style="cursor: pointer"
(userRowSelect)="onRowClick($event)"
>
</angular2-smart-table>
</div>
</div>
<ng-template #noTask>
<div class="no-data col-12">
<ngx-no-data-message [message]="'SM_TABLE.NO_DATA.TASK' | translate"> </ngx-no-data-message>
</div>
</ng-template>
</div>
</ng-template>
@@ -3,18 +3,19 @@ import { combineLatest, Subject, Observable } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { QueueItem, SyncHealth } from '../models/logs.models';
import { LogService } from '../services/logs.service';
import { Angular2SmartTableComponent, Cell, LocalDataSource } from 'angular2-smart-table';
import { Angular2SmartTableComponent, Cell, LocalDataSource, Angular2SmartTableModule } from 'angular2-smart-table';
import { TranslateService } from '@ngx-translate/core';
import { StatusBadgeComponent } from './activity-render/status-render';
import { LocalDateParse } from '../pipes/date.pipe';
import { NbDialogService } from '@nebular/theme';
import { NbDialogService, NbCardModule, NbTabsetModule, NbSpinnerModule } from '@nebular/theme';
import { StatusMapper } from '../../shared/utils/queue-status-mapper.util';
import { NgTemplateOutlet, AsyncPipe } from '@angular/common';
@Component({
selector: 'app-sync-page',
templateUrl: './activity-sync.component.html',
styleUrls: ['./activity-sync.component.scss'],
standalone: false
selector: 'app-sync-page',
templateUrl: './activity-sync.component.html',
styleUrls: ['./activity-sync.component.scss'],
imports: [NbCardModule, NbTabsetModule, NgTemplateOutlet, NbSpinnerModule, Angular2SmartTableModule, AsyncPipe]
})
export class SyncPageComponent implements OnInit, OnDestroy {
items$: Observable<QueueItem[]> = this.svc.queueStream$;
@@ -1,16 +1,18 @@
import { Component, Inject, OnInit, OnDestroy } from '@angular/core';
import { NbMenuItem, NbSidebarState } from '@nebular/theme';
import { NbMenuItem, NbSidebarState, NbLayoutModule, NbSidebarModule, NbMenuModule } from '@nebular/theme';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
import { GAUZY_ENV } from '../constants';
import { IpcService } from './services/ipc.service';
import { TasksService } from './services/tasks-service';
import { NgClass } from '@angular/common';
import { RouterOutlet } from '@angular/router';
@Component({
selector: 'ngx-agent-dashboard',
templateUrl: './agent-dashboard.component.html',
styleUrls: ['./agent-dashboard.component.scss'],
standalone: false
selector: 'ngx-agent-dashboard',
templateUrl: './agent-dashboard.component.html',
styleUrls: ['./agent-dashboard.component.scss'],
imports: [NbLayoutModule, NbSidebarModule, NgClass, NbMenuModule, RouterOutlet]
})
export class AgentDashboardComponent implements OnInit, OnDestroy {
menu: NbMenuItem[] = [
@@ -42,49 +42,47 @@ import { StatusBadgeComponent } from './activity-sync/activity-render/status-ren
import { ActivitySyncDetailModalComponent } from './activity-sync/activity-sync-detail-modal/activity-sync-detail-modal.component';
@NgModule({
declarations: [
AgentDashboardComponent,
LogsPageComponent,
SyncPageComponent,
StatusBadgeComponent,
ActivitySyncDetailModalComponent
],
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
FormsModule,
ReactiveFormsModule,
RouterModule,
NbThemeModule.forRoot({ name: 'dark' }),
NbLayoutModule,
NbSidebarModule.forRoot(),
NbMenuModule,
NbIconModule,
NbTablerIconsModule,
NbButtonModule,
NbCardModule,
NbActionsModule,
NbSelectModule,
NbToggleModule,
NbListModule,
NbBadgeModule,
NbUserModule,
NbTabsetModule,
NbTooltipModule,
NbProgressBarModule,
NbSpinnerModule,
NbContextMenuModule,
NbInputModule,
NbCheckboxModule,
NbAlertModule,
FilterStatusPipe,
LocalDateParse,
NbRouteTabsetModule,
NbDialogModule.forChild(),
TasksModule,
Angular2SmartTableModule
],
exports: [FilterStatusPipe, LocalDateParse]
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
FormsModule,
ReactiveFormsModule,
RouterModule,
NbThemeModule.forRoot({ name: 'dark' }),
NbLayoutModule,
NbSidebarModule.forRoot(),
NbMenuModule,
NbIconModule,
NbTablerIconsModule,
NbButtonModule,
NbCardModule,
NbActionsModule,
NbSelectModule,
NbToggleModule,
NbListModule,
NbBadgeModule,
NbUserModule,
NbTabsetModule,
NbTooltipModule,
NbProgressBarModule,
NbSpinnerModule,
NbContextMenuModule,
NbInputModule,
NbCheckboxModule,
NbAlertModule,
FilterStatusPipe,
LocalDateParse,
NbRouteTabsetModule,
NbDialogModule.forChild(),
TasksModule,
Angular2SmartTableModule,
AgentDashboardComponent,
LogsPageComponent,
SyncPageComponent,
StatusBadgeComponent,
ActivitySyncDetailModalComponent
],
exports: [FilterStatusPipe, LocalDateParse]
})
export class AgentDashboardModule {}
@@ -2,12 +2,15 @@ import { Component, ViewChild, ElementRef, AfterViewChecked, OnDestroy, OnInit }
import { Observable, Subscription } from 'rxjs';
import { LogEntry } from '../models/logs.models';
import { LogService } from '../services/logs.service';
import { NbCardModule, NbSelectModule, NbOptionModule, NbInputModule, NbCheckboxModule } from '@nebular/theme';
import { FormsModule } from '@angular/forms';
import { NgClass, AsyncPipe, DatePipe } from '@angular/common';
@Component({
selector: 'app-logs-page',
templateUrl: './logs.component.html',
styleUrls: ['./logs.component.scss'],
standalone: false
selector: 'app-logs-page',
templateUrl: './logs.component.html',
styleUrls: ['./logs.component.scss'],
imports: [NbCardModule, NbSelectModule, NbOptionModule, NbInputModule, FormsModule, NbCheckboxModule, NgClass, AsyncPipe, DatePipe]
})
export class LogsPageComponent implements AfterViewChecked, OnDestroy, OnInit {
@ViewChild('logContainer') private logContainer: ElementRef;
@@ -1,18 +1,21 @@
import { Component, NgZone, OnDestroy, OnInit, Inject, Renderer2, HostBinding, HostListener } from '@angular/core';
import { NbIconLibraries } from '@nebular/theme';
import { NbIconLibraries, NbLayoutModule, NbCardModule, NbButtonModule, NbIconModule, NbTooltipModule } from '@nebular/theme';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { BehaviorSubject, Observable, Subscription, tap } from 'rxjs';
import { LanguageElectronService } from '../language/language-electron.service';
import { AlwaysOnService, AlwaysOnStateEnum, ITimeCounter, ITimerStatus } from './always-on.service';
import { faPlay, faPause, faStopwatch, faBars, faDollar } from '@fortawesome/free-solid-svg-icons';
import { GAUZY_ENV } from '../constants';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { NgClass, AsyncPipe } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'gauzy-always-on',
templateUrl: './always-on.component.html',
styleUrls: ['./always-on.component.scss'],
standalone: false
selector: 'gauzy-always-on',
templateUrl: './always-on.component.html',
styleUrls: ['./always-on.component.scss'],
imports: [NbLayoutModule, NbCardModule, FaIconComponent, NgClass, NbButtonModule, NbIconModule, NbTooltipModule, AsyncPipe, TranslatePipe]
})
export class AlwaysOnComponent implements OnInit, OnDestroy {
@HostBinding('class.rounded-theme') isRounded = false;
@@ -9,19 +9,19 @@ import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { NbTablerIconsModule } from '@gauzy/ui-core/theme';
@NgModule({
declarations: [AlwaysOnComponent],
imports: [
CommonModule,
NbLayoutModule,
LanguageModule.forChild(),
NbIconModule,
NbTablerIconsModule,
NbTooltipModule,
NbButtonModule,
NbCardModule,
FormsModule,
FontAwesomeModule
],
providers: [AlwaysOnService]
imports: [
CommonModule,
NbLayoutModule,
LanguageModule.forChild(),
NbIconModule,
NbTablerIconsModule,
NbTooltipModule,
NbButtonModule,
NbCardModule,
FormsModule,
FontAwesomeModule,
AlwaysOnComponent
],
providers: [AlwaysOnService]
})
export class AlwaysOnModule {}
@@ -6,10 +6,10 @@ import {
NbRequestPasswordComponent,
NbResetPasswordComponent
} from '@nebular/auth';
import { NgxLoginComponent } from '../login';
import { NgxLoginMagicComponent } from '../login/features/login-magic/login-magic.component';
import { NgxLoginWorkspaceComponent } from '../login/features/login-workspace/login-workspace.component';
import { NgxMagicSignInWorkspaceComponent } from '../login/features/magic-login-workspace/magic-login-workspace.component';
import { NoAuthGuard } from './no-auth.guard';
export const authRoutes: Route[] = [
@@ -24,7 +24,7 @@ export const authRoutes: Route[] = [
},
{
path: 'login',
component: NgxLoginComponent,
loadComponent: () => import('../login').then(m => m.NgxLoginComponent),
canActivate: [NoAuthGuard]
},
{
@@ -50,7 +50,7 @@ export const authRoutes: Route[] = [
// Register the path 'login-workspace'
path: 'login-workspace',
// Register the component to load component: NgxLoginWorkspaceComponent,
component: NgxLoginWorkspaceComponent,
loadComponent: () => import('../login/features/login-workspace/login-workspace.component').then(m => m.NgxLoginWorkspaceComponent),
// Register the data object
canActivate: [NoAuthGuard]
},
@@ -58,7 +58,7 @@ export const authRoutes: Route[] = [
// Register the path 'login-magic'
path: 'login-magic',
// Register the component to load component: NgxLoginMagicComponent,
component: NgxLoginMagicComponent,
loadComponent: () => import('../login/features/login-magic/login-magic.component').then(m => m.NgxLoginMagicComponent),
// Register the data object
canActivate: [NoAuthGuard]
},
@@ -66,7 +66,7 @@ export const authRoutes: Route[] = [
// Register the path 'magic-sign-in'
path: 'magic-sign-in',
// Register the component to load component: NgxMagicSignInWorkspaceComponent,
component: NgxMagicSignInWorkspaceComponent,
loadComponent: () => import('../login/features/magic-login-workspace/magic-login-workspace.component').then(m => m.NgxMagicSignInWorkspaceComponent),
// Register the data object
canActivate: [NoAuthGuard]
}
@@ -1,7 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
@NgModule({
imports: [CommonModule]
})
export class DesktopUiLibModule {}
@@ -4,12 +4,14 @@ import { UntilDestroy } from '@ngneat/until-destroy';
import { GAUZY_ENV } from '../../constants';
import { ElectronService } from '../../electron/services';
import { LanguageElectronService } from '../../language/language-electron.service';
import { NbLayoutModule, NbCardModule } from '@nebular/theme';
import { TranslatePipe } from '@ngx-translate/core';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'gauzy-about',
templateUrl: './about.component.html',
styleUrls: ['./about.component.scss'],
standalone: false
selector: 'gauzy-about',
templateUrl: './about.component.html',
styleUrls: ['./about.component.scss'],
imports: [NbLayoutModule, NbCardModule, TranslatePipe]
})
export class AboutComponent implements OnInit {
private _application = {
@@ -5,7 +5,6 @@ import { LanguageModule } from '../../language/language.module';
import { AboutComponent } from './about.component';
@NgModule({
declarations: [AboutComponent],
imports: [CommonModule, NbCardModule, NbButtonModule, NbLayoutModule, LanguageModule.forChild()]
imports: [CommonModule, NbCardModule, NbButtonModule, NbLayoutModule, LanguageModule.forChild(), AboutComponent]
})
export class AboutModule {}
@@ -8,8 +8,8 @@ describe('AlertComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AlertComponent]
}).compileComponents();
imports: [AlertComponent]
}).compileComponents();
});
beforeEach(() => {
@@ -1,5 +1,6 @@
import { Component, Input } from '@angular/core';
import { NbDialogRef } from '@nebular/theme';
import { NbDialogRef, NbCardModule, NbButtonModule } from '@nebular/theme';
import { TranslatePipe } from '@ngx-translate/core';
export interface AlertDialogOptions {
title?: string;
@@ -9,10 +10,10 @@ export interface AlertDialogOptions {
dismissText?: string;
}
@Component({
selector: 'ngx-alert',
templateUrl: './alert.component.html',
styleUrls: ['./alert.component.scss'],
standalone: false
selector: 'ngx-alert',
templateUrl: './alert.component.html',
styleUrls: ['./alert.component.scss'],
imports: [NbCardModule, NbButtonModule, TranslatePipe]
})
export class AlertComponent {
@Input() data: AlertDialogOptions;
@@ -1,26 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AlertComponent } from './alert.component';
import {
NbLayoutModule,
NbCardModule,
NbIconModule,
NbButtonModule,
NbAlertModule
} from '@nebular/theme';
import { TranslateModule } from '@ngx-translate/core';
@NgModule({
declarations: [AlertComponent],
imports: [
CommonModule,
NbLayoutModule,
NbCardModule,
NbIconModule,
NbButtonModule,
NbAlertModule,
TranslateModule
],
exports: [AlertComponent]
})
export class AlertModule {}
@@ -2,10 +2,7 @@ import { Directive, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output
import { Subject, Subscription, tap } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
@Directive({
selector: '[debounceClick]',
standalone: false
})
@Directive({ selector: '[debounceClick]' })
export class DebounceClickDirective implements OnInit, OnDestroy {
private clicks: Subject<Event> = new Subject<Event>();
private subscription: Subscription;
@@ -1,21 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { NbSpinnerModule } from '@nebular/theme';
import { DebounceClickDirective } from './debounce-click.directive';
import { DynamicDirective } from './dynamic.directive';
import { SpinnerButtonDirective } from './spinner-button.directive';
import { TextMaskDirective } from './text-mask.directive';
import { ReadMoreDirective } from './read-more.directive';
@NgModule({
declarations: [
SpinnerButtonDirective,
DynamicDirective,
TextMaskDirective,
DebounceClickDirective,
ReadMoreDirective
],
exports: [SpinnerButtonDirective, DynamicDirective, TextMaskDirective, DebounceClickDirective, ReadMoreDirective],
imports: [CommonModule, NbSpinnerModule]
})
export class DesktopDirectiveModule {}
@@ -1,9 +1,6 @@
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[dynamicDirective]',
standalone: false
})
@Directive({ selector: '[dynamicDirective]' })
export class DynamicDirective {
constructor(public viewContainerRef: ViewContainerRef) {}
}
@@ -1,9 +1,6 @@
import { AfterViewInit, Directive, ElementRef, Input, Renderer2 } from '@angular/core';
@Directive({
selector: '[readMore]',
standalone: false
})
@Directive({ selector: '[readMore]' })
export class ReadMoreDirective implements AfterViewInit {
@Input('readMore') maxLength = 100;
@Input() readMoreText = 'Read More';
@@ -1,10 +1,7 @@
import { Directive, Input, Renderer2, TemplateRef, ViewContainerRef, inject } from '@angular/core';
import { NbSpinnerComponent } from '@nebular/theme';
@Directive({
selector: '[gauzySpinnerButton]',
standalone: false
})
@Directive({ selector: '[gauzySpinnerButton]' })
export class SpinnerButtonDirective {
private _isSpinning: boolean | null = null;
private _spinner: HTMLElement | null = null;
@@ -8,10 +8,7 @@ interface IMaskConfig {
maskFromLeft: boolean; // New property to control mask direction
}
@Directive({
selector: '[gaTextMask]',
standalone: false
})
@Directive({ selector: '[gaTextMask]' })
export class TextMaskDirective {
// Default configuration for text masking
private readonly _config: IMaskConfig = {
@@ -7,8 +7,8 @@ describe('ImageViewerComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ImageViewerComponent],
}).compileComponents();
imports: [ImageViewerComponent],
}).compileComponents();
});
beforeEach(() => {
@@ -4,7 +4,9 @@ import { ElectronService } from '../electron/services';
import { SafeUrl } from '@angular/platform-browser';
import { ImageViewerService } from './image-viewer.service';
import { from } from 'rxjs';
import { NbIconLibraries } from '@nebular/theme';
import { NbIconLibraries, NbLayoutModule, NbButtonModule, NbIconModule, NbSpinnerModule } from '@nebular/theme';
import { NgTemplateOutlet, NgClass, AsyncPipe } from '@angular/common';
import { DateTimePipe } from '../time-tracker/pipes/date-time.pipe';
export const fadeInOutAnimation = trigger('fadeInOut', [
transition(':enter', [
@@ -19,11 +21,11 @@ export const fadeInOutAnimation = trigger('fadeInOut', [
]);
@Component({
selector: 'ngx-image-viewer',
templateUrl: './image-viewer.component.html',
styleUrls: ['./image-viewer.component.scss'],
animations: [fadeInOutAnimation],
standalone: false
selector: 'ngx-image-viewer',
templateUrl: './image-viewer.component.html',
styleUrls: ['./image-viewer.component.scss'],
animations: [fadeInOutAnimation],
imports: [NbLayoutModule, NbButtonModule, NbIconModule, NbSpinnerModule, NgTemplateOutlet, NgClass, AsyncPipe, DateTimePipe]
})
export class ImageViewerComponent implements OnInit {
active_index: number;
@@ -16,19 +16,19 @@ import { ImageViewerService } from './image-viewer.service';
import { NbTablerIconsModule } from '@gauzy/ui-core/theme';
@NgModule({
declarations: [ImageViewerComponent],
imports: [
CommonModule,
NbLayoutModule,
NbCardModule,
NbIconModule,
NbTablerIconsModule,
NbDialogModule,
NbButtonModule,
NbSpinnerModule,
PipeModule
],
exports: [ImageViewerComponent],
providers: [NbDialogService, ImageViewerService, ImageCacheService, StorageService, Store]
imports: [
CommonModule,
NbLayoutModule,
NbCardModule,
NbIconModule,
NbTablerIconsModule,
NbDialogModule,
NbButtonModule,
NbSpinnerModule,
PipeModule,
ImageViewerComponent
],
exports: [ImageViewerComponent],
providers: [NbDialogService, ImageViewerService, ImageCacheService, StorageService, Store]
})
export class ImageViewerModule {}
@@ -8,9 +8,8 @@ import { ActivityWatchViewService } from './activity-watch-view.service';
import { ActivityWatchElectronService } from './activity-watch-electron.service';
@NgModule({
declarations: [ActivityWatchComponent],
exports: [ActivityWatchComponent],
imports: [CommonModule, NbIconModule, NbTooltipModule, NbToggleModule, TranslateModule],
providers: [ActivityWatchEventService, ActivityWatchViewService, ActivityWatchElectronService]
exports: [ActivityWatchComponent],
imports: [CommonModule, NbIconModule, NbTooltipModule, NbToggleModule, TranslateModule, ActivityWatchComponent],
providers: [ActivityWatchEventService, ActivityWatchViewService, ActivityWatchElectronService]
})
export class ActivityWatchModule {}
@@ -1,12 +1,15 @@
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { ActivityWatchViewService } from '../activity-watch-view.service';
import { NbTooltipModule, NbToggleModule, NbIconModule } from '@nebular/theme';
import { AsyncPipe } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
@Component({
selector: 'gauzy-activity-watch',
templateUrl: './activity-watch.component.html',
styleUrls: ['./activity-watch.component.scss'],
standalone: false
imports: [NbTooltipModule, NbToggleModule, NbIconModule, AsyncPipe, TranslatePipe]
})
export class ActivityWatchComponent {
constructor(private readonly activityWatchViewService: ActivityWatchViewService) {}
@@ -1,5 +1,5 @@
import { AfterViewInit, Component, Input, NgZone, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { TranslateService, TranslatePipe } from '@ngx-translate/core';
import { ILanguage, IUser, IUserUpdateInput, LanguagesEnum } from '@gauzy/contracts';
import { distinctUntilChange } from '@gauzy/ui-core/common';
import { UserOrganizationService } from '../time-tracker/organization-selector/user-organization.service';
@@ -9,13 +9,15 @@ import { tap, filter, from, BehaviorSubject, Observable, concatMap, Subject } fr
import { Store } from '../services';
import { LanguageSelectorService } from './language-selector.service';
import { ElectronService } from '../electron/services';
import { NbSelectModule, NbOptionModule } from '@nebular/theme';
import { AsyncPipe } from '@angular/common';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'gauzy-language-selector',
templateUrl: './language-selector.component.html',
styleUrls: ['./language-selector.component.scss'],
standalone: false
imports: [NbSelectModule, NbOptionModule, AsyncPipe, TranslatePipe]
})
export class LanguageSelectorComponent implements OnInit, AfterViewInit {
private _user: IUser;
@@ -10,9 +10,8 @@ import { LanguageSelectorService } from './language-selector.service';
import { LanguageService } from './language.service';
@NgModule({
declarations: [LanguageSelectorComponent],
imports: [CommonModule, NgxTranslateModule, NbSelectModule],
exports: [LanguageSelectorComponent, NgxTranslateModule]
imports: [CommonModule, NgxTranslateModule, NbSelectModule, LanguageSelectorComponent],
exports: [LanguageSelectorComponent, NgxTranslateModule]
})
export class LanguageModule {
static forRoot(): ModuleWithProviders<LanguageModule> {
@@ -1,19 +1,27 @@
import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { AbstractControl, FormBuilder, FormGroup, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ActivatedRoute, Params, Router, RouterLink } from '@angular/router';
import { NB_AUTH_OPTIONS, NbAuthService, NbLoginComponent } from '@nebular/auth';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { EMPTY, Subscription, catchError, filter, finalize, firstValueFrom, interval, tap } from 'rxjs';
import { AuthService } from '../../../auth';
import { GAUZY_ENV, patterns } from '../../../constants';
import { ErrorHandlerService } from '../../../services';
import { LogoComponent } from '../../shared/ui/logo/logo.component';
import { SwitchThemeComponent } from '../../../theme-selector/switch-theme/switch-theme.component';
import { NgClass, NgStyle } from '@angular/common';
import { NbFormFieldModule, NbInputModule, NbIconModule, NbButtonModule } from '@nebular/theme';
import { DebounceClickDirective } from '../../../directives/debounce-click.directive';
import { SpinnerButtonDirective } from '../../../directives/spinner-button.directive';
import { SocialLinksComponent } from '../../shared/ui/social-links/social-links.component';
import { TranslatePipe } from '@ngx-translate/core';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'ngx-login-magic',
templateUrl: './login-magic.component.html',
styleUrls: ['./login-magic.component.scss'],
standalone: false
imports: [LogoComponent, SwitchThemeComponent, NgClass, FormsModule, ReactiveFormsModule, NbFormFieldModule, NbInputModule, NbIconModule, DebounceClickDirective, NbButtonModule, SpinnerButtonDirective, NgStyle, RouterLink, SocialLinksComponent, TranslatePipe]
})
export class NgxLoginMagicComponent extends NbLoginComponent implements OnInit {
public countdown: number;
@@ -1,18 +1,24 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { NavigationExtras, Router } from '@angular/router';
import { FormBuilder, FormControl, FormGroup, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NavigationExtras, Router, RouterLink } from '@angular/router';
import { HttpStatus, IAuthResponse, IUser, IUserSigninWorkspaceResponse, IWorkspaceResponse } from '@gauzy/contracts';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { asyncScheduler, catchError, EMPTY, filter, tap } from 'rxjs';
import { AuthService } from '../../../auth';
import { ErrorHandlerService, Store, TimeTrackerDateManager } from '../../../services';
import { WorkspaceSelectionComponent } from '../../shared/ui/workspace-selection/workspace-selection.component';
import { LogoComponent } from '../../shared/ui/logo/logo.component';
import { NgTemplateOutlet, NgStyle } from '@angular/common';
import { NbInputModule, NbFormFieldModule, NbButtonModule, NbIconModule } from '@nebular/theme';
import { SpinnerButtonDirective } from '../../../directives/spinner-button.directive';
import { TranslatePipe } from '@ngx-translate/core';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'ngx-login-workspace',
templateUrl: './login-workspace.component.html',
styleUrls: ['./login-workspace.component.scss'],
standalone: false
imports: [WorkspaceSelectionComponent, LogoComponent, NgTemplateOutlet, RouterLink, FormsModule, ReactiveFormsModule, NbInputModule, NbFormFieldModule, NbButtonModule, NbIconModule, SpinnerButtonDirective, NgStyle, TranslatePipe]
})
export class NgxLoginWorkspaceComponent implements OnInit {
public confirmedEmail: string;
@@ -5,13 +5,16 @@ import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { asyncScheduler, catchError, EMPTY, filter, firstValueFrom, tap } from 'rxjs';
import { AuthService } from '../../../auth';
import { ErrorHandlerService, Store, TimeTrackerDateManager } from '../../../services';
import { WorkspaceSelectionComponent } from '../../shared/ui/workspace-selection/workspace-selection.component';
import { LogoComponent } from '../../shared/ui/logo/logo.component';
import { TranslatePipe } from '@ngx-translate/core';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'ngx-magic-sign-in-workspace',
templateUrl: './magic-login-workspace.component.html',
styleUrls: ['./magic-login-workspace.component.scss'],
standalone: false
imports: [WorkspaceSelectionComponent, LogoComponent, TranslatePipe]
})
export class NgxMagicSignInWorkspaceComponent implements OnInit {
public error: boolean = false;
@@ -1,6 +1,6 @@
import { ChangeDetectorRef, Component, Inject, OnInit, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { NavigationExtras, Router } from '@angular/router';
import { NgForm, FormsModule } from '@angular/forms';
import { NavigationExtras, Router, RouterLink } from '@angular/router';
import { HttpStatus, IUserSigninWorkspaceResponse } from '@gauzy/contracts';
import { NB_AUTH_OPTIONS, NbAuthService, NbLoginComponent } from '@nebular/auth';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
@@ -10,13 +10,20 @@ import { GAUZY_ENV } from '../constants';
import { ElectronService } from '../electron/services';
import { LanguageElectronService } from '../language/language-electron.service';
import { ErrorHandlerService } from '../services';
import { LogoComponent } from './shared/ui/logo/logo.component';
import { SwitchThemeComponent } from '../theme-selector/switch-theme/switch-theme.component';
import { NbAlertModule, NbInputModule, NbFormFieldModule, NbButtonModule, NbIconModule, NbCheckboxModule } from '@nebular/theme';
import { SpinnerButtonDirective } from '../directives/spinner-button.directive';
import { NgStyle } from '@angular/common';
import { SocialLinksComponent } from './shared/ui/social-links/social-links.component';
import { TranslatePipe } from '@ngx-translate/core';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'ngx-desktop-timer-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss'],
standalone: false
imports: [LogoComponent, SwitchThemeComponent, NbAlertModule, FormsModule, NbInputModule, NbFormFieldModule, NbButtonModule, NbIconModule, NbCheckboxModule, SpinnerButtonDirective, NgStyle, RouterLink, SocialLinksComponent, TranslatePipe]
})
export class NgxLoginComponent extends NbLoginComponent implements OnInit {
@ViewChild('form')
@@ -13,10 +13,10 @@ import {
NbInputModule,
NbListModule
} from '@nebular/theme';
import { DesktopDirectiveModule } from '../directives/desktop-directive.module';
import { LanguageModule } from '../language/language.module';
import { AvatarModule } from '../shared/components/ui/avatar/avatar.module';
import { SwitchThemeModule } from '../theme-selector/switch-theme/switch-theme.module';
import { NgxLoginMagicComponent } from './features/login-magic/login-magic.component';
import { NgxLoginWorkspaceComponent } from './features/login-workspace/login-workspace.component';
import { NgxMagicSignInWorkspaceComponent } from './features/magic-login-workspace/magic-login-workspace.component';
@@ -33,26 +33,23 @@ const shared = [
];
@NgModule({
imports: [
CommonModule,
FormsModule,
RouterModule,
NbAlertModule,
NbAuthModule,
NbButtonModule,
NbCardModule,
NbCheckboxModule,
NbIconModule,
NbInputModule,
NbFormFieldModule,
DesktopDirectiveModule,
LanguageModule.forChild(),
ReactiveFormsModule,
SwitchThemeModule,
NbListModule,
AvatarModule
],
declarations: [LogoComponent, SocialLinksComponent, WorkspaceSelectionComponent, ...shared],
exports: [...shared]
imports: [
CommonModule,
FormsModule,
RouterModule,
NbAlertModule,
NbAuthModule,
NbButtonModule,
NbCardModule,
NbCheckboxModule,
NbIconModule,
NbInputModule,
NbFormFieldModule,
LanguageModule.forChild(),
ReactiveFormsModule,
NbListModule,
LogoComponent, SocialLinksComponent, WorkspaceSelectionComponent, ...shared
],
exports: [...shared]
})
export class NgxLoginModule {}
@@ -5,8 +5,7 @@ import { GAUZY_ENV } from '../../../../constants';
@Component({
selector: 'gauzy-logo',
templateUrl: './logo.component.html',
styleUrls: ['./logo.component.scss'],
standalone: false
styleUrls: ['./logo.component.scss']
})
export class LogoComponent {
constructor(
@@ -3,33 +3,22 @@
{{ 'LOGIN_PAGE.OR_SIGN_IN_WITH' | translate }}
<div class="socials">
@for (socialLink of socialLinks; track socialLink) { @if (socialLink.link) {
<a
[routerLink]="socialLink.link"
[attr.target]="socialLink.target"
[attr.rel]="socialLink.target === '_blank' ? 'noopener noreferrer' : null"
class="social-link"
>
<ng-container *ngTemplateOutlet="linkContentEl; context: { $implicit: socialLink }"></ng-container>
<a [routerLink]="socialLink.link" [attr.target]="socialLink.target" class="social-link">
@if (socialLink.icon) {
<nb-icon [icon]="socialLink.icon"></nb-icon>
} @else {
{{ socialLink.title }}
}
</a>
} @else if (socialLink.url) {
<a
[attr.href]="socialLink.url"
[attr.target]="socialLink.target"
[attr.rel]="socialLink.target === '_blank' ? 'noopener noreferrer' : null"
class="social-link"
>
<ng-container *ngTemplateOutlet="linkContentEl; context: { $implicit: socialLink }"></ng-container>
} @if (socialLink.url) {
<a [attr.href]="socialLink.url" [attr.target]="socialLink.target" class="social-link">
@if (socialLink.icon) {
<nb-icon [icon]="socialLink.icon"></nb-icon>
} @else {
{{ socialLink.title }}
}
</a>
} }
</div>
</div>
} }
<!-- Reusable template for social link content (icon or title) -->
<ng-template let-socialLink #linkContentEl>
@if (socialLink.icon) {
<nb-icon [icon]="socialLink.icon"></nb-icon>
} @else {
{{ socialLink.title }}
}
</ng-template>
@@ -2,6 +2,10 @@ import { Component, OnInit } from '@angular/core';
import { UntilDestroy } from '@ngneat/until-destroy';
import { Observable, of } from 'rxjs';
import { socialLinks } from '../../../../constants';
import { AsyncPipe } from '@angular/common';
import { RouterLink } from '@angular/router';
import { NbIconModule } from '@nebular/theme';
import { TranslatePipe } from '@ngx-translate/core';
/**
* Interface representing a social link.
@@ -24,7 +28,7 @@ export interface ISocialLink {
selector: 'ngx-social-links',
templateUrl: './social-links.component.html',
styleUrls: ['./social-links.component.scss'],
standalone: false
imports: [RouterLink, NbIconModule, AsyncPipe, TranslatePipe]
})
export class SocialLinksComponent implements OnInit {
/** */
@@ -1,11 +1,17 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { IWorkspaceResponse } from '@gauzy/contracts';
import { LogoComponent } from '../logo/logo.component';
import { NbCardModule, NbListModule, NbIconModule } from '@nebular/theme';
import { DebounceClickDirective } from '../../../../directives/debounce-click.directive';
import { AvatarComponent } from '../../../../shared/components/ui/avatar/avatar.component';
import { SpinnerButtonDirective } from '../../../../directives/spinner-button.directive';
import { TranslatePipe } from '@ngx-translate/core';
@Component({
selector: 'ngx-workspace-selection',
templateUrl: './workspace-selection.component.html',
styleUrls: ['./workspace-selection.component.scss'],
standalone: false
imports: [LogoComponent, NbCardModule, NbListModule, DebounceClickDirective, AvatarComponent, SpinnerButtonDirective, NbIconModule, TranslatePipe]
})
export class WorkspaceSelectionComponent {
selected: IWorkspaceResponse = null;
@@ -5,8 +5,13 @@ import { AutoRefreshService } from '../../+state/auto-refresh/auto-refresh.servi
import { RecapQuery } from '../../+state/recap.query';
import { RecapService } from '../../+state/recap.service';
import { RequestQuery } from '../../+state/request/request.query';
import { IStatisticItem } from '../../shared/ui/statistic/statistic.component';
import { IStatisticItem, StatisticComponent } from '../../shared/ui/statistic/statistic.component';
import { ActivityStatisticsAdapter } from '../../shared/utils/adapters/activity.adapter';
import { NbCardModule } from '@nebular/theme';
import { AsyncPipe } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { NoDataMessageComponent } from '../../../time-tracker/no-data-message/no-data-message.component';
@UntilDestroy({ checkProperties: true })
@Component({
@@ -14,7 +19,7 @@ import { ActivityStatisticsAdapter } from '../../shared/utils/adapters/activity.
templateUrl: './activities.component.html',
styleUrls: ['./activities.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
imports: [NbCardModule, StatisticComponent, NoDataMessageComponent, AsyncPipe, TranslatePipe]
})
export class ActivitiesComponent implements OnInit {
constructor(
@@ -7,8 +7,8 @@ describe('FilterComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [FilterComponent]
}).compileComponents();
imports: [FilterComponent]
}).compileComponents();
fixture = TestBed.createComponent(FilterComponent);
component = fixture.componentInstance;
@@ -3,13 +3,17 @@ import { ITimeLogFilters } from '@gauzy/contracts';
import { Observable } from 'rxjs';
import { RequestQuery } from '../../+state/request/request.query';
import { RequestStore } from '../../+state/request/request.store';
import { NbButtonModule, NbPopoverModule, NbIconModule } from '@nebular/theme';
import { GauzyFiltersComponent } from '../../shared/features/gauzy-filters/gauzy-filters.component';
import { AutoRefreshComponent } from '../../shared/ui/auto-refresh/auto-refresh.component';
import { AsyncPipe } from '@angular/common';
@Component({
selector: 'ngx-filter',
templateUrl: './filter.component.html',
styleUrls: ['./filter.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
imports: [NbButtonModule, NbPopoverModule, NbIconModule, GauzyFiltersComponent, AutoRefreshComponent, AsyncPipe]
})
export class FilterComponent {
constructor(private readonly store: RequestStore, private readonly query: RequestQuery) {}
@@ -5,8 +5,13 @@ import { AutoRefreshService } from '../../+state/auto-refresh/auto-refresh.servi
import { RecapQuery } from '../../+state/recap.query';
import { RecapService } from '../../+state/recap.service';
import { RequestQuery } from '../../+state/request/request.query';
import { IStatisticItem } from '../../shared/ui/statistic/statistic.component';
import { IStatisticItem, StatisticComponent } from '../../shared/ui/statistic/statistic.component';
import { ProjectStatisticsAdapter } from '../../shared/utils/adapters/project.adapter';
import { NbCardModule } from '@nebular/theme';
import { AsyncPipe } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { NoDataMessageComponent } from '../../../time-tracker/no-data-message/no-data-message.component';
@UntilDestroy({ checkProperties: true })
@Component({
@@ -14,7 +19,7 @@ import { ProjectStatisticsAdapter } from '../../shared/utils/adapters/project.ad
templateUrl: './projects.component.html',
styleUrls: ['./projects.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
imports: [NbCardModule, StatisticComponent, NoDataMessageComponent, AsyncPipe, TranslatePipe]
})
export class ProjectsComponent implements OnInit {
constructor(
@@ -4,6 +4,12 @@ import { Observable } from 'rxjs';
import { RecapQuery } from '../../+state/recap.query';
import { RecapStore } from '../../+state/recap.store';
import { IDateRangePicker } from '../../shared/features/date-range-picker/date-picker.interface';
import { NbCardModule, NbIconModule } from '@nebular/theme';
import { SegmentedControlComponent } from '../../shared/features/segmented-control/segmented-control.component';
import { DateRangePickerComponent } from '../../shared/features/date-range-picker/date-range-picker.component';
import { FilterComponent } from '../filter/filter.component';
import { RouterOutlet } from '@angular/router';
import { AsyncPipe } from '@angular/common';
@UntilDestroy({ checkProperties: true })
@Component({
@@ -11,7 +17,7 @@ import { IDateRangePicker } from '../../shared/features/date-range-picker/date-p
templateUrl: './recap.component.html',
styleUrls: ['./recap.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
imports: [NbCardModule, SegmentedControlComponent, NbIconModule, DateRangePickerComponent, FilterComponent, RouterOutlet, AsyncPipe]
})
export class RecapComponent {
private readonly basePath = ['/', 'time-tracker', 'daily'];
@@ -5,8 +5,13 @@ import { AutoRefreshService } from '../../+state/auto-refresh/auto-refresh.servi
import { RecapQuery } from '../../+state/recap.query';
import { RecapService } from '../../+state/recap.service';
import { RequestQuery } from '../../+state/request/request.query';
import { IStatisticItem } from '../../shared/ui/statistic/statistic.component';
import { IStatisticItem, StatisticComponent } from '../../shared/ui/statistic/statistic.component';
import { TaskStatisticsAdapter } from '../../shared/utils/adapters/task.adapter';
import { NbCardModule } from '@nebular/theme';
import { AsyncPipe } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { NoDataMessageComponent } from '../../../time-tracker/no-data-message/no-data-message.component';
@UntilDestroy({ checkProperties: true })
@Component({
@@ -14,7 +19,7 @@ import { TaskStatisticsAdapter } from '../../shared/utils/adapters/task.adapter'
templateUrl: './tasks.component.html',
styleUrls: ['./tasks.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
imports: [NbCardModule, StatisticComponent, NoDataMessageComponent, AsyncPipe, TranslatePipe]
})
export class TasksComponent implements OnInit {
constructor(
@@ -1,13 +1,18 @@
import { AsyncPipe, PercentPipe } from '@angular/common';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { ITimeSlot } from '@gauzy/contracts';
import { progressStatus } from '@gauzy/ui-core/common';
import { NbBadgeModule, NbCardModule } from '@nebular/theme';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { BehaviorSubject, combineLatest, concatMap, from, map } from 'rxjs';
import { Observable } from 'rxjs';
import { TranslatePipe } from '@ngx-translate/core';
import { BarChartModule } from '@swimlane/ngx-charts';
import { BehaviorSubject, combineLatest, concatMap, from, map, Observable } from 'rxjs';
import { AutoRefreshService } from '../../+state/auto-refresh/auto-refresh.service';
import { RecapQuery } from '../../+state/recap.query';
import { RecapService } from '../../+state/recap.service';
import { RequestQuery } from '../../+state/request/request.query';
import { NoDataMessageComponent } from '../../../time-tracker/no-data-message/no-data-message.component';
import { PipeModule } from '../../../time-tracker/pipes/pipe.module';
import { IChartData } from '../../shared/utils/adapters/chart.adapter';
@UntilDestroy({ checkProperties: true })
@@ -16,7 +21,16 @@ import { IChartData } from '../../shared/utils/adapters/chart.adapter';
templateUrl: './time-tracking-charts.component.html',
styleUrls: ['./time-tracking-charts.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
imports: [
NbCardModule,
BarChartModule,
NbBadgeModule,
NoDataMessageComponent,
AsyncPipe,
PercentPipe,
TranslatePipe,
PipeModule
]
})
export class TimeTrackingChartsComponent implements OnInit {
private readonly _chartData$: BehaviorSubject<IChartData[]> = new BehaviorSubject([]);
@@ -2,13 +2,15 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
import { map } from 'rxjs';
import { MonthlyRecapService } from '../../+state/monthly.service';
import { IDateRangePicker } from '../../../shared/features/date-range-picker/date-picker.interface';
import { DateRangePickerComponent } from '../../../shared/features/date-range-picker/date-range-picker.component';
import { AsyncPipe } from '@angular/common';
@Component({
selector: 'ngx-monthly-calendar',
templateUrl: './monthly-calendar.component.html',
styleUrls: ['./monthly-calendar.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
imports: [DateRangePickerComponent, AsyncPipe]
})
export class MonthlyCalendarComponent {
constructor(private readonly monthlyRecapService: MonthlyRecapService) {}
@@ -3,6 +3,12 @@ import { ReportDayData } from '@gauzy/contracts';
import { map, tap } from 'rxjs';
import { MonthlyRecapService } from '../../+state/monthly.service';
import { updateMonthWeeks, weekDateRange } from '../../../shared/features/date-range-picker';
import { ProgressStatusComponent } from '../../../shared/ui/progress-status/progress-status.component';
import { AsyncPipe } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { NoDataMessageComponent } from '../../../../time-tracker/no-data-message/no-data-message.component';
import { PipeModule } from '../../../../time-tracker/pipes/pipe.module';
export interface IMonthWeekdays {
week: string;
@@ -10,11 +16,11 @@ export interface IMonthWeekdays {
}
@Component({
selector: 'ngx-monthly-progress',
templateUrl: './monthly-progress.component.html',
styleUrls: ['./monthly-progress.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
selector: 'ngx-monthly-progress',
templateUrl: './monthly-progress.component.html',
styleUrls: ['./monthly-progress.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ProgressStatusComponent, NoDataMessageComponent, AsyncPipe, TranslatePipe, PipeModule]
})
export class MonthlyProgressComponent {
public monthWeekdays: IMonthWeekdays[] = [];
@@ -5,6 +5,12 @@ import { MonthlyRecapService } from '../../+state/monthly.service';
import { AutoRefreshService } from '../../../+state/auto-refresh/auto-refresh.service';
import { RequestQuery } from '../../../+state/request/request.query';
import { LoggerService } from '../../../../electron/services';
import { NbCardModule, NbIconModule } from '@nebular/theme';
import { MonthlyCalendarComponent } from '../monthly-calendar/monthly-calendar.component';
import { FilterComponent } from '../../../features/filter/filter.component';
import { MonthlyStatisticComponent } from '../monthly-statistic/monthly-statistic.component';
import { MonthlyProgressComponent } from '../monthly-progress/monthly-progress.component';
import { AsyncPipe } from '@angular/common';
@UntilDestroy({ checkProperties: true })
@Component({
@@ -12,7 +18,7 @@ import { LoggerService } from '../../../../electron/services';
templateUrl: './monthly-recap.component.html',
styleUrls: ['./monthly-recap.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
imports: [NbCardModule, NbIconModule, MonthlyCalendarComponent, FilterComponent, MonthlyStatisticComponent, MonthlyProgressComponent, AsyncPipe]
})
export class MonthlyRecapComponent implements OnInit {
public isLoading$ = new BehaviorSubject(false);
@@ -1,13 +1,17 @@
import { AsyncPipe, PercentPipe } from '@angular/common';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { NbCardModule } from '@nebular/theme';
import { TranslatePipe } from '@ngx-translate/core';
import { map } from 'rxjs';
import { MonthlyRecapService } from '../../+state/monthly.service';
import { PipeModule } from '../../../../time-tracker/pipes/pipe.module';
@Component({
selector: 'ngx-monthly-statistic',
templateUrl: './monthly-statistic.component.html',
styleUrls: ['./monthly-statistic.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
selector: 'ngx-monthly-statistic',
templateUrl: './monthly-statistic.component.html',
styleUrls: ['./monthly-statistic.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NbCardModule, AsyncPipe, PercentPipe, TranslatePipe, PipeModule]
})
export class MonthlyStatisticComponent {
constructor(private readonly monthlyRecapService: MonthlyRecapService) {}
@@ -1,8 +1,4 @@
import { Routes } from '@angular/router';
import { TimeTrackingChartsComponent } from './features/time-tracking-charts/time-tracking-charts.component';
import { ActivityReportComponent } from './shared/features/activity-report/activity-report.component';
import { TasksComponent } from './features/tasks/tasks.component';
import { ProjectsComponent } from './features/projects/projects.component';
export const recapChildRoutes: Routes = [
{
@@ -12,19 +8,23 @@ export const recapChildRoutes: Routes = [
},
{
path: 'hourly',
component: TimeTrackingChartsComponent
loadComponent: () =>
import('./features/time-tracking-charts/time-tracking-charts.component').then(
(m) => m.TimeTrackingChartsComponent
)
},
{
path: 'activities',
component: ActivityReportComponent
loadComponent: () =>
import('./shared/features/activity-report/activity-report.component').then((m) => m.ActivityReportComponent)
},
{
path: 'tasks',
component: TasksComponent
loadComponent: () => import('./features/tasks/tasks.component').then((m) => m.TasksComponent)
},
{
path: 'projects',
component: ProjectsComponent
loadComponent: () => import('./features/projects/projects.component').then((m) => m.ProjectsComponent)
},
{
path: '**',
@@ -1,8 +1,6 @@
import { Routes } from '@angular/router';
import { RecapComponent } from './features/recap/recap.component';
import { recapChildRoutes } from './recap-children-routing.module';
import { WeeklyRecapComponent } from './weekly/features/weekly-recap/weekly-recap.component';
import { MonthlyRecapComponent } from './monthly/features/monthly-recap/monthly-recap.component';
export const recapRoutes: Routes = [
{
@@ -12,21 +10,22 @@ export const recapRoutes: Routes = [
},
{
path: 'daily',
component: RecapComponent,
loadComponent: () => import('./features/recap/recap.component').then((m) => m.RecapComponent),
children: recapChildRoutes
},
{
path: 'weekly',
component: WeeklyRecapComponent
loadComponent: () =>
import('./weekly/features/weekly-recap/weekly-recap.component').then((m) => m.WeeklyRecapComponent)
},
{
path: 'monthly',
component: MonthlyRecapComponent
loadComponent: () =>
import('./monthly/features/monthly-recap/monthly-recap.component').then((m) => m.MonthlyRecapComponent)
},
{
path: 'tasks',
loadChildren: () =>
import('../time-tracker/task-table/task-table.module').then((m) => m.TaskTableModule)
loadChildren: () => import('../time-tracker/task-table/task-table.module').then((m) => m.TaskTableModule)
},
{
path: '**',
@@ -16,9 +16,9 @@ import {
NbToggleModule
} from '@nebular/theme';
import { NgxChartsModule } from '@swimlane/ngx-charts';
import { LanguageModule } from '../language/language.module';
import { ToastrNotificationService } from '../services';
import { NoDataMessageModule } from '../time-tracker/no-data-message/no-data-message.module';
import { TranslateModule } from '@ngx-translate/core';
import { PipeModule } from '../time-tracker/pipes/pipe.module';
import { AutoRefreshQuery } from './+state/auto-refresh/auto-refresh.query';
import { AutoRefreshService } from './+state/auto-refresh/auto-refresh.service';
@@ -28,52 +28,12 @@ import { RecapService } from './+state/recap.service';
import { RecapStore } from './+state/recap.store';
import { RequestQuery } from './+state/request/request.query';
import { RequestStore } from './+state/request/request.store';
import { ActivitiesComponent } from './features/activities/activities.component';
import { FilterComponent } from './features/filter/filter.component';
import { ProjectsComponent } from './features/projects/projects.component';
import { RecapComponent } from './features/recap/recap.component';
import { TasksComponent } from './features/tasks/tasks.component';
import { TimeTrackingChartsComponent } from './features/time-tracking-charts/time-tracking-charts.component';
import { MonthlyCalendarComponent } from './monthly/features/monthly-calendar/monthly-calendar.component';
import { MonthlyProgressComponent } from './monthly/features/monthly-progress/monthly-progress.component';
import { MonthlyRecapComponent } from './monthly/features/monthly-recap/monthly-recap.component';
import { MonthlyStatisticComponent } from './monthly/features/monthly-statistic/monthly-statistic.component';
import { recapRoutes } from './recap-routing.module';
import { ActivityService, TimesheetService, TimesheetStatisticsService } from './services/timesheet';
import { ActivityReportComponent } from './shared/features/activity-report/activity-report.component';
import { DateRangePickerModule } from './shared/features/date-range-picker/date-range-picker.module';
import { GauzyFiltersModule } from './shared/features/gauzy-filters';
import { SegmentedControlComponent } from './shared/features/segmented-control/segmented-control.component';
import { AutoRefreshComponent } from './shared/ui/auto-refresh/auto-refresh.component';
import { ProgressStatusModule } from './shared/ui/progress-status/progress-status.module';
import { ProjectColumnViewModule } from './shared/ui/project-column-view/project-column-view.module';
import { StatisticComponent } from './shared/ui/statistic/statistic.component';
import { WeeklyCalendarComponent } from './weekly/features/weekly-calendar/weekly-calendar.component';
import { WeeklyProgressComponent } from './weekly/features/weekly-progress/weekly-progress.component';
import { WeeklyRecapComponent } from './weekly/features/weekly-recap/weekly-recap.component';
import { WeeklyStatisticComponent } from './weekly/features/weekly-statistic/weekly-statistic.component';
import { recapRoutes } from './recap-routing.module';
@NgModule({
declarations: [
RecapComponent,
ProjectsComponent,
TasksComponent,
ActivitiesComponent,
TimeTrackingChartsComponent,
FilterComponent,
StatisticComponent,
AutoRefreshComponent,
ActivityReportComponent,
SegmentedControlComponent,
WeeklyRecapComponent,
WeeklyCalendarComponent,
WeeklyProgressComponent,
WeeklyStatisticComponent,
MonthlyRecapComponent,
MonthlyCalendarComponent,
MonthlyProgressComponent,
MonthlyStatisticComponent
],
imports: [
CommonModule,
NbLayoutModule,
@@ -82,7 +42,6 @@ import { recapRoutes } from './recap-routing.module';
NbProgressBarModule,
NbIconModule,
NbButtonModule,
NoDataMessageModule,
NbPopoverModule,
NbTableModule,
NgxChartsModule,
@@ -92,10 +51,8 @@ import { recapRoutes } from './recap-routing.module';
GauzyFiltersModule,
NbBadgeModule,
NbToggleModule,
ProjectColumnViewModule,
ProgressStatusModule,
NbSpinnerModule,
LanguageModule.forChild(),
TranslateModule.forChild(),
RouterModule.forChild(recapRoutes)
],
providers: [
@@ -111,7 +68,6 @@ import { recapRoutes } from './recap-routing.module';
AutoRefreshStore,
RequestQuery,
RequestStore
],
exports: [RecapComponent, WeeklyRecapComponent, MonthlyRecapComponent]
]
})
export class RecapModule {}
@@ -1,19 +1,34 @@
import { AsyncPipe, NgTemplateOutlet } from '@angular/common';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { IDailyActivity } from '@gauzy/contracts';
import { NbCardModule, NbSpinnerModule } from '@nebular/theme';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslatePipe } from '@ngx-translate/core';
import { BehaviorSubject, combineLatest, concatMap, map, Observable } from 'rxjs';
import { AutoRefreshService } from '../../../+state/auto-refresh/auto-refresh.service';
import { RecapQuery } from '../../../+state/recap.query';
import { RecapService } from '../../../+state/recap.service';
import { RequestQuery } from '../../../+state/request/request.query';
import { NoDataMessageComponent } from '../../../../time-tracker/no-data-message/no-data-message.component';
import { ProgressStatusComponent } from '../../ui/progress-status/progress-status.component';
import { ProjectColumnViewComponent } from '../../ui/project-column-view/project-column-view.component';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'ngx-activity-report',
templateUrl: './activity-report.component.html',
styleUrls: ['./activity-report.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
selector: 'ngx-activity-report',
templateUrl: './activity-report.component.html',
styleUrls: ['./activity-report.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
NbSpinnerModule,
NbCardModule,
NgTemplateOutlet,
NoDataMessageComponent,
ProgressStatusComponent,
ProjectColumnViewComponent,
AsyncPipe,
TranslatePipe
]
})
export class ActivityReportComponent implements OnInit {
public isLoading$ = new BehaviorSubject<boolean>(false);
@@ -14,11 +14,7 @@ import { distinctUntilChange } from '@gauzy/ui-core/common';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateService } from '@ngx-translate/core';
import * as moment from 'moment-timezone';
import {
DaterangepickerDirective as DateRangePickerDirective,
LocaleConfig,
DaterangepickerComponent as NgxDateRangePickerComponent
} from 'ngx-daterangepicker-material';
import { DaterangepickerDirective as DateRangePickerDirective, LocaleConfig, DaterangepickerComponent as NgxDateRangePickerComponent, NgxDaterangepickerMd } from 'ngx-daterangepicker-material';
import { BehaviorSubject, filter, Subject } from 'rxjs';
import { debounceTime, tap } from 'rxjs/operators';
import { RecapQuery } from '../../../+state/recap.query';
@@ -27,14 +23,17 @@ import { Arrow } from './arrow/context/arrow.class';
import { Next, Previous } from './arrow/strategies';
import { DateRangeKeyEnum, DateRanges, IDateRangePicker, TimePeriod } from './date-picker.interface';
import { dayOfWeekAsString, shiftUTCtoLocal } from './date-picker.utils';
import { NbButtonModule, NbIconModule, NbInputModule } from '@nebular/theme';
import { FormsModule } from '@angular/forms';
import { NgClass } from '@angular/common';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'ngx-date-range-picker',
templateUrl: './date-range-picker.component.html',
styleUrls: ['./date-range-picker.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
selector: 'ngx-date-range-picker',
templateUrl: './date-range-picker.component.html',
styleUrls: ['./date-range-picker.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NbButtonModule, NbIconModule, NbInputModule, NgxDaterangepickerMd, FormsModule, NgClass]
})
export class DateRangePickerComponent implements OnInit, OnDestroy {
public picker: NgxDateRangePickerComponent;
@@ -13,22 +13,22 @@ import { dayOfWeekAsString } from './date-picker.utils';
import { DateRangePickerComponent } from './date-range-picker.component';
@NgModule({
declarations: [DateRangePickerComponent],
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
NbButtonModule,
NbIconModule,
NbInputModule,
NgSelectModule,
TranslateModule,
PipeModule,
NgxDateRangePickerMd.forRoot({
firstDay: dayOfWeekAsString(WeekDaysEnum.MONDAY)
})
],
providers: [RecapStore, RecapQuery],
exports: [DateRangePickerComponent]
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
NbButtonModule,
NbIconModule,
NbInputModule,
NgSelectModule,
TranslateModule,
PipeModule,
NgxDateRangePickerMd.forRoot({
firstDay: dayOfWeekAsString(WeekDaysEnum.MONDAY)
}),
DateRangePickerComponent
],
providers: [RecapStore, RecapQuery],
exports: [DateRangePickerComponent]
})
export class DateRangePickerModule {}
@@ -1,17 +1,39 @@
import { ChangeContext, NgxSliderModule, Options } from '@angular-slider/ngx-slider';
import { KeyValuePipe, TitleCasePipe } from '@angular/common';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { ChangeContext, Options } from '@angular-slider/ngx-slider';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateService } from '@ngx-translate/core';
import { tap } from 'rxjs';
import { ITimeLogFilters, PermissionsEnum, TimeFormatEnum, TimeLogSourceEnum, TimeLogType } from '@gauzy/contracts';
import {
NbButtonModule,
NbCardModule,
NbIconModule,
NbOptionModule,
NbPopoverModule,
NbSelectModule
} from '@nebular/theme';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import { tap } from 'rxjs';
import { PipeModule } from '../../../../time-tracker/pipes/pipe.module';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'ngx-gauzy-filters',
templateUrl: './gauzy-filters.component.html',
styleUrls: ['./gauzy-filters.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
selector: 'ngx-gauzy-filters',
templateUrl: './gauzy-filters.component.html',
styleUrls: ['./gauzy-filters.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
NbCardModule,
NbButtonModule,
NbIconModule,
NbSelectModule,
NbOptionModule,
NbPopoverModule,
NgxSliderModule,
TitleCasePipe,
KeyValuePipe,
TranslatePipe,
PipeModule
]
})
export class GauzyFiltersComponent implements OnInit, OnDestroy {
// declaration of variables
@@ -9,20 +9,20 @@ import { PipeModule } from './../../../../time-tracker/pipes/pipe.module';
import { GauzyFiltersComponent } from './gauzy-filters.component';
@NgModule({
declarations: [GauzyFiltersComponent],
exports: [GauzyFiltersComponent],
imports: [
CommonModule,
FormsModule,
NbButtonModule,
NbCardModule,
NbIconModule,
NbPopoverModule,
NbSelectModule,
NgxSliderModule,
TranslateModule,
PipeModule
],
providers: [TimesheetFilterService]
exports: [GauzyFiltersComponent],
imports: [
CommonModule,
FormsModule,
NbButtonModule,
NbCardModule,
NbIconModule,
NbPopoverModule,
NbSelectModule,
NgxSliderModule,
TranslateModule,
PipeModule,
GauzyFiltersComponent
],
providers: [TimesheetFilterService]
})
export class GauzyFiltersModule {}
@@ -3,13 +3,16 @@ import { Router } from '@angular/router';
import { Observable, from } from 'rxjs';
import { SegmentControlService } from './+state/segment-control.service';
import { ISegmentControlState } from './+state/segment-control.store';
import { NgClass, AsyncPipe } from '@angular/common';
import { NbIconModule } from '@nebular/theme';
import { TranslatePipe } from '@ngx-translate/core';
@Component({
selector: 'ngx-segmented-control',
templateUrl: './segmented-control.component.html',
styleUrls: ['./segmented-control.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
imports: [NgClass, NbIconModule, AsyncPipe, TranslatePipe]
})
export class SegmentedControlComponent implements OnInit {
@Input()
@@ -7,8 +7,8 @@ describe('AutoRefreshComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AutoRefreshComponent]
}).compileComponents();
imports: [AutoRefreshComponent]
}).compileComponents();
fixture = TestBed.createComponent(AutoRefreshComponent);
component = fixture.componentInstance;
@@ -2,6 +2,9 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { UntilDestroy } from '@ngneat/until-destroy';
import { Observable } from 'rxjs';
import { AutoRefreshService } from '../../../+state/auto-refresh/auto-refresh.service';
import { NbToggleModule, NbButtonModule, NbIconModule } from '@nebular/theme';
import { AsyncPipe } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
@UntilDestroy({ checkProperties: true })
@Component({
@@ -9,7 +12,7 @@ import { AutoRefreshService } from '../../../+state/auto-refresh/auto-refresh.se
templateUrl: './auto-refresh.component.html',
styleUrls: ['./auto-refresh.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
imports: [NbToggleModule, NbButtonModule, NbIconModule, AsyncPipe, TranslatePipe]
})
export class AutoRefreshComponent {
private service = inject(AutoRefreshService);
@@ -8,9 +8,9 @@ describe('ProgressStatusComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ProgressStatusComponent],
teardown: { destroyAfterEach: false }
}).compileComponents();
imports: [ProgressStatusComponent],
teardown: { destroyAfterEach: false }
}).compileComponents();
});
beforeEach(() => {
@@ -1,6 +1,7 @@
import { Component, Input } from '@angular/core';
import { progressStatus } from '@gauzy/ui-core/common';
import { NbComponentOrCustomStatus } from '@nebular/theme';
import { NbComponentOrCustomStatus, NbProgressBarModule } from '@nebular/theme';
import { PercentPipe } from '@angular/common';
export interface IProgressStatusDisplayValue {
in?: boolean;
@@ -11,7 +12,7 @@ export interface IProgressStatusDisplayValue {
selector: 'ngx-progress-status',
templateUrl: './progress-status.component.html',
styleUrls: ['./progress-status.component.scss'],
standalone: false
imports: [NbProgressBarModule, PercentPipe]
})
export class ProgressStatusComponent {
/*
@@ -1,11 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { NbProgressBarModule } from '@nebular/theme';
import { ProgressStatusComponent } from './progress-status.component';
@NgModule({
imports: [CommonModule, NbProgressBarModule],
declarations: [ProgressStatusComponent],
exports: [ProgressStatusComponent]
})
export class ProgressStatusModule {}
@@ -5,8 +5,7 @@ import { DEFAULT_SVG } from '@gauzy/ui-core/common';
@Component({
selector: 'ga-project-column-view',
templateUrl: './project-column-view.component.html',
styleUrls: ['./project-column-view.component.scss'],
standalone: false
styleUrls: ['./project-column-view.component.scss']
})
export class ProjectColumnViewComponent {
fallbackSvg = DEFAULT_SVG;
@@ -1,10 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { ProjectColumnViewComponent } from './project-column-view.component';
@NgModule({
imports: [CommonModule],
declarations: [ProjectColumnViewComponent],
exports: [ProjectColumnViewComponent]
})
export class ProjectColumnViewModule {}
@@ -1,5 +1,6 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { progressStatus } from '@gauzy/ui-core/common';
import { NbListModule, NbProgressBarModule } from '@nebular/theme';
export interface IStatisticItem {
imageUrl?: string;
@@ -9,11 +10,11 @@ export interface IStatisticItem {
}
@Component({
selector: 'ngx-statistic',
templateUrl: './statistic.component.html',
styleUrls: ['./statistic.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
selector: 'ngx-statistic',
templateUrl: './statistic.component.html',
styleUrls: ['./statistic.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NbListModule, NbProgressBarModule]
})
export class StatisticComponent {
private _items: IStatisticItem[] = [];
@@ -1,14 +1,17 @@
import { AsyncPipe } from '@angular/common';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { map } from 'rxjs';
import { WeeklyRecapService } from '../../+state/weekly.service';
import { PipeModule } from '../../../../time-tracker/pipes/pipe.module';
import { IDateRangePicker } from '../../../shared/features/date-range-picker/date-picker.interface';
import { DateRangePickerComponent } from '../../../shared/features/date-range-picker/date-range-picker.component';
@Component({
selector: 'ngx-weekly-calendar',
templateUrl: './weekly-calendar.component.html',
styleUrls: ['./weekly-calendar.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
selector: 'ngx-weekly-calendar',
templateUrl: './weekly-calendar.component.html',
styleUrls: ['./weekly-calendar.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [DateRangePickerComponent, AsyncPipe, PipeModule]
})
export class WeeklyCalendarComponent {
constructor(private readonly weeklyRecapService: WeeklyRecapService) {}
@@ -2,13 +2,19 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
import { map, tap } from 'rxjs';
import { WeeklyRecapService } from '../../+state/weekly.service';
import { updateWeekDays } from '../../../shared/features/date-range-picker';
import { ProgressStatusComponent } from '../../../shared/ui/progress-status/progress-status.component';
import { AsyncPipe } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { NoDataMessageComponent } from '../../../../time-tracker/no-data-message/no-data-message.component';
import { PipeModule } from '../../../../time-tracker/pipes/pipe.module';
@Component({
selector: 'ngx-weekly-progress',
templateUrl: './weekly-progress.component.html',
styleUrls: ['./weekly-progress.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
selector: 'ngx-weekly-progress',
templateUrl: './weekly-progress.component.html',
styleUrls: ['./weekly-progress.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ProgressStatusComponent, NoDataMessageComponent, AsyncPipe, TranslatePipe, PipeModule]
})
export class WeeklyProgressComponent {
public weekDays: string[] = [];
@@ -1,18 +1,34 @@
import { AsyncPipe } from '@angular/common';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { NbCardModule, NbIconModule } from '@nebular/theme';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { BehaviorSubject, combineLatest, concatMap } from 'rxjs';
import { WeeklyRecapService } from '../../+state/weekly.service';
import { AutoRefreshService } from '../../../+state/auto-refresh/auto-refresh.service';
import { RequestQuery } from '../../../+state/request/request.query';
import { LoggerService } from '../../../../electron/services';
import { PipeModule } from '../../../../time-tracker/pipes/pipe.module';
import { FilterComponent } from '../../../features/filter/filter.component';
import { WeeklyCalendarComponent } from '../weekly-calendar/weekly-calendar.component';
import { WeeklyProgressComponent } from '../weekly-progress/weekly-progress.component';
import { WeeklyStatisticComponent } from '../weekly-statistic/weekly-statistic.component';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'ngx-weekly-recap',
templateUrl: './weekly-recap.component.html',
styleUrls: ['./weekly-recap.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
selector: 'ngx-weekly-recap',
templateUrl: './weekly-recap.component.html',
styleUrls: ['./weekly-recap.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
NbCardModule,
NbIconModule,
WeeklyCalendarComponent,
FilterComponent,
WeeklyStatisticComponent,
WeeklyProgressComponent,
AsyncPipe,
PipeModule
]
})
export class WeeklyRecapComponent implements OnInit {
public isLoading$ = new BehaviorSubject(false);
@@ -35,11 +51,14 @@ export class WeeklyRecapComponent implements OnInit {
public async load(): Promise<void> {
try {
this.isLoading$.next(true);
await Promise.allSettled([this.weeklyRecapService.getCounts(), this.weeklyRecapService.getWeeklyActivities()]);
await Promise.allSettled([
this.weeklyRecapService.getCounts(),
this.weeklyRecapService.getWeeklyActivities()
]);
} catch (error) {
this.logger.error(error)
}finally {
this.isLoading$.next(false)
this.logger.error(error);
} finally {
this.isLoading$.next(false);
}
}
}
@@ -1,13 +1,17 @@
import { AsyncPipe, PercentPipe } from '@angular/common';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { NbCardModule } from '@nebular/theme';
import { TranslatePipe } from '@ngx-translate/core';
import { map } from 'rxjs';
import { WeeklyRecapService } from '../../+state/weekly.service';
import { PipeModule } from '../../../../time-tracker/pipes/pipe.module';
@Component({
selector: 'ngx-weekly-statistic',
templateUrl: './weekly-statistic.component.html',
styleUrls: ['./weekly-statistic.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
selector: 'ngx-weekly-statistic',
templateUrl: './weekly-statistic.component.html',
styleUrls: ['./weekly-statistic.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NbCardModule, AsyncPipe, PercentPipe, TranslatePipe, PipeModule]
})
export class WeeklyStatisticComponent {
constructor(private readonly weeklyRecapService: WeeklyRecapService) {}
@@ -8,8 +8,8 @@ describe('ScreenCaptureComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ScreenCaptureComponent]
}).compileComponents();
imports: [ScreenCaptureComponent]
}).compileComponents();
}));
beforeEach(() => {

Some files were not shown because too many files have changed in this diff Show More