Enhancement: confirm buttons (#5680)

This commit is contained in:
shamoon
2024-02-08 10:23:06 -08:00
committed by GitHub
parent b643a68fa3
commit 6487dab132
15 changed files with 368 additions and 278 deletions

View File

@@ -0,0 +1,22 @@
<button
type="button"
class="btn {{buttonClasses}}"
(click)="onClick($event)"
[disabled]="disabled"
[ngbPopover]="popoverContent"
[autoClose]="true"
(hidden)="confirming = false"
#popover="ngbPopover"
popoverClass="popover-slim"
>
@if (iconName) {
<i-bs [class.me-1]="label" name="{{iconName}}"></i-bs>
}
<ng-container>{{label}}</ng-container>
</button>
<ng-template #popoverContent>
<div>
{{confirmMessage}}&nbsp;<button class="btn btn-link btn-sm text-danger p-0 m-0 lh-1" type="button" (click)="onConfirm($event)">Yes</button>
</div>
</ng-template>

View File

@@ -0,0 +1,12 @@
// Taken from bootstrap rules, obv
::ng-deep .input-group > pngx-confirm-button:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) > button,
::ng-deep .btn-group > pngx-confirm-button:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) > button {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
::ng-deep .input-group:not(.has-validation) > pngx-confirm-button:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating) > button,
::ng-deep .btn-group:not(.has-validation) > pngx-confirm-button:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating) > button {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}

View File

@@ -0,0 +1,37 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { ConfirmButtonComponent } from './confirm-button.component'
import { NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
describe('ConfirmButtonComponent', () => {
let component: ConfirmButtonComponent
let fixture: ComponentFixture<ConfirmButtonComponent>
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ConfirmButtonComponent],
imports: [NgbPopoverModule, NgxBootstrapIconsModule.pick(allIcons)],
}).compileComponents()
fixture = TestBed.createComponent(ConfirmButtonComponent)
component = fixture.componentInstance
fixture.detectChanges()
})
it('should show confirm on click', () => {
expect(component.popover.isOpen()).toBeFalsy()
expect(component.confirming).toBeFalsy()
component.onClick(new MouseEvent('click'))
expect(component.popover.isOpen()).toBeTruthy()
expect(component.confirming).toBeTruthy()
})
it('should emit confirm on confirm', () => {
const confirmSpy = jest.spyOn(component.confirm, 'emit')
component.onConfirm(new MouseEvent('click'))
expect(confirmSpy).toHaveBeenCalled()
expect(component.popover.isOpen()).toBeFalsy()
expect(component.confirming).toBeFalsy()
})
})

View File

@@ -0,0 +1,55 @@
import {
Component,
EventEmitter,
Input,
Output,
ViewChild,
} from '@angular/core'
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
@Component({
selector: 'pngx-confirm-button',
templateUrl: './confirm-button.component.html',
styleUrl: './confirm-button.component.scss',
})
export class ConfirmButtonComponent {
@Input()
label: string
@Input()
confirmMessage: string = $localize`Are you sure?`
@Input()
buttonClasses: string = 'btn-primary'
@Input()
iconName: string
@Input()
disabled: boolean = false
@Output()
confirm: EventEmitter<void> = new EventEmitter<void>()
@ViewChild('popover') popover: NgbPopover
public confirming: boolean = false
public onClick(event: MouseEvent) {
if (!this.confirming) {
this.confirming = true
this.popover.open()
}
event.preventDefault()
event.stopImmediatePropagation()
}
public onConfirm(event: MouseEvent) {
this.confirm.emit()
this.confirming = false
event.preventDefault()
event.stopImmediatePropagation()
}
}