Add new components, styles, and services for user management and navigation

This commit is contained in:
liosha84
2025-06-25 13:44:35 +03:00
parent 9b7465d3dc
commit 2ae1871330
125 changed files with 12940 additions and 1610 deletions
@@ -44,7 +44,8 @@
<input matInput required
[(ngModel)]="tutorial.title">
</mat-form-field>
<kendo-editor [(ngModel)]="tutorial.description" ></kendo-editor>
<!-- <kendo-editor [(ngModel)]="tutorial.description" ></kendo-editor>-->
<textarea matInput required [(ngModel)]="tutorial.description"></textarea>
</mat-card-content>
<mat-card-actions>
<button matButton (click)="saveTutorial()" *ngIf="!submitted">Save</button>
@@ -1,12 +1,32 @@
import { Component, OnInit } from '@angular/core';
import {Component, CUSTOM_ELEMENTS_SCHEMA, OnInit} from '@angular/core';
import {Tutorial} from '../../models/tutorial.model';
import {TutorialService} from '../../services/tutorial.service';
import {MatCard, MatCardActions, MatCardContent, MatCardHeader} from '@angular/material/card';
import {FormsModule} from '@angular/forms';
import {MatButton} from '@angular/material/button';
import {MatFormField, MatInput, MatLabel} from '@angular/material/input';
import {NgIf} from '@angular/common';
@Component({
selector: 'app-add-tutorial',
templateUrl: './add-tutorial.component.html',
styleUrls: ['./add-tutorial.component.scss'],
standalone: false
imports: [
MatCardActions,
FormsModule,
MatCard,
MatCardHeader,
MatCardContent,
MatFormField,
MatLabel,
MatButton,
MatInput,
NgIf,
MatLabel,
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AddTutorialComponent implements OnInit {
@@ -1,25 +1,45 @@
import {Component, computed, model, OnInit} from '@angular/core';
import {Component, computed, CUSTOM_ELEMENTS_SCHEMA, model, OnInit} from '@angular/core';
import {User} from "../../models/user.model";
import {MatChipInputEvent} from "@angular/material/chips";
import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete";
import {MatChipGrid, MatChipInput, MatChipInputEvent, MatChipRow} from "@angular/material/chips";
import {
MatAutocomplete,
MatAutocompleteSelectedEvent,
MatAutocompleteTrigger,
MatOption
} from "@angular/material/autocomplete";
import {COMMA, ENTER} from "@angular/cdk/keycodes";
import {AsyncPipe} from "@angular/common";
import {FormControl} from "@angular/forms";
import {AsyncPipe, NgForOf} from "@angular/common";
import {FormControl, ReactiveFormsModule} from "@angular/forms";
import {Observable, startWith} from "rxjs";
import {map} from "rxjs/operators";
import {UserService} from '../../services/user.service';
import {RolesService} from '../../services/roles.service';
import {Role} from '../../models/role';
import {MatIcon} from '@angular/material/icon';
import {MatFormField} from '@angular/material/form-field';
@Component({
selector: 'app-board-admin',
templateUrl: './board-admin.component.html',
styleUrls: ['./board-admin.component.scss'],
standalone: false,
selector: 'app-board-admin',
templateUrl: './board-admin.component.html',
styleUrls: ['./board-admin.component.scss'],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
imports: [
MatAutocomplete,
ReactiveFormsModule,
MatOption,
NgForOf,
MatFormField,
MatChipGrid,
MatChipRow,
MatIcon,
MatChipInput,
MatAutocompleteTrigger
]
})
export class BoardAdminComponent implements OnInit {
private gridApi: any;
@@ -0,0 +1,16 @@
<div class="card" [ngClass]="cardClass()">
@if (showHeader()) {
<div class="card-header d-flex align-items-center justify-content-between" [ngClass]="headerClass()">
<div>
<h5>{{ cardTitle() }}</h5>
<ng-container *ngTemplateOutlet="headerTitleTemplate"></ng-container>
</div>
<ng-container *ngTemplateOutlet="headerOptionsTemplate"></ng-container>
</div>
}
@if (showContent()) {
<div class="card-body" [ngClass]="blockClass()" [style.padding.px]="padding()">
<ng-content></ng-content>
</div>
}
</div>
@@ -0,0 +1,58 @@
// Angular import
import { Component, ContentChild, ElementRef, TemplateRef, input } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-card',
standalone: true,
imports: [CommonModule],
templateUrl: './card.component.html',
styleUrls: ['./card.component.scss']
})
export class CardComponent {
// public props
/**
* Title of card. It will be visible at left side of card header
*/
cardTitle = input<string>();
/**
* Class to be applied at card level
*/
cardClass = input<string>();
/**
* To hide content from card
*/
showContent = input(true);
/**
* Class to be applied at card content.
*/
blockClass = input<string>();
/**
* Class to be applied on card header
*/
headerClass = input<string>();
/**
* To hide header from card
*/
showHeader = input(true);
/**
* padding around card content. default in px
*/
padding = input(20); // set default to 24 px
/**
* Template reference of header actions on custom header
*/
@ContentChild('headerOptionsTemplate') headerOptionsTemplate!: TemplateRef<ElementRef>;
/**
* Template reference of header actions besides title at left
*/
@ContentChild('headerTitleTemplate') headerTitleTemplate!: TemplateRef<ElementRef>;
}
@@ -14,7 +14,8 @@ import {MatFormField, MatLabel, MatSuffix} from "@angular/material/form-field";
import {MatInput} from "@angular/material/input";
import {FormsModule} from "@angular/forms";
import {MatIcon} from "@angular/material/icon";
import {DialogData} from "../../app.component";
import {DialogData} from '../../main-module/main.component/main.component';
@@ -0,0 +1,51 @@
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
<p>home.component works!</p>
@@ -8,12 +8,10 @@ describe('HomeComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ HomeComponent ]
imports: [HomeComponent]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
@@ -0,0 +1,11 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-home.component',
imports: [],
templateUrl: './home.component.html',
styleUrl: './home.component.scss'
})
export class HomeComponent {
}
@@ -1,145 +0,0 @@
<p-splitter [style]="{ height: '300px' }" styleClass="mb-8" layout="vertical">
<ng-template #panel>
<div class="flex items-center justify-center h-full">Panel 1</div>
</ng-template>
<ng-template #panel>
<div class="flex items-center justify-center h-full">Panel 2</div>
<p-scrollPanel [style]="{ width: '100%', height: '150px' }">
<p>
Lorem ipsum dolor sit amet...
</p>
<p>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium...
</p>
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos...
dfsd
f
sdf
dsf
sd
f
sd
fs
fs
fsfs
fs
fs
fs
fs
fs
</p>
<app-article-comments />
</p-scrollPanel>
</ng-template>
</p-splitter>
<p-scrollPanel [style]="{ width: '100%', height: '150px' }">
<p>
Lorem ipsum dolor sit amet...
</p>
<p>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium...
</p>
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos...
dfsd
f
sdf
dsf
sd
f
sd
fs
fs
fsfs
fs
fs
fs
fs
fs
</p>
<app-article-comments />
</p-scrollPanel>
<!--
@defer (on viewport(container); prefetch on idle) {
<app-article-comments></app-article-comments>
} @loading {
<mat-progress-spinner></mat-progress-spinner>
loading
} @placeholder {
<div class="skeleton-loader"></div>
<app-article-comments></app-article-comments>
placeholder
} @error {
Error
}
<div #container>
<h1>How I feel about Angular</h1>
<article>
<p>
Angular is my favorite framework, and
this is why. Angular has the coolest
deferrable view feature that makes defer
loading content the easiest and most
ergonomic it could possibly be.
</p>
</article>
@defer {
<app-article-comments />
} @placeholder (minimum 1s) {
<p>Placeholder for comments</p>
} @loading (minimum 1s; after 500ms) {
<p>Loading comments...</p>
} @error {
<p>Failed to load comments</p>
}
</div>
<ng-container [ngComponentOutlet]="profileComponent()" />
-->
<mat-card #showComments appearance="outlined" >
<mat-card-header>
<mat-card-title>Tutorials</mat-card-title>
</mat-card-header>
<mat-card-content>
</mat-card-content>
</mat-card>
@defer (on hover; on interaction(showComments)) {
<app-article-comments />
} @placeholder ( ;minimum 1s) {
<p>Placeholder for comments</p>
} @loading (minimum 1s; after 500ms) {
<p>Loading comments...</p>
} @error {
<p>Failed to load comments</p>
}
@for (tutorial of tutorials; track $index){
<mat-card appearance="outlined" class="tutorial-card">
<mat-card-content [innerHTML]="tutorial.description">
</mat-card-content>
</mat-card>
}
@@ -1,10 +0,0 @@
mat-card{
margin: 20px;
background-color: rgba(0, 0, 0, 0.7);
}
mat-card-title{
color: cyan;
}
.tutorial-card{
color: white;
}
@@ -1,38 +0,0 @@
import {Component, computed, OnInit} from '@angular/core';
import {TutorialService} from '../../services/tutorial.service';
import {Tutorial} from '../../models/tutorial.model';
import {ArticleComments} from '../article-comments/article-comments';
import {AddTutorialComponent} from '../add-tutorial/add-tutorial.component';
import { ScrollPanelModule } from 'primeng/scrollpanel';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'],
standalone: false
})
export class HomeComponent implements OnInit {
content?: string;
tutorials?: Tutorial[];
constructor(private tutorialService: TutorialService) { }
ngOnInit(): void {
this.retrieveTutorials();
}
retrieveTutorials(): void {
this.tutorialService.getAll()
.subscribe(
data => {
this.tutorials = data;
console.log(data);
},
error => {
console.log(error);
});
}
profileComponent = computed(() => AddTutorialComponent);
}
@@ -1,12 +1,16 @@
import { Component, OnInit } from '@angular/core';
import {TokenStorageService} from '../../services/token-storage.service';
import {NgForOf, NgIf} from '@angular/common';
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.scss'],
standalone: false
selector: 'app-profile',
templateUrl: './profile.component.html',
imports: [
NgForOf,
NgIf
],
styleUrls: ['./profile.component.scss']
})
export class ProfileComponent implements OnInit {
currentUser: any;
@@ -1,12 +1,17 @@
import { Component, OnInit } from '@angular/core';
import {AuthService} from '../../services/auth.service';
import {FormsModule} from '@angular/forms';
import {NgIf} from '@angular/common';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.scss'],
standalone: false
selector: 'app-register',
templateUrl: './register.component.html',
imports: [
FormsModule,
NgIf
],
styleUrls: ['./register.component.scss']
})
export class RegisterComponent implements OnInit {
form: any = {
@@ -3,13 +3,18 @@ import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import {Tutorial} from '../../models/tutorial.model';
import {TutorialService} from '../../services/tutorial.service';
import {FormsModule} from '@angular/forms';
import {NgIf} from '@angular/common';
@Component({
selector: 'app-tutorial-details',
templateUrl: './tutorial-details.component.html',
styleUrls: ['./tutorial-details.component.scss'],
standalone: false
selector: 'app-tutorial-details',
templateUrl: './tutorial-details.component.html',
imports: [
FormsModule,
NgIf
],
styleUrls: ['./tutorial-details.component.scss']
})
export class TutorialDetailsComponent implements OnInit {
@@ -3,12 +3,19 @@ import { Component, OnInit } from '@angular/core';
import {Tutorial} from '../../models/tutorial.model';
import {TutorialService} from '../../services/tutorial.service';
import {FormsModule} from '@angular/forms';
import {RouterLink} from '@angular/router';
import {NgIf} from '@angular/common';
@Component({
selector: 'app-tutorials-list',
templateUrl: './tutorials-list.component.html',
styleUrls: ['./tutorials-list.component.scss'],
standalone: false
selector: 'app-tutorials-list',
templateUrl: './tutorials-list.component.html',
imports: [
FormsModule,
RouterLink,
NgIf
],
styleUrls: ['./tutorials-list.component.scss']
})
export class TutorialsListComponent implements OnInit {
@@ -0,0 +1,9 @@
@for (tutorial of tutorials; track $index){
<mat-card appearance="outlined" class="tutorial-card">
<mat-card-header>
<mat-card-title>{{tutorial.title}}</mat-card-title>
</mat-card-header>
<mat-card-content [innerHTML]="tutorial.description">
</mat-card-content>
</mat-card>
}
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TutorialsComponent } from './tutorials.component';
describe('TutorialsComponent', () => {
let component: TutorialsComponent;
let fixture: ComponentFixture<TutorialsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [TutorialsComponent]
})
.compileComponents();
fixture = TestBed.createComponent(TutorialsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,39 @@
import {Component, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
import {Tutorial} from '../../models/tutorial.model';
import {TutorialService} from '../../services/tutorial.service';
import {MatCard, MatCardContent, MatCardHeader} from '@angular/material/card';
@Component({
selector: 'app-tutorials.component',
imports: [
MatCard,
MatCardContent,
MatCardHeader
],
templateUrl: './tutorials.component.html',
styleUrl: './tutorials.component.scss',
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class TutorialsComponent {
tutorials?: Tutorial[];
constructor(private tutorialService: TutorialService) {
this.retrieveTutorials();
}
// ngOnInit(): void {
// this.retrieveTutorials();
// }
retrieveTutorials(): void {
this.tutorialService.getAll()
.subscribe(
data => {
this.tutorials = data;
console.log(data);
},
error => {
console.log(error);
});
}
}