Refactor admin component and update application properties for production setup

Gradle _jambotron_build
aplication.properties for dev and prod
This commit is contained in:
liosha84
2025-07-30 01:27:11 +03:00
parent 90b2eaa036
commit 4e030b2a52
118 changed files with 254 additions and 3488 deletions
@@ -1,69 +0,0 @@
<!--<div>-->
<!-- <div class="submit-form">-->
<!-- <div *ngIf="!submitted">-->
<!-- <div class="form-group">-->
<!-- <label for="title">Title</label>-->
<!-- <input-->
<!-- type="text"-->
<!-- class="form-control"-->
<!-- id="title"-->
<!-- required-->
<!-- [(ngModel)]="tutorial.title"-->
<!-- name="title"-->
<!-- />-->
<!-- </div>-->
<!-- <div class="form-group">-->
<!-- <label for="description">Description</label>-->
<!-- <input-->
<!-- class="form-control"-->
<!-- id="description"-->
<!-- required-->
<!-- [(ngModel)]="tutorial.description"-->
<!-- name="description"-->
<!-- />-->
<!-- </div>-->
<!-- <button (click)="saveTutorial()" class="btn btn-success">Submit</button>-->
<!-- </div>-->
<!-- <div *ngIf="submitted">-->
<!-- <h4>Tutorial was submitted successfully!</h4>-->
<!-- <button class="btn btn-success" (click)="newTutorial()">Add</button>-->
<!-- </div>-->
<!-- </div>-->
<!--</div>-->
<mat-card appearance="outlined">
<mat-card-header>
<mat-card-title>Add tutorial</mat-card-title>
</mat-card-header>
<mat-card-content >
<mat-form-field class="example-full-width">
<mat-label>Title</mat-label>
<input matInput required
[(ngModel)]="tutorial.title">
</mat-form-field>
<mat-tab-group>
<mat-tab label="Markdown text">
<textarea class="variable-textarea" [(ngModel)]="tutorial.description"></textarea>
<markdown class="variable-binding" [data]="tutorial.description"></markdown>
</mat-tab>
<mat-tab label="Result">
<markdown class="preview" [data]="tutorial.description"></markdown>
</mat-tab>
<mat-tab label="Example">
<textarea class="variable-textarea" [(ngModel)]="markdown"></textarea>
<markdown class="variable-binding" [data]="markdown"></markdown>
</mat-tab>
</mat-tab-group>
</mat-card-content>
<mat-card-actions>
<button matButton (click)="saveTutorial()" *ngIf="!submitted">Save</button>
<div *ngIf="submitted">
<h4>Tutorial was submitted successfully!</h4>
<button matButton (click)="newTutorial()">Add new tutorial</button>
</div>
</mat-card-actions>
</mat-card>
@@ -1,52 +0,0 @@
.submit-form {
max-width: 400px;
margin: auto;
}
mat-card{
margin: 20px;
}
mat-card-title{
color: cyan;
}
.example-form {
min-width: 150px;
max-width: 500px;
width: 100%;
}
.example-full-width {
width: 100%;
}
.variable-binding,
.variable-textarea {
width: 49%;
}
.variable-textarea {
border-radius: 5px;
box-shadow: 0 1px 2px rgba(0,0,0,.07);
min-height: 420px;
padding: 8px;
transition: all 300ms ease-out;
}
.variable-textarea:hover {
box-shadow: 0 6px 12px 3px rgba(0,0,0,.09),
0 2px 3px 1px rgba(0,0,0,.06);
}
.variable-binding {
display: block;
float: right;
}
.preview {
/* display: block;
float: right;*/
}
@@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AddTutorialComponent } from './add-tutorial.component';
describe('AddTutorialComponent', () => {
let component: AddTutorialComponent;
let fixture: ComponentFixture<AddTutorialComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AddTutorialComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AddTutorialComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,96 +0,0 @@
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';
import {MatTab, MatTabGroup} from '@angular/material/tabs';
import {MarkdownComponent} from 'ngx-markdown';
@Component({
selector: 'app-add-tutorial',
templateUrl: './add-tutorial.component.html',
styleUrls: ['./add-tutorial.component.scss'],
imports: [
MatCardActions,
FormsModule,
MatCard,
MatCardHeader,
MatCardContent,
MatFormField,
MatLabel,
MatButton,
MatInput,
NgIf,
MatLabel,
MatTabGroup,
MatTab,
MarkdownComponent,
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AddTutorialComponent implements OnInit {
tutorial: Tutorial = {
title: '',
description: '',
published: false
};
submitted = false
markdown = `## Markdown __rulez__!
---
### Syntax highlight
\`\`\`typescript
const language = 'typescript';
\`\`\`
### Lists
1. Ordered list
2. Another bullet point
- Unordered list
- Another unordered bullet
### Blockquote
> Blockquote to the max`;
constructor(private tutorialService: TutorialService) {
this.tutorial.description = this.markdown;
}
ngOnInit(): void {
}
saveTutorial(): void {
const data = {
title: this.tutorial.title,
description: this.tutorial.description
};
/* this.tutorialService.create(data)
.subscribe(
response => {
console.log(response);
this.submitted = true;
},
error => {
console.log(error);
});*/
}
newTutorial(): void {
this.submitted = false;
this.tutorial = {
title: '',
description: '',
published: false
};
}
}
@@ -1,10 +0,0 @@
<h2>Comments</h2>
<p class="comment">
Building for the web is fantastic!
</p>
<p class="comment">
The new template syntax is great
</p>
<p class="comment">
I agree with the other comments!
</p>
@@ -1,6 +0,0 @@
.comment {
padding: 15px;
margin-left: 30px;
background-color: paleturquoise;
border-radius: 20px;
}
@@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ArticleComments } from './article-comments';
describe('ArticleComments', () => {
let component: ArticleComments;
let fixture: ComponentFixture<ArticleComments>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ArticleComments]
})
.compileComponents();
fixture = TestBed.createComponent(ArticleComments);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,11 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-article-comments',
imports: [],
templateUrl: './article-comments.html',
styleUrl: './article-comments.scss'
})
export class ArticleComments {
}
@@ -1,51 +0,0 @@
<div class="col-md-6">
<h4>Users List</h4>
<ul class="list-group">
<li
class="list-group-item"
*ngFor="let row of rowData; let i = index"
>
{{ row.username }}
{{ row.email}}
{{ row.password}}
<form>
<mat-form-field class="example-chip-list">
<mat-chip-grid #chipGrid aria-label="Role selection">
@for (role of row.roles; track $index) {
<mat-chip-row (removed)="remove(role)">
{{role.name}}
<button matChipRemove [attr.aria-label]="'remove ' + role.name">
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
}
</mat-chip-grid>
<input
name="currentFruit"
placeholder="Add role..."
#fruitInput
[(ngModel)]="currentRole"
[matChipInputFor]="chipGrid"
[matAutocomplete]="auto"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[formControl]="myControl"
(matChipInputTokenEnd)="add($event)"
(input)="change($event,filteredRoles(row.roles))"
/>
<mat-autocomplete [formControl]="ac" autoActiveFirstOption #auto="matAutocomplete" (optionSelected)="selected(row.roles,$event); ">
@for (role of filteredRoles(row.roles); track role) {
<mat-option [value]="role">{{role.name}}</mat-option>
}
</mat-autocomplete>
</mat-form-field>
</form>
</li>
</ul>
</div>
@@ -1,3 +0,0 @@
.example-chip-list {
width: 100%;
}
@@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BoardAdminComponent } from './board-admin.component';
describe('BoardAdminComponent', () => {
let component: BoardAdminComponent;
let fixture: ComponentFixture<BoardAdminComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ BoardAdminComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(BoardAdminComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,143 +0,0 @@
import {Component, computed, CUSTOM_ELEMENTS_SCHEMA, model, OnInit} from '@angular/core';
import {User} from "../../models/user.model";
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, 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'],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
imports: [
MatAutocomplete,
ReactiveFormsModule,
MatOption,
NgForOf,
MatFormField,
MatChipGrid,
MatChipRow,
MatIcon,
MatChipInput,
MatAutocompleteTrigger
]
})
export class BoardAdminComponent implements OnInit {
private gridApi: any;
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
rowData?: User[];
allRoles: any;
readonly currentRole = model('');
protected myControl = new FormControl('');
protected ac = new FormControl('');
constructor(private userService: UserService, private roleService: RolesService ) {
this.getAllRoles();
}
ngOnInit(): void {
//this.myControl.valueChanges.pipe(
// startWith(''),
// map(value => this._filter(value || '')),
//);
this.userService.getAdminBoard().subscribe(
(data : any) => {
this.rowData = data;
},
(err : any)=> {
this.rowData = JSON.parse(err.error).message;
}
);
}
filteredRoles(roles : Role[]):any {
return this.allRoles.filter(
(r:Role) => !roles.some((item) => item.id === r.id),
);
}
// private _filter(value: string): string[] {
// const filterValue = value.toLowerCase();
// this.ac.
// return this.options.filter(option => option.toLowerCase().includes(filterValue));
//}
getAllRoles():any{
this.roleService.getAllRoles().subscribe(
(data : any) => {
this.allRoles = data;
},
(err : any)=> {
this.allRoles = JSON.parse(err.error).message;
}
);
}
remove(role: string): void {
// this.fruits.update(fruits => {
// const index = fruits.indexOf(fruit);
// if (index < 0) {
// return fruits;
// }
// fruits.splice(index, 1);
// this.announcer.announce(`Removed ${fruit}`);
// return [...fruits];
}
add(event: MatChipInputEvent): void {
const value = (event.value || '').trim();
// Add our fruit
if (value) {
// this.fruits.update(fruits => [...fruits, value]);
}
// Clear the input value
this.currentRole.set('');
}
selected(roles : Role[], event: MatAutocompleteSelectedEvent): void {
roles.push(event.option.value);
this.currentRole.set('');
event.option.deselect();
}
change($event: Event, roles: Role[]) {
roles.filter(
(r:Role) => !roles.some((item) => item.name?.toLowerCase() === r.id),
)
}
}
@@ -1 +0,0 @@
<p>board-moderator works!</p>
@@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BoardModeratorComponent } from './board-moderator.component';
describe('BoardModeratorComponent', () => {
let component: BoardModeratorComponent;
let fixture: ComponentFixture<BoardModeratorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ BoardModeratorComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(BoardModeratorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,16 +0,0 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-board-moderator',
templateUrl: './board-moderator.component.html',
styleUrls: ['./board-moderator.component.scss'],
standalone: false
})
export class BoardModeratorComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
@@ -1 +0,0 @@
<p>board-user works!</p>
@@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BoardUserComponent } from './board-user.component';
describe('BoardUserComponent', () => {
let component: BoardUserComponent;
let fixture: ComponentFixture<BoardUserComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ BoardUserComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(BoardUserComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,16 +0,0 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-board-user',
templateUrl: './board-user.component.html',
styleUrls: ['./board-user.component.scss'],
standalone: false
})
export class BoardUserComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
@@ -1,43 +0,0 @@
@for (breadcrumb of navigationList; track breadcrumb; let last = $last) {
@if (last && breadcrumb.breadcrumbs !== false) {
<div class="page-header">
<div class="page-block">
<div class="row align-items-center">
<div class="col-md-12">
<ul class="breadcrumb">
<li class="breadcrumb-item">
@if (type === 'theme2') {
<a [routerLink]="['/main/home']" title="Home" class="home"><i class="feather icon-home"></i></a>
}
@if (type === 'theme1') {
<a [routerLink]="['/main/home']" class="home">Home</a>
}
</li>
@for (breadcrumb of navigationList; track breadcrumb) {
@if (breadcrumb.url !== false) {
<li class="breadcrumb-item">
<a [routerLink]="breadcrumb.url" class="f-14 f-w-600">{{ breadcrumb.title }}</a>
</li>
}
@if (breadcrumb.url === false && breadcrumb.type !== 'group') {
<li class="breadcrumb-item">
<a href="javascript:">{{ breadcrumb.title }}</a>
</li>
}
}
</ul>
</div>
<div class="col-md-12">
<div class="page-header-title">
@for (breadcrumb of navigationList; track breadcrumb; let last = $last) {
@if (last) {
<h2 class="mb-0 f-w-600 mt-2">{{ breadcrumb.title }}</h2>
}
}
</div>
</div>
</div>
</div>
</div>
}
}
@@ -1,103 +0,0 @@
// Angular Import
import { Component, Input, inject, input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NavigationEnd, Router, RouterModule, Event } from '@angular/router';
import { Title } from '@angular/platform-browser';
// project import
//import { NavigationItem, NavigationItems } from 'src/app/theme/layouts/admin-layout/navigation/navigation';
// icons
import { IconService } from '@ant-design/icons-angular';
import { GlobalOutline, NodeExpandOutline } from '@ant-design/icons-angular/icons';
import {NavigationItem, NavigationItems} from '../../layouts/admin-layout/navigation/navigation';
interface titleType {
// eslint-disable-next-line
url: any;
title: string;
breadcrumbs: unknown;
type: string;
link?: string | undefined;
description?: string | undefined;
path?: string | undefined;
}
@Component({
selector: 'app-breadcrumb',
imports: [CommonModule, RouterModule],
templateUrl: './breadcrumb.component.html',
styleUrls: ['./breadcrumb.component.scss']
})
export class BreadcrumbComponent {
private route = inject(Router);
private titleService = inject(Title);
private iconService = inject(IconService);
// public props
@Input() type: string;
dashboard = input(true);
Component = input(false);
navigations: NavigationItem[];
ComponentNavigations: NavigationItem[] = [];
breadcrumbList: Array<string> = [];
navigationList!: titleType[];
componentList!: titleType[];
// constructor
constructor() {
this.navigations = NavigationItems;
this.type = 'theme1';
this.setBreadcrumb();
this.iconService.addIcon(...[GlobalOutline, NodeExpandOutline]);
}
// public method
setBreadcrumb() {
this.route.events.subscribe((router: Event) => {
if (router instanceof NavigationEnd) {
const activeLink = router.url;
const breadcrumbList = this.filterNavigation(this.navigations, activeLink);
this.navigationList = breadcrumbList;//breadcrumbList.slice(breadcrumbList.length - 1, breadcrumbList.length);
const title = breadcrumbList[breadcrumbList.length - 1]?.title || 'Welcome';
this.titleService.setTitle(title );
}
});
}
filterNavigation(navItems: NavigationItem[], activeLink: string): titleType[] {
for (const navItem of navItems) {
if (navItem.type === 'item' && 'url' in navItem && navItem.url === activeLink) {
return [
{
url: 'url' in navItem ? navItem.url : false,
title: navItem.title,
link: navItem.link,
description: navItem.description,
path: navItem.path,
breadcrumbs: 'breadcrumbs' in navItem ? navItem.breadcrumbs : true,
type: navItem.type
}
];
}
if ((navItem.type === 'group' || navItem.type === 'collapse') && 'children' in navItem) {
const breadcrumbList = this.filterNavigation(navItem.children!, activeLink);
if (breadcrumbList.length > 0) {
breadcrumbList.unshift({
url: 'url' in navItem ? navItem.url : false,
title: navItem.title,
link: navItem.link,
path: navItem.path,
description: navItem.description,
breadcrumbs: 'breadcrumbs' in navItem ? navItem.breadcrumbs : true,
type: navItem.type
});
return breadcrumbList;
}
}
}
return [];
}
}
@@ -1,16 +0,0 @@
<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>
@@ -1,58 +0,0 @@
// 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>;
}
@@ -1,9 +1,9 @@
import {Component, CUSTOM_ELEMENTS_SCHEMA, Input, OnInit, Renderer2} from '@angular/core';
import {Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, Renderer2} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {MatButton} from '@angular/material/button';
import {MatCard, MatCardActions, MatCardContent, MatCardHeader} from '@angular/material/card';
import {MatFormField, MatInput, MatLabel} from '@angular/material/input';
import {AsyncPipe, NgIf, NgOptimizedImage} from '@angular/common';
import {AsyncPipe} from '@angular/common';
import {Image} from '../../models/image';
import {ZhipuaiImageService} from '../../services/zhipuai-image.service';
import {MatProgressSpinner} from '@angular/material/progress-spinner';
@@ -25,9 +25,7 @@ import Viewer from 'viewerjs';
MatInput,
MatLabel,
MatProgressSpinner,
AsyncPipe,
AsyncPipe
],
templateUrl: './generate-image.component.html',
styleUrl: './generate-image.component.scss',
@@ -1,120 +0,0 @@
<div class="navbar-wrapper">
<div class="m-header">
<mat-label>Jambotron</mat-label>
<a href="javascript:" class="b-brand">
<img src="assets/images/logo-dark.svg" alt="theme-logo" class="logo logo-dark logo-lg" />
</a>
</div>
<!-- <app-nav-content (NavCollapsedMob)="navCollapseMob()" class="scroll-div w-100 compact"></app-nav-content>-->
<mat-nav-list>
<a mat-list-item routerLink="user-welcome">
<span class="entry">
<mat-icon>house</mat-icon>
@if (!isCollapsed) {
<span >Dashboard</span>
}
</span>
</a>
<a mat-list-item routerLink="tutorials-list">
<span class="entry">
<mat-icon>newspaper</mat-icon>
@if (!isCollapsed) {
<span >Tutorials</span>
}
</span>
</a>
<a mat-list-item routerLink="ai-models">
<span class="entry">
<mat-icon>house</mat-icon>
@if (!isCollapsed) {
<span >AI tools</span>
}
</span>
</a>
</mat-nav-list>
<div class="example-action-buttons">
<button matButton (click)="accordion().openAll()">Expand All</button>
<button matButton (click)="accordion().closeAll()">Collapse All</button>
<!-- #docregion multi -->
<mat-accordion class="example-headers-align" multi>
<!-- #enddocregion multi -->
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
<a mat-list-item routerLink="user-welcome">
<span class="entry">
<mat-icon>house</mat-icon>
@if (!isCollapsed) {
<span >Dashboard</span>
}
</span>
</a>
</mat-panel-title>
</mat-expansion-panel-header>
<mat-nav-list>
<a mat-list-item routerLink="user-welcome">
<span class="entry">
<mat-icon>house</mat-icon>
@if (!isCollapsed) {
<span >Dashboard</span>
}
</span>
</a>
<a mat-list-item routerLink="tutorials-list">
<span class="entry">
<mat-icon>newspaper</mat-icon>
@if (!isCollapsed) {
<span >Tutorials</span>
}
</span>
</a>
<a mat-list-item routerLink="ai-models">
<span class="entry">
<mat-icon>house</mat-icon>
@if (!isCollapsed) {
<span >AI tools</span>
}
</span>
</a>
</mat-nav-list>
</mat-expansion-panel>
<!-- #docregion disabled -->
<mat-expansion-panel disabled>
<!-- #enddocregion disabled -->
<mat-expansion-panel-header>
<mat-panel-title> Destination </mat-panel-title>
<mat-panel-description>
Type the country name
<mat-icon>map</mat-icon>
</mat-panel-description>
</mat-expansion-panel-header>
<mat-form-field>
<mat-label>Country</mat-label>
<input matInput />
</mat-form-field>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title> Day of the trip </mat-panel-title>
<mat-panel-description>
Inform the date you wish to travel
<mat-icon>date_range</mat-icon>
</mat-panel-description>
</mat-expansion-panel-header>
<mat-form-field>
<mat-label>Date</mat-label>
<input matInput [matDatepicker]="picker" (focus)="picker.open()" readonly />
</mat-form-field>
<mat-datepicker #picker></mat-datepicker>
</mat-expansion-panel>
</mat-accordion>
</div>
</div>
@@ -1,21 +0,0 @@
.entry{
display: flex;
align-items: center;
gap: 1rem;
padding:0.75rem;
}
.example-action-buttons {
padding-bottom: 20px;
}
.example-headers-align .mat-expansion-panel-header-description {
justify-content: space-between;
align-items: center;
}
.example-headers-align .mat-mdc-form-field + .mat-mdc-form-field {
margin-left: 8px;
}
@@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SideBarComponent } from './side-bar.component';
describe('SideBarComponent', () => {
let component: SideBarComponent;
let fixture: ComponentFixture<SideBarComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SideBarComponent]
})
.compileComponents();
fixture = TestBed.createComponent(SideBarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,79 +0,0 @@
import {ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, viewChild} from '@angular/core';
import {MatTree, MatTreeNode} from '@angular/material/tree';
import {MatFormField, MatInput, MatLabel} from '@angular/material/input';
import {MatDivider, MatListItem, MatNavList} from '@angular/material/list';
import {MatIcon} from '@angular/material/icon';
import {RouterLink} from '@angular/router';
import {
MatAccordion, MatExpansionModule,
MatExpansionPanel,
MatExpansionPanelDescription,
MatExpansionPanelTitle
} from '@angular/material/expansion';
import {MatDatepicker, MatDatepickerInput} from '@angular/material/datepicker';
import {provideNativeDateAdapter} from '@angular/material/core';
import {MatButton} from '@angular/material/button';
@Component({
selector: 'app-side-bar',
imports: [
MatTree,
MatTreeNode,
MatLabel,
MatNavList,
MatListItem,
MatIcon,
RouterLink,
MatExpansionPanel,
MatExpansionPanelTitle,
MatExpansionPanelDescription,
MatFormField,
MatInput,
MatDatepickerInput,
MatDatepicker,
MatDivider,
MatAccordion,
MatButton,
MatExpansionModule
],
templateUrl: './side-bar.component.html',
styleUrl: './side-bar.component.scss',
schemas:[CUSTOM_ELEMENTS_SCHEMA],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [provideNativeDateAdapter()],
})
export class SideBarComponent {
isCollapsed = false;
accordion = viewChild.required(MatAccordion);
}
const TREE_DATA: TreeNode[] = [
{
name: 'Fruit',
children: [{name: 'Apple'}, {name: 'Banana'}, {name: 'Fruit loops'}],
},
{
name: 'Vegetables',
children: [
{
name: 'Green',
children: [{name: 'Broccoli'}, {name: 'Brussels sprouts'}],
},
{
name: 'Orange',
children: [{name: 'Pumpkins'}, {name: 'Carrots'}],
},
],
},
];
interface TreeNode {
name: string;
children?: TreeNode[];
}
@@ -1,110 +0,0 @@
<mat-card>
<mat-card-header>
<mat-card-title>System</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-divider></mat-divider>
<mat-tab-group>
<mat-tab label="Custom beans">
Content 1
<table mat-table
[dataSource]="customBeans" multiTemplateDataRows="true" class="mat-elevation-z8">
@for (column of displayedColumns; track column) {
<ng-container matColumnDef="{{column}}">
<th mat-header-cell *matHeaderCellDef>{{column}}</th>
<td mat-cell *matCellDef="let element ; let k = dataIndex;">{{element[column]}}</td>
</ng-container>
}
<ng-container matColumnDef="expand">
<th mat-header-cell *matHeaderCellDef aria-label="row actions">&nbsp;</th>
<td mat-cell *matCellDef="let element">
<button
matIconButton
aria-label="expand row"
(click)="toggle(element); $event.stopPropagation()"
class="example-toggle-button"
[class.example-toggle-button-expanded]="isExpanded(element)">
<mat-icon>keyboard_arrow_down</mat-icon>
</button>
</td>
</ng-container>
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplayWithExpand.length">
<div class="example-element-detail-wrapper"
[class.example-element-detail-wrapper-expanded]="isExpanded(element)">
<div class="example-element-detail">
<mat-list role="list">
<mat-list-item role="listitem">Name: {{element.name}}</mat-list-item>
<mat-list-item role="listitem">Type: {{element.type}}</mat-list-item>
</mat-list>
</div>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplayWithExpand"></tr>
<tr mat-row *matRowDef="let element; columns: columnsToDisplayWithExpand;"
class="example-element-row"
[class.example-expanded-row]="isExpanded(element)"
(click)="toggle(element)">
</tr>
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
</table>
</mat-tab>
<mat-tab label="All beans">
Content 2
<table mat-table
[dataSource]="allBeans" multiTemplateDataRows="true" class="mat-elevation-z8">
@for (column of displayedColumns; track column) {
<ng-container matColumnDef="{{column}}">
<th mat-header-cell *matHeaderCellDef>{{column}}</th>
<td mat-cell *matCellDef="let element ; let k = dataIndex;">{{element[column]}}</td>
</ng-container>
}
<ng-container matColumnDef="expand">
<th mat-header-cell *matHeaderCellDef aria-label="row actions">&nbsp;</th>
<td mat-cell *matCellDef="let element">
<button
matIconButton
aria-label="expand row"
(click)="toggle(element); $event.stopPropagation()"
class="example-toggle-button"
[class.example-toggle-button-expanded]="isExpanded(element)">
<mat-icon>keyboard_arrow_down</mat-icon>
</button>
</td>
</ng-container>
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplayWithExpand.length">
<div class="example-element-detail-wrapper"
[class.example-element-detail-wrapper-expanded]="isExpanded(element)">
<div class="example-element-detail">
<mat-list role="list">
<mat-list-item role="listitem">Name: {{element.name}}</mat-list-item>
<mat-list-item role="listitem">Type: {{element.type}}</mat-list-item>
</mat-list>
</div>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplayWithExpand"></tr>
<tr mat-row *matRowDef="let element; columns: columnsToDisplayWithExpand;"
class="example-element-row"
[class.example-expanded-row]="isExpanded(element)"
(click)="toggle(element)">
</tr>
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
</table>
</mat-tab>
</mat-tab-group>
</mat-card-content>
</mat-card>
@@ -1,113 +0,0 @@
mat-card{
margin: 20px;
background-color: rgba(240, 248, 255, 0.7);
backdrop-filter: blur(8px);
}
mat-card-title{
color: cyan;
}
mat-card-subtitle{
color: #009dff;
}
mat-tab{
color:black;
}
table {
width: 100%;
margin-top: 20px;
color:lightgrey;
}
mat-list{
//background-color: #1389d3;
color:black;
width: 100%;
}
mat-list-item{
margin: 10px 10px 10px 10px;
background-color: #447694;
color: #009dff;
}
tr.example-detail-row {
height: 0;
background: #fffdfd;
}
tr.example-element-row {
cursor: pointer;
color: #1389d3;
background: #fffdfd;
}
tr.example-element-row:not(.example-expanded-row):hover {
background: whitesmoke;
}
tr.example-element-row:not(.example-expanded-row):active {
background: #efefef;
}
.example-element-row td {
border-bottom-width: 0;
}
.example-element-detail-wrapper {
overflow: hidden;
display: grid;
grid-template-rows: 0fr;
grid-template-columns: 100%;
transition: grid-template-rows 225ms cubic-bezier(0.4, 0, 0.2, 1);
}
.example-element-detail-wrapper-expanded {
grid-template-rows: 1fr;
}
.example-element-detail {
display: flex;
min-height: 0;
}
.example-element-diagram {
min-width: 80px;
border: 2px solid black;
padding: 8px;
font-weight: lighter;
margin: 8px 0;
height: 104px;
}
.example-element-symbol {
font-weight: bold;
font-size: 40px;
line-height: normal;
}
.example-element-description {
padding: 16px;
}
.example-element-description-attribution {
opacity: 0.5;
}
.example-toggle-button {
transition: transform 225ms cubic-bezier(0.4, 0, 0.2, 1);
}
.example-toggle-button-expanded {
transform: rotate(180deg);
}
@@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SystemComponent } from './system.component';
describe('SystemComponent', () => {
let component: SystemComponent;
let fixture: ComponentFixture<SystemComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SystemComponent]
})
.compileComponents();
fixture = TestBed.createComponent(SystemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,148 +0,0 @@
import { Component } from '@angular/core';
import {Bean} from '../../models/Bean';
import {SystemService} from '../../services/system.service';
import {
MatCard,
MatCardContent,
MatCardHeader,
MatCardSubtitle,
MatCardTitle,
MatCardTitleGroup
} from '@angular/material/card';
import {MatDivider} from '@angular/material/divider';
import {
MatCell,
MatCellDef,
MatColumnDef,
MatHeaderCell,
MatHeaderCellDef, MatHeaderRow,
MatHeaderRowDef, MatRow, MatRowDef,
MatTable
} from '@angular/material/table';
import {MatIconButton} from '@angular/material/button';
import {MatIcon} from '@angular/material/icon';
import {MatList, MatListItem} from '@angular/material/list';
import {MatTab, MatTabGroup} from '@angular/material/tabs';
@Component({
selector: 'app-system.component',
imports: [
MatCard,
MatCardSubtitle,
MatCardContent,
MatCardHeader,
MatCardTitle,
MatDivider,
MatTable,
MatColumnDef,
MatHeaderCell,
MatCell,
MatIconButton,
MatIcon,
MatHeaderCellDef,
MatCellDef,
MatHeaderRowDef,
MatRowDef,
MatRow,
MatHeaderRow,
MatList,
MatListItem,
MatTabGroup,
MatTab
],
templateUrl: './system.component.html',
styleUrl: './system.component.scss'
})
export class SystemComponent {
// @ViewChild(MatPaginator) paginator: MatPaginator;
// @ViewChild(MatSort) sort: MatSort;
customBeans:Bean[] = [] ;
allBeans:Bean[] = [] ;
displayedColumns: string[] = ['shortName', 'typeShortName', 'scope'];
columnsToDisplayWithExpand = [...this.displayedColumns, 'expand'];
expandedElement: Bean | null = null;
resultsLength = 0;
isLoadingResults = true;
isRateLimitReached = false;
constructor(private systemService: SystemService) { }
ngOnInit(): void {
this.retrieveBeans();
}
retrieveBeans(): void {
this.systemService.getCustomBeans()
.subscribe(
(data: Bean[]) => {
this.customBeans = data;
console.log(data);
},
(error: any) => {
console.log(error);
});
this.systemService.getAllBeans()
.subscribe(
(data: Bean[]) => {
this.allBeans = data;
console.log(data);
},
(error: any) => {
console.log(error);
});
}
/** Checks whether an element is expanded. */
isExpanded(element: Bean) {
return this.expandedElement === element;
}
/** Toggles the expanded state of an element. */
toggle(element: Bean) {
this.expandedElement = this.isExpanded(element) ? null : element;
}
ngAfterViewInit() {
//this.exampleDatabase = new ExampleHttpDatabase(this._httpClient);
// If the user changes the sort order, reset back to the first page.
/* this.sort.sortChange.subscribe(() => (this.paginator.pageIndex = 0));
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
return this.exampleDatabase!.getRepoIssues(
this.sort.active,
this.sort.direction,
this.paginator.pageIndex,
).pipe(catchError(() => observableOf(null)));
}),
map(data => {
// Flip flag to show that loading has finished.
this.isLoadingResults = false;
this.isRateLimitReached = data === null;
if (data === null) {
return [];
}
// Only refresh the result length if there is new data. In case of rate
// limit errors, we do not want to reset the paginator to zero, as that
// would prevent users from re-triggering requests.
this.resultsLength = data.total_count;
return data.items;
}),
)
.subscribe(data => (this.data = data));*/
}
}
@@ -1,65 +0,0 @@
<div>
<div *ngIf="currentTutorial.id" class="edit-form">
<h4>Tutorial</h4>
<form>
<div class="form-group">
<label for="title">Title</label>
<input
type="text"
class="form-control"
id="title"
[(ngModel)]="currentTutorial.title"
name="title"
/>
</div>
<div class="form-group">
<label for="description">Description</label>
<input
type="text"
class="form-control"
id="description"
[(ngModel)]="currentTutorial.description"
name="description"
/>
</div>
<div class="form-group">
<label><strong>Status:</strong></label>
{{ currentTutorial.published ? "Published" : "Pending" }}
</div>
</form>
<button
class="badge badge-primary mr-2"
*ngIf="currentTutorial.published"
(click)="updatePublished(false)"
>
UnPublish
</button>
<button
*ngIf="!currentTutorial.published"
class="badge badge-primary mr-2"
(click)="updatePublished(true)"
>
Publish
</button>
<button class="badge badge-danger mr-2" (click)="deleteTutorial()">
Delete
</button>
<button
type="submit"
class="badge badge-success mb-2"
(click)="updateTutorial()"
>
Update
</button>
<p>{{ message }}</p>
</div>
<div *ngIf="!currentTutorial.id">
<br />
<p>Cannot access this Tutorial...</p>
</div>
</div>
@@ -1,4 +0,0 @@
.edit-form {
max-width: 400px;
margin: auto;
}
@@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TutorialDetailsComponent } from './tutorial-details.component';
describe('TutorialDetailsComponent', () => {
let component: TutorialDetailsComponent;
let fixture: ComponentFixture<TutorialDetailsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TutorialDetailsComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TutorialDetailsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,96 +0,0 @@
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',
imports: [
FormsModule,
NgIf
],
styleUrls: ['./tutorial-details.component.scss']
})
export class TutorialDetailsComponent implements OnInit {
currentTutorial: Tutorial = {
title: '',
description: '',
published: false
};
message = '';
constructor(
private tutorialService: TutorialService,
private route: ActivatedRoute,
private router: Router) { }
ngOnInit(): void {
this.message = '';
this.getTutorial(this.route.snapshot.params['id']);
}
getTutorial(id: string): void {
/* this.tutorialService.get(id)
.subscribe(
data => {
this.currentTutorial = data;
console.log(data);
},
error => {
console.log(error);
});*/
}
updatePublished(status: boolean): void {
const data = {
title: this.currentTutorial.title,
description: this.currentTutorial.description,
published: status
};
this.message = '';
/* this.tutorialService.update(this.currentTutorial.id, data)
.subscribe(
response => {
this.currentTutorial.published = status;
console.log(response);
this.message = response.message ? response.message : 'The status was updated successfully!';
},
error => {
console.log(error);
});*/
}
updateTutorial(): void {
/* this.message = '';
this.tutorialService.update(this.currentTutorial.id, this.currentTutorial)
.subscribe(
response => {
console.log(response);
this.message = response.message ? response.message : 'This tutorial was updated successfully!';
},
error => {
console.log(error);
});*/
}
deleteTutorial(): void {
/* this.tutorialService.delete(this.currentTutorial.id)
.subscribe(
response => {
console.log(response);
this.router.navigate(['/tutorials']);
},
error => {
console.log(error);
});*/
}
}
@@ -1,63 +0,0 @@
<div class="list row">
<div class="col-md-8">
<div class="input-group mb-3">
<input
type="text"
class="form-control"
placeholder="Search by title"
[(ngModel)]="title"
/>
<div class="input-group-append">
<button
class="btn btn-outline-secondary"
type="button"
(click)="searchTitle()"
>
Search
</button>
</div>
</div>
</div>
<div class="col-md-6">
<h4>Tutorials List</h4>
<ul class="list-group">
<li
class="list-group-item"
*ngFor="let tutorial of tutorials; let i = index"
[class.active]="i == currentIndex"
(click)="setActiveTutorial(tutorial, i)"
>
{{ tutorial.title }}
</li>
</ul>
<button class="m-3 btn btn-sm btn-danger" (click)="removeAllTutorials()">
Remove All
</button>
</div>
<div class="col-md-6">
<div *ngIf="currentTutorial.id">
<h4>Tutorial</h4>
<div>
<label><strong>Title:</strong></label> {{ currentTutorial.title }}
</div>
<div>
<label><strong>Description:</strong></label>
{{ currentTutorial.description }}
</div>
<div>
<label><strong>Status:</strong></label>
{{ currentTutorial.published ? "Published" : "Pending" }}
</div>
<a class="badge badge-warning" routerLink="/tutorials/{{ currentTutorial.id }}">
Edit
</a>
</div>
<div *ngIf="!currentTutorial">
<br />
<p>Please click on a Tutorial...</p>
</div>
</div>
</div>
@@ -1,6 +0,0 @@
.list {
text-align: left;
max-width: 750px;
margin: auto;
}
@@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TutorialsListComponent } from './tutorials-list.component';
describe('TutorialsListComponent', () => {
let component: TutorialsListComponent;
let fixture: ComponentFixture<TutorialsListComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TutorialsListComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TutorialsListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,82 +0,0 @@
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',
imports: [
FormsModule,
RouterLink,
NgIf
],
styleUrls: ['./tutorials-list.component.scss']
})
export class TutorialsListComponent implements OnInit {
tutorials?: Tutorial[];
currentTutorial: Tutorial = {};
currentIndex = -1;
title = '';
constructor(private tutorialService: TutorialService) { }
ngOnInit(): void {
this.retrieveTutorials();
}
retrieveTutorials(): void {
this.tutorialService.getAllPublic()
.subscribe(
(data: Tutorial[] ) => {
this.tutorials = data;
console.log(data);
},
error => {
console.log(error);
});
}
refreshList(): void {
this.retrieveTutorials();
this.currentTutorial = {};
this.currentIndex = -1;
}
setActiveTutorial(tutorial: Tutorial, index: number): void {
this.currentTutorial = tutorial;
this.currentIndex = index;
}
removeAllTutorials(): void {
/* this.tutorialService.deleteAll()
.subscribe(
response => {
console.log(response);
this.refreshList();
},
error => {
console.log(error);
});*/
}
searchTitle(): void {
this.currentTutorial = {};
this.currentIndex = -1;
this.tutorialService.findByTitle(this.title)
.subscribe(
data => {
this.tutorials = data;
console.log(data);
},
error => {
console.log(error);
});
}
}