Compare commits

...

57 Commits

Author SHA1 Message Date
Sercan Yemen
3018c0235f Added the missing release date to the changelog 2022-06-03 11:00:40 +03:00
Sercan Yemen
a6399c0cf4 (@fuse) Fixed couple lint issues 2022-06-03 10:46:40 +03:00
Sercan Yemen
22d91673ae (dependencies) Updated to Angular and Angular Material v14.0.0 stable
(dependencies) Updated various other packages
2022-06-03 10:41:07 +03:00
Sercan Yemen
3e303a041a Updated the changelog 2022-06-02 11:02:30 +03:00
Sercan Yemen
714bc49c4e Updated the version number and added the changelog 2022-06-02 10:48:17 +03:00
Sercan Yemen
3cc4f31238 (dependencies) Updated Angular & Angular Material 2022-06-02 10:28:07 +03:00
Sercan Yemen
c5aa094230 (icons) Removed iconsmind icons pack because of the bundle size concerns 2022-05-27 13:48:31 +03:00
Sercan Yemen
cbd35d57f8 (global) Replaced iconsmind icons with heroicons 2022-05-27 13:45:52 +03:00
Sercan Yemen
11d5dcdb9d Updated various other packages 2022-05-26 14:01:50 +03:00
Sercan Yemen
66e5511402 Migrated to Angular Material to 14.rc-1 2022-05-26 13:59:01 +03:00
Sercan Yemen
20a03c3689 Migrated to Angular to 14.rc-2 2022-05-26 13:57:37 +03:00
Sercan Yemen
d033470851 (layout) Fixed: The theme settings cog is not positioned correctly in Empty layout 2022-05-25 23:17:12 +03:00
Sercan Yemen
c374c2c6cf (global) Replaced linked buttons with a tags + removed unnecessary routerLink attributes from some buttons 2022-05-25 13:29:47 +03:00
Sercan Yemen
30d75c9bd7 (@fuse/navigation) Keep the fragment as null if it's not provided to prevent empty hashtag appearing at the end of the url 2022-05-25 12:28:25 +03:00
Sercan Yemen
54cd21f496 (docs) Updated docs for FuseNavigation 2022-05-25 12:18:24 +03:00
Sercan Yemen
57d87fa1c4 (@fuse/navigation) Added "fragment" and "queryParams" support along with "preserveFragment" and "queryParamsHandling" 2022-05-25 12:17:56 +03:00
Sercan Yemen
cd8c6ece0f (@fuse/service/confirmation) Cleaned-up the dialog component 2022-05-25 11:43:23 +03:00
Sercan Yemen
1bf4c48cdc (@fuse/service/platform) Added comments to the service file 2022-05-25 11:25:37 +03:00
Sercan Yemen
ea9efc3dc2 (global) Added custom scrollbar styling for platforms other than macOS and iOS 2022-05-24 14:39:02 +03:00
Sercan Yemen
878a6bf191 (@fuse/services/platform) Added platform checker service 2022-05-24 14:38:50 +03:00
Sercan Yemen
099e745a36 (apps/academy) Fixed: Ring outside the current step's number is not visible 2022-05-24 12:58:06 +03:00
Sercan Yemen
150ddc64d7 (mock-api) Replaced the 'refresh-access-token' url with 'sign-in-with-token'
(auth) Changed the url on 'signInUsingToken' method to reflect the mock-api changes
2022-05-24 12:43:51 +03:00
Sercan Yemen
a6d64b1747 (auth) Made the renewing token on "sign-in-with-token" process an optional step to simplify the login process 2022-05-24 12:42:23 +03:00
Sercan Yemen
6eff4a1898 (@fuse/overrides/quill) Added tooltip styles for better compatibility, closes #171 2022-05-24 12:17:45 +03:00
Sercan Yemen
e3630218b5 (apps/mailbox) Fixed: Quill editor tooltips are not positioning correctly 2022-05-24 12:17:09 +03:00
Sercan Yemen
154095da0f (auth/sign-up) Added missing ngForm reference, closes #165 2022-05-24 11:30:10 +03:00
Sercan Yemen
a32970b7c2 (@fuse/navigation) Moved the margin into the children's first child for smoother animations, closes #173 2022-05-24 09:56:44 +03:00
Sercan Yemen
2771d3b1ae (global) Replace @import with @use 2022-05-17 12:40:52 +03:00
Sercan Yemen
9b44793b64 (ui/page-layouts) Fixed: Toggle button selected background is not visible 2022-05-15 15:28:28 +03:00
Sercan Yemen
9521257b4d (apps/mailbox) Fixed: Empty route related issues 2022-05-12 23:50:43 +03:00
Sercan Yemen
5378a6b6ef (apps/chat) Fixed: Empty route related issues 2022-05-12 23:49:42 +03:00
Sercan Yemen
c41e48df7f Angular 14 related changes 2022-05-12 23:40:40 +03:00
Sercan Yemen
b87173b056 (layout/common/search) Implemented the new MatAutocomplete "autoSelectActiveOption" functionality 2022-05-12 23:37:33 +03:00
Sercan Yemen
6aaa355a48 (ui/icons) Updated the route configuration 2022-05-12 23:28:07 +03:00
Sercan Yemen
b96dd041d9 (docs) Updated the directory structure 2022-05-12 23:25:51 +03:00
Sercan Yemen
9786c6baf5 (mock-api/file-manager) Fixed: http params are not working properly because of the new string conversion 2022-05-12 23:18:10 +03:00
Sercan Yemen
f5cc14939c (apps/chat) Fixed: Empty route related issues 2022-05-12 23:13:02 +03:00
Sercan Yemen
8fd434600b Updated various other packages 2022-05-12 21:36:32 +03:00
Sercan Yemen
4c82f6749b Updated Angular & Angular Material to 14.0.0-rc.0 2022-05-12 21:23:12 +03:00
Sercan Yemen
b0830148a3 (@fuse) Better scrolling for Quill editor 2022-05-12 13:36:40 +03:00
Sercan Yemen
cdc54ab05e (Documentation) Updated the FuseDrawer documentation and example 2022-03-29 16:38:49 +03:00
Sercan Yemen
e6ad547d27 (FuseDrawer) Updated the overlay and animation handling code for better stability 2022-03-29 16:38:42 +03:00
Sercan Yemen
afda4b35c9 Updated the changelog 2022-02-21 11:59:41 +03:00
Sercan Yemen
3b88638dee Updated various packages
Re-enabled AngularCLI cache since Tailwind related issues are appeared to be fixed
2022-02-21 11:47:35 +03:00
Sercan Yemen
b96182c848 (layouts/dense) Fixed: Navigation appearance doesn't set correctly on small devices 2022-01-14 11:36:38 +03:00
Sercan Yemen
443a103d6f (@fuse/masonry) Removed the unnecessary scss file 2022-01-14 11:35:41 +03:00
Sercan Yemen
42241b279d (@fuse/navigation) Expose the width variables as css custom properties, so they can be overridden from the outside
(@fuse/drawer) Expose the width variable as a css custom property, so it can be overridden from the outside
2022-01-14 11:35:12 +03:00
Sercan Yemen
e5eaea5013 Fixed: Typo on changelog 2022-01-01 23:05:09 +03:00
Sercan Yemen
6e85b9ff2a Fixed: Typo on changelog 2022-01-01 23:01:51 +03:00
Sercan Yemen
6e593b1f1e Updated version number and the changelog 2022-01-01 22:50:22 +03:00
Sercan Yemen
57a3f6ae99 Updated various packages 2022-01-01 22:47:49 +03:00
Sercan Yemen
700a117654 Moved to the new syntax on Tailwind config 2022-01-01 22:33:23 +03:00
Sercan Yemen
5337c95782 Fixed: Typo on resolve object 2022-01-01 22:32:39 +03:00
Sercan Yemen
964c4b23a9 Fixed: Accent and Warn colors are not being generated for themes other than the Default 2022-01-01 22:32:24 +03:00
Sercan Yemen
a8337ce617 Removed extra import 2021-12-22 14:36:30 +03:00
Sercan Yemen
3ceda2cf3f Removed extract-config plugin entry 2021-12-22 14:28:13 +03:00
Sercan Yemen
805b50707e Updated Angular to v13.1
Updated ESLint to v13
Updated Tailwind to v3
Updated various other packages
2021-12-22 14:19:21 +03:00
215 changed files with 8398 additions and 41603 deletions

View File

@@ -1,6 +1,11 @@
{ {
"$schema": "./node_modules/@angular/cli/lib/config/schema.json", "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1, "version": 1,
"cli": {
"schematicCollections": [
"@angular-eslint/schematics"
]
},
"newProjectRoot": "projects", "newProjectRoot": "projects",
"projects": { "projects": {
"fuse": { "fuse": {
@@ -136,9 +141,5 @@
} }
} }
} }
},
"defaultProject": "fuse",
"cli": {
"defaultCollection": "@angular-eslint/schematics"
} }
} }

15760
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "@fuse/demo", "name": "fuse-angular",
"version": "14.0.0", "version": "15.0.0",
"description": "Fuse - Angular Admin Template and Starter Project", "description": "Fuse - Angular Admin Template and Starter Project",
"author": "https://themeforest.net/user/srcn", "author": "https://themeforest.net/user/srcn",
"license": "https://themeforest.net/licenses/standard", "license": "https://themeforest.net/licenses/standard",
@@ -14,68 +14,67 @@
"lint": "ng lint" "lint": "ng lint"
}, },
"dependencies": { "dependencies": {
"@angular/animations": "13.0.1", "@angular/animations": "14.0.0",
"@angular/cdk": "13.0.0", "@angular/cdk": "14.0.0",
"@angular/common": "13.0.1", "@angular/common": "14.0.0",
"@angular/compiler": "13.0.1", "@angular/compiler": "14.0.0",
"@angular/core": "13.0.1", "@angular/core": "14.0.0",
"@angular/forms": "13.0.1", "@angular/forms": "14.0.0",
"@angular/material": "13.0.0", "@angular/material": "14.0.0",
"@angular/material-moment-adapter": "13.0.0", "@angular/material-moment-adapter": "14.0.0",
"@angular/platform-browser": "13.0.1", "@angular/platform-browser": "14.0.0",
"@angular/platform-browser-dynamic": "13.0.1", "@angular/platform-browser-dynamic": "14.0.0",
"@angular/router": "13.0.1", "@angular/router": "14.0.0",
"@ngneat/transloco": "3.1.0", "@ngneat/transloco": "4.0.0",
"apexcharts": "3.29.0", "apexcharts": "3.35.3",
"crypto-js": "3.3.0", "crypto-js": "3.3.0",
"highlight.js": "11.3.1", "highlight.js": "11.5.1",
"lodash-es": "4.17.21", "lodash-es": "4.17.21",
"moment": "2.29.1", "moment": "2.29.3",
"ng-apexcharts": "1.5.12", "ng-apexcharts": "1.7.1",
"ngx-markdown": "13.0.0", "ngx-markdown": "13.1.0",
"ngx-quill": "16.0.1", "ngx-quill": "17.0.0",
"perfect-scrollbar": "1.5.3", "perfect-scrollbar": "1.5.5",
"quill": "1.3.7", "quill": "1.3.7",
"rxjs": "7.4.0", "rxjs": "7.5.5",
"tslib": "2.3.1", "tslib": "2.4.0",
"zone.js": "0.11.4" "zone.js": "0.11.5"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "13.0.2", "@angular-devkit/build-angular": "14.0.0",
"@angular-eslint/builder": "12.6.1", "@angular-eslint/builder": "13.2.1",
"@angular-eslint/eslint-plugin": "12.6.1", "@angular-eslint/eslint-plugin": "13.2.1",
"@angular-eslint/eslint-plugin-template": "12.6.1", "@angular-eslint/eslint-plugin-template": "13.2.1",
"@angular-eslint/schematics": "12.6.1", "@angular-eslint/schematics": "13.2.1",
"@angular-eslint/template-parser": "12.6.1", "@angular-eslint/template-parser": "13.2.1",
"@angular/cli": "13.0.2", "@angular/cli": "14.0.0",
"@angular/compiler-cli": "13.0.1", "@angular/compiler-cli": "14.0.0",
"@tailwindcss/aspect-ratio": "0.3.0", "@tailwindcss/aspect-ratio": "0.4.0",
"@tailwindcss/line-clamp": "0.2.2", "@tailwindcss/line-clamp": "0.4.0",
"@tailwindcss/typography": "0.4.1", "@tailwindcss/typography": "0.5.2",
"@types/chroma-js": "2.1.3", "@types/chroma-js": "2.1.3",
"@types/crypto-js": "3.1.47", "@types/crypto-js": "3.1.47",
"@types/highlight.js": "10.1.0", "@types/highlight.js": "10.1.0",
"@types/jasmine": "3.10.2", "@types/jasmine": "4.0.3",
"@types/lodash": "4.14.176", "@types/lodash": "4.14.182",
"@types/lodash-es": "4.17.5", "@types/lodash-es": "4.17.6",
"@types/node": "12.20.37", "@typescript-eslint/eslint-plugin": "5.27.0",
"@typescript-eslint/eslint-plugin": "5.3.1", "@typescript-eslint/parser": "5.27.0",
"@typescript-eslint/parser": "5.3.1", "autoprefixer": "10.4.7",
"autoprefixer": "10.4.0", "chroma-js": "2.4.2",
"chroma-js": "2.1.2", "eslint": "8.16.0",
"eslint": "7.32.0", "eslint-plugin-import": "2.26.0",
"eslint-plugin-import": "2.25.3", "eslint-plugin-jsdoc": "39.3.2",
"eslint-plugin-jsdoc": "37.0.3",
"eslint-plugin-prefer-arrow": "1.2.3", "eslint-plugin-prefer-arrow": "1.2.3",
"jasmine-core": "3.10.1", "jasmine-core": "4.1.1",
"karma": "6.3.8", "karma": "6.3.20",
"karma-chrome-launcher": "3.1.0", "karma-chrome-launcher": "3.1.1",
"karma-coverage": "2.0.3", "karma-coverage": "2.2.0",
"karma-jasmine": "4.0.1", "karma-jasmine": "5.0.1",
"karma-jasmine-html-reporter": "1.7.0", "karma-jasmine-html-reporter": "1.7.0",
"lodash": "4.17.21", "lodash": "4.17.21",
"postcss": "8.3.11", "postcss": "8.4.14",
"tailwindcss": "2.2.19", "tailwindcss": "3.0.24",
"typescript": "4.4.4" "typescript": "4.7.2"
} }
} }

View File

@@ -53,6 +53,7 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
*/ */
@HostBinding('class') get classList(): any @HostBinding('class') get classList(): any
{ {
/* eslint-disable @typescript-eslint/naming-convention */
return { return {
'fuse-alert-appearance-border' : this.appearance === 'border', 'fuse-alert-appearance-border' : this.appearance === 'border',
'fuse-alert-appearance-fill' : this.appearance === 'fill', 'fuse-alert-appearance-fill' : this.appearance === 'fill',
@@ -70,6 +71,7 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
'fuse-alert-type-warning' : this.type === 'warning', 'fuse-alert-type-warning' : this.type === 'warning',
'fuse-alert-type-error' : this.type === 'error' 'fuse-alert-type-error' : this.type === 'error'
}; };
/* eslint-enable @typescript-eslint/naming-convention */
} }
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------

View File

@@ -38,12 +38,14 @@ export class FuseCardComponent implements OnChanges
*/ */
@HostBinding('class') get classList(): any @HostBinding('class') get classList(): any
{ {
/* eslint-disable @typescript-eslint/naming-convention */
return { return {
'fuse-card-expanded' : this.expanded, 'fuse-card-expanded' : this.expanded,
'fuse-card-face-back' : this.flippable && this.face === 'back', 'fuse-card-face-back' : this.flippable && this.face === 'back',
'fuse-card-face-front': this.flippable && this.face === 'front', 'fuse-card-face-front': this.flippable && this.face === 'front',
'fuse-card-flippable' : this.flippable 'fuse-card-flippable' : this.flippable
}; };
/* eslint-enable @typescript-eslint/naming-convention */
} }
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------

View File

