Skip to content

Commit

Permalink
Items: Implement copy button inside the details view
Browse files Browse the repository at this point in the history
  • Loading branch information
SchoolGuy committed Nov 1, 2024
1 parent c879cb0 commit 91d0687
Show file tree
Hide file tree
Showing 20 changed files with 570 additions and 111 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<h1 mat-dialog-title>Copy {{ data.itemType }}</h1>
<mat-dialog-content>
<mat-form-field class="form-field-full-width">
<mat-label>Old name</mat-label>
<input matInput readonly value="{{ data.itemName }}" />
</mat-form-field>

<mat-form-field class="form-field-full-width">
<mat-label>New name</mat-label>
<input
matInput
[(ngModel)]="dialogCloseSignal"
cdkFocusInitial
placeholder="New name"
/>
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button (click)="onNoClick()">Close</button>
<button mat-button [mat-dialog-close]="dialogCloseSignal()">Copy</button>
</mat-dialog-actions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.form-field-full-width {
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {
MAT_DIALOG_DATA,
MatDialogModule,
MatDialogRef,
} from '@angular/material/dialog';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { provideRouter } from '@angular/router';

import { DialogItemCopyComponent } from './dialog-item-copy.component';

describe('DialogItemRenameComponent', () => {
let component: DialogItemCopyComponent;
let fixture: ComponentFixture<DialogItemCopyComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DialogItemCopyComponent, MatDialogModule, NoopAnimationsModule],
providers: [
{
provide: MatDialogRef,
useValue: {},
},
{
provide: MAT_DIALOG_DATA,
useValue: { itemType: 'Test', itemName: 'test', itemUid: '' },
},
],
}).compileComponents();

fixture = TestBed.createComponent(DialogItemCopyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
ChangeDetectionStrategy,
Component,
inject,
Inject,
model,
} from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButton, MatButtonModule } from '@angular/material/button';
import {
MAT_DIALOG_DATA,
MatDialogModule,
MatDialogRef,
} from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';

export interface DialogItemCopyData {
itemType: string;
itemName: string;
itemUid: string;
}