@@ -1,14 +1,16 @@
/* Variables */ /* Variables */
$fuse-drawer-width: 320; :root {
--fuse-drawer-width: 320px;
}
fuse-drawer { fuse-drawer {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1 1 auto; flex: 1 1 auto;
width: #{$fuse-drawer-width}px; width: var(--fuse-drawer-width);
min-width: #{$fuse-drawer-width}px; min-width: var(--fuse-drawer-width);
max-width: #{$fuse-drawer-width}px; max-width: var(--fuse-drawer-width);
z-index: 300; z-index: 300;
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, .35); box-shadow: 0 2px 8px 0 rgba(0, 0, 0, .35);
@apply bg-card; @apply bg-card;
@@ -43,7 +45,7 @@ fuse-drawer {
/* Side mode */ /* Side mode */
&.fuse-drawer-mode-side { &.fuse-drawer-mode-side {
margin-left: -#{$fuse-drawer-width}px; margin-left: calc(var(--fuse-drawer-width) * -1);
&.fuse-drawer-opened { &.fuse-drawer-opened {
margin-left: 0; margin-left: 0;
@@ -71,7 +73,7 @@ fuse-drawer {
/* Side mode */ /* Side mode */
&.fuse-drawer-mode-side { &.fuse-drawer-mode-side {
margin-right: -#{$fuse-drawer-width}px; margin-right: calc(var(--fuse-drawer-width) * -1);
&.fuse-drawer-opened { &.fuse-drawer-opened {
margin-right: 0; margin-right: 0;

View File

@@ -32,6 +32,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
@Output() readonly positionChanged: EventEmitter<FuseDrawerPosition> = new EventEmitter<FuseDrawerPosition>(); @Output() readonly positionChanged: EventEmitter<FuseDrawerPosition> = new EventEmitter<FuseDrawerPosition>();
private _animationsEnabled: boolean = false; private _animationsEnabled: boolean = false;
private readonly _handleOverlayClick: any;
private _hovered: boolean = false; private _hovered: boolean = false;
private _overlay: HTMLElement; private _overlay: HTMLElement;
private _player: AnimationPlayer; private _player: AnimationPlayer;
@@ -47,6 +48,9 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
private _fuseUtilsService: FuseUtilsService private _fuseUtilsService: FuseUtilsService
) )
{ {
this._handleOverlayClick = (): void => {
this.close();
};
} }
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------
@@ -58,6 +62,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
*/ */
@HostBinding('class') get classList(): any @HostBinding('class') get classList(): any
{ {
/* eslint-disable @typescript-eslint/naming-convention */
return { return {
'fuse-drawer-animations-enabled' : this._animationsEnabled, 'fuse-drawer-animations-enabled' : this._animationsEnabled,
'fuse-drawer-fixed' : this.fixed, 'fuse-drawer-fixed' : this.fixed,
@@ -66,6 +71,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
'fuse-drawer-opened' : this.opened, 'fuse-drawer-opened' : this.opened,
[`fuse-drawer-position-${this.position}`]: true [`fuse-drawer-position-${this.position}`]: true
}; };
/* eslint-enable @typescript-eslint/naming-convention */
} }
/** /**
@@ -318,12 +324,6 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
// Create the backdrop element // Create the backdrop element
this._overlay = this._renderer2.createElement('div'); this._overlay = this._renderer2.createElement('div');
// Return if overlay couldn't be create for some reason
if ( !this._overlay )
{
return;
}
// Add a class to the backdrop element // Add a class to the backdrop element
this._overlay.classList.add('fuse-drawer-overlay'); this._overlay.classList.add('fuse-drawer-overlay');
@@ -342,27 +342,17 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
// Append the backdrop to the parent of the drawer // Append the backdrop to the parent of the drawer
this._renderer2.appendChild(this._elementRef.nativeElement.parentElement, this._overlay); this._renderer2.appendChild(this._elementRef.nativeElement.parentElement, this._overlay);
// Create the enter animation and attach it to the player // Create enter animation and attach it to the player
this._player = this._animationBuilder.build([ this._player = this._animationBuilder.build([
style({opacity: 0}), style({opacity: 0}),
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({opacity: 1})) animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({opacity: 1}))
]).create(this._overlay); ]).create(this._overlay);
// Once the animation is done...
this._player.onDone(() => {
// Destroy the player
this._player.destroy();
this._player = null;
});
// Play the animation // Play the animation
this._player.play(); this._player.play();
// Add an event listener to the overlay // Add an event listener to the overlay
this._overlay.addEventListener('click', () => { this._overlay.addEventListener('click', this._handleOverlayClick);
this.close();
});
} }
/** /**
@@ -388,14 +378,13 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
// Once the animation is done... // Once the animation is done...
this._player.onDone(() => { this._player.onDone(() => {
// Destroy the player // If the overlay still exists...
this._player.destroy();
this._player = null;
// If the backdrop still exists...
if ( this._overlay ) if ( this._overlay )
{ {
// Remove the backdrop // Remove the event listener
this._overlay.removeEventListener('click', this._handleOverlayClick);
// Remove the overlay
this._overlay.parentNode.removeChild(this._overlay); this._overlay.parentNode.removeChild(this._overlay);
this._overlay = null; this._overlay = null;
} }

View File

@@ -5,7 +5,6 @@ import { FuseMediaWatcherService } from '@fuse/services/media-watcher';
@Component({ @Component({
selector : 'fuse-masonry', selector : 'fuse-masonry',
templateUrl : './masonry.component.html', templateUrl : './masonry.component.html',
styleUrls : ['./masonry.component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
animations : fuseAnimations, animations : fuseAnimations,
exportAs : 'fuseMasonry' exportAs : 'fuseMasonry'

View File

@@ -10,6 +10,10 @@
class="fuse-horizontal-navigation-item" class="fuse-horizontal-navigation-item"
[ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}" [ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}"
[routerLink]="[item.link]" [routerLink]="[item.link]"
[fragment]="item.fragment ?? null"
[preserveFragment]="item.preserveFragment ?? false"
[queryParams]="item.queryParams ?? null"
[queryParamsHandling]="item.queryParamsHandling ?? null"
[routerLinkActive]="'fuse-horizontal-navigation-item-active'" [routerLinkActive]="'fuse-horizontal-navigation-item-active'"
[routerLinkActiveOptions]="isActiveMatchOptions" [routerLinkActiveOptions]="isActiveMatchOptions"
[matTooltip]="item.tooltip || ''"> [matTooltip]="item.tooltip || ''">
@@ -45,6 +49,10 @@
class="fuse-horizontal-navigation-item" class="fuse-horizontal-navigation-item"
[ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}" [ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}"
[routerLink]="[item.link]" [routerLink]="[item.link]"
[fragment]="item.fragment ?? null"
[preserveFragment]="item.preserveFragment ?? false"
[queryParams]="item.queryParams ?? null"
[queryParamsHandling]="item.queryParamsHandling ?? null"
[routerLinkActive]="'fuse-horizontal-navigation-item-active'" [routerLinkActive]="'fuse-horizontal-navigation-item-active'"
[routerLinkActiveOptions]="isActiveMatchOptions" [routerLinkActiveOptions]="isActiveMatchOptions"
[matTooltip]="item.tooltip || ''" [matTooltip]="item.tooltip || ''"

View File

@@ -1,4 +1,4 @@
import { IsActiveMatchOptions } from '@angular/router'; import { IsActiveMatchOptions, Params, QueryParamsHandling } from '@angular/router';
export interface FuseNavigationItem export interface FuseNavigationItem
{ {
@@ -17,6 +17,10 @@ export interface FuseNavigationItem
disabled?: boolean; disabled?: boolean;
tooltip?: string; tooltip?: string;
link?: string; link?: string;
fragment?: string;
preserveFragment?: boolean;
queryParams?: Params | null;
queryParamsHandling?: QueryParamsHandling | null;
externalLink?: boolean; externalLink?: boolean;
target?: target?:
| '_blank' | '_blank'

View File

@@ -10,6 +10,10 @@
class="fuse-vertical-navigation-item" class="fuse-vertical-navigation-item"
[ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}" [ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}"
[routerLink]="[item.link]" [routerLink]="[item.link]"
[fragment]="item.fragment ?? null"
[preserveFragment]="item.preserveFragment ?? false"
[queryParams]="item.queryParams ?? null"
[queryParamsHandling]="item.queryParamsHandling ?? null"
[routerLinkActive]="'fuse-vertical-navigation-item-active'" [routerLinkActive]="'fuse-vertical-navigation-item-active'"
[routerLinkActiveOptions]="isActiveMatchOptions" [routerLinkActiveOptions]="isActiveMatchOptions"
[matTooltip]="item.tooltip || ''"> [matTooltip]="item.tooltip || ''">
@@ -45,6 +49,10 @@
class="fuse-vertical-navigation-item" class="fuse-vertical-navigation-item"
[ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}" [ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}"
[routerLink]="[item.link]" [routerLink]="[item.link]"
[fragment]="item.fragment ?? null"
[preserveFragment]="item.preserveFragment ?? false"
[queryParams]="item.queryParams ?? null"
[queryParamsHandling]="item.queryParamsHandling ?? null"
[routerLinkActive]="'fuse-vertical-navigation-item-active'" [routerLinkActive]="'fuse-vertical-navigation-item-active'"
[routerLinkActiveOptions]="isActiveMatchOptions" [routerLinkActiveOptions]="isActiveMatchOptions"
[matTooltip]="item.tooltip || ''" [matTooltip]="item.tooltip || ''"

View File

@@ -48,10 +48,12 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
*/ */
@HostBinding('class') get classList(): any @HostBinding('class') get classList(): any
{ {
/* eslint-disable @typescript-eslint/naming-convention */
return { return {
'fuse-vertical-navigation-item-collapsed': this.isCollapsed, 'fuse-vertical-navigation-item-collapsed': this.isCollapsed,
'fuse-vertical-navigation-item-expanded' : this.isExpanded 'fuse-vertical-navigation-item-expanded' : this.isExpanded
}; };
/* eslint-enable @typescript-eslint/naming-convention */
} }
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------

View File

@@ -1,20 +1,22 @@
/* Variables */ /* Variables */
$fuse-vertical-navigation-compact-width: 112px; :root {
--fuse-vertical-navigation-compact-width: 112px;
}
fuse-vertical-navigation { fuse-vertical-navigation {
/* Compact appearance overrides */ /* Compact appearance overrides */
&.fuse-vertical-navigation-appearance-compact { &.fuse-vertical-navigation-appearance-compact {
width: $fuse-vertical-navigation-compact-width; width: var(--fuse-vertical-navigation-compact-width);
min-width: $fuse-vertical-navigation-compact-width; min-width: var(--fuse-vertical-navigation-compact-width);
max-width: $fuse-vertical-navigation-compact-width; max-width: var(--fuse-vertical-navigation-compact-width);
/* Left positioned */ /* Left positioned */
&.fuse-vertical-navigation-position-left { &.fuse-vertical-navigation-position-left {
/* Side mode */ /* Side mode */
&.fuse-vertical-navigation-mode-side { &.fuse-vertical-navigation-mode-side {
margin-left: -$fuse-vertical-navigation-compact-width; margin-left: calc(var(--fuse-vertical-navigation-compact-width) * -1);
} }
/* Opened */ /* Opened */
@@ -28,7 +30,7 @@ fuse-vertical-navigation {
/* Side mode */ /* Side mode */
&.fuse-vertical-navigation-mode-side { &.fuse-vertical-navigation-mode-side {
margin-right: -$fuse-vertical-navigation-compact-width; margin-right: calc(var(--fuse-vertical-navigation-compact-width) * -1);
} }
/* Opened */ /* Opened */
@@ -39,7 +41,7 @@ fuse-vertical-navigation {
/* Aside wrapper */ /* Aside wrapper */
.fuse-vertical-navigation-aside-wrapper { .fuse-vertical-navigation-aside-wrapper {
left: auto; left: auto;
right: $fuse-vertical-navigation-compact-width; right: var(--fuse-vertical-navigation-compact-width);
} }
} }
@@ -104,7 +106,7 @@ fuse-vertical-navigation {
/* Aside wrapper */ /* Aside wrapper */
.fuse-vertical-navigation-aside-wrapper { .fuse-vertical-navigation-aside-wrapper {
left: $fuse-vertical-navigation-compact-width; left: var(--fuse-vertical-navigation-compact-width);
} }
} }
} }

View File

@@ -1,5 +1,7 @@
/* Variables */ /* Variables */
$fuse-vertical-navigation-width: 280px; :root {
--fuse-vertical-navigation-width: 280px;
}
fuse-vertical-navigation { fuse-vertical-navigation {
position: sticky; position: sticky;
@@ -7,9 +9,9 @@ fuse-vertical-navigation {
flex-direction: column; flex-direction: column;
flex: 1 0 auto; flex: 1 0 auto;
top: 0; top: 0;
width: $fuse-vertical-navigation-width; width: var(--fuse-vertical-navigation-width);
min-width: $fuse-vertical-navigation-width; min-width: var(--fuse-vertical-navigation-width);
max-width: $fuse-vertical-navigation-width; max-width: var(--fuse-vertical-navigation-width);
height: 100vh; height: 100vh;
min-height: 100vh; min-height: 100vh;
max-height: 100vh; max-height: 100vh;
@@ -45,7 +47,7 @@ fuse-vertical-navigation {
/* Side mode */ /* Side mode */
&.fuse-vertical-navigation-mode-side { &.fuse-vertical-navigation-mode-side {
margin-left: -$fuse-vertical-navigation-width; margin-left: calc(#{var(--fuse-vertical-navigation-width)} * -1);
&.fuse-vertical-navigation-opened { &.fuse-vertical-navigation-opened {
margin-left: 0; margin-left: 0;
@@ -73,7 +75,7 @@ fuse-vertical-navigation {
/* Side mode */ /* Side mode */
&.fuse-vertical-navigation-mode-side { &.fuse-vertical-navigation-mode-side {
margin-right: -$fuse-vertical-navigation-width; margin-right: calc(var(--fuse-vertical-navigation-width) * -1);
&.fuse-vertical-navigation-opened { &.fuse-vertical-navigation-opened {
margin-right: 0; margin-right: 0;
@@ -170,8 +172,8 @@ fuse-vertical-navigation {
flex-direction: column; flex-direction: column;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: $fuse-vertical-navigation-width; left: var(--fuse-vertical-navigation-width);
width: $fuse-vertical-navigation-width; width: var(--fuse-vertical-navigation-width);
height: 100%; height: 100%;
z-index: 5; z-index: 5;
overflow-x: hidden; overflow-x: hidden;
@@ -196,7 +198,7 @@ fuse-vertical-navigation {
.fuse-vertical-navigation-aside-wrapper { .fuse-vertical-navigation-aside-wrapper {
left: auto; left: auto;
right: $fuse-vertical-navigation-width; right: var(--fuse-vertical-navigation-width);
} }
} }
@@ -335,7 +337,10 @@ fuse-vertical-navigation {
} }
> .fuse-vertical-navigation-item-children { > .fuse-vertical-navigation-item-children {
margin-top: 6px;
> *:first-child {
margin-top: 6px;
}
> *:last-child { > *:last-child {
padding-bottom: 6px; padding-bottom: 6px;

View File

@@ -1,6 +1,8 @@
/* Variables */ /* Variables */
$fuse-vertical-navigation-width: 280px; :root {
$fuse-vertical-navigation-dense-width: 80px; --fuse-vertical-navigation-width: 280px;
--fuse-vertical-navigation-dense-width: 80px;
}
fuse-vertical-navigation { fuse-vertical-navigation {
@@ -8,16 +10,16 @@ fuse-vertical-navigation {
&.fuse-vertical-navigation-appearance-dense { &.fuse-vertical-navigation-appearance-dense {
&:not(.fuse-vertical-navigation-mode-over) { &:not(.fuse-vertical-navigation-mode-over) {
width: $fuse-vertical-navigation-dense-width; width: var(--fuse-vertical-navigation-dense-width);
min-width: $fuse-vertical-navigation-dense-width; min-width: var(--fuse-vertical-navigation-dense-width);
max-width: $fuse-vertical-navigation-dense-width; max-width: var(--fuse-vertical-navigation-dense-width);
/* Left positioned */ /* Left positioned */
&.fuse-vertical-navigation-position-left { &.fuse-vertical-navigation-position-left {
/* Side mode */ /* Side mode */
&.fuse-vertical-navigation-mode-side { &.fuse-vertical-navigation-mode-side {
margin-left: -$fuse-vertical-navigation-dense-width; margin-left: calc(var(--fuse-vertical-navigation-dense-width) * -1);
} }
/* Opened */ /* Opened */
@@ -31,7 +33,7 @@ fuse-vertical-navigation {
/* Side mode */ /* Side mode */
&.fuse-vertical-navigation-mode-side { &.fuse-vertical-navigation-mode-side {
margin-right: -$fuse-vertical-navigation-dense-width; margin-right: calc(var(--fuse-vertical-navigation-dense-width) * -1);
} }
/* Opened */ /* Opened */
@@ -42,14 +44,14 @@ fuse-vertical-navigation {
/* Aside wrapper */ /* Aside wrapper */
.fuse-vertical-navigation-aside-wrapper { .fuse-vertical-navigation-aside-wrapper {
left: auto; left: auto;
right: $fuse-vertical-navigation-dense-width; right: var(--fuse-vertical-navigation-dense-width);
} }
&.fuse-vertical-navigation-hover { &.fuse-vertical-navigation-hover {
.fuse-vertical-navigation-aside-wrapper { .fuse-vertical-navigation-aside-wrapper {
left: auto; left: auto;
right: $fuse-vertical-navigation-width; right: var(--fuse-vertical-navigation-width);
} }
} }
} }
@@ -69,9 +71,9 @@ fuse-vertical-navigation {
.fuse-vertical-navigation-item-wrapper { .fuse-vertical-navigation-item-wrapper {
.fuse-vertical-navigation-item { .fuse-vertical-navigation-item {
width: $fuse-vertical-navigation-dense-width - 24px; width: calc(var(--fuse-vertical-navigation-dense-width) - 24px);
min-width: $fuse-vertical-navigation-dense-width - 24px; min-width: calc(var(--fuse-vertical-navigation-dense-width) - 24px);
max-width: $fuse-vertical-navigation-dense-width - 24px; max-width: calc(var(--fuse-vertical-navigation-dense-width) - 24px);
.fuse-vertical-navigation-item-arrow, .fuse-vertical-navigation-item-arrow,
.fuse-vertical-navigation-item-badge, .fuse-vertical-navigation-item-badge,
@@ -142,23 +144,23 @@ fuse-vertical-navigation {
/* Aside wrapper */ /* Aside wrapper */
.fuse-vertical-navigation-aside-wrapper { .fuse-vertical-navigation-aside-wrapper {
left: $fuse-vertical-navigation-dense-width; left: var(--fuse-vertical-navigation-dense-width);
} }
/* Hover */ /* Hover */
&.fuse-vertical-navigation-hover { &.fuse-vertical-navigation-hover {
.fuse-vertical-navigation-wrapper { .fuse-vertical-navigation-wrapper {
width: $fuse-vertical-navigation-width; width: var(--fuse-vertical-navigation-width);
.fuse-vertical-navigation-content { .fuse-vertical-navigation-content {
.fuse-vertical-navigation-item-wrapper { .fuse-vertical-navigation-item-wrapper {
.fuse-vertical-navigation-item { .fuse-vertical-navigation-item {
width: $fuse-vertical-navigation-width - 24px; width: calc(var(--fuse-vertical-navigation-width) - 24px);
min-width: $fuse-vertical-navigation-width - 24px; min-width: calc(var(--fuse-vertical-navigation-width) - 24px);
max-width: $fuse-vertical-navigation-width - 24px; max-width: calc(var(--fuse-vertical-navigation-width) - 24px);
.fuse-vertical-navigation-item-arrow, .fuse-vertical-navigation-item-arrow,
.fuse-vertical-navigation-item-badge, .fuse-vertical-navigation-item-badge,
@@ -173,7 +175,7 @@ fuse-vertical-navigation {
} }
.fuse-vertical-navigation-aside-wrapper { .fuse-vertical-navigation-aside-wrapper {
left: $fuse-vertical-navigation-width; left: var(--fuse-vertical-navigation-width);
} }
} }
} }

View File

@@ -1,19 +1,21 @@
/* Variables */ /* Variables */
$fuse-vertical-navigation-thin-width: 80px; :root {
--fuse-vertical-navigation-thin-width: 80px;
}
fuse-vertical-navigation { fuse-vertical-navigation {
/* Thin appearance overrides */ /* Thin appearance overrides */
&.fuse-vertical-navigation-appearance-thin { &.fuse-vertical-navigation-appearance-thin {
width: $fuse-vertical-navigation-thin-width; width: var(--fuse-vertical-navigation-thin-width);
min-width: $fuse-vertical-navigation-thin-width; min-width: var(--fuse-vertical-navigation-thin-width);
max-width: $fuse-vertical-navigation-thin-width; max-width: var(--fuse-vertical-navigation-thin-width);
/* Left positioned */ /* Left positioned */
&.fuse-vertical-navigation-position-left { &.fuse-vertical-navigation-position-left {
&.fuse-vertical-navigation-mode-side { &.fuse-vertical-navigation-mode-side {
margin-left: -$fuse-vertical-navigation-thin-width; margin-left: calc(var(--fuse-vertical-navigation-thin-width) * -1);
} }
&.fuse-vertical-navigation-opened { &.fuse-vertical-navigation-opened {
@@ -25,7 +27,7 @@ fuse-vertical-navigation {
&.fuse-vertical-navigation-position-right { &.fuse-vertical-navigation-position-right {
&.fuse-vertical-navigation-mode-side { &.fuse-vertical-navigation-mode-side {
margin-right: -$fuse-vertical-navigation-thin-width; margin-right: calc(var(--fuse-vertical-navigation-thin-width) * -1);
} }
&.fuse-vertical-navigation-opened { &.fuse-vertical-navigation-opened {
@@ -34,7 +36,7 @@ fuse-vertical-navigation {
.fuse-vertical-navigation-aside-wrapper { .fuse-vertical-navigation-aside-wrapper {
left: auto; left: auto;
right: $fuse-vertical-navigation-thin-width; right: var(--fuse-vertical-navigation-thin-width);
} }
} }
@@ -91,7 +93,7 @@ fuse-vertical-navigation {
/* Aside wrapper */ /* Aside wrapper */
.fuse-vertical-navigation-aside-wrapper { .fuse-vertical-navigation-aside-wrapper {
left: $fuse-vertical-navigation-thin-width; left: var(--fuse-vertical-navigation-thin-width);
} }
} }
} }

View File

@@ -1,4 +1,4 @@
@import 'styles/appearances/default'; @use 'styles/appearances/default';
@import 'styles/appearances/compact'; @use 'styles/appearances/compact';
@import 'styles/appearances/dense'; @use 'styles/appearances/dense';
@import 'styles/appearances/thin'; @use 'styles/appearances/thin';

View File

@@ -89,6 +89,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
*/ */
@HostBinding('class') get classList(): any @HostBinding('class') get classList(): any
{ {
/* eslint-disable @typescript-eslint/naming-convention */
return { return {
'fuse-vertical-navigation-animations-enabled' : this._animationsEnabled, 'fuse-vertical-navigation-animations-enabled' : this._animationsEnabled,
[`fuse-vertical-navigation-appearance-${this.appearance}`]: true, [`fuse-vertical-navigation-appearance-${this.appearance}`]: true,
@@ -100,6 +101,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
'fuse-vertical-navigation-position-left' : this.position === 'left', 'fuse-vertical-navigation-position-left' : this.position === 'left',
'fuse-vertical-navigation-position-right' : this.position === 'right' 'fuse-vertical-navigation-position-right' : this.position === 'right'
}; };
/* eslint-enable @typescript-eslint/naming-convention */
} }
/** /**

View File

@@ -4,8 +4,8 @@ import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
import { FuseConfirmationModule } from '@fuse/services/confirmation'; import { FuseConfirmationModule } from '@fuse/services/confirmation';
import { FuseLoadingModule } from '@fuse/services/loading'; import { FuseLoadingModule } from '@fuse/services/loading';
import { FuseMediaWatcherModule } from '@fuse/services/media-watcher/media-watcher.module'; import { FuseMediaWatcherModule } from '@fuse/services/media-watcher/media-watcher.module';
import { FusePlatformModule } from '@fuse/services/platform/platform.module';
import { FuseSplashScreenModule } from '@fuse/services/splash-screen/splash-screen.module'; import { FuseSplashScreenModule } from '@fuse/services/splash-screen/splash-screen.module';
import { FuseTailwindConfigModule } from '@fuse/services/tailwind/tailwind.module';
import { FuseUtilsModule } from '@fuse/services/utils/utils.module'; import { FuseUtilsModule } from '@fuse/services/utils/utils.module';
@NgModule({ @NgModule({
@@ -13,8 +13,8 @@ import { FuseUtilsModule } from '@fuse/services/utils/utils.module';
FuseConfirmationModule, FuseConfirmationModule,
FuseLoadingModule, FuseLoadingModule,
FuseMediaWatcherModule, FuseMediaWatcherModule,
FusePlatformModule,
FuseSplashScreenModule, FuseSplashScreenModule,
FuseTailwindConfigModule,
FuseUtilsModule FuseUtilsModule
], ],
providers: [ providers: [

View File

@@ -35,6 +35,7 @@ export class FuseConfigService
this._config.next(config); this._config.next(config);
} }
// eslint-disable-next-line @typescript-eslint/member-ordering
get config$(): Observable<any> get config$(): Observable<any>
{ {
return this._config.asObservable(); return this._config.asObservable();

View File

@@ -1,12 +1,11 @@
import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, Inject, ViewEncapsulation } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { FuseConfirmationConfig } from '@fuse/services/confirmation/confirmation.types'; import { FuseConfirmationConfig } from '@fuse/services/confirmation/confirmation.types';
@Component({ @Component({
selector : 'fuse-confirmation-dialog', selector : 'fuse-confirmation-dialog',
templateUrl : './dialog.component.html', templateUrl : './dialog.component.html',
styles : [ styles : [
/* language=SCSS */
` `
.fuse-confirmation-dialog-panel { .fuse-confirmation-dialog-panel {
@screen md { @screen md {
@@ -21,32 +20,13 @@ import { FuseConfirmationConfig } from '@fuse/services/confirmation/confirmation
], ],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class FuseConfirmationDialogComponent implements OnInit export class FuseConfirmationDialogComponent
{ {
/** /**
* Constructor * Constructor
*/ */
constructor( constructor(@Inject(MAT_DIALOG_DATA) public data: FuseConfirmationConfig)
@Inject(MAT_DIALOG_DATA) public data: FuseConfirmationConfig,
public matDialogRef: MatDialogRef<FuseConfirmationDialogComponent>
)
{ {
} }
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
} }

View File

@@ -1,7 +1,8 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout'; import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
import { map, Observable, ReplaySubject, switchMap } from 'rxjs'; import { map, Observable, ReplaySubject, switchMap } from 'rxjs';
import { FuseTailwindService } from '@fuse/services/tailwind/tailwind.service'; import { fromPairs } from 'lodash-es';
import { FuseConfigService } from '@fuse/services/config';
@Injectable() @Injectable()
export class FuseMediaWatcherService export class FuseMediaWatcherService
@@ -13,11 +14,12 @@ export class FuseMediaWatcherService
*/ */
constructor( constructor(
private _breakpointObserver: BreakpointObserver, private _breakpointObserver: BreakpointObserver,
private _fuseTailwindConfigService: FuseTailwindService private _fuseConfigService: FuseConfigService
) )
{ {
this._fuseTailwindConfigService.tailwindConfig$.pipe( this._fuseConfigService.config$.pipe(
switchMap(config => this._breakpointObserver.observe(Object.values(config.breakpoints)).pipe( map(config => fromPairs(Object.entries(config.screens).map(([alias, screen]) => ([alias, `(min-width: ${screen})`])))),
switchMap(screens => this._breakpointObserver.observe(Object.values(screens)).pipe(
map((state) => { map((state) => {
// Prepare the observable values and set their defaults // Prepare the observable values and set their defaults
@@ -29,7 +31,7 @@ export class FuseMediaWatcherService
for ( const [query] of matchingBreakpoints ) for ( const [query] of matchingBreakpoints )
{ {
// Find the alias of the matching query // Find the alias of the matching query
const matchingAlias = Object.entries(config.breakpoints).find(([alias, q]) => q === query)[0]; const matchingAlias = Object.entries(screens).find(([alias, q]) => q === query)[0];
// Add the matching query to the observable values // Add the matching query to the observable values
if ( matchingAlias ) if ( matchingAlias )

View File

@@ -0,0 +1 @@
export * from '@fuse/services/platform/public-api';

View File

@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { FusePlatformService } from '@fuse/services/platform/platform.service';
@NgModule({
providers: [
FusePlatformService
]
})
export class FusePlatformModule
{
/**
* Constructor
*/
constructor(private _fusePlatformService: FusePlatformService)
{
}
}

View File

@@ -0,0 +1,59 @@
import { Injectable } from '@angular/core';
import { Platform } from '@angular/cdk/platform';
@Injectable({
providedIn: 'root'
})
export class FusePlatformService
{
osName = 'os-unknown';
/**
* Constructor
*/
constructor(private _platform: Platform)
{
// If the platform is not a browser, return immediately
if ( !this._platform.isBrowser )
{
return;
}
// Windows
if ( navigator.userAgent.includes('Win') )
{
this.osName = 'os-windows';
}
// Mac OS
if ( navigator.userAgent.includes('Mac') )
{
this.osName = 'os-mac';
}
// Unix
if ( navigator.userAgent.includes('X11') )
{
this.osName = 'os-unix';
}
// Linux
if ( navigator.userAgent.includes('Linux') )
{
this.osName = 'os-linux';
}
// iOS
if ( this._platform.IOS )
{
this.osName = 'os-ios';
}
// Android
if ( this._platform.ANDROID )
{
this.osName = 'os-android';
}
}
}

View File

@@ -0,0 +1 @@
export * from '@fuse/services/platform/platform.service';

View File

@@ -1 +0,0 @@
export * from '@fuse/services/tailwind/public-api';

View File

@@ -1,2 +0,0 @@
export * from '@fuse/services/tailwind/tailwind.module';
export * from '@fuse/services/tailwind/tailwind.service';

View File

@@ -1,17 +0,0 @@
import { NgModule } from '@angular/core';
import { FuseTailwindService } from '@fuse/services/tailwind/tailwind.service';
@NgModule({
providers: [
FuseTailwindService
]
})
export class FuseTailwindConfigModule
{
/**
* Constructor
*/
constructor(private _fuseTailwindConfigService: FuseTailwindService)
{
}
}

View File

@@ -1,58 +0,0 @@
import { Injectable } from '@angular/core';
import { Observable, ReplaySubject } from 'rxjs';
import { fromPairs, map } from 'lodash-es';
import * as extractedTailwindConfigStyle from '@fuse/styles/core/tailwind-config.scss';
@Injectable()
export class FuseTailwindService
{
private _tailwindConfig: ReplaySubject<any> = new ReplaySubject<any>(1);
/**
* Constructor
*/
constructor()
{
// Prepare the config object
const config: any = {};
// Extract the style from the class
const regexpForClass = /\.fuse-tailwind-extracted-config\s\{([\s\S]*)\}/g;
const style = regexpForClass.exec(extractedTailwindConfigStyle.default)[1].trim();
// Extract the rules
const regexp = /(--[\s\S]*?):'([\s\S]*?)';/g;
let rules = regexp.exec(style);
// Add to the config
while ( rules !== null )
{
const configGroup = /--([\s\S]*?)-/g.exec(rules[1])[1];
if ( !config[configGroup] )
{
config[configGroup] = {};
}
config[configGroup][rules[1].replace(/(--[\s\S]*?-)/g, '')] = rules[2];
rules = regexp.exec(style);
}
// Parse the themes objects
config.themes = fromPairs(map(config.themes, (value, key) => [key, JSON.parse(value)]));
// Execute the observable with the config
this._tailwindConfig.next(config);
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Getter for _tailwindConfig
*/
get tailwindConfig$(): Observable<any>
{
return this._tailwindConfig.asObservable();
}
}

View File

@@ -1,6 +0,0 @@
/* ----------------------------------------------------------------------------------------------------- */
/* @ Any configuration we need from Tailwind's config file will be extracted here so we can import this
/* @ file from "config.ts" to access the extracted configuration from TypeScript
/* ----------------------------------------------------------------------------------------------------- */
@variants fuse-tailwind-extracted-config {
}

View File

@@ -1,12 +1,9 @@
/* 1. Core */ /* 1. Components */
@import 'core/tailwind-config'; @use 'components/example-viewer';
@use 'components/input';
/* 2. Components */ /* 2. Overrides */
@import 'components/example-viewer'; @use 'overrides/angular-material';
@import 'components/input'; @use 'overrides/highlightjs';
@use 'overrides/perfect-scrollbar';
/* 3. Overrides */ @use 'overrides/quill';
@import 'overrides/angular-material';
@import 'overrides/highlightjs';
@import 'overrides/perfect-scrollbar';
@import 'overrides/quill';

View File

@@ -80,7 +80,9 @@
} }
.ql-container { .ql-container {
overflow: hidden; overflow: auto;
min-height: 160px;
max-height: 400px;
border-radius: 0 0 6px 6px; border-radius: 0 0 6px 6px;
@apply border-gray-300 border-opacity-100 shadow-sm #{'!important'}; @apply border-gray-300 border-opacity-100 shadow-sm #{'!important'};
@@ -89,17 +91,52 @@
} }
.ql-editor { .ql-editor {
min-height: 160px;
max-height: 160px;
height: 160px;
@apply bg-card; @apply bg-card;
.dark & { .dark & {
background-color: rgba(0, 0, 0, 0.05); //background-color: rgba(0, 0, 0, 0.05);
} }
&.ql-blank::before { &.ql-blank::before {
@apply text-hint; @apply text-hint;
} }
} }
.ql-tooltip {
@apply px-3 py-1 shadow-sm rounded-md bg-gray-100 border-gray-300;
.dark & {
@apply shadow-lg bg-gray-700 border-gray-700 #{'!important'};
}
// Label
&:before {
@apply text-secondary;
}
.ql-action,
.ql-remove {
@apply text-primary border-gray-300;
.dark & {
@apply text-primary-400 border-gray-300;
}
}
.ql-action:after {
@apply border-r border-r-gray-300 #{'!important'};
.dark & {
@apply border-r-gray-500 #{'!important'};
}
}
input {
@apply rounded-sm text-default bg-white border-gray-300 #{'!important'};
.dark & {
@apply bg-gray-700 border-gray-500 #{'!important'};
}
}
}
} }

View File

@@ -76,6 +76,46 @@
} }
} }
/* Style scrollbars on platforms other than MacOS and iOS */
@media only screen and (min-width: 960px) {
body:not(.os-mac) {
::-webkit-scrollbar {
width: 8px;
height: 8px;
background-color: rgba(0, 0, 0, 0);
}
::-webkit-scrollbar:hover {
width: 8px;
height: 8px;
background-color: rgba(0, 0, 0, 0.06);
}
::-webkit-scrollbar-thumb {
border: 2px solid transparent;
border-radius: 20px;
box-shadow: inset 0 0 0 20px rgba(0, 0, 0, 0.24);
}
::-webkit-scrollbar-thumb:active {
border-radius: 20px;
box-shadow: inset 0 0 0 20px rgba(0, 0, 0, 0.37);
}
&.dark {
::-webkit-scrollbar-thumb {
box-shadow: inset 0 0 0 20px rgba(255, 255, 255, 0.24);
}
::-webkit-scrollbar-thumb:active {
box-shadow: inset 0 0 0 20px rgba(255, 255, 255, 0.37);
}
}
}
}
[disabled] * { [disabled] * {
@apply text-disabled #{'!important'}; @apply text-disabled #{'!important'};
} }

View File

@@ -72,38 +72,38 @@ body .light {
is-dark: map.get(map.get($base-light-theme, color), is-dark), is-dark: map.get(map.get($base-light-theme, color), is-dark),
foreground: ( foreground: (
base: #000000, base: #000000,
divider: #E2E8F0, /* blueGray.200 */ divider: #E2E8F0, /* slate.200 */
dividers: #E2E8F0, /* blueGray.200 */ dividers: #E2E8F0, /* slate.200 */
disabled: #94A3B8, /* blueGray.400 */ disabled: #94A3B8, /* slate.400 */
disabled-button: #94A3B8, /* blueGray.400 */ disabled-button: #94A3B8, /* slate.400 */
disabled-text: #94A3B8, /* blueGray.400 */ disabled-text: #94A3B8, /* slate.400 */
elevation: #000000, elevation: #000000,
hint-text: #94A3B8, /* blueGray.400 */ hint-text: #94A3B8, /* slate.400 */
secondary-text: #64748B, /* blueGray.500 */ secondary-text: #64748B, /* slate.500 */
icon: #64748B, /* blueGray.500 */ icon: #64748B, /* slate.500 */
icons: #64748B, /* blueGray.500 */ icons: #64748B, /* slate.500 */
mat-icon: #64748B, /* blueGray.500 */ mat-icon: #64748B, /* slate.500 */
text: #1E293B, /* blueGray.800 */ text: #1E293B, /* slate.800 */
slider-min: #1E293B, /* blueGray.800 */ slider-min: #1E293B, /* slate.800 */
slider-off: #CBD5E1, /* blueGray.300 */ slider-off: #CBD5E1, /* slate.300 */
slider-off-active: #94A3B8 /* blueGray.400 */ slider-off-active: #94A3B8 /* slate.400 */
), ),
background: ( background: (
status-bar: #CBD5E1, /* blueGray.300 */ status-bar: #CBD5E1, /* slate.300 */
app-bar: #FFFFFF, app-bar: #FFFFFF,
background: #F1F5F9, /* blueGray.100 */ background: #F1F5F9, /* slate.100 */
hover: rgba(148, 163, 184, 0.12), /* blueGray.400 + opacity */ hover: rgba(148, 163, 184, 0.12), /* slate.400 + opacity */
card: #FFFFFF, card: #FFFFFF,
dialog: #FFFFFF, dialog: #FFFFFF,
disabled-button: rgba(148, 163, 184, 0.38), /* blueGray.400 + opacity */ disabled-button: rgba(148, 163, 184, 0.38), /* slate.400 + opacity */
raised-button: #FFFFFF, raised-button: #FFFFFF,
focused-button: #64748B, /* blueGray.500 */ focused-button: #64748B, /* slate.500 */
selected-button: #E2E8F0, /* blueGray.200 */ selected-button: #E2E8F0, /* slate.200 */
selected-disabled-button: #E2E8F0, /* blueGray.200 */ selected-disabled-button: #E2E8F0, /* slate.200 */
disabled-button-toggle: #CBD5E1, /* blueGray.300 */ disabled-button-toggle: #CBD5E1, /* slate.300 */
unselected-chip: #E2E8F0, /* blueGray.200 */ unselected-chip: #E2E8F0, /* slate.200 */
disabled-list-option: #CBD5E1, /* blueGray.300 */ disabled-list-option: #CBD5E1, /* slate.300 */
tooltip: #1E293B /* blueGray.800 */ tooltip: #1E293B /* slate.800 */
) )
) )
); );
@@ -126,38 +126,38 @@ body .dark {
is-dark: map.get(map.get($base-dark-theme, color), is-dark), is-dark: map.get(map.get($base-dark-theme, color), is-dark),
foreground: ( foreground: (
base: #FFFFFF, base: #FFFFFF,
divider: rgba(241, 245, 249, 0.12), /* blueGray.100 + opacity */ divider: rgba(241, 245, 249, 0.12), /* slate.100 + opacity */
dividers: rgba(241, 245, 249, 0.12), /* blueGray.100 + opacity */ dividers: rgba(241, 245, 249, 0.12), /* slate.100 + opacity */
disabled: #475569, /* blueGray.600 */ disabled: #475569, /* slate.600 */
disabled-button: #1E293B, /* blueGray.800 */ disabled-button: #1E293B, /* slate.800 */
disabled-text: #475569, /* blueGray.600 */ disabled-text: #475569, /* slate.600 */
elevation: #000000, elevation: #000000,
hint-text: #64748B, /* blueGray.500 */ hint-text: #64748B, /* slate.500 */
secondary-text: #94A3B8, /* blueGray.400 */ secondary-text: #94A3B8, /* slate.400 */
icon: #F1F5F9, /* blueGray.100 */ icon: #F1F5F9, /* slate.100 */
icons: #F1F5F9, /* blueGray.100 */ icons: #F1F5F9, /* slate.100 */
mat-icon: #94A3B8, /* blueGray.400 */ mat-icon: #94A3B8, /* slate.400 */
text: #FFFFFF, text: #FFFFFF,
slider-min: #FFFFFF, slider-min: #FFFFFF,
slider-off: #64748B, /* blueGray.500 */ slider-off: #64748B, /* slate.500 */
slider-off-active: #94A3B8 /* blueGray.400 */ slider-off-active: #94A3B8 /* slate.400 */
), ),
background: ( background: (
status-bar: #0F172A, /* blueGray.900 */ status-bar: #0F172A, /* slate.900 */
app-bar: #0F172A, /* blueGray.900 */ app-bar: #0F172A, /* slate.900 */
background: #0F172A, /* blueGray.900 */ background: #0F172A, /* slate.900 */
hover: rgba(255, 255, 255, 0.05), hover: rgba(255, 255, 255, 0.05),
card: #1E293B, /* blueGray.800 */ card: #1E293B, /* slate.800 */
dialog: #1E293B, /* blueGray.800 */ dialog: #1E293B, /* slate.800 */
disabled-button: rgba(15, 23, 42, 0.38), /* blueGray.900 + opacity */ disabled-button: rgba(15, 23, 42, 0.38), /* slate.900 + opacity */
raised-button: #0F172A, /* blueGray.900 */ raised-button: #0F172A, /* slate.900 */
focused-button: #E2E8F0, /* blueGray.200 */ focused-button: #E2E8F0, /* slate.200 */
selected-button: rgba(255, 255, 255, 0.05), selected-button: rgba(255, 255, 255, 0.05),
selected-disabled-button: #1E293B, /* blueGray.800 */ selected-disabled-button: #1E293B, /* slate.800 */
disabled-button-toggle: #0F172A, /* blueGray.900 */ disabled-button-toggle: #0F172A, /* slate.900 */
unselected-chip: #475569, /* blueGray.600 */ unselected-chip: #475569, /* slate.600 */
disabled-list-option: #E2E8F0, /* blueGray.200 */ disabled-list-option: #E2E8F0, /* slate.200 */
tooltip: #64748B /* blueGray.500 */ tooltip: #64748B /* slate.500 */
) )
) )
); );

View File

@@ -1,38 +0,0 @@
const plugin = require('tailwindcss/plugin');
const buildMediaQuery = require('tailwindcss/lib/util/buildMediaQuery').default;
const extractConfig = plugin(({
addVariant,
theme
}) =>
{
addVariant('fuse-tailwind-extracted-config', ({container}) =>
{
// Prepare the extracted config variable
let extractedConfig = '';
// Breakpoints
Object.entries(theme('screens')).forEach(([key, value]) =>
{
extractedConfig = `${extractedConfig} --breakpoints-${key}:'${buildMediaQuery(value)}';`;
});
// Themes
(theme('fuse.themes')).forEach((value) =>
{
Object.entries(value).forEach(([key, value]) =>
{
extractedConfig = `${extractedConfig} --themes-${key}:'${JSON.stringify(value)}';`;
});
});
// Append the extracted config
container.append(`
.fuse-tailwind-extracted-config {
${extractedConfig}
}
`);
});
});
module.exports = extractConfig;

View File

@@ -1,17 +1,14 @@
const plugin = require('tailwindcss/plugin'); const plugin = require('tailwindcss/plugin');
const iconSize = plugin(({ module.exports = plugin(
addUtilities, ({
theme, matchUtilities,
e, theme
variants
}) => }) =>
{ {
const values = theme('iconSize'); matchUtilities(
{
addUtilities( 'icon-size': (value) => ({
Object.entries(values).map(([key, value]) => ({
[`.${e(`icon-size-${key}`)}`]: {
width : value, width : value,
height : value, height : value,
minWidth : value, minWidth : value,
@@ -22,13 +19,14 @@ const iconSize = plugin(({
width : value, width : value,
height: value height: value
} }
} })
})), },
variants('iconSize') {
); values: theme('iconSize')
});
}, },
{ {
theme : { theme: {
iconSize: { iconSize: {
3 : '0.75rem', 3 : '0.75rem',
3.5: '0.875rem', 3.5: '0.875rem',
@@ -47,10 +45,6 @@ const iconSize = plugin(({
22 : '5.5rem', 22 : '5.5rem',
24 : '6rem' 24 : '6rem'
} }
},
variants: {
iconSize: ['responsive']
} }
}); }
);
module.exports = iconSize;

View File

@@ -102,7 +102,7 @@ const theming = plugin.withOptions((options) => ({
// @ Map variable colors // @ Map variable colors
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------
const mapVariableColors = _.fromPairs(_.map(options.themes, (theme, themeName) => [ const mapVariableColors = _.fromPairs(_.map(options.themes, (theme, themeName) => [
themeName === 'default' ? 'body' : `body.theme-${e(themeName)}`, themeName === 'default' ? 'body, .theme-default' : `.theme-${e(themeName)}`,
_.fromPairs(_.flatten(_.map(flattenColorPalette(_.fromPairs(_.flatten(_.map(normalizeTheme(theme), (palette, paletteName) => [ _.fromPairs(_.flatten(_.map(flattenColorPalette(_.fromPairs(_.flatten(_.map(normalizeTheme(theme), (palette, paletteName) => [
[ [
e(paletteName), e(paletteName),
@@ -185,47 +185,46 @@ const theming = plugin.withOptions((options) => ({
light: { light: {
'bg-app-bar' : '#FFFFFF', 'bg-app-bar' : '#FFFFFF',
'bg-card' : '#FFFFFF', 'bg-card' : '#FFFFFF',
'bg-default' : colors.blueGray[100], 'bg-default' : colors.slate[100],
'bg-dialog' : '#FFFFFF', 'bg-dialog' : '#FFFFFF',
'bg-hover' : chroma(colors.blueGray[400]).alpha(0.12).css(), 'bg-hover' : chroma(colors.slate[400]).alpha(0.12).css(),
'bg-status-bar': colors.blueGray[300] 'bg-status-bar': colors.slate[300]
}, },
dark : { dark : {
'bg-app-bar' : colors.blueGray[900], 'bg-app-bar' : colors.slate[900],
'bg-card' : colors.blueGray[800], 'bg-card' : colors.slate[800],
'bg-default' : colors.blueGray[900], 'bg-default' : colors.slate[900],
'bg-dialog' : colors.blueGray[800], 'bg-dialog' : colors.slate[800],
'bg-hover' : 'rgba(255, 255, 255, 0.05)', 'bg-hover' : 'rgba(255, 255, 255, 0.05)',
'bg-status-bar': colors.blueGray[900] 'bg-status-bar': colors.slate[900]
} }
}, },
foreground: { foreground: {
light: { light: {
'text-default' : colors.blueGray[800], 'text-default' : colors.slate[800],
'text-secondary': colors.blueGray[500], 'text-secondary': colors.slate[500],
'text-hint' : colors.blueGray[400], 'text-hint' : colors.slate[400],
'text-disabled' : colors.blueGray[400], 'text-disabled' : colors.slate[400],
'border' : colors.blueGray[200], 'border' : colors.slate[200],
'divider' : colors.blueGray[200], 'divider' : colors.slate[200],
'icon' : colors.blueGray[500], 'icon' : colors.slate[500],
'mat-icon' : colors.blueGray[500] 'mat-icon' : colors.slate[500]
}, },
dark : { dark : {
'text-default' : '#FFFFFF', 'text-default' : '#FFFFFF',
'text-secondary': colors.blueGray[400], 'text-secondary': colors.slate[400],
'text-hint' : colors.blueGray[500], 'text-hint' : colors.slate[500],
'text-disabled' : colors.blueGray[600], 'text-disabled' : colors.slate[600],
'border' : chroma(colors.blueGray[100]).alpha(0.12).css(), 'border' : chroma(colors.slate[100]).alpha(0.12).css(),
'divider' : chroma(colors.blueGray[100]).alpha(0.12).css(), 'divider' : chroma(colors.slate[100]).alpha(0.12).css(),
'icon' : colors.blueGray[400], 'icon' : colors.slate[400],
'mat-icon' : colors.blueGray[400] 'mat-icon' : colors.slate[400]
} }
} }
}, },
themes : generateThemesObject(options.themes) themes : generateThemesObject(options.themes)
} }
}, }
variants: {}
}; };
} }
); );

View File

@@ -1,6 +1,6 @@
const plugin = require('tailwindcss/plugin'); const plugin = require('tailwindcss/plugin');
const utilities = plugin(({ module.exports = plugin(({
addComponents addComponents
}) => }) =>
{ {
@@ -54,9 +54,6 @@ const utilities = plugin(({
'--tw-ring-opacity': '1 !important', '--tw-ring-opacity': '1 !important',
'--tw-ring-color' : 'rgba(var(--fuse-bg-card-rgb), var(--tw-ring-opacity)) !important' '--tw-ring-color' : 'rgba(var(--fuse-bg-card-rgb), var(--tw-ring-opacity)) !important'
} }
},
{
variants: ['dark', 'responsive', 'group-hover', 'hover']
} }
); );
@@ -65,11 +62,6 @@ const utilities = plugin(({
'.bg-hover': { '.bg-hover': {
backgroundColor: 'var(--fuse-bg-hover) !important' backgroundColor: 'var(--fuse-bg-hover) !important'
} }
},
{
variants: ['dark', 'group-hover', 'hover']
} }
); );
}); });
module.exports = utilities;

View File

@@ -1,3 +1,3 @@
import { Version } from '@fuse/version/version'; import { Version } from '@fuse/version/version';
export const FUSE_VERSION = new Version('14.0.0').full; export const FUSE_VERSION = new Version('15.0.0').full;

View File

@@ -3,4 +3,4 @@
flex: 1 1 auto; flex: 1 1 auto;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }

View File

@@ -96,8 +96,8 @@ export class AuthService
*/ */
signInUsingToken(): Observable<any> signInUsingToken(): Observable<any>
{ {
// Renew token // Sign in using the token
return this._httpClient.post('api/auth/refresh-access-token', { return this._httpClient.post('api/auth/sign-in-with-token', {
accessToken: this.accessToken accessToken: this.accessToken
}).pipe( }).pipe(
catchError(() => catchError(() =>
@@ -107,8 +107,17 @@ export class AuthService
), ),
switchMap((response: any) => { switchMap((response: any) => {
// Store the access token in the local storage // Replace the access token with the new one if it's available on
this.accessToken = response.accessToken; // the response object.
//
// This is an added optional step for better security. Once you sign
// in using the token, you should generate a new one on the server
// side and attach it to the response object. Then the following
// piece of code can replace the token with the refreshed one.
if ( response.accessToken )
{
this.accessToken = response.accessToken;
}
// Set the authenticated flag to true // Set the authenticated flag to true
this._authenticated = true; this._authenticated = true;

View File

@@ -2,7 +2,9 @@ import { Layout } from 'app/layout/layout.types';
// Types // Types
export type Scheme = 'auto' | 'dark' | 'light'; export type Scheme = 'auto' | 'dark' | 'light';
export type Theme = 'default' | string; export type Screens = { [key: string]: string };
export type Theme = 'theme-default' | string;
export type Themes = { id: string; name: string }[];
/** /**
* AppConfig interface. Update this interface to strictly type your config * AppConfig interface. Update this interface to strictly type your config
@@ -12,7 +14,9 @@ export interface AppConfig
{ {
layout: Layout; layout: Layout;
scheme: Scheme; scheme: Scheme;
screens: Screens;
theme: Theme; theme: Theme;
themes: Themes;
} }
/** /**
@@ -22,9 +26,46 @@ export interface AppConfig
* If you need to store global configuration for your app, you can use this * If you need to store global configuration for your app, you can use this
* object to set the defaults. To access, update and reset the config, use * object to set the defaults. To access, update and reset the config, use
* FuseConfigService and its methods. * FuseConfigService and its methods.
*
* "Screens" are carried over to the BreakpointObserver for accessing them within
* components, and they are required.
*
* "Themes" are required for Tailwind to generate themes.
*/ */
export const appConfig: AppConfig = { export const appConfig: AppConfig = {
layout: 'classy', layout : 'classy',
scheme: 'light', scheme : 'light',
theme : 'default' screens: {
sm: '600px',
md: '960px',
lg: '1280px',
xl: '1440px'
},
theme : 'theme-default',
themes : [
{
id : 'theme-default',
name: 'Default'
},
{
id : 'theme-brand',
name: 'Brand'
},
{
id : 'theme-teal',
name: 'Teal'
},
{
id : 'theme-rose',
name: 'Rose'
},
{
id : 'theme-purple',
name: 'Purple'
},
{
id : 'theme-amber',
name: 'Amber'
}
]
}; };

View File

@@ -17,7 +17,6 @@ export class IconsModule
this._matIconRegistry.addSvgIconSet(this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/material-twotone.svg')); this._matIconRegistry.addSvgIconSet(this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/material-twotone.svg'));
this._matIconRegistry.addSvgIconSetInNamespace('mat_outline', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/material-outline.svg')); this._matIconRegistry.addSvgIconSetInNamespace('mat_outline', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/material-outline.svg'));
this._matIconRegistry.addSvgIconSetInNamespace('mat_solid', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/material-solid.svg')); this._matIconRegistry.addSvgIconSetInNamespace('mat_solid', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/material-solid.svg'));
this._matIconRegistry.addSvgIconSetInNamespace('iconsmind', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/iconsmind.svg'));
this._matIconRegistry.addSvgIconSetInNamespace('feather', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/feather.svg')); this._matIconRegistry.addSvgIconSetInNamespace('feather', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/feather.svg'));
this._matIconRegistry.addSvgIconSetInNamespace('heroicons_outline', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/heroicons-outline.svg')); this._matIconRegistry.addSvgIconSetInNamespace('heroicons_outline', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/heroicons-outline.svg'));
this._matIconRegistry.addSvgIconSetInNamespace('heroicons_solid', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/heroicons-solid.svg')); this._matIconRegistry.addSvgIconSetInNamespace('heroicons_solid', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/heroicons-solid.svg'));

View File

@@ -5,7 +5,7 @@
#messagesOrigin> #messagesOrigin>
<ng-container *ngIf="unreadCount > 0"> <ng-container *ngIf="unreadCount > 0">
<span class="absolute top-0 right-0 left-0 flex items-center justify-center h-3"> <span class="absolute top-0 right-0 left-0 flex items-center justify-center h-3">
<span class="flex items-center justify-center flex-shrink-0 min-w-4 h-4 px-1 ml-4 mt-2.5 rounded-full bg-indigo-600 text-indigo-50 text-xs font-medium"> <span class="flex items-center justify-center shrink-0 min-w-4 h-4 px-1 ml-4 mt-2.5 rounded-full bg-indigo-600 text-indigo-50 text-xs font-medium">
{{unreadCount}} {{unreadCount}}
</span> </span>
</span> </span>
@@ -19,7 +19,7 @@
<div class="fixed inset-0 sm:static sm:inset-auto flex flex-col sm:min-w-90 sm:w-90 sm:rounded-2xl overflow-hidden shadow-lg"> <div class="fixed inset-0 sm:static sm:inset-auto flex flex-col sm:min-w-90 sm:w-90 sm:rounded-2xl overflow-hidden shadow-lg">
<!-- Header --> <!-- Header -->
<div class="flex flex-shrink-0 items-center py-4 pr-4 pl-6 bg-primary text-on-primary"> <div class="flex shrink-0 items-center py-4 pr-4 pl-6 bg-primary text-on-primary">
<div class="sm:hidden -ml-1 mr-3"> <div class="sm:hidden -ml-1 mr-3">
<button <button
mat-icon-button mat-icon-button
@@ -108,7 +108,7 @@
<ng-template #messageContent> <ng-template #messageContent>
<!-- Icon --> <!-- Icon -->
<ng-container *ngIf="message.icon && !message.image"> <ng-container *ngIf="message.icon && !message.image">
<div class="flex flex-shrink-0 items-center justify-center w-8 h-8 mr-4 rounded-full bg-gray-100 dark:bg-gray-700"> <div class="flex shrink-0 items-center justify-center w-8 h-8 mr-4 rounded-full bg-gray-100 dark:bg-gray-700">
<mat-icon <mat-icon
class="icon-size-5" class="icon-size-5"
[svgIcon]="message.icon"> [svgIcon]="message.icon">
@@ -118,7 +118,7 @@
<!-- Image --> <!-- Image -->
<ng-container *ngIf="message.image"> <ng-container *ngIf="message.image">
<img <img
class="flex-shrink-0 w-8 h-8 mr-4 rounded-full overflow-hidden object-cover object-center" class="shrink-0 w-8 h-8 mr-4 rounded-full overflow-hidden object-cover object-center"
[src]="message.image" [src]="message.image"
[alt]="'Message image'"> [alt]="'Message image'">
</ng-container> </ng-container>

View File

@@ -5,7 +5,7 @@
#notificationsOrigin> #notificationsOrigin>
<ng-container *ngIf="unreadCount > 0"> <ng-container *ngIf="unreadCount > 0">
<span class="absolute top-0 right-0 left-0 flex items-center justify-center h-3"> <span class="absolute top-0 right-0 left-0 flex items-center justify-center h-3">
<span class="flex items-center justify-center flex-shrink-0 min-w-4 h-4 px-1 ml-4 mt-2.5 rounded-full bg-teal-600 text-indigo-50 text-xs font-medium"> <span class="flex items-center justify-center shrink-0 min-w-4 h-4 px-1 ml-4 mt-2.5 rounded-full bg-teal-600 text-indigo-50 text-xs font-medium">
{{unreadCount}} {{unreadCount}}
</span> </span>
</span> </span>
@@ -19,7 +19,7 @@
<div class="fixed inset-0 sm:static sm:inset-auto flex flex-col sm:min-w-90 sm:w-90 sm:rounded-2xl overflow-hidden shadow-lg"> <div class="fixed inset-0 sm:static sm:inset-auto flex flex-col sm:min-w-90 sm:w-90 sm:rounded-2xl overflow-hidden shadow-lg">
<!-- Header --> <!-- Header -->
<div class="flex flex-shrink-0 items-center py-4 pr-4 pl-6 bg-primary text-on-primary"> <div class="flex shrink-0 items-center py-4 pr-4 pl-6 bg-primary text-on-primary">
<div class="sm:hidden -ml-1 mr-3"> <div class="sm:hidden -ml-1 mr-3">
<button <button
mat-icon-button mat-icon-button
@@ -109,7 +109,7 @@
<ng-template #notificationContent> <ng-template #notificationContent>
<!-- Icon --> <!-- Icon -->
<ng-container *ngIf="notification.icon && !notification.image"> <ng-container *ngIf="notification.icon && !notification.image">
<div class="flex flex-shrink-0 items-center justify-center w-8 h-8 mr-4 rounded-full bg-gray-100 dark:bg-gray-700"> <div class="flex shrink-0 items-center justify-center w-8 h-8 mr-4 rounded-full bg-gray-100 dark:bg-gray-700">
<mat-icon <mat-icon
class="icon-size-5" class="icon-size-5"
[svgIcon]="notification.icon"> [svgIcon]="notification.icon">
@@ -119,7 +119,7 @@
<!-- Image --> <!-- Image -->
<ng-container *ngIf="notification.image"> <ng-container *ngIf="notification.image">
<img <img
class="flex-shrink-0 w-8 h-8 mr-4 rounded-full overflow-hidden object-cover object-center" class="shrink-0 w-8 h-8 mr-4 rounded-full overflow-hidden object-cover object-center"
[src]="notification.image" [src]="notification.image"
[alt]="'Notification image'"> [alt]="'Notification image'">
</ng-container> </ng-container>

View File

@@ -1,6 +1,6 @@
<div class="fixed lg:sticky top-0 bottom-0 lg:left-full w-full sm:w-96 lg:w-16 lg:h-screen lg:shadow"> <div class="fixed lg:sticky top-0 bottom-0 lg:left-full w-full sm:w-96 lg:w-16 lg:h-screen lg:shadow">
<div <div
class="flex flex-col w-full sm:w-96 h-full transform transition-transform duration-400 ease-drawer bg-card" class="flex flex-col w-full sm:w-96 h-full transition-transform duration-400 ease-drawer bg-card"
[ngClass]="{'-translate-x-full sm:-translate-x-96 lg:-translate-x-80 shadow': opened, 'translate-x-0': !opened}"> [ngClass]="{'-translate-x-full sm:-translate-x-96 lg:-translate-x-80 shadow': opened, 'translate-x-0': !opened}">
<!-- Header --> <!-- Header -->
@@ -93,7 +93,7 @@
<div class="flex flex-col flex-auto border-l overflow-hidden bg-gray-50 dark:bg-transparent"> <div class="flex flex-col flex-auto border-l overflow-hidden bg-gray-50 dark:bg-transparent">
<ng-container *ngIf="chat; else selectChatOrStartNew"> <ng-container *ngIf="chat; else selectChatOrStartNew">
<div class="flex flex-col-reverse overflow-y-auto overscroll-y-contain"> <div class="flex flex-col-reverse overflow-y-auto overscroll-y-contain">
<div class="flex flex-col flex-auto flex-shrink p-6"> <div class="flex flex-col flex-auto shrink p-6">
<ng-container *ngFor="let message of chat.messages; let i = index; let first = first; let last = last; trackBy: trackByFn"> <ng-container *ngFor="let message of chat.messages; let i = index; let first = first; let last = last; trackBy: trackByFn">
<!-- Start of the day --> <!-- Start of the day -->
<ng-container *ngIf="first || (chat.messages[i - 1].createdAt | date:'d') !== (message.createdAt | date:'d')"> <ng-container *ngIf="first || (chat.messages[i - 1].createdAt | date:'d') !== (message.createdAt | date:'d')">
@@ -108,20 +108,20 @@
<div <div
class="flex flex-col" class="flex flex-col"
[ngClass]="{'items-end': message.isMine, [ngClass]="{'items-end': message.isMine,
'items-start': !message.isMine, 'items-start': !message.isMine,
'mt-0.5': i > 0 && chat.messages[i - 1].isMine === message.isMine, 'mt-0.5': i > 0 && chat.messages[i - 1].isMine === message.isMine,
'mt-3': i > 0 && chat.messages[i - 1].isMine !== message.isMine}"> 'mt-3': i > 0 && chat.messages[i - 1].isMine !== message.isMine}">
<!-- Bubble --> <!-- Bubble -->
<div <div
class="relative max-w-3/4 px-3 py-2 rounded-lg" class="relative max-w-3/4 px-3 py-2 rounded-lg"
[ngClass]="{'bg-blue-500 text-blue-50': message.isMine, [ngClass]="{'bg-blue-500 text-blue-50': message.isMine,
'bg-gray-500 text-gray-50': !message.isMine}"> 'bg-gray-500 text-gray-50': !message.isMine}">
<!-- Speech bubble tail --> <!-- Speech bubble tail -->
<ng-container *ngIf="last || chat.messages[i + 1].isMine !== message.isMine"> <ng-container *ngIf="last || chat.messages[i + 1].isMine !== message.isMine">
<div <div
class="absolute bottom-0 w-3 transform" class="absolute bottom-0 w-3"
[ngClass]="{'text-blue-500 -right-1 -mr-px mb-px': message.isMine, [ngClass]="{'text-blue-500 -right-1 -mr-px mb-px': message.isMine,
'text-gray-500 -left-1 -ml-px mb-px -scale-x-1': !message.isMine}"> 'text-gray-500 -left-1 -ml-px mb-px -scale-x-1': !message.isMine}">
<ng-container *ngTemplateOutlet="speechBubbleExtension"></ng-container> <ng-container *ngTemplateOutlet="speechBubbleExtension"></ng-container>
</div> </div>
</ng-container> </ng-container>
@@ -140,7 +140,7 @@
<div <div
class="my-0.5 text-sm font-medium text-secondary" class="my-0.5 text-sm font-medium text-secondary"
[ngClass]="{'mr-3': message.isMine, [ngClass]="{'mr-3': message.isMine,
'ml-3': !message.isMine}"> 'ml-3': !message.isMine}">
{{message.createdAt | date:'HH:mm'}} {{message.createdAt | date:'HH:mm'}}
</div> </div>
</ng-container> </ng-container>
@@ -163,7 +163,7 @@
<button <button
mat-icon-button> mat-icon-button>
<mat-icon <mat-icon
class="transform rotate-90" class="rotate-90"
[svgIcon]="'heroicons_outline:paper-airplane'"></mat-icon> [svgIcon]="'heroicons_outline:paper-airplane'"></mat-icon>
</button> </button>
</div> </div>
@@ -178,8 +178,8 @@
<ng-template #selectChatOrStartNew> <ng-template #selectChatOrStartNew>
<div class="flex flex-col flex-auto items-center justify-center w-full h-full p-4"> <div class="flex flex-col flex-auto items-center justify-center w-full h-full p-4">
<mat-icon <mat-icon
class="icon-size-20" class="icon-size-24"
[svgIcon]="'iconsmind:speach_bubble'"></mat-icon> [svgIcon]="'heroicons_outline:chat'"></mat-icon>
<div class="mt-4 text-xl text-center font-medium tracking-tight text-secondary">Select a conversation</div> <div class="mt-4 text-xl text-center font-medium tracking-tight text-secondary">Select a conversation</div>
</div> </div>
</ng-template> </ng-template>

View File

@@ -7,7 +7,7 @@
<mat-icon [svgIcon]="'heroicons_outline:search'"></mat-icon> <mat-icon [svgIcon]="'heroicons_outline:search'"></mat-icon>
</button> </button>
<div <div
class="absolute inset-0 flex items-center flex-shrink-0 z-99 bg-card" class="absolute inset-0 flex items-center shrink-0 z-99 bg-card"
*ngIf="opened" *ngIf="opened"
@slideInTop @slideInTop
@slideOutTop> @slideOutTop>
@@ -18,11 +18,12 @@
class="w-full h-full px-16 sm:px-18" class="w-full h-full px-16 sm:px-18"
[formControl]="searchControl" [formControl]="searchControl"
[matAutocomplete]="matAutocomplete" [matAutocomplete]="matAutocomplete"
[placeholder]="'Search for a page or a contact'" [placeholder]="'Search...'"
(keydown)="onKeydown($event)" (keydown)="onKeydown($event)"
#barSearchInput> #barSearchInput>
<mat-autocomplete <mat-autocomplete
class="max-h-128 sm:px-2 border-t rounded-b shadow-md" class="max-h-128 sm:px-2 border-t rounded-b shadow-md"
[autoSelectActiveOption]="true"
[disableRipple]="true" [disableRipple]="true"
#matAutocomplete="matAutocomplete"> #matAutocomplete="matAutocomplete">
<mat-option <mat-option
@@ -37,7 +38,8 @@
<ng-container *ngFor="let result of resultSet.results; trackBy: trackByFn"> <ng-container *ngFor="let result of resultSet.results; trackBy: trackByFn">
<mat-option <mat-option
class="group relative mb-1 py-0 px-6 text-md rounded-md hover:bg-gray-100 dark:hover:bg-hover" class="group relative mb-1 py-0 px-6 text-md rounded-md hover:bg-gray-100 dark:hover:bg-hover"
[routerLink]="result.link"> [routerLink]="result.link"
[value]="result.value">
<!-- Contacts --> <!-- Contacts -->
<ng-container *ngIf="resultSet.id === 'contacts'"> <ng-container *ngIf="resultSet.id === 'contacts'">
<ng-container *ngTemplateOutlet="contactResult; context: {$implicit: result}"></ng-container> <ng-container *ngTemplateOutlet="contactResult; context: {$implicit: result}"></ng-container>
@@ -55,7 +57,7 @@
</ng-container> </ng-container>
</mat-autocomplete> </mat-autocomplete>
<button <button
class="absolute top-1/2 right-5 sm:right-7 flex-shrink-0 w-10 h-10 -mt-5" class="absolute top-1/2 right-5 sm:right-7 shrink-0 w-10 h-10 -mt-5"
mat-icon-button mat-icon-button
(click)="close()"> (click)="close()">
<mat-icon [svgIcon]="'heroicons_outline:x'"></mat-icon> <mat-icon [svgIcon]="'heroicons_outline:x'"></mat-icon>
@@ -74,11 +76,12 @@
matInput matInput
[formControl]="searchControl" [formControl]="searchControl"
[matAutocomplete]="matAutocomplete" [matAutocomplete]="matAutocomplete"
[placeholder]="'Search for a page or a contact'" [placeholder]="'Search...'"
(keydown)="onKeydown($event)"> (keydown)="onKeydown($event)">
</mat-form-field> </mat-form-field>
<mat-autocomplete <mat-autocomplete
class="max-h-128 mt-1 rounded" class="max-h-128 mt-1 rounded"
[autoSelectActiveOption]="true"
[disableRipple]="true" [disableRipple]="true"
#matAutocomplete="matAutocomplete"> #matAutocomplete="matAutocomplete">
<mat-option <mat-option
@@ -93,7 +96,8 @@
<ng-container *ngFor="let result of resultSet.results; trackBy: trackByFn"> <ng-container *ngFor="let result of resultSet.results; trackBy: trackByFn">
<mat-option <mat-option
class="group relative mb-1 py-0 px-6 text-md rounded-md hover:bg-gray-100 dark:hover:bg-hover" class="group relative mb-1 py-0 px-6 text-md rounded-md hover:bg-gray-100 dark:hover:bg-hover"
[routerLink]="result.link"> [routerLink]="result.link"
[value]="result.value">
<!-- Contacts --> <!-- Contacts -->
<ng-container *ngIf="resultSet.id === 'contacts'"> <ng-container *ngIf="resultSet.id === 'contacts'">
<ng-container *ngTemplateOutlet="contactResult; context: {$implicit: result}"></ng-container> <ng-container *ngTemplateOutlet="contactResult; context: {$implicit: result}"></ng-container>
@@ -118,7 +122,7 @@
#contactResult #contactResult
let-result> let-result>
<div class="flex items-center"> <div class="flex items-center">
<div class="flex flex-shrink-0 items-center justify-center w-8 h-8 rounded-full overflow-hidden bg-primary-100 dark:bg-primary-800"> <div class="flex shrink-0 items-center justify-center w-8 h-8 rounded-full overflow-hidden bg-primary-100 dark:bg-primary-800">
<img <img
*ngIf="result.avatar" *ngIf="result.avatar"
[src]="result.avatar"> [src]="result.avatar">

View File

@@ -1,6 +1,7 @@
import { Component, ElementRef, EventEmitter, HostBinding, Input, OnChanges, OnDestroy, OnInit, Output, Renderer2, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core'; import { Component, ElementRef, EventEmitter, HostBinding, Input, OnChanges, OnDestroy, OnInit, Output, Renderer2, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core';
import { FormControl } from '@angular/forms'; import { UntypedFormControl } from '@angular/forms';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { MatAutocomplete } from '@angular/material/autocomplete';
import { debounceTime, filter, map, Subject, takeUntil } from 'rxjs'; import { debounceTime, filter, map, Subject, takeUntil } from 'rxjs';
import { fuseAnimations } from '@fuse/animations/public-api'; import { fuseAnimations } from '@fuse/animations/public-api';
@@ -20,7 +21,8 @@ export class SearchComponent implements OnChanges, OnInit, OnDestroy
opened: boolean = false; opened: boolean = false;
resultSets: any[]; resultSets: any[];
searchControl: FormControl = new FormControl(); searchControl: UntypedFormControl = new UntypedFormControl();
private _matAutocomplete: MatAutocomplete;
private _unsubscribeAll: Subject<any> = new Subject<any>(); private _unsubscribeAll: Subject<any> = new Subject<any>();
/** /**
@@ -59,7 +61,7 @@ export class SearchComponent implements OnChanges, OnInit, OnDestroy
set barSearchInput(value: ElementRef) set barSearchInput(value: ElementRef)
{ {
// If the value exists, it means that the search input // If the value exists, it means that the search input
// is now in the DOM and we can focus on the input.. // is now in the DOM, and we can focus on the input..
if ( value ) if ( value )
{ {
// Give Angular time to complete the change detection cycle // Give Angular time to complete the change detection cycle
@@ -71,6 +73,17 @@ export class SearchComponent implements OnChanges, OnInit, OnDestroy
} }
} }
/**
* Setter for mat-autocomplete element reference
*
* @param value
*/
@ViewChild('matAutocomplete')
set matAutocomplete(value: MatAutocomplete)
{
this._matAutocomplete = value;
}
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks // @ Lifecycle hooks
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------
@@ -152,14 +165,12 @@ export class SearchComponent implements OnChanges, OnInit, OnDestroy
*/ */
onKeydown(event: KeyboardEvent): void onKeydown(event: KeyboardEvent): void
{ {
// Listen for escape to close the search // Escape
// if the appearance is 'bar' if ( event.code === 'Escape' )
if ( this.appearance === 'bar' )
{ {
// Escape // If the appearance is 'bar' and the mat-autocomplete is not open, close the search
if ( event.code === 'Escape' ) if ( this.appearance === 'bar' && !this._matAutocomplete.isOpen )
{ {
// Close the search
this.close(); this.close();
} }
} }

View File

@@ -1,5 +1,5 @@
<div <div
class="fixed flex items-center justify-center right-0 w-10 h-10 shadow-lg rounded-l-lg z-90 cursor-pointer bg-red-600 bg-opacity-90 print:hidden" class="settings-cog fixed flex items-center justify-center right-0 w-10 h-10 shadow-lg rounded-l-lg z-90 cursor-pointer bg-red-600 bg-opacity-90 print:hidden"
[class.lg:right-0]="config.layout === 'centered' || config.layout === 'material'" [class.lg:right-0]="config.layout === 'centered' || config.layout === 'material'"
[class.lg:right-16]="config.layout !== 'centered' && config.layout !== 'material'" [class.lg:right-16]="config.layout !== 'centered' && config.layout !== 'material'"
style="top: 275px" style="top: 275px"
@@ -38,18 +38,19 @@
<!-- Theme --> <!-- Theme -->
<div class="text-md font-semibold text-secondary">THEME</div> <div class="text-md font-semibold text-secondary">THEME</div>
<div class="grid grid-cols-2 sm:grid-cols-3 gap-3 mt-6"> <div class="grid grid-cols-2 sm:grid-cols-3 gap-3 mt-6">
<ng-container *ngFor="let theme of themes"> <ng-container *ngFor="let theme of config.themes">
<div <div
class="flex items-center justify-center px-4 py-3 rounded-full cursor-pointer ring-inset ring-primary bg-hover" class="flex items-center justify-center px-4 py-3 rounded-full cursor-pointer ring-inset ring-primary bg-hover"
[class.ring-2]="config.theme === theme[0]" [class.ring-2]="config.theme === theme.id"
(click)="setTheme(theme[0])"> [ngClass]="theme.id"
(click)="setTheme(theme.id)">
<div <div
class="flex-0 w-3 h-3 rounded-full" class="flex-0 w-3 h-3 rounded-full bg-primary"
[style.background-color]="theme[1].primary"></div> ></div>
<div <div
class="ml-2.5 font-medium leading-5 truncate" class="ml-2.5 font-medium leading-5 truncate"
[class.text-secondary]="config.theme !== theme[0]"> [class.text-secondary]="config.theme !== theme.id">
{{theme[0] | titlecase}} {{theme.name}}
</div> </div>
</div> </div>
</ng-container> </ng-container>

View File

@@ -2,8 +2,7 @@ import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { Subject, takeUntil } from 'rxjs'; import { Subject, takeUntil } from 'rxjs';
import { FuseConfigService } from '@fuse/services/config'; import { FuseConfigService } from '@fuse/services/config';
import { FuseTailwindService } from '@fuse/services/tailwind'; import { AppConfig, Scheme, Theme, Themes } from 'app/core/config/app.config';
import { AppConfig, Scheme, Theme } from 'app/core/config/app.config';
import { Layout } from 'app/layout/layout.types'; import { Layout } from 'app/layout/layout.types';
@Component({ @Component({
@@ -17,6 +16,13 @@ import { Layout } from 'app/layout/layout.types';
flex: none; flex: none;
width: auto; width: auto;
} }
@media (screen and min-width: 1280px) {
empty-layout + settings .settings-cog {
right: 0 !important;
}
}
` `
], ],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
@@ -27,7 +33,7 @@ export class SettingsComponent implements OnInit, OnDestroy
layout: Layout; layout: Layout;
scheme: 'dark' | 'light'; scheme: 'dark' | 'light';
theme: string; theme: string;
themes: [string, any][] = []; themes: Themes;
private _unsubscribeAll: Subject<any> = new Subject<any>(); private _unsubscribeAll: Subject<any> = new Subject<any>();
/** /**
@@ -35,8 +41,7 @@ export class SettingsComponent implements OnInit, OnDestroy
*/ */
constructor( constructor(
private _router: Router, private _router: Router,
private _fuseConfigService: FuseConfigService, private _fuseConfigService: FuseConfigService
private _fuseTailwindService: FuseTailwindService
) )
{ {
} }
@@ -50,13 +55,6 @@ export class SettingsComponent implements OnInit, OnDestroy
*/ */
ngOnInit(): void ngOnInit(): void
{ {
// Get the themes
this._fuseTailwindService.tailwindConfig$
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this.themes = Object.entries(config.themes);
});
// Subscribe to config changes // Subscribe to config changes
this._fuseConfigService.config$ this._fuseConfigService.config$
.pipe(takeUntil(this._unsubscribeAll)) .pipe(takeUntil(this._unsubscribeAll))

View File

@@ -11,7 +11,7 @@
<div class="fixed inset-0 sm:static sm:inset-auto flex flex-col sm:min-w-90 sm:w-90 sm:rounded-2xl overflow-hidden shadow-lg"> <div class="fixed inset-0 sm:static sm:inset-auto flex flex-col sm:min-w-90 sm:w-90 sm:rounded-2xl overflow-hidden shadow-lg">
<!-- Header --> <!-- Header -->
<div class="flex flex-shrink-0 items-center py-4 pr-4 pl-6 bg-primary text-on-primary"> <div class="flex shrink-0 items-center py-4 pr-4 pl-6 bg-primary text-on-primary">
<div class="sm:hidden -ml-1 mr-3"> <div class="sm:hidden -ml-1 mr-3">
<button <button
mat-icon-button mat-icon-button
@@ -128,7 +128,7 @@
</a> </a>
<!-- Link content template --> <!-- Link content template -->
<ng-template #linkContent> <ng-template #linkContent>
<div class="relative flex flex-shrink-0 items-center justify-center w-12 h-12 mb-3 rounded-full bg-gray-100 dark:bg-gray-700"> <div class="relative flex shrink-0 items-center justify-center w-12 h-12 mb-3 rounded-full bg-gray-100 dark:bg-gray-700">
<mat-icon <mat-icon
class="absolute opacity-0 group-hover:opacity-100 z-20 icon-size-5" class="absolute opacity-0 group-hover:opacity-100 z-20 icon-size-5"
*ngIf="mode === 'modify'" *ngIf="mode === 'modify'"

View File

@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Overlay, OverlayRef } from '@angular/cdk/overlay'; import { Overlay, OverlayRef } from '@angular/cdk/overlay';
import { TemplatePortal } from '@angular/cdk/portal'; import { TemplatePortal } from '@angular/cdk/portal';
import { MatButton } from '@angular/material/button'; import { MatButton } from '@angular/material/button';
@@ -20,7 +20,7 @@ export class ShortcutsComponent implements OnInit, OnDestroy
@ViewChild('shortcutsPanel') private _shortcutsPanel: TemplateRef<any>; @ViewChild('shortcutsPanel') private _shortcutsPanel: TemplateRef<any>;
mode: 'view' | 'modify' | 'add' | 'edit' = 'view'; mode: 'view' | 'modify' | 'add' | 'edit' = 'view';
shortcutForm: FormGroup; shortcutForm: UntypedFormGroup;
shortcuts: Shortcut[]; shortcuts: Shortcut[];
private _overlayRef: OverlayRef; private _overlayRef: OverlayRef;
private _unsubscribeAll: Subject<any> = new Subject<any>(); private _unsubscribeAll: Subject<any> = new Subject<any>();
@@ -30,7 +30,7 @@ export class ShortcutsComponent implements OnInit, OnDestroy
*/ */
constructor( constructor(
private _changeDetectorRef: ChangeDetectorRef, private _changeDetectorRef: ChangeDetectorRef,
private _formBuilder: FormBuilder, private _formBuilder: UntypedFormBuilder,
private _shortcutsService: ShortcutsService, private _shortcutsService: ShortcutsService,
private _overlay: Overlay, private _overlay: Overlay,
private _viewContainerRef: ViewContainerRef private _viewContainerRef: ViewContainerRef

View File

@@ -4,6 +4,7 @@ import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { combineLatest, filter, map, Subject, takeUntil } from 'rxjs'; import { combineLatest, filter, map, Subject, takeUntil } from 'rxjs';
import { FuseConfigService } from '@fuse/services/config'; import { FuseConfigService } from '@fuse/services/config';
import { FuseMediaWatcherService } from '@fuse/services/media-watcher'; import { FuseMediaWatcherService } from '@fuse/services/media-watcher';
import { FusePlatformService } from '@fuse/services/platform';
import { FUSE_VERSION } from '@fuse/version'; import { FUSE_VERSION } from '@fuse/version';
import { Layout } from 'app/layout/layout.types'; import { Layout } from 'app/layout/layout.types';
import { AppConfig } from 'app/core/config/app.config'; import { AppConfig } from 'app/core/config/app.config';
@@ -31,7 +32,8 @@ export class LayoutComponent implements OnInit, OnDestroy
private _renderer2: Renderer2, private _renderer2: Renderer2,
private _router: Router, private _router: Router,
private _fuseConfigService: FuseConfigService, private _fuseConfigService: FuseConfigService,
private _fuseMediaWatcherService: FuseMediaWatcherService private _fuseMediaWatcherService: FuseMediaWatcherService,
private _fusePlatformService: FusePlatformService
) )
{ {
} }
@@ -102,6 +104,9 @@ export class LayoutComponent implements OnInit, OnDestroy
// Set the app version // Set the app version
this._renderer2.setAttribute(this._document.querySelector('[ng-version]'), 'fuse-version', FUSE_VERSION); this._renderer2.setAttribute(this._document.querySelector('[ng-version]'), 'fuse-version', FUSE_VERSION);
// Set the OS name
this._renderer2.addClass(this._document.body, this._fusePlatformService.osName);
} }
/** /**
@@ -203,6 +208,6 @@ export class LayoutComponent implements OnInit, OnDestroy
}); });
// Add class name for the currently selected theme // Add class name for the currently selected theme
this._document.body.classList.add(`theme-${this.theme}`); this._document.body.classList.add(this.theme);
} }
} }

View File

@@ -37,10 +37,10 @@
[svgIcon]="'heroicons_solid:user-circle'"></mat-icon> [svgIcon]="'heroicons_solid:user-circle'"></mat-icon>
</div> </div>
<div class="flex flex-col items-center justify-center w-full mt-6"> <div class="flex flex-col items-center justify-center w-full mt-6">
<div class="w-full whitespace-nowrap overflow-ellipsis overflow-hidden text-center leading-normal font-medium"> <div class="w-full whitespace-nowrap text-ellipsis overflow-hidden text-center leading-normal font-medium">
{{user.name}} {{user.name}}
</div> </div>
<div class="w-full mt-0.5 whitespace-nowrap overflow-ellipsis overflow-hidden text-center text-md leading-normal font-medium text-secondary"> <div class="w-full mt-0.5 whitespace-nowrap text-ellipsis overflow-hidden text-center text-md leading-normal font-medium text-secondary">
{{user.email}} {{user.email}}
</div> </div>
</div> </div>

View File

@@ -66,6 +66,9 @@ export class DenseLayoutComponent implements OnInit, OnDestroy
// Check if the screen is small // Check if the screen is small
this.isScreenSmall = !matchingAliases.includes('md'); this.isScreenSmall = !matchingAliases.includes('md');
// Change the navigation appearance
this.navigationAppearance = this.isScreenSmall ? 'default' : 'dense';
}); });
} }

View File

@@ -23,10 +23,10 @@
<div class="flex items-center w-full px-6 py-8 border-t"> <div class="flex items-center w-full px-6 py-8 border-t">
<user></user> <user></user>
<div class="flex flex-col w-full ml-4 overflow-hidden"> <div class="flex flex-col w-full ml-4 overflow-hidden">
<div class="w-full whitespace-nowrap overflow-ellipsis overflow-hidden leading-normal text-current opacity-80"> <div class="w-full whitespace-nowrap text-ellipsis overflow-hidden leading-normal text-current opacity-80">
{{user.name}} {{user.name}}
</div> </div>
<div class="w-full mt-0.5 whitespace-nowrap text-sm overflow-ellipsis overflow-hidden leading-normal text-current opacity-50"> <div class="w-full mt-0.5 whitespace-nowrap text-sm text-ellipsis overflow-hidden leading-normal text-current opacity-50">
brian.hughes@company.com brian.hughes@company.com
</div> </div>
</div> </div>

View File

@@ -38,8 +38,8 @@ export class FileManagerMockApi
// Clone the items // Clone the items
let items = cloneDeep(this._items); let items = cloneDeep(this._items);
// See if a folder id exist // See if the folder id exist
const folderId = request.params.get('folderId') ?? null; const folderId = request.params.get('folderId') === 'null' ? null : request.params.get('folderId');
// Filter the items by folder id. If folder id is null, // Filter the items by folder id. If folder id is null,
// that means we want to root items which have folder id // that means we want to root items which have folder id

View File

@@ -87,10 +87,10 @@ export class AuthMockApi
}); });
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------
// @ Verify and refresh the access token - POST // @ Sign in using the access token - POST
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------
this._fuseMockApiService this._fuseMockApiService
.onPost('api/auth/refresh-access-token') .onPost('api/auth/sign-in-with-token')
.reply(({request}) => { .reply(({request}) => {
// Get the access token // Get the access token

View File

@@ -819,12 +819,6 @@ export const defaultNavigation: FuseNavigationItem[] = [
type : 'basic', type : 'basic',
link : '/ui/icons/material-solid' link : '/ui/icons/material-solid'
}, },
{
id : 'user-interface.icons.iconsmind',
title: 'Iconsmind',
type : 'basic',
link : '/ui/icons/iconsmind'
},
{ {
id : 'user-interface.icons.feather', id : 'user-interface.icons.feather',
title: 'Feather', title: 'Feather',
@@ -973,7 +967,7 @@ export const defaultNavigation: FuseNavigationItem[] = [
icon : 'heroicons_outline:speakerphone', icon : 'heroicons_outline:speakerphone',
link : '/docs/changelog', link : '/docs/changelog',
badge: { badge: {
title : '14.0.0', title : '15.0.0',
classes: 'px-2 bg-yellow-300 text-black rounded-full' classes: 'px-2 bg-yellow-300 text-black rounded-full'
} }
}, },

View File

@@ -79,6 +79,9 @@ export class SearchMockApi
// Add a link // Add a link
result.link = '/apps/contacts/' + result.id; result.link = '/apps/contacts/' + result.id;
// Add the name as the value
result.value = result.name;
}); });
// Add to the results // Add to the results
@@ -95,6 +98,8 @@ export class SearchMockApi
// Normalize the results // Normalize the results
pagesResults.forEach((result: any) => { pagesResults.forEach((result: any) => {
// Add the page title as the value
result.value = result.title;
}); });
// Add to the results // Add to the results
@@ -113,6 +118,9 @@ export class SearchMockApi
// Add a link // Add a link
result.link = '/apps/tasks/' + result.id; result.link = '/apps/tasks/' + result.id;
// Add the title as the value
result.value = result.title;
}); });
// Add to the results // Add to the results

View File

@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { FuseMockApiService } from '@fuse/lib/mock-api'; import { FuseMockApiService } from '@fuse/lib/mock-api';
import { feather, heroicons, iconsmind, material } from 'app/mock-api/ui/icons/data'; import { feather, heroicons, material } from 'app/mock-api/ui/icons/data';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -10,7 +10,6 @@ export class IconsMockApi
{ {
private readonly _feather: any = feather; private readonly _feather: any = feather;
private readonly _heroicons: any = heroicons; private readonly _heroicons: any = heroicons;
private readonly _iconsmind: any = iconsmind;
private readonly _material: any = material; private readonly _material: any = material;
/** /**
@@ -41,7 +40,7 @@ export class IconsMockApi
{ {
namespace: 'feather', namespace: 'feather',
name : 'Feather', name : 'Feather',
grid : 6, grid : 'icon-size-6',
list : cloneDeep(this._feather) list : cloneDeep(this._feather)
} }
]); ]);
@@ -56,7 +55,7 @@ export class IconsMockApi
{ {
namespace: 'heroicons_outline', namespace: 'heroicons_outline',
name : 'Heroicons Outline', name : 'Heroicons Outline',
grid : 6, grid : 'icon-size-6',
list : cloneDeep(this._heroicons) list : cloneDeep(this._heroicons)
} }
]); ]);
@@ -71,26 +70,11 @@ export class IconsMockApi
{ {
namespace: 'heroicons_solid', namespace: 'heroicons_solid',
name : 'Heroicons Solid', name : 'Heroicons Solid',
grid : 5, grid : 'icon-size-5',
list : cloneDeep(this._heroicons) list : cloneDeep(this._heroicons)
} }
]); ]);
// -----------------------------------------------------------------------------------------------------
// @ Iconsmind icons - GET
// -----------------------------------------------------------------------------------------------------
this._fuseMockApiService
.onGet('api/ui/icons/iconsmind')
.reply(() => [
200,
{
namespace: 'iconsmind',
name : 'Iconsmind',
grid : 10,
list : cloneDeep(this._iconsmind)
}
]);
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------
// @ Material solid icons - GET // @ Material solid icons - GET
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------
@@ -101,7 +85,7 @@ export class IconsMockApi
{ {
namespace: 'mat_solid', namespace: 'mat_solid',
name : 'Material Solid', name : 'Material Solid',
grid : 6, grid : 'icon-size-6',
list : cloneDeep(this._material) list : cloneDeep(this._material)
} }
]); ]);
@@ -116,7 +100,7 @@ export class IconsMockApi
{ {
namespace: 'mat_outline', namespace: 'mat_outline',
name : 'Material Outline', name : 'Material Outline',
grid : 6, grid : 'icon-size-6',
list : cloneDeep(this._material) list : cloneDeep(this._material)
} }
]); ]);
@@ -131,7 +115,7 @@ export class IconsMockApi
{ {
namespace: '', namespace: '',
name : 'Material Twotone', name : 'Material Twotone',
grid : 6, grid : 'icon-size-6',
list : cloneDeep(this._material) list : cloneDeep(this._material)
} }
]); ]);

File diff suppressed because it is too large Load Diff

View File

@@ -61,8 +61,8 @@
class="relative flex items-start cursor-pointer" class="relative flex items-start cursor-pointer"
(click)="goToStep(step.order)"> (click)="goToStep(step.order)">
<div <div
class="flex flex-0 items-center justify-center w-8 h-8 rounded-full ring-2 ring-inset ring-transparent bg-card dark:bg-default" class="flex flex-0 items-center justify-center w-8 h-8 rounded-full ring-2 ring-inset bg-card dark:bg-default"
[ngClass]="{'bg-primary dark:bg-primary text-on-primary group-hover:bg-primary-800': step.order < currentStep, [ngClass]="{'bg-primary dark:bg-primary text-on-primary group-hover:bg-primary-800 ring-transparent': step.order < currentStep,
'ring-primary': step.order === currentStep, 'ring-primary': step.order === currentStep,
'ring-gray-300 dark:ring-gray-600 group-hover:ring-gray-400': step.order > currentStep}"> 'ring-gray-300 dark:ring-gray-600 group-hover:ring-gray-400': step.order > currentStep}">
<!-- Check icon, show if the step is completed --> <!-- Check icon, show if the step is completed -->
@@ -98,11 +98,11 @@
<!-- Header --> <!-- Header -->
<div class="lg:hidden flex flex-0 items-center py-2 pl-4 pr-6 sm:py-4 md:pl-6 md:pr-8 border-b lg:border-b-0 bg-card dark:bg-transparent"> <div class="lg:hidden flex flex-0 items-center py-2 pl-4 pr-6 sm:py-4 md:pl-6 md:pr-8 border-b lg:border-b-0 bg-card dark:bg-transparent">
<!-- Title & Actions --> <!-- Title & Actions -->
<button <a
mat-icon-button mat-icon-button
[routerLink]="['..']"> [routerLink]="['..']">
<mat-icon [svgIcon]="'heroicons_outline:arrow-sm-left'"></mat-icon> <mat-icon [svgIcon]="'heroicons_outline:arrow-sm-left'"></mat-icon>
</button> </a>
<h2 class="ml-2.5 text-md sm:text-xl font-medium tracking-tight truncate"> <h2 class="ml-2.5 text-md sm:text-xl font-medium tracking-tight truncate">
{{course.title}} {{course.title}}
</h2> </h2>

View File

@@ -146,7 +146,7 @@
<!-- Course launch button --> <!-- Course launch button -->
<div class="px-6 py-4 text-right bg-gray-50 dark:bg-transparent"> <div class="px-6 py-4 text-right bg-gray-50 dark:bg-transparent">
<button <a
mat-stroked-button mat-stroked-button
[routerLink]="[course.id]"> [routerLink]="[course.id]">
<span class="inline-flex items-center"> <span class="inline-flex items-center">
@@ -172,7 +172,7 @@
class="ml-1.5 icon-size-5" class="ml-1.5 icon-size-5"
[svgIcon]="'heroicons_solid:arrow-sm-right'"></mat-icon> [svgIcon]="'heroicons_solid:arrow-sm-right'"></mat-icon>
</span> </span>
</button> </a>
</div> </div>
</div> </div>
</div> </div>
@@ -184,8 +184,8 @@
<ng-template #noCourses> <ng-template #noCourses>
<div class="flex flex-auto flex-col items-center justify-center bg-gray-100 dark:bg-transparent"> <div class="flex flex-auto flex-col items-center justify-center bg-gray-100 dark:bg-transparent">
<mat-icon <mat-icon
class="icon-size-20" class="icon-size-24"
[svgIcon]="'iconsmind:file_search'"></mat-icon> [svgIcon]="'heroicons_outline:document-search'"></mat-icon>
<div class="mt-6 text-2xl font-semibold tracking-tight text-secondary">No courses found!</div> <div class="mt-6 text-2xl font-semibold tracking-tight text-secondary">No courses found!</div>
</div> </div>
</ng-template> </ng-template>

View File

@@ -12,6 +12,7 @@ import { chatRoutes } from 'app/modules/admin/apps/chat/chat.routing';
import { ChatComponent } from 'app/modules/admin/apps/chat/chat.component'; import { ChatComponent } from 'app/modules/admin/apps/chat/chat.component';
import { ChatsComponent } from 'app/modules/admin/apps/chat/chats/chats.component'; import { ChatsComponent } from 'app/modules/admin/apps/chat/chats/chats.component';
import { ContactInfoComponent } from 'app/modules/admin/apps/chat/contact-info/contact-info.component'; import { ContactInfoComponent } from 'app/modules/admin/apps/chat/contact-info/contact-info.component';
import { EmptyConversationComponent } from 'app/modules/admin/apps/chat/empty-conversation/empty-conversation.component';
import { ConversationComponent } from 'app/modules/admin/apps/chat/conversation/conversation.component'; import { ConversationComponent } from 'app/modules/admin/apps/chat/conversation/conversation.component';
import { NewChatComponent } from 'app/modules/admin/apps/chat/new-chat/new-chat.component'; import { NewChatComponent } from 'app/modules/admin/apps/chat/new-chat/new-chat.component';
import { ProfileComponent } from 'app/modules/admin/apps/chat/profile/profile.component'; import { ProfileComponent } from 'app/modules/admin/apps/chat/profile/profile.component';
@@ -22,6 +23,7 @@ import { ProfileComponent } from 'app/modules/admin/apps/chat/profile/profile.co
ChatsComponent, ChatsComponent,
ContactInfoComponent, ContactInfoComponent,
ConversationComponent, ConversationComponent,
EmptyConversationComponent,
NewChatComponent, NewChatComponent,
ProfileComponent ProfileComponent
], ],

View File

@@ -3,6 +3,7 @@ import { ChatChatResolver, ChatChatsResolver, ChatContactsResolver, ChatProfileR
import { ChatComponent } from 'app/modules/admin/apps/chat/chat.component'; import { ChatComponent } from 'app/modules/admin/apps/chat/chat.component';
import { ChatsComponent } from 'app/modules/admin/apps/chat/chats/chats.component'; import { ChatsComponent } from 'app/modules/admin/apps/chat/chats/chats.component';
import { ConversationComponent } from 'app/modules/admin/apps/chat/conversation/conversation.component'; import { ConversationComponent } from 'app/modules/admin/apps/chat/conversation/conversation.component';
import { EmptyConversationComponent } from 'app/modules/admin/apps/chat/empty-conversation/empty-conversation.component';
export const chatRoutes: Route[] = [ export const chatRoutes: Route[] = [
{ {
@@ -20,15 +21,15 @@ export const chatRoutes: Route[] = [
children : [ children : [
{ {
path : '', path : '',
pathMatch: 'full',
component: EmptyConversationComponent
},
{
path : ':id',
component: ConversationComponent, component: ConversationComponent,
children : [ resolve : {
{ conversation: ChatChatResolver
path : ':id', }
resolve: {
conversation: ChatChatResolver
}
}
]
} }
] ]
} }

View File

@@ -115,7 +115,7 @@
<div class="flex-auto overflow-y-auto"> <div class="flex-auto overflow-y-auto">
<ng-container *ngIf="filteredChats.length > 0; else noChats"> <ng-container *ngIf="filteredChats.length > 0; else noChats">
<ng-container *ngFor="let chat of filteredChats; trackBy: trackByFn"> <ng-container *ngFor="let chat of filteredChats; trackBy: trackByFn">
<div <a
class="z-20 flex items-center py-5 px-8 cursor-pointer border-b" class="z-20 flex items-center py-5 px-8 cursor-pointer border-b"
[ngClass]="{'hover:bg-gray-100 dark:hover:bg-hover': !selectedChat || selectedChat.id !== chat.id, [ngClass]="{'hover:bg-gray-100 dark:hover:bg-hover': !selectedChat || selectedChat.id !== chat.id,
'bg-primary-50 dark:bg-hover': selectedChat && selectedChat.id === chat.id}" 'bg-primary-50 dark:bg-hover': selectedChat && selectedChat.id === chat.id}"
@@ -155,7 +155,7 @@
[svgIcon]="'heroicons_solid:volume-off'"></mat-icon> [svgIcon]="'heroicons_solid:volume-off'"></mat-icon>
</ng-container> </ng-container>
</div> </div>
</div> </a>
</ng-container> </ng-container>
</ng-container> </ng-container>
</div> </div>
@@ -169,7 +169,7 @@
<div class="flex flex-auto flex-col items-center justify-center h-full"> <div class="flex flex-auto flex-col items-center justify-center h-full">
<mat-icon <mat-icon
class="icon-size-24" class="icon-size-24"
[svgIcon]="'iconsmind:speach_bubble'"></mat-icon> [svgIcon]="'heroicons_outline:chat'"></mat-icon>
<div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">No chats</div> <div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">No chats</div>
</div> </div>
</ng-template> </ng-template>

View File

@@ -99,7 +99,7 @@
<!-- Conversation --> <!-- Conversation -->
<div class="flex overflow-y-auto flex-col-reverse"> <div class="flex overflow-y-auto flex-col-reverse">
<div class="flex flex-col flex-auto flex-shrink p-6 bg-card dark:bg-transparent"> <div class="flex flex-col flex-auto shrink p-6 bg-card dark:bg-transparent">
<ng-container *ngFor="let message of chat.messages; let i = index; let first = first; let last = last; trackBy: trackByFn"> <ng-container *ngFor="let message of chat.messages; let i = index; let first = first; let last = last; trackBy: trackByFn">
<!-- Start of the day --> <!-- Start of the day -->
<ng-container *ngIf="first || (chat.messages[i - 1].createdAt | date:'d') !== (message.createdAt | date:'d')"> <ng-container *ngIf="first || (chat.messages[i - 1].createdAt | date:'d') !== (message.createdAt | date:'d')">
@@ -114,20 +114,20 @@
<div <div
class="flex flex-col" class="flex flex-col"
[ngClass]="{'items-end': message.isMine, [ngClass]="{'items-end': message.isMine,
'items-start': !message.isMine, 'items-start': !message.isMine,
'mt-0.5': i > 0 && chat.messages[i - 1].isMine === message.isMine, 'mt-0.5': i > 0 && chat.messages[i - 1].isMine === message.isMine,
'mt-3': i > 0 && chat.messages[i - 1].isMine !== message.isMine}"> 'mt-3': i > 0 && chat.messages[i - 1].isMine !== message.isMine}">
<!-- Bubble --> <!-- Bubble -->
<div <div
class="relative max-w-3/4 px-3 py-2 rounded-lg" class="relative max-w-3/4 px-3 py-2 rounded-lg"
[ngClass]="{'bg-blue-500 text-blue-50': message.isMine, [ngClass]="{'bg-blue-500 text-blue-50': message.isMine,
'bg-gray-500 text-gray-50': !message.isMine}"> 'bg-gray-500 text-gray-50': !message.isMine}">
<!-- Speech bubble tail --> <!-- Speech bubble tail -->
<ng-container *ngIf="last || chat.messages[i + 1].isMine !== message.isMine"> <ng-container *ngIf="last || chat.messages[i + 1].isMine !== message.isMine">
<div <div
class="absolute bottom-0 w-3 transform" class="absolute bottom-0 w-3"
[ngClass]="{'text-blue-500 -right-1 -mr-px mb-px': message.isMine, [ngClass]="{'text-blue-500 -right-1 -mr-px mb-px': message.isMine,
'text-gray-500 -left-1 -ml-px mb-px -scale-x-1': !message.isMine}"> 'text-gray-500 -left-1 -ml-px mb-px -scale-x-1': !message.isMine}">
<ng-container *ngTemplateOutlet="speechBubbleExtension"></ng-container> <ng-container *ngTemplateOutlet="speechBubbleExtension"></ng-container>
</div> </div>
</ng-container> </ng-container>
@@ -146,7 +146,7 @@
<div <div
class="my-0.5 text-sm font-medium text-secondary" class="my-0.5 text-sm font-medium text-secondary"
[ngClass]="{'mr-3': message.isMine, [ngClass]="{'mr-3': message.isMine,
'ml-3': !message.isMine}"> 'ml-3': !message.isMine}">
{{message.createdAt | date:'HH:mm'}} {{message.createdAt | date:'HH:mm'}}
</div> </div>
</ng-container> </ng-container>
@@ -179,7 +179,7 @@
<button <button
mat-icon-button> mat-icon-button>
<mat-icon <mat-icon
class="transform rotate-90" class="rotate-90"
[svgIcon]="'heroicons_outline:paper-airplane'"></mat-icon> [svgIcon]="'heroicons_outline:paper-airplane'"></mat-icon>
</button> </button>
</div> </div>
@@ -196,7 +196,7 @@
<div class="flex flex-col flex-auto items-center justify-center bg-gray-100 dark:bg-transparent"> <div class="flex flex-col flex-auto items-center justify-center bg-gray-100 dark:bg-transparent">
<mat-icon <mat-icon
class="icon-size-24" class="icon-size-24"
[svgIcon]="'iconsmind:speach_bubble'"></mat-icon> [svgIcon]="'heroicons_outline:chat'"></mat-icon>
<div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">Select a conversation or start a new chat</div> <div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">Select a conversation or start a new chat</div>
</div> </div>
</ng-template> </ng-template>

View File

@@ -0,0 +1,11 @@
<div class="flex flex-col flex-auto overflow-y-auto lg:overflow-hidden bg-card dark:bg-default">
<!-- Select chat or start new -->
<div class="flex flex-col flex-auto items-center justify-center bg-gray-100 dark:bg-transparent">
<mat-icon
class="icon-size-24"
[svgIcon]="'heroicons_outline:chat'"></mat-icon>
<div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">Select a conversation or start a new chat</div>
</div>
</div>

View File

@@ -0,0 +1,17 @@
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
@Component({
selector : 'chat-empty-conversation',
templateUrl : './empty-conversation.component.html',
encapsulation : ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class EmptyConversationComponent
{
/**
* Constructor
*/
constructor()
{
}
}

View File

@@ -17,7 +17,7 @@ export const contactsRoutes: Route[] = [
path : '', path : '',
component: ContactsListComponent, component: ContactsListComponent,
resolve : { resolve : {
tasks : ContactsResolver, contacts : ContactsResolver,
countries: ContactsCountriesResolver countries: ContactsCountriesResolver
}, },
children : [ children : [
@@ -25,7 +25,7 @@ export const contactsRoutes: Route[] = [
path : ':id', path : ':id',
component : ContactsDetailsComponent, component : ContactsDetailsComponent,
resolve : { resolve : {
task : ContactsContactResolver, contact : ContactsContactResolver,
countries: ContactsCountriesResolver countries: ContactsCountriesResolver
}, },
canDeactivate: [CanDeactivateContactsDetails] canDeactivate: [CanDeactivateContactsDetails]

View File

@@ -13,14 +13,14 @@
</ng-container> </ng-container>
<!-- Close button --> <!-- Close button -->
<div class="flex items-center justify-end w-full max-w-3xl mx-auto pt-6"> <div class="flex items-center justify-end w-full max-w-3xl mx-auto pt-6">
<button <a
mat-icon-button mat-icon-button
[matTooltip]="'Close'" [matTooltip]="'Close'"
[routerLink]="['../']"> [routerLink]="['../']">
<mat-icon <mat-icon
class="text-white" class="text-white"
[svgIcon]="'heroicons_outline:x'"></mat-icon> [svgIcon]="'heroicons_outline:x'"></mat-icon>
</button> </a>
</div> </div>
</div> </div>
@@ -183,14 +183,14 @@
</ng-container> </ng-container>
<!-- Close button --> <!-- Close button -->
<div class="flex items-center justify-end w-full max-w-3xl mx-auto pt-6"> <div class="flex items-center justify-end w-full max-w-3xl mx-auto pt-6">
<button <a
mat-icon-button mat-icon-button
[matTooltip]="'Close'" [matTooltip]="'Close'"
[routerLink]="['../']"> [routerLink]="['../']">
<mat-icon <mat-icon
class="text-white" class="text-white"
[svgIcon]="'heroicons_outline:x'"></mat-icon> [svgIcon]="'heroicons_outline:x'"></mat-icon>
</button> </a>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, Renderer2, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, Renderer2, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { TemplatePortal } from '@angular/cdk/portal'; import { TemplatePortal } from '@angular/cdk/portal';
import { Overlay, OverlayRef } from '@angular/cdk/overlay'; import { Overlay, OverlayRef } from '@angular/cdk/overlay';
import { MatDrawerToggleResult } from '@angular/material/sidenav'; import { MatDrawerToggleResult } from '@angular/material/sidenav';
@@ -27,7 +27,7 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
tagsEditMode: boolean = false; tagsEditMode: boolean = false;
filteredTags: Tag[]; filteredTags: Tag[];
contact: Contact; contact: Contact;
contactForm: FormGroup; contactForm: UntypedFormGroup;
contacts: Contact[]; contacts: Contact[];
countries: Country[]; countries: Country[];
private _tagsPanelOverlayRef: OverlayRef; private _tagsPanelOverlayRef: OverlayRef;
@@ -41,7 +41,7 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
private _changeDetectorRef: ChangeDetectorRef, private _changeDetectorRef: ChangeDetectorRef,
private _contactsListComponent: ContactsListComponent, private _contactsListComponent: ContactsListComponent,
private _contactsService: ContactsService, private _contactsService: ContactsService,
private _formBuilder: FormBuilder, private _formBuilder: UntypedFormBuilder,
private _fuseConfirmationService: FuseConfirmationService, private _fuseConfirmationService: FuseConfirmationService,
private _renderer2: Renderer2, private _renderer2: Renderer2,
private _router: Router, private _router: Router,
@@ -100,8 +100,8 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
this.contact = contact; this.contact = contact;
// Clear the emails and phoneNumbers form arrays // Clear the emails and phoneNumbers form arrays
(this.contactForm.get('emails') as FormArray).clear(); (this.contactForm.get('emails') as UntypedFormArray).clear();
(this.contactForm.get('phoneNumbers') as FormArray).clear(); (this.contactForm.get('phoneNumbers') as UntypedFormArray).clear();
// Patch values to the form // Patch values to the form
this.contactForm.patchValue(contact); this.contactForm.patchValue(contact);
@@ -136,7 +136,7 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
// Add the email form groups to the emails form array // Add the email form groups to the emails form array
emailFormGroups.forEach((emailFormGroup) => { emailFormGroups.forEach((emailFormGroup) => {
(this.contactForm.get('emails') as FormArray).push(emailFormGroup); (this.contactForm.get('emails') as UntypedFormArray).push(emailFormGroup);
}); });
// Setup the phone numbers form array // Setup the phone numbers form array
@@ -171,7 +171,7 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
// Add the phone numbers form groups to the phone numbers form array // Add the phone numbers form groups to the phone numbers form array
phoneNumbersFormGroups.forEach((phoneNumbersFormGroup) => { phoneNumbersFormGroups.forEach((phoneNumbersFormGroup) => {
(this.contactForm.get('phoneNumbers') as FormArray).push(phoneNumbersFormGroup); (this.contactForm.get('phoneNumbers') as UntypedFormArray).push(phoneNumbersFormGroup);
}); });
// Toggle the edit mode off // Toggle the edit mode off
@@ -639,7 +639,7 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
}); });
// Add the email form group to the emails form array // Add the email form group to the emails form array
(this.contactForm.get('emails') as FormArray).push(emailFormGroup); (this.contactForm.get('emails') as UntypedFormArray).push(emailFormGroup);
// Mark for check // Mark for check
this._changeDetectorRef.markForCheck(); this._changeDetectorRef.markForCheck();
@@ -653,7 +653,7 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
removeEmailField(index: number): void removeEmailField(index: number): void
{ {
// Get form array for emails // Get form array for emails
const emailsFormArray = this.contactForm.get('emails') as FormArray; const emailsFormArray = this.contactForm.get('emails') as UntypedFormArray;
// Remove the email field // Remove the email field
emailsFormArray.removeAt(index); emailsFormArray.removeAt(index);
@@ -675,7 +675,7 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
}); });
// Add the phone number form group to the phoneNumbers form array // Add the phone number form group to the phoneNumbers form array
(this.contactForm.get('phoneNumbers') as FormArray).push(phoneNumberFormGroup); (this.contactForm.get('phoneNumbers') as UntypedFormArray).push(phoneNumberFormGroup);
// Mark for check // Mark for check
this._changeDetectorRef.markForCheck(); this._changeDetectorRef.markForCheck();
@@ -689,7 +689,7 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
removePhoneNumberField(index: number): void removePhoneNumberField(index: number): void
{ {
// Get form array for phone numbers // Get form array for phone numbers
const phoneNumbersFormArray = this.contactForm.get('phoneNumbers') as FormArray; const phoneNumbersFormArray = this.contactForm.get('phoneNumbers') as UntypedFormArray;
// Remove the phone number field // Remove the phone number field
phoneNumbersFormArray.removeAt(index); phoneNumbersFormArray.removeAt(index);

View File

@@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { DOCUMENT } from '@angular/common'; import { DOCUMENT } from '@angular/common';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { FormControl } from '@angular/forms'; import { UntypedFormControl } from '@angular/forms';
import { MatDrawer } from '@angular/material/sidenav'; import { MatDrawer } from '@angular/material/sidenav';
import { filter, fromEvent, Observable, Subject, switchMap, takeUntil } from 'rxjs'; import { filter, fromEvent, Observable, Subject, switchMap, takeUntil } from 'rxjs';
import { FuseMediaWatcherService } from '@fuse/services/media-watcher'; import { FuseMediaWatcherService } from '@fuse/services/media-watcher';
@@ -24,7 +24,7 @@ export class ContactsListComponent implements OnInit, OnDestroy
contactsTableColumns: string[] = ['name', 'email', 'phoneNumber', 'job']; contactsTableColumns: string[] = ['name', 'email', 'phoneNumber', 'job'];
countries: Country[]; countries: Country[];
drawerMode: 'side' | 'over'; drawerMode: 'side' | 'over';
searchInputControl: FormControl = new FormControl(); searchInputControl: UntypedFormControl = new UntypedFormControl();
selectedContact: Contact; selectedContact: Contact;
private _unsubscribeAll: Subject<any> = new Subject<any>(); private _unsubscribeAll: Subject<any> = new Subject<any>();

View File

@@ -11,7 +11,7 @@
<!-- Title --> <!-- Title -->
<div class="text-4xl font-extrabold tracking-tight">Inventory</div> <div class="text-4xl font-extrabold tracking-tight">Inventory</div>
<!-- Actions --> <!-- Actions -->
<div class="flex flex-shrink-0 items-center mt-6 sm:mt-0 sm:ml-4"> <div class="flex shrink-0 items-center mt-6 sm:mt-0 sm:ml-4">
<!-- Search --> <!-- Search -->
<mat-form-field class="fuse-mat-dense fuse-mat-no-subscript fuse-mat-rounded min-w-64"> <mat-form-field class="fuse-mat-dense fuse-mat-no-subscript fuse-mat-rounded min-w-64">
<mat-icon <mat-icon

View File

@@ -1,5 +1,5 @@
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { MatCheckboxChange } from '@angular/material/checkbox'; import { MatCheckboxChange } from '@angular/material/checkbox';
import { MatPaginator } from '@angular/material/paginator'; import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
@@ -49,9 +49,9 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
flashMessage: 'success' | 'error' | null = null; flashMessage: 'success' | 'error' | null = null;
isLoading: boolean = false; isLoading: boolean = false;
pagination: InventoryPagination; pagination: InventoryPagination;
searchInputControl: FormControl = new FormControl(); searchInputControl: UntypedFormControl = new UntypedFormControl();
selectedProduct: InventoryProduct | null = null; selectedProduct: InventoryProduct | null = null;
selectedProductForm: FormGroup; selectedProductForm: UntypedFormGroup;
tags: InventoryTag[]; tags: InventoryTag[];
tagsEditMode: boolean = false; tagsEditMode: boolean = false;
vendors: InventoryVendor[]; vendors: InventoryVendor[];
@@ -63,7 +63,7 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
constructor( constructor(
private _changeDetectorRef: ChangeDetectorRef, private _changeDetectorRef: ChangeDetectorRef,
private _fuseConfirmationService: FuseConfirmationService, private _fuseConfirmationService: FuseConfirmationService,
private _formBuilder: FormBuilder, private _formBuilder: UntypedFormBuilder,
private _inventoryService: InventoryService private _inventoryService: InventoryService
) )
{ {

View File

@@ -2,11 +2,11 @@
<!-- Close button --> <!-- Close button -->
<div class="flex items-center justify-end"> <div class="flex items-center justify-end">
<button <a
mat-icon-button mat-icon-button
[routerLink]="['../../']"> [routerLink]="['../../']">
<mat-icon [svgIcon]="'heroicons_outline:x'"></mat-icon> <mat-icon [svgIcon]="'heroicons_outline:x'"></mat-icon>
</button> </a>
</div> </div>
<!-- Preview --> <!-- Preview -->
@@ -14,13 +14,13 @@
<div class="flex items-center justify-center border rounded-lg bg-gray-50 dark:bg-card"> <div class="flex items-center justify-center border rounded-lg bg-gray-50 dark:bg-card">
<ng-container *ngIf="item.type === 'folder'"> <ng-container *ngIf="item.type === 'folder'">
<mat-icon <mat-icon
class="icon-size-14 text-hint" class="icon-size-24 text-hint"
[svgIcon]="'iconsmind:folder'"></mat-icon> [svgIcon]="'heroicons_outline:folder'"></mat-icon>
</ng-container> </ng-container>
<ng-container *ngIf="item.type !== 'folder'"> <ng-container *ngIf="item.type !== 'folder'">
<mat-icon <mat-icon
class="icon-size-14 text-hint" class="icon-size-24 text-hint"
[svgIcon]="'iconsmind:file'"></mat-icon> [svgIcon]="'heroicons_outline:document'"></mat-icon>
</ng-container> </ng-container>
</div> </div>
</div> </div>

View File

@@ -94,7 +94,7 @@
<!-- Icon --> <!-- Icon -->
<mat-icon <mat-icon
class="icon-size-14 text-hint" class="icon-size-14 text-hint"
[svgIcon]="'iconsmind:folder'"></mat-icon> [svgIcon]="'heroicons_outline:folder'"></mat-icon>
</div> </div>
</div> </div>
<div class="flex flex-col flex-auto justify-center text-center text-sm font-medium"> <div class="flex flex-col flex-auto justify-center text-center text-sm font-medium">
@@ -128,7 +128,7 @@
<div class="relative"> <div class="relative">
<mat-icon <mat-icon
class="icon-size-14 text-hint" class="icon-size-14 text-hint"
[svgIcon]="'iconsmind:file'"></mat-icon> [svgIcon]="'heroicons_outline:document'"></mat-icon>
<div <div
class="absolute left-0 bottom-0 px-1.5 rounded text-sm font-semibold leading-5 text-white" class="absolute left-0 bottom-0 px-1.5 rounded text-sm font-semibold leading-5 text-white"
[class.bg-red-600]="file.type === 'PDF'" [class.bg-red-600]="file.type === 'PDF'"
@@ -162,7 +162,7 @@
<div class="flex flex-auto flex-col items-center justify-center bg-gray-100 dark:bg-transparent"> <div class="flex flex-auto flex-col items-center justify-center bg-gray-100 dark:bg-transparent">
<mat-icon <mat-icon
class="icon-size-24" class="icon-size-24"
[svgIcon]="'iconsmind:file_hide'"></mat-icon> [svgIcon]="'heroicons_outline:folder-open'"></mat-icon>
<div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">There are no items!</div> <div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">There are no items!</div>
</div> </div>
</ng-template> </ng-template>

View File

@@ -37,7 +37,7 @@
<!-- Next --> <!-- Next -->
<a <a
class="mt-8 flex items-center justify-between p-6 sm:px-10 rounded-2xl shadow hover:shadow-lg bg-card transform transition-shadow ease-in-out duration-150" class="mt-8 flex items-center justify-between p-6 sm:px-10 rounded-2xl shadow hover:shadow-lg bg-card transition-shadow ease-in-out duration-150"
[routerLink]="'.'"> [routerLink]="'.'">
<div> <div>
<div class="text-secondary">Next</div> <div class="text-secondary">Next</div>

View File

@@ -35,7 +35,7 @@
<!-- Cards --> <!-- Cards -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-y-8 md:gap-y-0 md:gap-x-6 w-full max-w-sm md:max-w-4xl -mt-16 sm:-mt-24"> <div class="grid grid-cols-1 md:grid-cols-3 gap-y-8 md:gap-y-0 md:gap-x-6 w-full max-w-sm md:max-w-4xl -mt-16 sm:-mt-24">
<!-- FAQs card --> <!-- FAQs card -->
<div class="relative flex flex-col rounded-2xl shadow hover:shadow-lg overflow-hidden bg-card transform transition-shadow ease-in-out duration-150"> <div class="relative flex flex-col rounded-2xl shadow hover:shadow-lg overflow-hidden bg-card transition-shadow ease-in-out duration-150">
<div class="flex flex-col flex-auto items-center p-8 text-center"> <div class="flex flex-col flex-auto items-center p-8 text-center">
<div class="text-2xl font-semibold">FAQs</div> <div class="text-2xl font-semibold">FAQs</div>
<div class="md:max-w-40 mt-1 text-secondary">Frequently asked questions and answers</div> <div class="md:max-w-40 mt-1 text-secondary">Frequently asked questions and answers</div>
@@ -53,7 +53,7 @@
</div> </div>
</div> </div>
<!-- Guides card --> <!-- Guides card -->
<div class="relative flex flex-col rounded-2xl shadow hover:shadow-lg overflow-hidden bg-card transform transition-shadow ease-in-out duration-150"> <div class="relative flex flex-col rounded-2xl shadow hover:shadow-lg overflow-hidden bg-card transition-shadow ease-in-out duration-150">
<div class="flex flex-col flex-auto items-center p-8 text-center"> <div class="flex flex-col flex-auto items-center p-8 text-center">
<div class="text-2xl font-semibold">Guides</div> <div class="text-2xl font-semibold">Guides</div>
<div class="md:max-w-40 mt-1 text-secondary">Articles and resources to guide you</div> <div class="md:max-w-40 mt-1 text-secondary">Articles and resources to guide you</div>
@@ -71,7 +71,7 @@
</div> </div>
</div> </div>
<!-- Support card --> <!-- Support card -->
<div class="relative flex flex-col rounded-2xl shadow hover:shadow-lg overflow-hidden bg-card transform transition-shadow ease-in-out duration-150"> <div class="relative flex flex-col rounded-2xl shadow hover:shadow-lg overflow-hidden bg-card transition-shadow ease-in-out duration-150">
<div class="flex flex-col flex-auto items-center p-8 text-center"> <div class="flex flex-col flex-auto items-center p-8 text-center">
<div class="text-2xl font-semibold">Support</div> <div class="text-2xl font-semibold">Support</div>
<div class="md:max-w-40 mt-1 text-secondary">Contact us for more detailed support</div> <div class="md:max-w-40 mt-1 text-secondary">Contact us for more detailed support</div>

View File

@@ -1,5 +1,5 @@
import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup, NgForm, Validators } from '@angular/forms';
import { fuseAnimations } from '@fuse/animations'; import { fuseAnimations } from '@fuse/animations';
import { HelpCenterService } from 'app/modules/admin/apps/help-center/help-center.service'; import { HelpCenterService } from 'app/modules/admin/apps/help-center/help-center.service';
@@ -14,13 +14,13 @@ export class HelpCenterSupportComponent implements OnInit
@ViewChild('supportNgForm') supportNgForm: NgForm; @ViewChild('supportNgForm') supportNgForm: NgForm;
alert: any; alert: any;
supportForm: FormGroup; supportForm: UntypedFormGroup;
/** /**
* Constructor * Constructor
*/ */
constructor( constructor(
private _formBuilder: FormBuilder, private _formBuilder: UntypedFormBuilder,
private _helpCenterService: HelpCenterService private _helpCenterService: HelpCenterService
) )
{ {

View File

@@ -72,6 +72,7 @@
<quill-editor <quill-editor
class="mt-2" class="mt-2"
[formControlName]="'body'" [formControlName]="'body'"
[bounds]="'self'"
[modules]="quillModules"></quill-editor> [modules]="quillModules"></quill-editor>
<!-- Actions --> <!-- Actions -->

View File

@@ -1,5 +1,5 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MatDialogRef } from '@angular/material/dialog'; import { MatDialogRef } from '@angular/material/dialog';
@Component({ @Component({
@@ -9,7 +9,7 @@ import { MatDialogRef } from '@angular/material/dialog';
}) })
export class MailboxComposeComponent implements OnInit export class MailboxComposeComponent implements OnInit
{ {
composeForm: FormGroup; composeForm: UntypedFormGroup;
copyFields: { cc: boolean; bcc: boolean } = { copyFields: { cc: boolean; bcc: boolean } = {
cc : false, cc : false,
bcc: false bcc: false
@@ -27,7 +27,7 @@ export class MailboxComposeComponent implements OnInit
*/ */
constructor( constructor(
public matDialogRef: MatDialogRef<MailboxComposeComponent>, public matDialogRef: MatDialogRef<MailboxComposeComponent>,
private _formBuilder: FormBuilder private _formBuilder: UntypedFormBuilder
) )
{ {
} }

View File

@@ -128,7 +128,7 @@
<!-- Threads --> <!-- Threads -->
<div <div
class="flex flex-col flex-auto flex-shrink-0 lg:flex-shrink p-3 lg:overflow-y-auto bg-gray-100 dark:bg-transparent" class="flex flex-col flex-auto shrink-0 lg:shrink p-3 lg:overflow-y-auto bg-gray-100 dark:bg-transparent"
fuseScrollReset> fuseScrollReset>
<!-- Thread --> <!-- Thread -->
@@ -400,7 +400,7 @@
<div class="flex flex-col flex-auto items-center justify-center bg-gray-100 dark:bg-transparent"> <div class="flex flex-col flex-auto items-center justify-center bg-gray-100 dark:bg-transparent">
<mat-icon <mat-icon
class="icon-size-24" class="icon-size-24"
[svgIcon]="'iconsmind:mailbox_empty'"></mat-icon> [svgIcon]="'heroicons_outline:mail'"></mat-icon>
<div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">Select a mail to read</div> <div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">Select a mail to read</div>
</div> </div>

View File

@@ -0,0 +1,11 @@
<div class="flex flex-col flex-auto overflow-y-auto lg:overflow-hidden bg-card dark:bg-default">
<!-- Select mail to read -->
<div class="flex flex-col flex-auto items-center justify-center bg-gray-100 dark:bg-transparent">
<mat-icon
class="icon-size-24"
[svgIcon]="'heroicons_outline:mail'"></mat-icon>
<div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">Select a mail to read</div>
</div>
</div>

View File

@@ -0,0 +1,16 @@
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector : 'mailbox-empty-details',
templateUrl : './empty-details.component.html',
encapsulation: ViewEncapsulation.None
})
export class MailboxEmptyDetailsComponent
{
/**
* Constructor
*/
constructor()
{
}
}

View File

@@ -136,7 +136,7 @@
<div class="z-100 absolute inset-0 flex flex-auto flex-col items-center justify-center bg-gray-100 dark:bg-transparent"> <div class="z-100 absolute inset-0 flex flex-auto flex-col items-center justify-center bg-gray-100 dark:bg-transparent">
<mat-icon <mat-icon
class="icon-size-24" class="icon-size-24"
[svgIcon]="'iconsmind:mailbox_empty'"></mat-icon> [svgIcon]="'heroicons_outline:mail'"></mat-icon>
<div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">There are no e-mails</div> <div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">There are no e-mails</div>
</div> </div>
</ng-template> </ng-template>

View File

@@ -20,6 +20,7 @@ import { SharedModule } from 'app/shared/shared.module';
import { MailboxComponent } from 'app/modules/admin/apps/mailbox/mailbox.component'; import { MailboxComponent } from 'app/modules/admin/apps/mailbox/mailbox.component';
import { MailboxComposeComponent } from 'app/modules/admin/apps/mailbox/compose/compose.component'; import { MailboxComposeComponent } from 'app/modules/admin/apps/mailbox/compose/compose.component';
import { MailboxDetailsComponent } from 'app/modules/admin/apps/mailbox/details/details.component'; import { MailboxDetailsComponent } from 'app/modules/admin/apps/mailbox/details/details.component';
import { MailboxEmptyDetailsComponent } from 'app/modules/admin/apps/mailbox/empty-details/empty-details.component';
import { MailboxListComponent } from 'app/modules/admin/apps/mailbox/list/list.component'; import { MailboxListComponent } from 'app/modules/admin/apps/mailbox/list/list.component';
import { MailboxSettingsComponent } from 'app/modules/admin/apps/mailbox/settings/settings.component'; import { MailboxSettingsComponent } from 'app/modules/admin/apps/mailbox/settings/settings.component';
import { MailboxSidebarComponent } from 'app/modules/admin/apps/mailbox/sidebar/sidebar.component'; import { MailboxSidebarComponent } from 'app/modules/admin/apps/mailbox/sidebar/sidebar.component';
@@ -30,6 +31,7 @@ import { mailboxRoutes } from 'app/modules/admin/apps/mailbox/mailbox.routing';
MailboxComponent, MailboxComponent,
MailboxComposeComponent, MailboxComposeComponent,
MailboxDetailsComponent, MailboxDetailsComponent,
MailboxEmptyDetailsComponent,
MailboxListComponent, MailboxListComponent,
MailboxSettingsComponent, MailboxSettingsComponent,
MailboxSidebarComponent MailboxSidebarComponent

View File

@@ -5,6 +5,7 @@ import { MailboxFiltersResolver, MailboxFoldersResolver, MailboxLabelsResolver,
import { MailboxListComponent } from 'app/modules/admin/apps/mailbox/list/list.component'; import { MailboxListComponent } from 'app/modules/admin/apps/mailbox/list/list.component';
import { MailboxDetailsComponent } from 'app/modules/admin/apps/mailbox/details/details.component'; import { MailboxDetailsComponent } from 'app/modules/admin/apps/mailbox/details/details.component';
import { MailboxSettingsComponent } from 'app/modules/admin/apps/mailbox/settings/settings.component'; import { MailboxSettingsComponent } from 'app/modules/admin/apps/mailbox/settings/settings.component';
import { MailboxEmptyDetailsComponent } from 'app/modules/admin/apps/mailbox/empty-details/empty-details.component';
/** /**
* Mailbox custom route matcher * Mailbox custom route matcher
@@ -141,15 +142,15 @@ export const mailboxRoutes: Route[] = [
children : [ children : [
{ {
path : '', path : '',
pathMatch: 'full',
component: MailboxEmptyDetailsComponent
},
{
path : ':id',
component: MailboxDetailsComponent, component: MailboxDetailsComponent,
children : [ resolve : {
{ mail: MailboxMailResolver
path : ':id', }
resolve: {
mail: MailboxMailResolver
}
}
]
} }
] ]
}, },

View File

@@ -1,5 +1,5 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { debounceTime, take } from 'rxjs'; import { debounceTime, take } from 'rxjs';
import { MailboxComponent } from 'app/modules/admin/apps/mailbox/mailbox.component'; import { MailboxComponent } from 'app/modules/admin/apps/mailbox/mailbox.component';
import { MailboxService } from 'app/modules/admin/apps/mailbox/mailbox.service'; import { MailboxService } from 'app/modules/admin/apps/mailbox/mailbox.service';
@@ -16,14 +16,14 @@ export class MailboxSettingsComponent implements OnInit
labelColors: any = labelColors; labelColors: any = labelColors;
labelColorDefs: any = labelColorDefs; labelColorDefs: any = labelColorDefs;
labels: MailLabel[]; labels: MailLabel[];
labelsForm: FormGroup; labelsForm: UntypedFormGroup;
/** /**
* Constructor * Constructor
*/ */
constructor( constructor(
public mailboxComponent: MailboxComponent, public mailboxComponent: MailboxComponent,
private _formBuilder: FormBuilder, private _formBuilder: UntypedFormBuilder,
private _mailboxService: MailboxService private _mailboxService: MailboxService
) )
{ {
@@ -67,7 +67,7 @@ export class MailboxSettingsComponent implements OnInit
}); });
// Add the label form group to the labels form array // Add the label form group to the labels form array
(this.labelsForm.get('labels') as FormArray).push(labelFormGroup); (this.labelsForm.get('labels') as UntypedFormArray).push(labelFormGroup);
}); });
}); });
@@ -92,7 +92,7 @@ export class MailboxSettingsComponent implements OnInit
this._mailboxService.addLabel(this.labelsForm.get('newLabel').value).subscribe((addedLabel) => { this._mailboxService.addLabel(this.labelsForm.get('newLabel').value).subscribe((addedLabel) => {
// Push the new label to the labels form array // Push the new label to the labels form array
(this.labelsForm.get('labels') as FormArray).push(this._formBuilder.group({ (this.labelsForm.get('labels') as UntypedFormArray).push(this._formBuilder.group({
id : [addedLabel.id], id : [addedLabel.id],
title: [addedLabel.title, Validators.required], title: [addedLabel.title, Validators.required],
slug : [addedLabel.slug], slug : [addedLabel.slug],
@@ -114,7 +114,7 @@ export class MailboxSettingsComponent implements OnInit
deleteLabel(id: string): void deleteLabel(id: string): void
{ {
// Get the labels form array // Get the labels form array
const labelsFormArray = this.labelsForm.get('labels') as FormArray; const labelsFormArray = this.labelsForm.get('labels') as UntypedFormArray;
// Remove the label from the labels form array // Remove the label from the labels form array
labelsFormArray.removeAt(labelsFormArray.value.findIndex(label => label.id === id)); labelsFormArray.removeAt(labelsFormArray.value.findIndex(label => label.id === id));
@@ -129,7 +129,7 @@ export class MailboxSettingsComponent implements OnInit
updateLabels(): void updateLabels(): void
{ {
// Iterate through the labels form array controls // Iterate through the labels form array controls
(this.labelsForm.get('labels') as FormArray).controls.forEach((labelFormGroup) => { (this.labelsForm.get('labels') as UntypedFormArray).controls.forEach((labelFormGroup) => {
// If the label has been edited... // If the label has been edited...
if ( labelFormGroup.dirty ) if ( labelFormGroup.dirty )

View File

@@ -207,7 +207,7 @@
<div class="flex flex-auto flex-col items-center justify-center bg-gray-100 dark:bg-transparent"> <div class="flex flex-auto flex-col items-center justify-center bg-gray-100 dark:bg-transparent">
<mat-icon <mat-icon
class="icon-size-24" class="icon-size-24"
[svgIcon]="'iconsmind:file_hide'"></mat-icon> [svgIcon]="'heroicons_outline:document'"></mat-icon>
<div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">There are no notes!</div> <div class="mt-4 text-2xl font-semibold tracking-tight text-secondary">There are no notes!</div>
</div> </div>
</ng-template> </ng-template>

View File

@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { CdkTextareaAutosize } from '@angular/cdk/text-field'; import { CdkTextareaAutosize } from '@angular/cdk/text-field';
import { FormBuilder, FormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
@Component({ @Component({
selector : 'scrumboard-board-add-card', selector : 'scrumboard-board-add-card',
@@ -15,7 +15,7 @@ export class ScrumboardBoardAddCardComponent implements OnInit
@Input() buttonTitle: string = 'Add a card'; @Input() buttonTitle: string = 'Add a card';
@Output() readonly saved: EventEmitter<string> = new EventEmitter<string>(); @Output() readonly saved: EventEmitter<string> = new EventEmitter<string>();
form: FormGroup; form: UntypedFormGroup;
formVisible: boolean = false; formVisible: boolean = false;
/** /**
@@ -23,7 +23,7 @@ export class ScrumboardBoardAddCardComponent implements OnInit
*/ */
constructor( constructor(
private _changeDetectorRef: ChangeDetectorRef, private _changeDetectorRef: ChangeDetectorRef,
private _formBuilder: FormBuilder private _formBuilder: UntypedFormBuilder
) )
{ {
} }

View File

@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
@Component({ @Component({
selector : 'scrumboard-board-add-list', selector : 'scrumboard-board-add-list',
@@ -13,7 +13,7 @@ export class ScrumboardBoardAddListComponent implements OnInit
@Input() buttonTitle: string = 'Add a list'; @Input() buttonTitle: string = 'Add a list';
@Output() readonly saved: EventEmitter<string> = new EventEmitter<string>(); @Output() readonly saved: EventEmitter<string> = new EventEmitter<string>();
form: FormGroup; form: UntypedFormGroup;
formVisible: boolean = false; formVisible: boolean = false;
/** /**
@@ -21,7 +21,7 @@ export class ScrumboardBoardAddListComponent implements OnInit
*/ */
constructor( constructor(
private _changeDetectorRef: ChangeDetectorRef, private _changeDetectorRef: ChangeDetectorRef,
private _formBuilder: FormBuilder private _formBuilder: UntypedFormBuilder
) )
{ {
} }

View File

@@ -9,7 +9,7 @@
</h2> </h2>
</div> </div>
<!-- Actions --> <!-- Actions -->
<div class="flex flex-shrink-0 items-center mt-6 sm:mt-0 sm:ml-4"> <div class="flex shrink-0 items-center mt-6 sm:mt-0 sm:ml-4">
<a <a
mat-stroked-button mat-stroked-button
[routerLink]="['..']"> [routerLink]="['..']">

View File

@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop'; import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
import { Subject, takeUntil } from 'rxjs'; import { Subject, takeUntil } from 'rxjs';
import * as moment from 'moment'; import * as moment from 'moment';
@@ -17,7 +17,7 @@ import { Board, Card, List } from 'app/modules/admin/apps/scrumboard/scrumboard.
export class ScrumboardBoardComponent implements OnInit, OnDestroy export class ScrumboardBoardComponent implements OnInit, OnDestroy
{ {
board: Board; board: Board;
listTitleForm: FormGroup; listTitleForm: UntypedFormGroup;
// Private // Private
private readonly _positionStep: number = 65536; private readonly _positionStep: number = 65536;
@@ -30,7 +30,7 @@ export class ScrumboardBoardComponent implements OnInit, OnDestroy
*/ */
constructor( constructor(
private _changeDetectorRef: ChangeDetectorRef, private _changeDetectorRef: ChangeDetectorRef,
private _formBuilder: FormBuilder, private _formBuilder: UntypedFormBuilder,
private _fuseConfirmationService: FuseConfirmationService, private _fuseConfirmationService: FuseConfirmationService,
private _scrumboardService: ScrumboardService private _scrumboardService: ScrumboardService
) )

View File

@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MatCheckboxChange } from '@angular/material/checkbox'; import { MatCheckboxChange } from '@angular/material/checkbox';
import { MatDialogRef } from '@angular/material/dialog'; import { MatDialogRef } from '@angular/material/dialog';
import { debounceTime, Subject, takeUntil, tap } from 'rxjs'; import { debounceTime, Subject, takeUntil, tap } from 'rxjs';
@@ -19,7 +19,7 @@ export class ScrumboardCardDetailsComponent implements OnInit, OnDestroy
@ViewChild('labelInput') labelInput: ElementRef<HTMLInputElement>; @ViewChild('labelInput') labelInput: ElementRef<HTMLInputElement>;
board: Board; board: Board;
card: Card; card: Card;
cardForm: FormGroup; cardForm: UntypedFormGroup;
labels: Label[]; labels: Label[];
filteredLabels: Label[]; filteredLabels: Label[];
@@ -32,7 +32,7 @@ export class ScrumboardCardDetailsComponent implements OnInit, OnDestroy
constructor( constructor(
public matDialogRef: MatDialogRef<ScrumboardCardDetailsComponent>, public matDialogRef: MatDialogRef<ScrumboardCardDetailsComponent>,
private _changeDetectorRef: ChangeDetectorRef, private _changeDetectorRef: ChangeDetectorRef,
private _formBuilder: FormBuilder, private _formBuilder: UntypedFormBuilder,
private _scrumboardService: ScrumboardService private _scrumboardService: ScrumboardService
) )
{ {

View File

@@ -49,11 +49,11 @@
</mat-menu> </mat-menu>
<!-- Close button --> <!-- Close button -->
<button <a
mat-icon-button mat-icon-button
[routerLink]="['../']"> [routerLink]="['../']">
<mat-icon [svgIcon]="'heroicons_outline:x'"></mat-icon> <mat-icon [svgIcon]="'heroicons_outline:x'"></mat-icon>
</button> </a>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,6 @@
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, Renderer2, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core'; import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, Renderer2, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { FormBuilder, FormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { TemplatePortal } from '@angular/cdk/portal'; import { TemplatePortal } from '@angular/cdk/portal';
import { Overlay, OverlayRef } from '@angular/cdk/overlay'; import { Overlay, OverlayRef } from '@angular/cdk/overlay';
import { MatDrawerToggleResult } from '@angular/material/sidenav'; import { MatDrawerToggleResult } from '@angular/material/sidenav';
@@ -28,7 +28,7 @@ export class TasksDetailsComponent implements OnInit, AfterViewInit, OnDestroy
tagsEditMode: boolean = false; tagsEditMode: boolean = false;
filteredTags: Tag[]; filteredTags: Tag[];
task: Task; task: Task;
taskForm: FormGroup; taskForm: UntypedFormGroup;
tasks: Task[]; tasks: Task[];
private _tagsPanelOverlayRef: OverlayRef; private _tagsPanelOverlayRef: OverlayRef;
private _unsubscribeAll: Subject<any> = new Subject<any>(); private _unsubscribeAll: Subject<any> = new Subject<any>();
@@ -39,7 +39,7 @@ export class TasksDetailsComponent implements OnInit, AfterViewInit, OnDestroy
constructor( constructor(
private _activatedRoute: ActivatedRoute, private _activatedRoute: ActivatedRoute,
private _changeDetectorRef: ChangeDetectorRef, private _changeDetectorRef: ChangeDetectorRef,
private _formBuilder: FormBuilder, private _formBuilder: UntypedFormBuilder,
private _fuseConfirmationService: FuseConfirmationService, private _fuseConfirmationService: FuseConfirmationService,
private _renderer2: Renderer2, private _renderer2: Renderer2,
private _router: Router, private _router: Router,

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