@Component({
selector: 'cobbler-dialog-item-copy',
standalone: true,
imports: [
MatDialogModule,
MatButtonModule,
ReactiveFormsModule,
MatFormFieldModule,
MatInputModule,
FormsModule,
],
templateUrl: './dialog-item-copy.component.html',
styleUrl: './dialog-item-copy.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DialogItemCopyComponent {
readonly dialogRef = inject(MatDialogRef<DialogItemCopyComponent>);
readonly dialogCloseSignal = model('');

constructor(@Inject(MAT_DIALOG_DATA) public data: DialogItemCopyData) {}

onNoClick(): void {
this.dialogRef.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ <h1 class="title title-cell-text">Name: {{ name }}</h1>
</button>
</span>
<span class="title-cell-button">
<button mat-icon-button (click)="this.copyDistro()" matTooltip="Copy">
<button mat-icon-button (click)="this.copyDistro(this.distro.uid, this.distro.name)" matTooltip="Copy">
<mat-icon>content_copy</mat-icon>
</button>
</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, inject, OnInit } from '@angular/core';
import { Component, Inject, inject, OnDestroy, OnInit } from '@angular/core';
import {
FormBuilder,
FormControl,
Expand All @@ -7,6 +7,7 @@ import {
} from '@angular/forms';
import { MatButton, MatIconButton } from '@angular/material/button';
import { MatCheckbox } from '@angular/material/checkbox';
import { MatDialog } from '@angular/material/dialog';
import { MatFormField, MatLabel } from '@angular/material/form-field';
import { MatIcon } from '@angular/material/icon';
import { MatInput } from '@angular/material/input';
Expand All @@ -15,6 +16,9 @@ import { MatSnackBar } from '@angular/material/snack-bar';
import { MatTooltip } from '@angular/material/tooltip';
import { ActivatedRoute, Router } from '@angular/router';
import { CobblerApiService, Distro } from 'cobbler-api';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { DialogItemCopyComponent } from '../../../common/dialog-item-copy/dialog-item-copy.component';
import { KeyValueEditorComponent } from '../../../common/key-value-editor/key-value-editor.component';
import { MultiSelectComponent } from '../../../common/multi-select/multi-select.component';
import { UserService } from '../../../services/user.service';
Expand Down Expand Up @@ -42,7 +46,11 @@ import Utils from '../../../utils';
templateUrl: './distro-edit.component.html',
styleUrl: './distro-edit.component.scss',
})
export class DistroEditComponent implements OnInit {
export class DistroEditComponent implements OnInit, OnDestroy {
// Unsubscribe
private ngUnsubscribe = new Subject<void>();

// Form
name: string;
distro: Distro;
private readonly _formBuilder = inject(FormBuilder);
Expand Down Expand Up @@ -101,6 +109,7 @@ export class DistroEditComponent implements OnInit {
private cobblerApiService: CobblerApiService,
private _snackBar: MatSnackBar,
private router: Router,
@Inject(MatDialog) readonly dialog: MatDialog,
) {
this.name = this.route.snapshot.paramMap.get('name');
}
Expand All @@ -109,9 +118,15 @@ export class DistroEditComponent implements OnInit {
this.refreshData();
}

ngOnDestroy(): void {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}

refreshData(): void {
this.cobblerApiService
.get_distro(this.name, false, false, this.userService.token)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(
(value) => {
this.distro = value;
Expand Down Expand Up @@ -238,6 +253,7 @@ export class DistroEditComponent implements OnInit {
removeDistro(): void {
this.cobblerApiService
.remove_distro(this.name, this.userService.token, false)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(
(value) => {
if (value) {
Expand All @@ -261,18 +277,44 @@ export class DistroEditComponent implements OnInit {
this._snackBar.open('Not implemented at the moment!', 'Close');
}

copyDistro(): void {
this.cobblerApiService
.copy_distro('', '', this.userService.token)
.subscribe(
(value) => {
// TODO
},
(error) => {
// HTML encode the error message since it originates from XML
this._snackBar.open(Utils.toHTML(error.message), 'Close');
},
);
copyDistro(uid: string, name: string): void {
const dialogRef = this.dialog.open(DialogItemCopyComponent, {
data: {
itemType: 'Distro',
itemName: name,
itemUid: uid,
},
});

dialogRef.afterClosed().subscribe((newItemName) => {
if (newItemName === undefined) {
// Cancel means we don't need to rename the distro
return;
}
this.cobblerApiService
.get_distro_handle(name, this.userService.token)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(
(distroHandle) => {
this.cobblerApiService
.copy_distro(distroHandle, newItemName, this.userService.token)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(
(value) => {
this.router.navigate(['/items', 'distro', newItemName]);
},
(error) => {
// HTML encode the error message since it originates from XML
this._snackBar.open(Utils.toHTML(error.message), 'Close');
},
);
},
(error) => {
// HTML encode the error message since it originates from XML
this._snackBar.open(Utils.toHTML(error.message), 'Close');
},
);
});
}

saveDistro(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ <h1 class="title title-cell-text">Name: {{ name }}</h1>
</button>
</span>
<span class="title-cell-button">
<button mat-icon-button (click)="this.copyFile()" matTooltip="Copy">
<button mat-icon-button (click)="this.copyFile(this.file.uid, this.file.name)" matTooltip="Copy">
<mat-icon>content_copy</mat-icon>
</button>
</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, inject, OnInit } from '@angular/core';
import { Component, Inject, inject, OnDestroy, OnInit } from '@angular/core';
import {
FormBuilder,
FormControl,
Expand All @@ -8,6 +8,7 @@ import {
import { MatOption } from '@angular/material/autocomplete';
import { MatButton, MatIconButton } from '@angular/material/button';
import { MatCheckbox } from '@angular/material/checkbox';
import { MatDialog } from '@angular/material/dialog';
import { MatFormField, MatLabel } from '@angular/material/form-field';
import { MatIcon } from '@angular/material/icon';
import { MatInput } from '@angular/material/input';
Expand All @@ -16,6 +17,9 @@ import { MatSnackBar } from '@angular/material/snack-bar';
import { MatTooltip } from '@angular/material/tooltip';
import { ActivatedRoute, Router } from '@angular/router';
import { CobblerApiService, File } from 'cobbler-api';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { DialogItemCopyComponent } from '../../../common/dialog-item-copy/dialog-item-copy.component';
import { UserService } from '../../../services/user.service';
import Utils from '../../../utils';

Expand All @@ -39,7 +43,11 @@ import Utils from '../../../utils';
templateUrl: './file-edit.component.html',
styleUrl: './file-edit.component.scss',
})
export class FileEditComponent implements OnInit {
export class FileEditComponent implements OnInit, OnDestroy {
// Unsubscribe
private ngUnsubscribe = new Subject<void>();

// Form
name: string;
file: File;
private readonly _formBuilder = inject(FormBuilder);
Expand Down Expand Up @@ -68,6 +76,7 @@ export class FileEditComponent implements OnInit {
private cobblerApiService: CobblerApiService,
private _snackBar: MatSnackBar,
private router: Router,
@Inject(MatDialog) readonly dialog: MatDialog,
) {
this.name = this.route.snapshot.paramMap.get('name');
}
Expand All @@ -76,9 +85,15 @@ export class FileEditComponent implements OnInit {
this.refreshData();
}

ngOnDestroy(): void {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}

refreshData(): void {
this.cobblerApiService
.get_file(this.name, false, false, this.userService.token)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(
(value) => {
this.file = value;
Expand Down Expand Up @@ -112,6 +127,7 @@ export class FileEditComponent implements OnInit {
removeFile(): void {
this.cobblerApiService
.remove_file(this.name, this.userService.token, false)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(
(value) => {
if (value) {
Expand All @@ -135,16 +151,44 @@ export class FileEditComponent implements OnInit {
this._snackBar.open('Not implemented at the moment!', 'Close');
}

copyFile(): void {
this.cobblerApiService.copy_file('', '', this.userService.token).subscribe(
(value) => {
// TODO
copyFile(uid: string, name: string): void {
const dialogRef = this.dialog.open(DialogItemCopyComponent, {
data: {
itemType: 'File',
itemName: name,
itemUid: uid,
},
(error) => {
// HTML encode the error message since it originates from XML
this._snackBar.open(Utils.toHTML(error.message), 'Close');
},
);
});

dialogRef.afterClosed().subscribe((newItemName) => {
if (newItemName === undefined) {
// Cancel means we don't need to rename the file
return;
}
this.cobblerApiService
.get_file_handle(name, this.userService.token)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(
(fileHandle) => {
this.cobblerApiService
.copy_file(fileHandle, newItemName, this.userService.token)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(
(value) => {
this.router.navigate(['/items', 'file', newItemName]);
},
(error) => {
// HTML encode the error message since it originates from XML
this._snackBar.open(Utils.toHTML(error.message), 'Close');
},
);
},
(error) => {
// HTML encode the error message since it originates from XML
this._snackBar.open(Utils.toHTML(error.message), 'Close');
},
);
});
}

saveFile(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ <h1 class="title title-cell-text">Name: {{ name }}</h1>
</button>
</span>
<span class="title-cell-button">
<button mat-icon-button (click)="this.copyImage()" matTooltip="Copy">
<button mat-icon-button (click)="this.copyImage(this.image.uid, this.image.name)" matTooltip="Copy">
<mat-icon>content_copy</mat-icon>
</button>
</span>
Expand Down
Loading

0 comments on commit 91d0687

Please sign in to comment.