mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-28 18:24:38 -05:00
Chore: Update Angular to v17 (#4980)
This commit is contained in:
@@ -1,9 +1,15 @@
|
||||
<button *ngIf="active" class="position-absolute top-0 start-100 translate-middle badge bg-secondary border border-light rounded-pill p-1" title="Clear" i18n-title (click)="onClick($event)">
|
||||
<svg *ngIf="!isNumbered && selected" width="1em" height="1em" class="check m-0 p-0 opacity-75" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
@if (active) {
|
||||
<button class="position-absolute top-0 start-100 translate-middle badge bg-secondary border border-light rounded-pill p-1" title="Clear" i18n-title (click)="onClick($event)">
|
||||
@if (!isNumbered && selected) {
|
||||
<svg width="1em" height="1em" class="check m-0 p-0 opacity-75" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check-lg"/>
|
||||
</svg>
|
||||
<div *ngIf="isNumbered" class="number">{{number}}<span class="visually-hidden">selected</span></div>
|
||||
</svg>
|
||||
}
|
||||
@if (isNumbered) {
|
||||
<div class="number">{{number}}<span class="visually-hidden">selected</span></div>
|
||||
}
|
||||
<svg width=".9em" height="1em" class="x m-0 p-0 opacity-75" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x-lg"/>
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x-lg"/>
|
||||
</svg>
|
||||
</button>
|
||||
</button>
|
||||
}
|
||||
|
@@ -1,24 +1,32 @@
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
|
||||
<button type="button" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p *ngIf="messageBold"><b>{{messageBold}}</b></p>
|
||||
<p class="mb-0" *ngIf="message" [innerHTML]="message | safeHtml"></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" [disabled]="!buttonsEnabled" i18n>
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
|
||||
<button type="button" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@if (messageBold) {
|
||||
<p><b>{{messageBold}}</b></p>
|
||||
}
|
||||
@if (message) {
|
||||
<p class="mb-0" [innerHTML]="message | safeHtml"></p>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" [disabled]="!buttonsEnabled" i18n>
|
||||
<span class="d-inline-block" style="padding-bottom: 1px;" >Cancel</span>
|
||||
</button>
|
||||
<button type="button" class="btn" [class]="btnClass" (click)="confirm()" [disabled]="!confirmButtonEnabled || !buttonsEnabled">
|
||||
<span>
|
||||
{{btnCaption}}
|
||||
<span class="visually-hidden">{{ seconds | number: '1.0-0' }} seconds</span>
|
||||
</span>
|
||||
<ngb-progressbar *ngIf="!confirmButtonEnabled" style="height: 1px;" type="dark" [max]="secondsTotal" [value]="seconds"></ngb-progressbar>
|
||||
</button>
|
||||
<button *ngIf="alternativeBtnCaption" type="button" class="btn" [class]="alternativeBtnClass" (click)="alternative()" [disabled]="!alternativeButtonEnabled || !buttonsEnabled">
|
||||
{{alternativeBtnCaption}}
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="btn" [class]="btnClass" (click)="confirm()" [disabled]="!confirmButtonEnabled || !buttonsEnabled">
|
||||
<span>
|
||||
{{btnCaption}}
|
||||
<span class="visually-hidden">{{ seconds | number: '1.0-0' }} seconds</span>
|
||||
</span>
|
||||
@if (!confirmButtonEnabled) {
|
||||
<ngb-progressbar style="height: 1px;" type="dark" [max]="secondsTotal" [value]="seconds"></ngb-progressbar>
|
||||
}
|
||||
</button>
|
||||
@if (alternativeBtnCaption) {
|
||||
<button type="button" class="btn" [class]="alternativeBtnClass" (click)="alternative()" [disabled]="!alternativeButtonEnabled || !buttonsEnabled">
|
||||
{{alternativeBtnCaption}}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
@@ -1,15 +1,18 @@
|
||||
<div class="btn-group w-100" ngbDropdown role="group">
|
||||
<div class="btn-group w-100" ngbDropdown role="group">
|
||||
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="dateBefore || dateAfter ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled">
|
||||
{{title}}
|
||||
<pngx-clearable-badge [selected]="isActive" (cleared)="reset()"></pngx-clearable-badge><span class="visually-hidden">selected</span>
|
||||
</button>
|
||||
<div class="dropdown-menu date-dropdown shadow pt-0" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
|
||||
<div class="list-group list-group-flush">
|
||||
<button *ngFor="let rd of relativeDates" class="list-group-item small list-goup list-group-item-action d-flex p-2" role="menuitem" (click)="setRelativeDate(rd.id)">
|
||||
@for (rd of relativeDates; track rd) {
|
||||
<button class="list-group-item small list-goup list-group-item-action d-flex p-2" role="menuitem" (click)="setRelativeDate(rd.id)">
|
||||
<div class="selected-icon">
|
||||
<svg *ngIf="relativeDate === rd.id" fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
@if (relativeDate === rd.id) {
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
}
|
||||
</div>
|
||||
<div class="d-flex justify-content-between w-100 align-items-center ps-2">
|
||||
<div class="pe-2 pe-lg-4">
|
||||
@@ -22,52 +25,57 @@
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<div class="list-group-item d-flex flex-column align-items-start" role="menuitem">
|
||||
}
|
||||
<div class="list-group-item d-flex flex-column align-items-start" role="menuitem">
|
||||
|
||||
<div class="mb-2 d-flex flex-row w-100 justify-content-between small">
|
||||
<div i18n>After</div>
|
||||
<a *ngIf="dateAfter" class="btn btn-link p-0 m-0" (click)="clearAfter()">
|
||||
<div class="mb-2 d-flex flex-row w-100 justify-content-between small">
|
||||
<div i18n>After</div>
|
||||
@if (dateAfter) {
|
||||
<a class="btn btn-link p-0 m-0" (click)="clearAfter()">
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg>
|
||||
<small i18n>Clear</small>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
|
||||
maxlength="10" [(ngModel)]="dateAfter" ngbDatepicker #dateAfterPicker="ngbDatepicker">
|
||||
<button class="btn btn-outline-secondary" (click)="dateAfterPicker.toggle()" type="button">
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#calendar"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
}
|
||||
</div>
|
||||
<div class="list-group-item d-flex flex-column align-items-start" role="menuitem">
|
||||
|
||||
<div class="mb-2 d-flex flex-row w-100 justify-content-between small">
|
||||
<div i18n>Before</div>
|
||||
<a *ngIf="dateBefore" class="btn btn-link p-0 m-0" (click)="clearBefore()">
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
|
||||
maxlength="10" [(ngModel)]="dateAfter" ngbDatepicker #dateAfterPicker="ngbDatepicker">
|
||||
<button class="btn btn-outline-secondary" (click)="dateAfterPicker.toggle()" type="button">
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#calendar"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="list-group-item d-flex flex-column align-items-start" role="menuitem">
|
||||
|
||||
<div class="mb-2 d-flex flex-row w-100 justify-content-between small">
|
||||
<div i18n>Before</div>
|
||||
@if (dateBefore) {
|
||||
<a class="btn btn-link p-0 m-0" (click)="clearBefore()">
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg>
|
||||
<small i18n>Clear</small>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
|
||||
maxlength="10" [(ngModel)]="dateBefore" ngbDatepicker #dateBeforePicker="ngbDatepicker">
|
||||
<button class="btn btn-outline-secondary" (click)="dateBeforePicker.toggle()" type="button">
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#calendar"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
|
||||
maxlength="10" [(ngModel)]="dateBefore" ngbDatepicker #dateBeforePicker="ngbDatepicker">
|
||||
<button class="btn btn-outline-secondary" (click)="dateBeforePicker.toggle()" type="button">
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#calendar"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,93 +1,95 @@
|
||||
<form [formGroup]="objectForm" (ngSubmit)="save()" autocomplete="off">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
||||
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></pngx-input-text>
|
||||
</div>
|
||||
<div class="col">
|
||||
<pngx-input-number i18n-title title="Sort order" formControlName="order" [showAdd]="false" [error]="error?.order"></pngx-input-number>
|
||||
</div>
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
||||
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></pngx-input-text>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<h5 class="border-bottom pb-2" i18n>Filters</h5>
|
||||
<p class="small" i18n>Process documents that match <em>all</em> filters specified below.</p>
|
||||
<pngx-input-select i18n-title title="Filter sources" [items]="sourceOptions" [multiple]="true" formControlName="sources" [error]="error?.sources"></pngx-input-select>
|
||||
<pngx-input-text i18n-title title="Filter filename" formControlName="filter_filename" i18n-hint hint="Apply to documents that match this filename. Wildcards such as *.pdf or *invoice* are allowed. Case insensitive." [error]="error?.filter_filename"></pngx-input-text>
|
||||
<pngx-input-text i18n-title title="Filter path" formControlName="filter_path" i18n-hint hint="Apply to documents that match this path. Wildcards specified as * are allowed. Case insensitive.</a>" [error]="error?.filter_path"></pngx-input-text>
|
||||
<pngx-input-select i18n-title title="Filter mail rule" [items]="mailRules" [allowNull]="true" formControlName="filter_mailrule" i18n-hint hint="Apply to documents consumed via this mail rule." [error]="error?.filter_mailrule"></pngx-input-select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h5 class="border-bottom pb-2" i18n>Assignments</h5>
|
||||
</div>
|
||||
<div class="col">
|
||||
<pngx-input-number i18n-title title="Sort order" formControlName="order" [showAdd]="false" [error]="error?.order"></pngx-input-number>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<h5 class="border-bottom pb-2" i18n>Filters</h5>
|
||||
<p class="small" i18n>Process documents that match <em>all</em> filters specified below.</p>
|
||||
<pngx-input-select i18n-title title="Filter sources" [items]="sourceOptions" [multiple]="true" formControlName="sources" [error]="error?.sources"></pngx-input-select>
|
||||
<pngx-input-text i18n-title title="Filter filename" formControlName="filter_filename" i18n-hint hint="Apply to documents that match this filename. Wildcards such as *.pdf or *invoice* are allowed. Case insensitive." [error]="error?.filter_filename"></pngx-input-text>
|
||||
<pngx-input-text i18n-title title="Filter path" formControlName="filter_path" i18n-hint hint="Apply to documents that match this path. Wildcards specified as * are allowed. Case insensitive.</a>" [error]="error?.filter_path"></pngx-input-text>
|
||||
<pngx-input-select i18n-title title="Filter mail rule" [items]="mailRules" [allowNull]="true" formControlName="filter_mailrule" i18n-hint hint="Apply to documents consumed via this mail rule." [error]="error?.filter_mailrule"></pngx-input-select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h5 class="border-bottom pb-2" i18n>Assignments</h5>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<pngx-input-text i18n-title title="Assign title" formControlName="assign_title" i18n-hint hint="Can include some placeholders, see <a target='_blank' href='https://docs.paperless-ngx.com/usage/#consumption-templates'>documentation</a>." [error]="error?.assign_title"></pngx-input-text>
|
||||
<pngx-input-tags [allowCreate]="false" i18n-title title="Assign tags" formControlName="assign_tags"></pngx-input-tags>
|
||||
<pngx-input-select i18n-title title="Assign document type" [items]="documentTypes" [allowNull]="true" formControlName="assign_document_type"></pngx-input-select>
|
||||
<pngx-input-select i18n-title title="Assign correspondent" [items]="correspondents" [allowNull]="true" formControlName="assign_correspondent"></pngx-input-select>
|
||||
<pngx-input-select i18n-title title="Assign storage path" [items]="storagePaths" [allowNull]="true" formControlName="assign_storage_path"></pngx-input-select>
|
||||
<pngx-input-select i18n-title title="Assign custom fields" multiple="true" [items]="customFields" [allowNull]="true" formControlName="assign_custom_fields"></pngx-input-select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<pngx-input-text i18n-title title="Assign title" formControlName="assign_title" i18n-hint hint="Can include some placeholders, see <a target='_blank' href='https://docs.paperless-ngx.com/usage/#consumption-templates'>documentation</a>." [error]="error?.assign_title"></pngx-input-text>
|
||||
<pngx-input-tags [allowCreate]="false" i18n-title title="Assign tags" formControlName="assign_tags"></pngx-input-tags>
|
||||
<pngx-input-select i18n-title title="Assign document type" [items]="documentTypes" [allowNull]="true" formControlName="assign_document_type"></pngx-input-select>
|
||||
<pngx-input-select i18n-title title="Assign correspondent" [items]="correspondents" [allowNull]="true" formControlName="assign_correspondent"></pngx-input-select>
|
||||
<pngx-input-select i18n-title title="Assign storage path" [items]="storagePaths" [allowNull]="true" formControlName="assign_storage_path"></pngx-input-select>
|
||||
<pngx-input-select i18n-title title="Assign custom fields" multiple="true" [items]="customFields" [allowNull]="true" formControlName="assign_custom_fields"></pngx-input-select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<pngx-input-select i18n-title title="Assign owner" [items]="users" bindLabel="username" formControlName="assign_owner" [allowNull]="true"></pngx-input-select>
|
||||
<div>
|
||||
<label class="form-label" i18n>Assign view permissions</label>
|
||||
<div class="mb-2">
|
||||
<div class="row mb-1">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2 text-nowrap" i18n>Users:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-user type="view" formControlName="assign_view_users"></pngx-permissions-user>
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label" i18n>Assign view permissions</label>
|
||||
<div class="mb-2">
|
||||
<div class="row mb-1">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2 text-nowrap" i18n>Users:</label>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2 text-nowrap" i18n>Groups:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-group type="view" formControlName="assign_view_groups"></pngx-permissions-group>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-user type="view" formControlName="assign_view_users"></pngx-permissions-user>
|
||||
</div>
|
||||
</div>
|
||||
<label class="form-label" i18n>Assign edit permissions</label>
|
||||
<div>
|
||||
<div class="row mb-1">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2 text-nowrap" i18n>Users:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-user type="change" formControlName="assign_change_users"></pngx-permissions-user>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2 text-nowrap" i18n>Groups:</label>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2 text-nowrap" i18n>Groups:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-group type="change" formControlName="assign_change_groups"></pngx-permissions-group>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-group type="view" formControlName="assign_view_groups"></pngx-permissions-group>
|
||||
</div>
|
||||
<small class="form-text text-muted text-end d-block" i18n>Edit permissions also grant viewing permissions</small>
|
||||
</div>
|
||||
</div>
|
||||
<label class="form-label" i18n>Assign edit permissions</label>
|
||||
<div>
|
||||
<div class="row mb-1">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2 text-nowrap" i18n>Users:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-user type="change" formControlName="assign_change_users"></pngx-permissions-user>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2 text-nowrap" i18n>Groups:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-group type="change" formControlName="assign_change_groups"></pngx-permissions-group>
|
||||
</div>
|
||||
</div>
|
||||
<small class="form-text text-muted text-end d-block" i18n>Edit permissions also grant viewing permissions</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<span class="text-danger" *ngIf="error?.non_field_errors"><ng-container i18n>Error</ng-container>: {{error.non_field_errors}}</span>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@if (error?.non_field_errors) {
|
||||
<span class="text-danger"><ng-container i18n>Error</ng-container>: {{error.non_field_errors}}</span>
|
||||
}
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@@ -8,8 +8,12 @@
|
||||
|
||||
<pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></pngx-input-text>
|
||||
<pngx-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></pngx-input-select>
|
||||
<pngx-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match" [error]="error?.match"></pngx-input-text>
|
||||
<pngx-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive" novalidate></pngx-input-check>
|
||||
@if (patternRequired) {
|
||||
<pngx-input-text i18n-title title="Matching pattern" formControlName="match" [error]="error?.match"></pngx-input-text>
|
||||
}
|
||||
@if (patternRequired) {
|
||||
<pngx-input-check i18n-title title="Case insensitive" formControlName="is_insensitive" novalidate></pngx-input-check>
|
||||
}
|
||||
|
||||
<div *pngxIfOwner="object">
|
||||
<pngx-permissions-form [users]="users" accordion="true" formControlName="permissions_form"></pngx-permissions-form>
|
||||
|
@@ -7,7 +7,9 @@
|
||||
<div class="modal-body">
|
||||
<pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></pngx-input-text>
|
||||
<pngx-input-select i18n-title title="Data type" [items]="getDataTypes()" formControlName="data_type"></pngx-input-select>
|
||||
<small class="d-block mt-n2" *ngIf="typeFieldDisabled" i18n>Data type cannot be changed after a field is created</small>
|
||||
@if (typeFieldDisabled) {
|
||||
<small class="d-block mt-n2" i18n>Data type cannot be changed after a field is created</small>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
|
||||
|
@@ -1,25 +1,29 @@
|
||||
<form [formGroup]="objectForm" (ngSubmit)="save()" autocomplete="off">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
||||
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="col">
|
||||
<pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></pngx-input-text>
|
||||
<pngx-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></pngx-input-select>
|
||||
<pngx-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match" [error]="error?.match"></pngx-input-text>
|
||||
<pngx-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive"></pngx-input-check>
|
||||
</div>
|
||||
|
||||
<div *pngxIfOwner="object">
|
||||
<pngx-permissions-form [users]="users" accordion="true" formControlName="permissions_form"></pngx-permissions-form>
|
||||
</div>
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
||||
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="col">
|
||||
<pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></pngx-input-text>
|
||||
<pngx-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></pngx-input-select>
|
||||
@if (patternRequired) {
|
||||
<pngx-input-text i18n-title title="Matching pattern" formControlName="match" [error]="error?.match"></pngx-input-text>
|
||||
}
|
||||
@if (patternRequired) {
|
||||
<pngx-input-check i18n-title title="Case insensitive" formControlName="is_insensitive"></pngx-input-check>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
|
||||
|
||||
<div *pngxIfOwner="object">
|
||||
<pngx-permissions-form [users]="users" accordion="true" formControlName="permissions_form"></pngx-permissions-form>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@@ -22,13 +22,15 @@
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="m-0 me-2">
|
||||
<ngb-alert #testResultAlert *ngIf="testResult" [type]="testResult" class="mb-0 py-2" (closed)="testResult = null">{{testResultMessage}}</ngb-alert>
|
||||
@if (testResult) {
|
||||
<ngb-alert #testResultAlert [type]="testResult" class="mb-0 py-2" (closed)="testResult = null">{{testResultMessage}}</ngb-alert>
|
||||
}
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-primary" (click)="test()" [disabled]="networkActive || testActive">
|
||||
<ng-container *ngIf="testActive">
|
||||
@if (testActive) {
|
||||
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||
<span class="visually-hidden mr-1" i18n>Loading...</span>
|
||||
</ng-container>
|
||||
}
|
||||
<ng-container i18n>Test</ng-container>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
|
||||
|
@@ -26,19 +26,25 @@
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<pngx-input-select i18n-title title="Action" [items]="actionOptions" formControlName="action" i18n-hint hint="Action is only performed when documents are consumed from the mail. Mails without attachments remain entirely untouched."></pngx-input-select>
|
||||
<pngx-input-text i18n-title title="Action parameter" *ngIf="showActionParamField" formControlName="action_parameter" [error]="error?.action_parameter"></pngx-input-text>
|
||||
@if (showActionParamField) {
|
||||
<pngx-input-text i18n-title title="Action parameter" formControlName="action_parameter" [error]="error?.action_parameter"></pngx-input-text>
|
||||
}
|
||||
<p class="small fst-italic mt-5" i18n>Assignments specified here will supersede any consumption templates.</p>
|
||||
<pngx-input-select i18n-title title="Assign title from" [items]="metadataTitleOptions" formControlName="assign_title_from"></pngx-input-select>
|
||||
<pngx-input-tags [allowCreate]="false" formControlName="assign_tags"></pngx-input-tags>
|
||||
<pngx-input-select i18n-title title="Assign document type" [items]="documentTypes" [allowNull]="true" formControlName="assign_document_type"></pngx-input-select>
|
||||
<pngx-input-select i18n-title title="Assign correspondent from" [items]="metadataCorrespondentOptions" formControlName="assign_correspondent_from"></pngx-input-select>
|
||||
<pngx-input-select *ngIf="showCorrespondentField" i18n-title title="Assign correspondent" [items]="correspondents" [allowNull]="true" formControlName="assign_correspondent"></pngx-input-select>
|
||||
@if (showCorrespondentField) {
|
||||
<pngx-input-select i18n-title title="Assign correspondent" [items]="correspondents" [allowNull]="true" formControlName="assign_correspondent"></pngx-input-select>
|
||||
}
|
||||
<pngx-input-check i18n-title title="Assign owner from rule" formControlName="assign_owner_from_rule"></pngx-input-check>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<span class="text-danger" *ngIf="error?.non_field_errors"><ng-container i18n>Error</ng-container>: {{error.non_field_errors}}</span>
|
||||
@if (error?.non_field_errors) {
|
||||
<span class="text-danger"><ng-container i18n>Error</ng-container>: {{error.non_field_errors}}</span>
|
||||
}
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
|
||||
</div>
|
||||
|
@@ -9,8 +9,12 @@
|
||||
<pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></pngx-input-text>
|
||||
<pngx-input-text i18n-title title="Path" formControlName="path" [error]="error?.path" [hint]="pathHint"></pngx-input-text>
|
||||
<pngx-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></pngx-input-select>
|
||||
<pngx-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match" [error]="error?.match"></pngx-input-text>
|
||||
<pngx-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive"></pngx-input-check>
|
||||
@if (patternRequired) {
|
||||
<pngx-input-text i18n-title title="Matching pattern" formControlName="match" [error]="error?.match"></pngx-input-text>
|
||||
}
|
||||
@if (patternRequired) {
|
||||
<pngx-input-check i18n-title title="Case insensitive" formControlName="is_insensitive"></pngx-input-check>
|
||||
}
|
||||
|
||||
<div *pngxIfOwner="object">
|
||||
<pngx-permissions-form [users]="users" accordion="true" formControlName="permissions_form"></pngx-permissions-form>
|
||||
|
@@ -1,26 +1,30 @@
|
||||
<form [formGroup]="objectForm" (ngSubmit)="save()" autocomplete="off">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
||||
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||
</button>
|
||||
<form [formGroup]="objectForm" (ngSubmit)="save()" autocomplete="off">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
||||
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></pngx-input-text>
|
||||
|
||||
<pngx-input-color i18n-title title="Color" formControlName="color" [error]="error?.color"></pngx-input-color>
|
||||
|
||||
<pngx-input-check i18n-title title="Inbox tag" formControlName="is_inbox_tag" i18n-hint hint="Inbox tags are automatically assigned to all consumed documents."></pngx-input-check>
|
||||
<pngx-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></pngx-input-select>
|
||||
@if (patternRequired) {
|
||||
<pngx-input-text i18n-title title="Matching pattern" formControlName="match" [error]="error?.match"></pngx-input-text>
|
||||
}
|
||||
@if (patternRequired) {
|
||||
<pngx-input-check i18n-title title="Case insensitive" formControlName="is_insensitive"></pngx-input-check>
|
||||
}
|
||||
|
||||
<div *pngxIfOwner="object">
|
||||
<pngx-permissions-form [users]="users" accordion="true" formControlName="permissions_form"></pngx-permissions-form>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></pngx-input-text>
|
||||
|
||||
<pngx-input-color i18n-title title="Color" formControlName="color" [error]="error?.color"></pngx-input-color>
|
||||
|
||||
<pngx-input-check i18n-title title="Inbox tag" formControlName="is_inbox_tag" i18n-hint hint="Inbox tags are automatically assigned to all consumed documents."></pngx-input-check>
|
||||
<pngx-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></pngx-input-select>
|
||||
<pngx-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match" [error]="error?.match"></pngx-input-text>
|
||||
<pngx-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive"></pngx-input-check>
|
||||
|
||||
<div *pngxIfOwner="object">
|
||||
<pngx-permissions-form [users]="users" accordion="true" formControlName="permissions_form"></pngx-permissions-form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@@ -4,49 +4,61 @@
|
||||
<use attr.xlink:href="assets/bootstrap-icons.svg#{{icon}}" />
|
||||
</svg>
|
||||
<div class="d-none d-sm-inline"> {{title}}</div>
|
||||
<ng-container *ngIf="!editing && selectionModel.totalCount > 0">
|
||||
@if (!editing && selectionModel.totalCount > 0) {
|
||||
<pngx-clearable-badge [number]="selectionModel.totalCount" [selected]="selectionModel.selectionSize() > 0" (cleared)="reset()"></pngx-clearable-badge>
|
||||
</ng-container>
|
||||
}
|
||||
</button>
|
||||
<div class="dropdown-menu py-0 shadow" ngbDropdownMenu attr.aria-labelledby="dropdown_{{name}}">
|
||||
<div class="list-group list-group-flush">
|
||||
<div *ngIf="!editing && manyToOne" class="list-group-item d-flex">
|
||||
<div class="btn-group btn-group-xs flex-fill" role="group">
|
||||
<input [(ngModel)]="selectionModel.logicalOperator" [disabled]="!modifierToggleEnabled" (ngModelChange)="selectionModel.toggleOperator()" type="radio" class="btn-check" id="logicalOperatorAnd_{{name}}" name="logicalOperatorAnd_{{name}}" value="and">
|
||||
<label class="btn btn-outline-primary" for="logicalOperatorAnd_{{name}}" i18n>All</label>
|
||||
<input [(ngModel)]="selectionModel.logicalOperator" [disabled]="!modifierToggleEnabled" (ngModelChange)="selectionModel.toggleOperator()" type="radio" class="btn-check" id="logicalOperatorOr_{{name}}" name="logicalOperatorOr_{{name}}" value="or">
|
||||
<label class="btn btn-outline-primary" for="logicalOperatorOr_{{name}}" i18n>Any</label>
|
||||
@if (!editing && manyToOne) {
|
||||
<div class="list-group-item d-flex">
|
||||
<div class="btn-group btn-group-xs flex-fill" role="group">
|
||||
<input [(ngModel)]="selectionModel.logicalOperator" [disabled]="!modifierToggleEnabled" (ngModelChange)="selectionModel.toggleOperator()" type="radio" class="btn-check" id="logicalOperatorAnd_{{name}}" name="logicalOperatorAnd_{{name}}" value="and">
|
||||
<label class="btn btn-outline-primary" for="logicalOperatorAnd_{{name}}" i18n>All</label>
|
||||
<input [(ngModel)]="selectionModel.logicalOperator" [disabled]="!modifierToggleEnabled" (ngModelChange)="selectionModel.toggleOperator()" type="radio" class="btn-check" id="logicalOperatorOr_{{name}}" name="logicalOperatorOr_{{name}}" value="or">
|
||||
<label class="btn btn-outline-primary" for="logicalOperatorOr_{{name}}" i18n>Any</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!editing && !manyToOne" class="list-group-item d-flex">
|
||||
<div class="btn-group btn-group-xs flex-fill" role="group">
|
||||
<input [(ngModel)]="selectionModel.intersection" [disabled]="!modifierToggleEnabled" (ngModelChange)="selectionModel.toggleIntersection()" type="radio" class="btn-check" id="intersectionInclude_{{name}}" name="intersectionInclude_{{name}}" value="include">
|
||||
<label class="btn btn-outline-primary" for="intersectionInclude_{{name}}" i18n>Include</label>
|
||||
<input [(ngModel)]="selectionModel.intersection" [disabled]="!modifierToggleEnabled" (ngModelChange)="selectionModel.toggleIntersection()" type="radio" class="btn-check" id="intersectionExclude_{{name}}" name="intersectionExclude_{{name}}" value="exclude">
|
||||
<label class="btn btn-outline-primary" for="intersectionExclude_{{name}}" i18n>Exclude</label>
|
||||
}
|
||||
@if (!editing && !manyToOne) {
|
||||
<div class="list-group-item d-flex">
|
||||
<div class="btn-group btn-group-xs flex-fill" role="group">
|
||||
<input [(ngModel)]="selectionModel.intersection" [disabled]="!modifierToggleEnabled" (ngModelChange)="selectionModel.toggleIntersection()" type="radio" class="btn-check" id="intersectionInclude_{{name}}" name="intersectionInclude_{{name}}" value="include">
|
||||
<label class="btn btn-outline-primary" for="intersectionInclude_{{name}}" i18n>Include</label>
|
||||
<input [(ngModel)]="selectionModel.intersection" [disabled]="!modifierToggleEnabled" (ngModelChange)="selectionModel.toggleIntersection()" type="radio" class="btn-check" id="intersectionExclude_{{name}}" name="intersectionExclude_{{name}}" value="exclude">
|
||||
<label class="btn btn-outline-primary" for="intersectionExclude_{{name}}" i18n>Exclude</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="list-group-item">
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control" type="text" [(ngModel)]="filterText" [placeholder]="filterPlaceholder" (keyup.enter)="listFilterEnter()" #listFilterTextInput>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="selectionModel.items" class="items" #buttonItems>
|
||||
<ng-container *ngFor="let item of selectionModel.itemsSorted | filter: filterText; let i = index">
|
||||
<pngx-toggleable-dropdown-button
|
||||
*ngIf="allowSelectNone || item.id" [item]="item" [hideCount]="hideCount(item)" [state]="selectionModel.get(item.id)" [count]="getUpdatedDocumentCount(item.id)" (toggle)="selectionModel.toggle(item.id)" (exclude)="excludeClicked(item.id)" (click)="setButtonItemIndex(i - 1)" [disabled]="disabled">
|
||||
</pngx-toggleable-dropdown-button>
|
||||
</ng-container>
|
||||
</div>
|
||||
<button *ngIf="editing" class="list-group-item list-group-item-action bg-light" (click)="applyClicked()" [disabled]="!modelIsDirty || disabled">
|
||||
<small class="ms-2" [ngClass]="{'fw-bold': modelIsDirty}" i18n>Apply</small>
|
||||
<svg width="1.5em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#arrow-right" />
|
||||
</svg>
|
||||
</button>
|
||||
<div *ngIf="!editing && manyToOne" class="list-group-item list-group-item-note pt-1 pb-2">
|
||||
<small i18n>Click again to exclude items.</small>
|
||||
</div>
|
||||
@if (selectionModel.items) {
|
||||
<div class="items" #buttonItems>
|
||||
@for (item of selectionModel.itemsSorted | filter: filterText; track item; let i = $index) {
|
||||
@if (allowSelectNone || item.id) {
|
||||
<pngx-toggleable-dropdown-button
|
||||
[item]="item" [hideCount]="hideCount(item)" [state]="selectionModel.get(item.id)" [count]="getUpdatedDocumentCount(item.id)" (toggle)="selectionModel.toggle(item.id)" (exclude)="excludeClicked(item.id)" (click)="setButtonItemIndex(i - 1)" [disabled]="disabled">
|
||||
</pngx-toggleable-dropdown-button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (editing) {
|
||||
<button class="list-group-item list-group-item-action bg-light" (click)="applyClicked()" [disabled]="!modelIsDirty || disabled">
|
||||
<small class="ms-2" [ngClass]="{'fw-bold': modelIsDirty}" i18n>Apply</small>
|
||||
<svg width="1.5em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#arrow-right" />
|
||||
</svg>
|
||||
</button>
|
||||
}
|
||||
@if (!editing && manyToOne) {
|
||||
<div class="list-group-item list-group-item-note pt-1 pb-2">
|
||||
<small i18n>Click again to exclude items.</small>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,24 +1,29 @@
|
||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="toggleItem($event)" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
<ng-container *ngIf="isChecked()">
|
||||
@if (isChecked()) {
|
||||
<svg fill="currentColor" class="buttonicon-sm bi-check">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="isPartiallyChecked()">
|
||||
}
|
||||
@if (isPartiallyChecked()) {
|
||||
<svg fill="currentColor" class="buttonicon-sm bi-dash">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#dash"/>
|
||||
</svg>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="isExcluded()">
|
||||
}
|
||||
@if (isExcluded()) {
|
||||
<svg fill="currentColor" class="buttonicon-sm bi-x">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg>
|
||||
</ng-container>
|
||||
}
|
||||
</div>
|
||||
<div class="me-1">
|
||||
<pngx-tag *ngIf="isTag; else displayName" [tag]="item" [clickable]="false"></pngx-tag>
|
||||
<ng-template #displayName><small>{{item.name}}</small></ng-template>
|
||||
@if (isTag) {
|
||||
<pngx-tag [tag]="item" [clickable]="false"></pngx-tag>
|
||||
} @else {
|
||||
<small>{{item.name}}</small>
|
||||
}
|
||||
</div>
|
||||
<div *ngIf="!hideCount" class="badge bg-light text-dark rounded-pill ms-auto me-1">{{count ?? item.document_count}}</div>
|
||||
@if (!hideCount) {
|
||||
<div class="badge bg-light text-dark rounded-pill ms-auto me-1">{{count ?? item.document_count}}</div>
|
||||
}
|
||||
</button>
|
||||
|
@@ -1,19 +1,27 @@
|
||||
<div class="mb-3">
|
||||
<div class="row">
|
||||
<div *ngIf="horizontal" class="d-flex align-items-center position-relative hidden-button-container col-md-3">
|
||||
<label class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
|
||||
<button type="button" *ngIf="removable" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
<div [ngClass]="{'col-md-9': horizontal, 'align-items-center': horizontal, 'd-flex': horizontal}">
|
||||
<div class="form-check">
|
||||
<input #inputField type="checkbox" class="form-check-input" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled">
|
||||
<label *ngIf="!horizontal" class="form-check-label" [for]="inputId">{{title}}</label>
|
||||
<div *ngIf="hint" class="form-text text-muted">{{hint}}</div>
|
||||
@if (horizontal) {
|
||||
<div class="d-flex align-items-center position-relative hidden-button-container col-md-3">
|
||||
<label class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
|
||||
@if (removable) {
|
||||
<button type="button" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<div [ngClass]="{'col-md-9': horizontal, 'align-items-center': horizontal, 'd-flex': horizontal}">
|
||||
<div class="form-check">
|
||||
<input #inputField type="checkbox" class="form-check-input" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled">
|
||||
@if (!horizontal) {
|
||||
<label class="form-check-label" [for]="inputId">{{title}}</label>
|
||||
}
|
||||
@if (hint) {
|
||||
<div class="form-text text-muted">{{hint}}</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,28 +1,32 @@
|
||||
<div class="mb-3">
|
||||
<label *ngIf="title" [for]="inputId">{{title}}</label>
|
||||
@if (title) {
|
||||
<label [for]="inputId">{{title}}</label>
|
||||
}
|
||||
|
||||
<div class="input-group" [class.is-invalid]="error">
|
||||
<span class="input-group-text" [style.background-color]="value"> </span>
|
||||
|
||||
<ng-template #popContent>
|
||||
<div style="min-width: 200px;" class="pb-3">
|
||||
<color-slider [color]="value" (onChangeComplete)="colorChanged($event.color.hex)"></color-slider>
|
||||
</div>
|
||||
<ng-template #popContent>
|
||||
<div style="min-width: 200px;" class="pb-3">
|
||||
<color-slider [color]="value" (onChangeComplete)="colorChanged($event.color.hex)"></color-slider>
|
||||
</div>
|
||||
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
|
||||
<input #inputField class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [autoClose]="'outside'" [ngbPopover]="popContent" placement="bottom" popoverClass="shadow">
|
||||
<input #inputField class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [autoClose]="'outside'" [ngbPopover]="popContent" placement="bottom" popoverClass="shadow">
|
||||
|
||||
<button class="btn btn-outline-secondary" type="button" (click)="randomize()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dice-5" viewBox="0 0 16 16">
|
||||
<path d="M13 1a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h10zM3 0a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V3a3 3 0 0 0-3-3H3z"/>
|
||||
<path d="M5.5 4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm-8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm4-4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary" type="button" (click)="randomize()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dice-5" viewBox="0 0 16 16">
|
||||
<path d="M13 1a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h10zM3 0a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V3a3 3 0 0 0-3-3H3z"/>
|
||||
<path d="M5.5 4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm-8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm4-4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
||||
<div class="invalid-feedback">
|
||||
{{error}}
|
||||
</div>
|
||||
</div>
|
||||
@if (hint) {
|
||||
<small class="form-text text-muted">{{hint}}</small>
|
||||
}
|
||||
<div class="invalid-feedback">
|
||||
{{error}}
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2,36 +2,44 @@
|
||||
<div class="row">
|
||||
<div class="d-flex align-items-center position-relative hidden-button-container" [class.col-md-3]="horizontal">
|
||||
<label class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
|
||||
<button type="button" *ngIf="removable" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
<div class="position-relative" [class.col-md-9]="horizontal">
|
||||
<div class="input-group" [class.is-invalid]="error">
|
||||
<input #inputField class="form-control" [class.is-invalid]="error" [placeholder]="placeholder" [id]="inputId" maxlength="10"
|
||||
(dateSelect)="onChange(value)" (change)="onChange(value)" (keypress)="onKeyPress($event)" (paste)="onPaste($event)"
|
||||
name="dp" [(ngModel)]="value" ngbDatepicker #datePicker="ngbDatepicker" #datePickerContent="ngModel" [disabled]="disabled">
|
||||
<button class="btn btn-outline-secondary calendar" (click)="datePicker.toggle()" type="button" [disabled]="disabled">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="buttonicon">
|
||||
<use _ngcontent-ng-c3750736003="" xlink:href="assets/bootstrap-icons.svg#calendar"></use>
|
||||
</svg>
|
||||
</button>
|
||||
<button *ngIf="showFilter" class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="this.value === null" title="{{ fitlerButtonTitle }}">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#filter" />
|
||||
</svg>
|
||||
</button>
|
||||
@if (removable) {
|
||||
<button type="button" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="position-relative" [class.col-md-9]="horizontal">
|
||||
<div class="input-group" [class.is-invalid]="error">
|
||||
<input #inputField class="form-control" [class.is-invalid]="error" [placeholder]="placeholder" [id]="inputId" maxlength="10"
|
||||
(dateSelect)="onChange(value)" (change)="onChange(value)" (keypress)="onKeyPress($event)" (paste)="onPaste($event)"
|
||||
name="dp" [(ngModel)]="value" ngbDatepicker #datePicker="ngbDatepicker" #datePickerContent="ngModel" [disabled]="disabled">
|
||||
<button class="btn btn-outline-secondary calendar" (click)="datePicker.toggle()" type="button" [disabled]="disabled">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="buttonicon">
|
||||
<use _ngcontent-ng-c3750736003="" xlink:href="assets/bootstrap-icons.svg#calendar"></use>
|
||||
</svg>
|
||||
</button>
|
||||
@if (showFilter) {
|
||||
<button class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="this.value === null" title="{{ filterButtonTitle }}">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#filter" />
|
||||
</svg>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="invalid-feedback position-absolute top-100" i18n>Invalid date.</div>
|
||||
@if (hint) {
|
||||
<small class="form-text text-muted">{{hint}}</small>
|
||||
}
|
||||
@if (getSuggestions().length > 0) {
|
||||
<small>
|
||||
<span i18n>Suggestions:</span>
|
||||
@for (s of getSuggestions(); track s) {
|
||||
<a (click)="onSuggestionClick(s)" [routerLink]="[]">{{s}}</a>
|
||||
}
|
||||
</small>
|
||||
}
|
||||
</div>
|
||||
<div class="invalid-feedback position-absolute top-100" i18n>Invalid date.</div>
|
||||
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
||||
<small *ngIf="getSuggestions().length > 0">
|
||||
<span i18n>Suggestions:</span>
|
||||
<ng-container *ngFor="let s of getSuggestions()">
|
||||
<a (click)="onSuggestionClick(s)" [routerLink]="[]">{{s}}</a>
|
||||
</ng-container>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,12 +1,16 @@
|
||||
<div class="mb-3 paperless-input-select" [class.disabled]="disabled">
|
||||
<div class="row">
|
||||
<div class="d-flex align-items-center position-relative hidden-button-container" [class.col-md-3]="horizontal">
|
||||
<label *ngIf="title" class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
|
||||
<button type="button" *ngIf="removable" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<div class="row">
|
||||
<div class="d-flex align-items-center position-relative hidden-button-container" [class.col-md-3]="horizontal">
|
||||
@if (title) {
|
||||
<label class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
|
||||
}
|
||||
@if (removable) {
|
||||
<button type="button" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div [class.col-md-9]="horizontal">
|
||||
<div>
|
||||
@@ -23,28 +27,30 @@
|
||||
[loading]="loading"
|
||||
[typeahead]="documentsInput$"
|
||||
(change)="onChange(selectedDocuments)">
|
||||
<ng-template ng-label-tmp let-document="item">
|
||||
<div class="d-flex align-items-center">
|
||||
<svg class="sidebaricon" fill="currentColor" xmlns="http://www.w3.org/2000/svg" (click)="unselect(document)">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg>
|
||||
<a routerLink="/documents/{{document.id}}" class="badge bg-light text-primary" (mousedown)="$event.stopImmediatePropagation();">
|
||||
<svg class="sidebaricon-sm me-1" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#file-text"/>
|
||||
</svg><span>{{document.title}}</span>
|
||||
</a>
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template ng-loadingspinner-tmp>
|
||||
<div class="spinner-border spinner-border-sm fw-normal ms-2 me-auto" role="status"></div>
|
||||
<div class="visually-hidden" i18n>Loading...</div>
|
||||
</ng-template>
|
||||
<ng-template ng-option-tmp let-document="item" let-index="index" let-search="searchTerm">
|
||||
<div>{{document.title}} <small class="text-muted">({{document.created | customDate:'shortDate'}})</small></div>
|
||||
</ng-template>
|
||||
</ng-select>
|
||||
<ng-template ng-label-tmp let-document="item">
|
||||
<div class="d-flex align-items-center">
|
||||
<svg class="sidebaricon" fill="currentColor" xmlns="http://www.w3.org/2000/svg" (click)="unselect(document)">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg>
|
||||
<a routerLink="/documents/{{document.id}}" class="badge bg-light text-primary" (mousedown)="$event.stopImmediatePropagation();">
|
||||
<svg class="sidebaricon-sm me-1" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#file-text"/>
|
||||
</svg><span>{{document.title}}</span>
|
||||
</a>
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template ng-loadingspinner-tmp>
|
||||
<div class="spinner-border spinner-border-sm fw-normal ms-2 me-auto" role="status"></div>
|
||||
<div class="visually-hidden" i18n>Loading...</div>
|
||||
</ng-template>
|
||||
<ng-template ng-option-tmp let-document="item" let-index="index" let-search="searchTerm">
|
||||
<div>{{document.title}} <small class="text-muted">({{document.created | customDate:'shortDate'}})</small></div>
|
||||
</ng-template>
|
||||
</ng-select>
|
||||
</div>
|
||||
@if (hint) {
|
||||
<small class="form-text text-muted">{{hint}}</small>
|
||||
}
|
||||
</div>
|
||||
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2,21 +2,27 @@
|
||||
<div class="row">
|
||||
<div class="d-flex align-items-center position-relative hidden-button-container" [class.col-md-3]="horizontal">
|
||||
<label class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
|
||||
<button type="button" *ngIf="removable" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
<div class="position-relative" [class.col-md-9]="horizontal">
|
||||
<div class="input-group" [class.is-invalid]="error">
|
||||
<input #inputField type="number" class="form-control" [step]="step" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [class.is-invalid]="error" [disabled]="disabled">
|
||||
<button *ngIf="showAdd" class="btn btn-outline-secondary" type="button" id="button-addon1" (click)="nextAsn()" [disabled]="disabled">+1</button>
|
||||
@if (removable) {
|
||||
<button type="button" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="invalid-feedback position-absolute top-100">
|
||||
{{error}}
|
||||
<div class="position-relative" [class.col-md-9]="horizontal">
|
||||
<div class="input-group" [class.is-invalid]="error">
|
||||
<input #inputField type="number" class="form-control" [step]="step" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [class.is-invalid]="error" [disabled]="disabled">
|
||||
@if (showAdd) {
|
||||
<button class="btn btn-outline-secondary" type="button" id="button-addon1" (click)="nextAsn()" [disabled]="disabled">+1</button>
|
||||
}
|
||||
</div>
|
||||
<div class="invalid-feedback position-absolute top-100">
|
||||
{{error}}
|
||||
</div>
|
||||
@if (hint) {
|
||||
<small class="form-text text-muted">{{hint}}</small>
|
||||
}
|
||||
</div>
|
||||
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2,14 +2,18 @@
|
||||
<label class="form-label" [for]="inputId">{{title}}</label>
|
||||
<div class="input-group" [class.is-invalid]="error">
|
||||
<input #inputField [type]="showReveal && textVisible ? 'text' : 'password'" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (focus)="onFocus()" (focusout)="onFocusOut()" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete">
|
||||
<button *ngIf="showReveal" type="button" class="btn btn-outline-secondary" (click)="toggleVisibility()" i18n-title title="Show password" [disabled]="disabled || disableRevealToggle">
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#eye" />
|
||||
</svg>
|
||||
</button>
|
||||
@if (showReveal) {
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="toggleVisibility()" i18n-title title="Show password" [disabled]="disabled || disableRevealToggle">
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#eye" />
|
||||
</svg>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{error}}
|
||||
</div>
|
||||
<small *ngIf="hint" class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
|
||||
@if (hint) {
|
||||
<small class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
|
||||
}
|
||||
</div>
|
||||
|
@@ -1,68 +1,75 @@
|
||||
<ng-container *ngIf="!accordion">
|
||||
@if (!accordion) {
|
||||
<h5 i18n>Permissions</h5>
|
||||
<ng-container [ngTemplateOutlet]="permissionsForm"></ng-container>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="accordion">
|
||||
<ngb-accordion #acc="ngbAccordion" activeIds="">
|
||||
<ngb-panel i18n-title title="Edit Permissions">
|
||||
<ng-template ngbPanelContent>
|
||||
<ng-container [ngTemplateOutlet]="permissionsForm"></ng-container>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
</ngb-accordion>
|
||||
</ng-container>
|
||||
}
|
||||
@if (accordion) {
|
||||
<div ngbAccordion activeIds="">
|
||||
<div ngbAccordionItem>
|
||||
<h2 ngbAccordionHeader>
|
||||
<button ngbAccordionButton i18n>Edit Permissions</button>
|
||||
</h2>
|
||||
<div ngbAccordionCollapse>
|
||||
<div ngbAccordionBody>
|
||||
<ng-template>
|
||||
<ng-container [ngTemplateOutlet]="permissionsForm"></ng-container>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<ng-template #permissionsForm>
|
||||
<div [formGroup]="form">
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2" i18n>Owner:</label>
|
||||
<div [formGroup]="form">
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2" i18n>Owner:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-input-select [items]="users" bindLabel="username" formControlName="owner" [allowNull]="true"></pngx-input-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-input-select [items]="users" bindLabel="username" formControlName="owner" [allowNull]="true"></pngx-input-select>
|
||||
<small class="form-text text-muted text-end d-block mt-n2" i18n>Objects without an owner can be viewed and edited by all users</small>
|
||||
<div formGroupName="set_permissions">
|
||||
<h6 class="mt-3" i18n>View</h6>
|
||||
<div formGroupName="view" class="mb-2">
|
||||
<div class="row mb-1">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2" i18n>Users:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-user type="view" formControlName="users"></pngx-permissions-user>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2" i18n>Groups:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-group type="view" formControlName="groups"></pngx-permissions-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h6 class="mt-4" i18n>Edit</h6>
|
||||
<div formGroupName="change">
|
||||
<div class="row mb-1">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2" i18n>Users:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-user type="change" formControlName="users"></pngx-permissions-user>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2" i18n>Groups:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-group type="change" formControlName="groups"></pngx-permissions-group>
|
||||
</div>
|
||||
</div>
|
||||
<small class="form-text text-muted text-end d-block" i18n>Edit permissions also grant viewing permissions</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<small class="form-text text-muted text-end d-block mt-n2" i18n>Objects without an owner can be viewed and edited by all users</small>
|
||||
<div formGroupName="set_permissions">
|
||||
<h6 class="mt-3" i18n>View</h6>
|
||||
<div formGroupName="view" class="mb-2">
|
||||
<div class="row mb-1">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2" i18n>Users:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-user type="view" formControlName="users"></pngx-permissions-user>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2" i18n>Groups:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-group type="view" formControlName="groups"></pngx-permissions-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h6 class="mt-4" i18n>Edit</h6>
|
||||
<div formGroupName="change">
|
||||
<div class="row mb-1">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2" i18n>Users:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-user type="change" formControlName="users"></pngx-permissions-user>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label d-block my-2" i18n>Groups:</label>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<pngx-permissions-group type="change" formControlName="groups"></pngx-permissions-group>
|
||||
</div>
|
||||
</div>
|
||||
<small class="form-text text-muted text-end d-block" i18n>Edit permissions also grant viewing permissions</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
@@ -1,57 +1,69 @@
|
||||
<div class="mb-3 paperless-input-select" [class.disabled]="disabled">
|
||||
<div class="row">
|
||||
<div class="d-flex align-items-center position-relative hidden-button-container" [class.col-md-3]="horizontal">
|
||||
<label *ngIf="title" class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
|
||||
<button type="button" *ngIf="removable" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
<div [class.col-md-9]="horizontal">
|
||||
<div [class.input-group]="allowCreateNew || showFilter" [class.is-invalid]="error">
|
||||
<ng-select name="inputId" [(ngModel)]="value"
|
||||
[disabled]="disabled"
|
||||
[style.color]="textColor"
|
||||
[style.background]="backgroundColor"
|
||||
[class.private]="isPrivate"
|
||||
[clearable]="allowNull"
|
||||
[items]="items"
|
||||
[addTag]="allowCreateNew && addItemRef"
|
||||
addTagText="Add item"
|
||||
i18n-addTagText="Used for both types, correspondents, storage paths"
|
||||
[placeholder]="placeholder"
|
||||
[notFoundText]="notFoundText"
|
||||
[multiple]="multiple"
|
||||
[bindLabel]="bindLabel"
|
||||
bindValue="id"
|
||||
(change)="onChange(value)"
|
||||
(search)="onSearch($event)"
|
||||
(focus)="clearLastSearchTerm()"
|
||||
(clear)="clearLastSearchTerm()"
|
||||
(blur)="onBlur()">
|
||||
</ng-select>
|
||||
<button *ngIf="allowCreateNew" class="btn btn-outline-secondary" type="button" (click)="addItem()" [disabled]="disabled">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#plus" />
|
||||
</svg>
|
||||
</button>
|
||||
<button *ngIf="showFilter" class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="isPrivate || this.value === null" title="{{ filterButtonTitle }}">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#filter" />
|
||||
</svg>
|
||||
</button>
|
||||
@if (title) {
|
||||
<label class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
|
||||
}
|
||||
@if (removable) {
|
||||
<button type="button" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{error}}
|
||||
<div [class.col-md-9]="horizontal">
|
||||
<div [class.input-group]="allowCreateNew || showFilter" [class.is-invalid]="error">
|
||||
<ng-select name="inputId" [(ngModel)]="value"
|
||||
[disabled]="disabled"
|
||||
[style.color]="textColor"
|
||||
[style.background]="backgroundColor"
|
||||
[class.private]="isPrivate"
|
||||
[clearable]="allowNull"
|
||||
[items]="items"
|
||||
[addTag]="allowCreateNew && addItemRef"
|
||||
addTagText="Add item"
|
||||
i18n-addTagText="Used for both types, correspondents, storage paths"
|
||||
[placeholder]="placeholder"
|
||||
[notFoundText]="notFoundText"
|
||||
[multiple]="multiple"
|
||||
[bindLabel]="bindLabel"
|
||||
bindValue="id"
|
||||
(change)="onChange(value)"
|
||||
(search)="onSearch($event)"
|
||||
(focus)="clearLastSearchTerm()"
|
||||
(clear)="clearLastSearchTerm()"
|
||||
(blur)="onBlur()">
|
||||
</ng-select>
|
||||
@if (allowCreateNew) {
|
||||
<button class="btn btn-outline-secondary" type="button" (click)="addItem()" [disabled]="disabled">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#plus" />
|
||||
</svg>
|
||||
</button>
|
||||
}
|
||||
@if (showFilter) {
|
||||
<button class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="isPrivate || this.value === null" title="{{ filterButtonTitle }}">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#filter" />
|
||||
</svg>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{error}}
|
||||
</div>
|
||||
@if (hint) {
|
||||
<small class="form-text text-muted">{{hint}}</small>
|
||||
}
|
||||
@if (getSuggestions().length > 0) {
|
||||
<small>
|
||||
<span i18n>Suggestions:</span>
|
||||
@for (s of getSuggestions(); track s) {
|
||||
<a (click)="value = s.id; onChange(value)" [routerLink]="[]">{{s.name}}</a>
|
||||
}
|
||||
</small>
|
||||
}
|
||||
</div>
|
||||
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
||||
<small *ngIf="getSuggestions().length > 0">
|
||||
<span i18n>Suggestions:</span>
|
||||
<ng-container *ngFor="let s of getSuggestions()">
|
||||
<a (click)="value = s.id; onChange(value)" [routerLink]="[]">{{s.name}}</a>
|
||||
</ng-container>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -122,7 +122,7 @@ export class SelectComponent extends AbstractInputComponent<number> {
|
||||
}
|
||||
}
|
||||
|
||||
addItem(name: string) {
|
||||
addItem(name: string = null) {
|
||||
if (name) this.createNew.next(name)
|
||||
else this.createNew.next(this._lastSearchTerm)
|
||||
this.clearLastSearchTerm()
|
||||
|
@@ -21,33 +21,45 @@
|
||||
<svg width="1.2em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg>
|
||||
<pngx-tag *ngIf="item.id && tags" style="background-color: none;" [tag]="getTag(item.id)"></pngx-tag>
|
||||
@if (item.id && tags) {
|
||||
<pngx-tag style="background-color: none;" [tag]="getTag(item.id)"></pngx-tag>
|
||||
}
|
||||
</span>
|
||||
</ng-template>
|
||||
<ng-template ng-option-tmp let-item="item" let-index="index" let-search="searchTerm">
|
||||
<div class="tag-wrap">
|
||||
<pngx-tag *ngIf="item.id && tags" class="me-2" [tag]="getTag(item.id)"></pngx-tag>
|
||||
@if (item.id && tags) {
|
||||
<pngx-tag class="me-2" [tag]="getTag(item.id)"></pngx-tag>
|
||||
}
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-select>
|
||||
<button *ngIf="allowCreate" class="btn btn-outline-secondary" type="button" (click)="createTag()" [disabled]="disabled">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#plus" />
|
||||
</svg>
|
||||
</button>
|
||||
<button *ngIf="showFilter" class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="hasPrivate || this.value === null" i18n-title title="Filter documents with these Tags">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#filter" />
|
||||
</svg>
|
||||
</button>
|
||||
@if (allowCreate) {
|
||||
<button class="btn btn-outline-secondary" type="button" (click)="createTag()" [disabled]="disabled">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#plus" />
|
||||
</svg>
|
||||
</button>
|
||||
}
|
||||
@if (showFilter) {
|
||||
<button class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="hasPrivate || this.value === null" i18n-title title="Filter documents with these Tags">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#filter" />
|
||||
</svg>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<small class="form-text text-muted" *ngIf="hint">{{hint}}</small>
|
||||
<small *ngIf="getSuggestions().length > 0" class="position-absolute top-100">
|
||||
<span i18n>Suggestions:</span>
|
||||
<ng-container *ngFor="let tag of getSuggestions()">
|
||||
<a (click)="addTag(tag.id)" [routerLink]="[]">{{tag?.name}}</a>
|
||||
</ng-container>
|
||||
</small>
|
||||
@if (hint) {
|
||||
<small class="form-text text-muted">{{hint}}</small>
|
||||
}
|
||||
@if (getSuggestions().length > 0) {
|
||||
<small class="position-absolute top-100">
|
||||
<span i18n>Suggestions:</span>
|
||||
@for (tag of getSuggestions(); track tag) {
|
||||
<a (click)="addTag(tag.id)" [routerLink]="[]">{{tag?.name}}</a>
|
||||
}
|
||||
</small>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
fakeAsync,
|
||||
tick,
|
||||
} from '@angular/core/testing'
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||
import {
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
@@ -15,7 +10,7 @@ import {
|
||||
DEFAULT_MATCHING_ALGORITHM,
|
||||
MATCH_ALL,
|
||||
} from 'src/app/data/matching-model'
|
||||
import { NgSelectComponent, NgSelectModule } from '@ng-select/ng-select'
|
||||
import { NgSelectModule } from '@ng-select/ng-select'
|
||||
import { RouterTestingModule } from '@angular/router/testing'
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing'
|
||||
import { of } from 'rxjs'
|
||||
|
@@ -2,18 +2,22 @@
|
||||
<div class="row">
|
||||
<div class="d-flex align-items-center position-relative hidden-button-container" [class.col-md-3]="horizontal">
|
||||
<label class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
|
||||
<button type="button" *ngIf="removable" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
<div class="position-relative" [class.col-md-9]="horizontal">
|
||||
<input #inputField type="text" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete">
|
||||
<small *ngIf="hint" class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
|
||||
<div class="invalid-feedback position-absolute top-100">
|
||||
{{error}}
|
||||
@if (removable) {
|
||||
<button type="button" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="position-relative" [class.col-md-9]="horizontal">
|
||||
<input #inputField type="text" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete">
|
||||
@if (hint) {
|
||||
<small class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
|
||||
}
|
||||
<div class="invalid-feedback position-absolute top-100">
|
||||
{{error}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,12 +1,14 @@
|
||||
<div class="mb-3" [class.pb-3]="error">
|
||||
<div class="row">
|
||||
<div class="d-flex align-items-center position-relative hidden-button-container" [class.col-md-3]="horizontal">
|
||||
<label class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
|
||||
<button type="button" *ngIf="removable" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<div class="row">
|
||||
<div class="d-flex align-items-center position-relative hidden-button-container" [class.col-md-3]="horizontal">
|
||||
<label class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
|
||||
@if (removable) {
|
||||
<button type="button" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
</svg> <ng-container i18n>Remove</ng-container>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div [class.col-md-9]="horizontal">
|
||||
<div class="input-group" [class.is-invalid]="error">
|
||||
@@ -20,7 +22,9 @@
|
||||
{{error}}
|
||||
</div>
|
||||
</div>
|
||||
<small *ngIf="hint" class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
|
||||
@if (hint) {
|
||||
<small class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<div class="col-md text-truncate">
|
||||
<h3 class="text-truncate" style="line-height: 1.4">
|
||||
{{title}}
|
||||
<span *ngIf="subTitle" class="h6 mb-0 d-block d-md-inline fw-normal ms-md-3 text-truncate" style="line-height: 1.4">{{subTitle}}</span>
|
||||
@if (subTitle) {
|
||||
<span class="h6 mb-0 d-block d-md-inline fw-normal ms-md-3 text-truncate" style="line-height: 1.4">{{subTitle}}</span>
|
||||
}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="btn-toolbar col col-md-auto">
|
||||
|
@@ -36,15 +36,6 @@ import { PDFSinglePageViewer } from 'pdfjs-dist/web/pdf_viewer'
|
||||
|
||||
PDFJS['verbosity'] = PDFJS.VerbosityLevel.ERRORS
|
||||
|
||||
// Yea this is a straight hack
|
||||
declare global {
|
||||
interface WeakKeyTypes {
|
||||
symbol: Object
|
||||
}
|
||||
|
||||
type WeakKey = WeakKeyTypes[keyof WeakKeyTypes]
|
||||
}
|
||||
|
||||
export enum RenderTextMode {
|
||||
DISABLED,
|
||||
ENABLED,
|
||||
|
@@ -1,22 +1,24 @@
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
|
||||
<button type="button" class="btn-close" aria-label="Close" (click)="cancelClicked()">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
|
||||
<button type="button" class="btn-close" aria-label="Close" (click)="cancelClicked()">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<p *ngIf="!object && message" class="mb-3" [innerHTML]="message | safeHtml"></p>
|
||||
@if (!object && message) {
|
||||
<p class="mb-3" [innerHTML]="message | safeHtml"></p>
|
||||
}
|
||||
|
||||
<form [formGroup]="form">
|
||||
<pngx-permissions-form [users]="users" formControlName="permissions_form"></pngx-permissions-form>
|
||||
</form>
|
||||
<form [formGroup]="form">
|
||||
<pngx-permissions-form [users]="users" formControlName="permissions_form"></pngx-permissions-form>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<ng-container *ngIf="!buttonsEnabled">
|
||||
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||
<span class="visually-hidden" i18n>Loading...</span>
|
||||
</ng-container>
|
||||
<button type="button" class="btn btn-outline-primary" (click)="cancelClicked()" [disabled]="!buttonsEnabled" i18n>Cancel</button>
|
||||
<button type="button" class="btn btn-primary" (click)="confirmClicked.emit(permissions)" [disabled]="!buttonsEnabled" i18n>Confirm</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@if (!buttonsEnabled) {
|
||||
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||
<span class="visually-hidden" i18n>Loading...</span>
|
||||
}
|
||||
<button type="button" class="btn btn-outline-primary" (click)="cancelClicked()" [disabled]="!buttonsEnabled" i18n>Cancel</button>
|
||||
<button type="button" class="btn btn-primary" (click)="confirmClicked.emit(permissions)" [disabled]="!buttonsEnabled" i18n>Confirm</button>
|
||||
</div>
|
||||
|
@@ -1,92 +1,106 @@
|
||||
<div class="btn-group w-100" ngbDropdown role="group">
|
||||
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="isActive ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled">
|
||||
<svg class="toolbaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#person-fill-lock" />
|
||||
</svg>
|
||||
<div class="d-none d-sm-inline"> {{title}}</div>
|
||||
<pngx-clearable-badge [selected]="isActive" (cleared)="reset()"></pngx-clearable-badge><span class="visually-hidden">selected</span>
|
||||
</button>
|
||||
<div class="dropdown-menu permission-filter-dropdown shadow py-0 w-2" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
|
||||
<div class="list-group list-group-flush">
|
||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="setFilter(OwnerFilterType.NONE)" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
<svg *ngIf="selectionModel.ownerFilter === OwnerFilterType.NONE" fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="me-1">
|
||||
<small i18n>All</small>
|
||||
</div>
|
||||
</button>
|
||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="setFilter(OwnerFilterType.SELF)" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
<svg *ngIf="selectionModel.ownerFilter === OwnerFilterType.SELF" fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="me-1">
|
||||
<small i18n>My documents</small>
|
||||
</div>
|
||||
</button>
|
||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="setFilter(OwnerFilterType.NOT_SELF)" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
<svg *ngIf="selectionModel.ownerFilter === OwnerFilterType.NOT_SELF" fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="me-1">
|
||||
<small i18n>Shared with me</small>
|
||||
</div>
|
||||
</button>
|
||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="setFilter(OwnerFilterType.SHARED_BY_ME)" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
<svg *ngIf="selectionModel.ownerFilter === OwnerFilterType.SHARED_BY_ME" fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="me-1">
|
||||
<small i18n>Shared by me</small>
|
||||
</div>
|
||||
</button>
|
||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="setFilter(OwnerFilterType.UNOWNED)" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
<svg *ngIf="selectionModel.ownerFilter === OwnerFilterType.UNOWNED" fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="me-1">
|
||||
<small i18n>Unowned</small>
|
||||
</div>
|
||||
</button>
|
||||
<button *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.User }" class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
<svg *ngIf="selectionModel.ownerFilter === OwnerFilterType.OTHERS" fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="me-1 w-100">
|
||||
<ng-select
|
||||
name="user"
|
||||
class="user-select small"
|
||||
[(ngModel)]="selectionModel.includeUsers"
|
||||
[disabled]="disabled"
|
||||
[clearable]="false"
|
||||
[items]="users"
|
||||
bindLabel="username"
|
||||
multiple="true"
|
||||
bindValue="id"
|
||||
placeholder="Users"
|
||||
i18n-placeholder
|
||||
(change)="onUserSelect()">
|
||||
</ng-select>
|
||||
</div>
|
||||
</button>
|
||||
<div *ngIf="selectionModel.ownerFilter === OwnerFilterType.NONE || selectionModel.ownerFilter === OwnerFilterType.NOT_SELF" class="list-group-item list-group-item-action d-flex align-items-center p-2 ps-3 border-bottom-0 border-start-0 border-end-0">
|
||||
<div class="form-check form-switch w-100">
|
||||
<input type="checkbox" class="form-check-input" id="hideUnowned" [(ngModel)]="this.selectionModel.hideUnowned" (change)="onChange()" [disabled]="disabled">
|
||||
<label class="form-check-label w-100" for="hideUnowned"><small i18n>Hide unowned</small></label>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="isActive ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled">
|
||||
<svg class="toolbaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#person-fill-lock" />
|
||||
</svg>
|
||||
<div class="d-none d-sm-inline"> {{title}}</div>
|
||||
<pngx-clearable-badge [selected]="isActive" (cleared)="reset()"></pngx-clearable-badge><span class="visually-hidden">selected</span>
|
||||
</button>
|
||||
<div class="dropdown-menu permission-filter-dropdown shadow py-0 w-2" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
|
||||
<div class="list-group list-group-flush">
|
||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="setFilter(OwnerFilterType.NONE)" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
@if (selectionModel.ownerFilter === OwnerFilterType.NONE) {
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
}
|
||||
</div>
|
||||
<div class="me-1">
|
||||
<small i18n>All</small>
|
||||
</div>
|
||||
</button>
|
||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="setFilter(OwnerFilterType.SELF)" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
@if (selectionModel.ownerFilter === OwnerFilterType.SELF) {
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
}
|
||||
</div>
|
||||
<div class="me-1">
|
||||
<small i18n>My documents</small>
|
||||
</div>
|
||||
</button>
|
||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="setFilter(OwnerFilterType.NOT_SELF)" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
@if (selectionModel.ownerFilter === OwnerFilterType.NOT_SELF) {
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
}
|
||||
</div>
|
||||
<div class="me-1">
|
||||
<small i18n>Shared with me</small>
|
||||
</div>
|
||||
</button>
|
||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="setFilter(OwnerFilterType.SHARED_BY_ME)" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
@if (selectionModel.ownerFilter === OwnerFilterType.SHARED_BY_ME) {
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
}
|
||||
</div>
|
||||
<div class="me-1">
|
||||
<small i18n>Shared by me</small>
|
||||
</div>
|
||||
</button>
|
||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="setFilter(OwnerFilterType.UNOWNED)" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
@if (selectionModel.ownerFilter === OwnerFilterType.UNOWNED) {
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
}
|
||||
</div>
|
||||
<div class="me-1">
|
||||
<small i18n>Unowned</small>
|
||||
</div>
|
||||
</button>
|
||||
<button *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.User }" class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" [disabled]="disabled">
|
||||
<div class="selected-icon me-1">
|
||||
@if (selectionModel.ownerFilter === OwnerFilterType.OTHERS) {
|
||||
<svg fill="currentColor" class="buttonicon-sm">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check"/>
|
||||
</svg>
|
||||
}
|
||||
</div>
|
||||
<div class="me-1 w-100">
|
||||
<ng-select
|
||||
name="user"
|
||||
class="user-select small"
|
||||
[(ngModel)]="selectionModel.includeUsers"
|
||||
[disabled]="disabled"
|
||||
[clearable]="false"
|
||||
[items]="users"
|
||||
bindLabel="username"
|
||||
multiple="true"
|
||||
bindValue="id"
|
||||
placeholder="Users"
|
||||
i18n-placeholder
|
||||
(change)="onUserSelect()">
|
||||
</ng-select>
|
||||
</div>
|
||||
</button>
|
||||
@if (selectionModel.ownerFilter === OwnerFilterType.NONE || selectionModel.ownerFilter === OwnerFilterType.NOT_SELF) {
|
||||
<div class="list-group-item list-group-item-action d-flex align-items-center p-2 ps-3 border-bottom-0 border-start-0 border-end-0">
|
||||
<div class="form-check form-switch w-100">
|
||||
<input type="checkbox" class="form-check-input" id="hideUnowned" [(ngModel)]="this.selectionModel.hideUnowned" (change)="onChange()" [disabled]="disabled">
|
||||
<label class="form-check-label w-100" for="hideUnowned"><small i18n>Hide unowned</small></label>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -9,19 +9,23 @@
|
||||
<div class="col" i18n>Delete</div>
|
||||
<div class="col" i18n>View</div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex" *ngFor="let type of PermissionType | keyvalue" [formGroupName]="type.key">
|
||||
<div class="col-3">{{type.key}}:</div>
|
||||
|
||||
<div class="col form-check form-check-inline form-switch" [ngbPopover]="inheritedWarning" [disablePopover]="!isInherited(type.key)" placement="left" triggers="mouseenter:mouseleave">
|
||||
<input type="checkbox" class="form-check-input" id="{{type.key}}_all" (change)="toggleAll($event, type.key)" [checked]="typesWithAllActions.has(type.key) || isInherited(type.key)" [attr.disabled]="disabled || isInherited(type.key) ? true : null">
|
||||
<label class="form-check-label visually-hidden" for="{{type.key}}_all" i18n>All</label>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let action of PermissionAction | keyvalue" class="col form-check form-check-inline" [ngbPopover]="inheritedWarning" [disablePopover]="!isInherited(type.key, action.key)" placement="left" triggers="mouseenter:mouseleave">
|
||||
<input type="checkbox" class="form-check-input" id="{{type.key}}_{{action.key}}" formControlName="{{action.key}}">
|
||||
<label class="form-check-label visually-hidden" for="{{type.key}}_{{action.key}}" i18n>{{action.key}}</label>
|
||||
</div>
|
||||
</li>
|
||||
<div *ngIf="error" class="invalid-feedback d-block">{{error}}</div>
|
||||
@for (type of PermissionType | keyvalue; track type) {
|
||||
<li class="list-group-item d-flex" [formGroupName]="type.key">
|
||||
<div class="col-3">{{type.key}}:</div>
|
||||
<div class="col form-check form-check-inline form-switch" [ngbPopover]="inheritedWarning" [disablePopover]="!isInherited(type.key)" placement="left" triggers="mouseenter:mouseleave">
|
||||
<input type="checkbox" class="form-check-input" id="{{type.key}}_all" (change)="toggleAll($event, type.key)" [checked]="typesWithAllActions.has(type.key) || isInherited(type.key)" [attr.disabled]="disabled || isInherited(type.key) ? true : null">
|
||||
<label class="form-check-label visually-hidden" for="{{type.key}}_all" i18n>All</label>
|
||||
</div>
|
||||
@for (action of PermissionAction | keyvalue; track action) {
|
||||
<div class="col form-check form-check-inline" [ngbPopover]="inheritedWarning" [disablePopover]="!isInherited(type.key, action.key)" placement="left" triggers="mouseenter:mouseleave">
|
||||
<input type="checkbox" class="form-check-input" id="{{type.key}}_{{action.key}}" formControlName="{{action.key}}">
|
||||
<label class="form-check-label visually-hidden" for="{{type.key}}_{{action.key}}" i18n>{{action.key}}</label>
|
||||
</div>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
@if (error) {
|
||||
<div class="invalid-feedback d-block">{{error}}</div>
|
||||
}
|
||||
</ul>
|
||||
</form>
|
||||
|
@@ -1,22 +1,28 @@
|
||||
<div class="preview-popup-container">
|
||||
<div *ngIf="error; else noError" class="w-100 h-100 position-relative">
|
||||
<p class="fst-italic position-absolute top-50 start-50 translate-middle" i18n>Error loading preview</p>
|
||||
@if (error) {
|
||||
<div class="w-100 h-100 position-relative">
|
||||
<p class="fst-italic position-absolute top-50 start-50 translate-middle" i18n>Error loading preview</p>
|
||||
</div>
|
||||
<ng-template #noError>
|
||||
<object *ngIf="renderAsObject; else pngxViewer" [data]="previewURL | safeUrl" width="100%" class="bg-light" [class.p-2]="!isPdf"></object>
|
||||
<ng-template #pngxViewer>
|
||||
<div *ngIf="requiresPassword" class="w-100 h-100 position-relative">
|
||||
<svg width="2em" height="2em" fill="currentColor" class="position-absolute top-50 start-50 translate-middle">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#file-earmark-lock"/>
|
||||
</svg>
|
||||
</div>
|
||||
<pngx-pdf-viewer *ngIf="!requiresPassword"
|
||||
[src]="previewURL"
|
||||
[original-size]="false"
|
||||
[show-borders]="true"
|
||||
[show-all]="true"
|
||||
(error)="onError($event)">
|
||||
</pngx-pdf-viewer>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
} @else {
|
||||
@if (renderAsObject) {
|
||||
<object [data]="previewURL | safeUrl" width="100%" class="bg-light" [class.p-2]="!isPdf"></object>
|
||||
} @else {
|
||||
@if (requiresPassword) {
|
||||
<div class="w-100 h-100 position-relative">
|
||||
<svg width="2em" height="2em" fill="currentColor" class="position-absolute top-50 start-50 translate-middle">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#file-earmark-lock"/>
|
||||
</svg>
|
||||
</div>
|
||||
}
|
||||
@if (!requiresPassword) {
|
||||
<pngx-pdf-viewer
|
||||
[src]="previewURL"
|
||||
[original-size]="false"
|
||||
[show-borders]="true"
|
||||
[show-all]="true"
|
||||
(error)="onError($event)">
|
||||
</pngx-pdf-viewer>
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
@@ -1,53 +1,57 @@
|
||||
<form [formGroup]="form" (ngSubmit)="save()" autocomplete="off">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title" i18n>Edit Profile</h4>
|
||||
<button type="button" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||
</button>
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title" i18n>Edit Profile</h4>
|
||||
<button type="button" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pngx-input-text i18n-title title="Email" formControlName="email" (keyup)="onEmailKeyUp($event)" [error]="error?.email"></pngx-input-text>
|
||||
<div ngbAccordion>
|
||||
<div ngbAccordionItem="first" [collapsed]="!showEmailConfirm" class="border-0 bg-transparent">
|
||||
<div ngbAccordionCollapse>
|
||||
<div ngbAccordionBody class="p-0 pb-3">
|
||||
<pngx-input-text i18n-title title="Confirm Email" formControlName="email_confirm" (keyup)="onEmailConfirmKeyUp($event)" autocomplete="email" [error]="error?.email_confirm"></pngx-input-text>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pngx-input-text i18n-title title="Email" formControlName="email" (keyup)="onEmailKeyUp($event)" [error]="error?.email"></pngx-input-text>
|
||||
<div ngbAccordion>
|
||||
<div ngbAccordionItem="first" [collapsed]="!showEmailConfirm" class="border-0 bg-transparent">
|
||||
<div ngbAccordionCollapse>
|
||||
<div ngbAccordionBody class="p-0 pb-3">
|
||||
<pngx-input-text i18n-title title="Confirm Email" formControlName="email_confirm" (keyup)="onEmailConfirmKeyUp($event)" autocomplete="email" [error]="error?.email_confirm"></pngx-input-text>
|
||||
</div>
|
||||
</div>
|
||||
<pngx-input-password i18n-title title="Password" formControlName="password" (keyup)="onPasswordKeyUp($event)" [showReveal]="true" autocomplete="current-password" [error]="error?.password"></pngx-input-password>
|
||||
<div ngbAccordion>
|
||||
<div ngbAccordionItem="first" [collapsed]="!showPasswordConfirm" class="border-0 bg-transparent">
|
||||
<div ngbAccordionCollapse>
|
||||
<div ngbAccordionBody class="p-0 pb-3">
|
||||
<pngx-input-password i18n-title title="Confirm Password" formControlName="password_confirm" (keyup)="onPasswordConfirmKeyUp($event)" autocomplete="new-password" [error]="error?.password_confirm"></pngx-input-password>
|
||||
</div>
|
||||
</div>
|
||||
<pngx-input-password i18n-title title="Password" formControlName="password" (keyup)="onPasswordKeyUp($event)" [showReveal]="true" autocomplete="current-password" [error]="error?.password"></pngx-input-password>
|
||||
<div ngbAccordion>
|
||||
<div ngbAccordionItem="first" [collapsed]="!showPasswordConfirm" class="border-0 bg-transparent">
|
||||
<div ngbAccordionCollapse>
|
||||
<div ngbAccordionBody class="p-0 pb-3">
|
||||
<pngx-input-password i18n-title title="Confirm Password" formControlName="password_confirm" (keyup)="onPasswordConfirmKeyUp($event)" autocomplete="new-password" [error]="error?.password_confirm"></pngx-input-password>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<pngx-input-text i18n-title title="First name" formControlName="first_name" [error]="error?.first_name"></pngx-input-text>
|
||||
<pngx-input-text i18n-title title="Last name" formControlName="last_name" [error]="error?.first_name"></pngx-input-text>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" i18n>API Auth Token</label>
|
||||
<div class="position-relative">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" formControlName="auth_token" readonly>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="copyAuthToken()" i18n-title title="Copy">
|
||||
<svg class="buttonicon-sm" fill="currentColor">
|
||||
@if (!copied) {
|
||||
<use xlink:href="assets/bootstrap-icons.svg#clipboard-fill" />
|
||||
}
|
||||
@if (copied) {
|
||||
<use xlink:href="assets/bootstrap-icons.svg#clipboard-check-fill" />
|
||||
}
|
||||
</svg><span class="visually-hidden" i18n>Copy</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="generateAuthToken()" i18n-title title="Regenerate auth token">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#arrow-repeat" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<span class="badge copied-badge bg-primary small fade ms-4 position-absolute top-50 translate-middle-y pe-none z-3" [class.show]="copied" i18n>Copied!</span>
|
||||
</div>
|
||||
<pngx-input-text i18n-title title="First name" formControlName="first_name" [error]="error?.first_name"></pngx-input-text>
|
||||
<pngx-input-text i18n-title title="Last name" formControlName="last_name" [error]="error?.first_name"></pngx-input-text>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" i18n>API Auth Token</label>
|
||||
<div class="position-relative">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" formControlName="auth_token" readonly>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="copyAuthToken()" i18n-title title="Copy">
|
||||
<svg class="buttonicon-sm" fill="currentColor">
|
||||
<use *ngIf="!copied" xlink:href="assets/bootstrap-icons.svg#clipboard-fill" />
|
||||
<use *ngIf="copied" xlink:href="assets/bootstrap-icons.svg#clipboard-check-fill" />
|
||||
</svg><span class="visually-hidden" i18n>Copy</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="generateAuthToken()" i18n-title title="Regenerate auth token">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#arrow-repeat" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<span class="badge copied-badge bg-primary small fade ms-4 position-absolute top-50 translate-middle-y pe-none z-3" [class.show]="copied" i18n>Copied!</span>
|
||||
</div>
|
||||
<div class="form-text text-muted text-end fst-italic" i18n>Warning: changing the token cannot be undone</div>
|
||||
</div>
|
||||
<div class="form-text text-muted text-end fst-italic" i18n>Warning: changing the token cannot be undone</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
|
||||
|
@@ -1,61 +1,79 @@
|
||||
<div ngbDropdown>
|
||||
<button class="btn btn-sm btn-outline-primary" id="shareLinksDropdown" [disabled]="disabled" ngbDropdownToggle>
|
||||
<svg class="toolbaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#link" />
|
||||
</svg>
|
||||
<div class="d-none d-sm-inline"> <ng-container i18n>Share Links</ng-container></div>
|
||||
</button>
|
||||
<div ngbDropdownMenu aria-labelledby="shareLinksDropdown" class="shadow share-links-dropdown">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li *ngIf="!shareLinks || shareLinks.length === 0" class="list-group-item fst-italic small text-center text-secondary" i18n>
|
||||
<button class="btn btn-sm btn-outline-primary" id="shareLinksDropdown" [disabled]="disabled" ngbDropdownToggle>
|
||||
<svg class="toolbaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#link" />
|
||||
</svg>
|
||||
<div class="d-none d-sm-inline"> <ng-container i18n>Share Links</ng-container></div>
|
||||
</button>
|
||||
<div ngbDropdownMenu aria-labelledby="shareLinksDropdown" class="shadow share-links-dropdown">
|
||||
<ul class="list-group list-group-flush">
|
||||
@if (!shareLinks || shareLinks.length === 0) {
|
||||
<li class="list-group-item fst-italic small text-center text-secondary" i18n>
|
||||
No existing links
|
||||
</li>
|
||||
<li class="list-group-item" *ngFor="let link of shareLinks">
|
||||
}
|
||||
@for (link of shareLinks; track link) {
|
||||
<li class="list-group-item">
|
||||
<div class="input-group input-group-sm w-100">
|
||||
<input type="text" class="form-control" aria-label="Share link" [value]="getShareUrl(link)" readonly>
|
||||
<span *ngIf="link.expiration" class="input-group-text">
|
||||
{{ getDaysRemaining(link) }}
|
||||
</span>
|
||||
@if (link.expiration) {
|
||||
<span class="input-group-text">
|
||||
{{ getDaysRemaining(link) }}
|
||||
</span>
|
||||
}
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" (click)="copy(link)">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use *ngIf="copied !== link.id" xlink:href="assets/bootstrap-icons.svg#clipboard-fill" />
|
||||
<use *ngIf="copied === link.id" xlink:href="assets/bootstrap-icons.svg#clipboard-check-fill" />
|
||||
</svg><span class="visually-hidden" i18n>Copy</span>
|
||||
</button>
|
||||
<button *ngIf="canShare(link)" type="button" class="btn btn-sm btn-outline-primary" (click)="share(link)">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#box-arrow-up" />
|
||||
</svg><span class="visually-hidden" i18n>Share</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger" (click)="delete(link)">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
@if (copied !== link.id) {
|
||||
<use xlink:href="assets/bootstrap-icons.svg#clipboard-fill" />
|
||||
}
|
||||
@if (copied === link.id) {
|
||||
<use xlink:href="assets/bootstrap-icons.svg#clipboard-check-fill" />
|
||||
}
|
||||
</svg><span class="visually-hidden" i18n>Copy</span>
|
||||
</button>
|
||||
@if (canShare(link)) {
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" (click)="share(link)">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#box-arrow-up" />
|
||||
</svg><span class="visually-hidden" i18n>Share</span>
|
||||
</button>
|
||||
}
|
||||
<button type="button" class="btn btn-sm btn-outline-danger" (click)="delete(link)">
|
||||
<svg class="buttonicon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#trash" />
|
||||
</svg><span class="visually-hidden" i18n>Delete</span>
|
||||
</button>
|
||||
</div>
|
||||
<span class="badge copied-badge bg-primary small fade ms-4 position-absolute top-50 translate-middle-y pe-none z-3" [class.show]="copied === link.id" i18n>Copied!</span>
|
||||
</li>
|
||||
<li class="list-group-item pt-3 pb-2">
|
||||
<div class="input-group input-group-sm w-100">
|
||||
<div class="form-check form-switch ms-auto small">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="versionSwitch" [disabled]="!hasArchiveVersion" [(ngModel)]="useArchiveVersion">
|
||||
<label class="form-check-label" for="versionSwitch" i18n>Share archive version</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group input-group-sm w-100 mt-2">
|
||||
<label class="input-group-text" for="addLink"><ng-container i18n>Expires</ng-container>:</label>
|
||||
<select class="form-select form-select-sm" [(ngModel)]="expirationDays">
|
||||
<option *ngFor="let option of EXPIRATION_OPTIONS" [ngValue]="option.value">{{ option.label }}</option>
|
||||
</select>
|
||||
<button class="btn btn-sm btn-outline-primary ms-auto" type="button" (click)="createLink()" [disabled]="loading">
|
||||
<div *ngIf="loading" class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||
<svg *ngIf="!loading" class="buttonicon me-1" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#plus" />
|
||||
</svg>
|
||||
<ng-container i18n>Create</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</svg><span class="visually-hidden" i18n>Delete</span>
|
||||
</button>
|
||||
</div>
|
||||
<span class="badge copied-badge bg-primary small fade ms-4 position-absolute top-50 translate-middle-y pe-none z-3" [class.show]="copied === link.id" i18n>Copied!</span>
|
||||
</li>
|
||||
}
|
||||
<li class="list-group-item pt-3 pb-2">
|
||||
<div class="input-group input-group-sm w-100">
|
||||
<div class="form-check form-switch ms-auto small">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="versionSwitch" [disabled]="!hasArchiveVersion" [(ngModel)]="useArchiveVersion">
|
||||
<label class="form-check-label" for="versionSwitch" i18n>Share archive version</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group input-group-sm w-100 mt-2">
|
||||
<label class="input-group-text" for="addLink"><ng-container i18n>Expires</ng-container>:</label>
|
||||
<select class="form-select form-select-sm" [(ngModel)]="expirationDays">
|
||||
@for (option of EXPIRATION_OPTIONS; track option) {
|
||||
<option [ngValue]="option.value">{{ option.label }}</option>
|
||||
}
|
||||
</select>
|
||||
<button class="btn btn-sm btn-outline-primary ms-auto" type="button" (click)="createLink()" [disabled]="loading">
|
||||
@if (loading) {
|
||||
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||
}
|
||||
@if (!loading) {
|
||||
<svg class="buttonicon me-1" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#plus" />
|
||||
</svg>
|
||||
}
|
||||
<ng-container i18n>Create</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,9 +1,15 @@
|
||||
<ng-container *ngIf="tag !== undefined; else privateTag" >
|
||||
<span *ngIf="!clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</span>
|
||||
<a [title]="linkTitle" *ngIf="clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</a>
|
||||
</ng-container>
|
||||
|
||||
<ng-template #privateTag>
|
||||
<span *ngIf="!clickable" class="badge private" i18n>Private</span>
|
||||
<a [title]="linkTitle" *ngIf="clickable" class="badge private" i18n>Private</a>
|
||||
</ng-template>
|
||||
@if (tag !== undefined) {
|
||||
@if (!clickable) {
|
||||
<span class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</span>
|
||||
}
|
||||
@if (clickable) {
|
||||
<a [title]="linkTitle" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</a>
|
||||
}
|
||||
} @else {
|
||||
@if (!clickable) {
|
||||
<span class="badge private" i18n>Private</span>
|
||||
}
|
||||
@if (clickable) {
|
||||
<a [title]="linkTitle" class="badge private" i18n>Private</a>
|
||||
}
|
||||
}
|
||||
|
@@ -1,43 +1,58 @@
|
||||
<ngb-toast
|
||||
*ngFor="let toast of toasts"
|
||||
[autohide]="true" [delay]="toast.delay"
|
||||
[class]="toast.classname"
|
||||
[class.mb-2]="true"
|
||||
(shown)="onShow(toast)"
|
||||
(hidden)="toastService.closeToast(toast)">
|
||||
<ngb-progressbar class="position-absolute h-100 w-100 top-90 start-0 bottom-0 end-0 pe-none" type="dark" [max]="toast.delay" [value]="toast.delayRemaining"></ngb-progressbar>
|
||||
<span class="visually-hidden">{{ toast.delayRemaining / 1000 | number: '1.0-0' }} seconds</span>
|
||||
<div class="d-flex align-items-top">
|
||||
<svg class="sidebaricon-sm mt-1 me-2 flex-shrink-0" fill="currentColor">
|
||||
<use *ngIf="!toast.error" xlink:href="assets/bootstrap-icons.svg#info-circle"/>
|
||||
<use *ngIf="toast.error" xlink:href="assets/bootstrap-icons.svg#exclamation-triangle"/>
|
||||
</svg>
|
||||
<div>
|
||||
<p class="mb-0">{{toast.content}}</p>
|
||||
<details *ngIf="toast.error">
|
||||
<div class="mt-2">
|
||||
<dl class="row mb-0" *ngIf="isDetailedError(toast.error)">
|
||||
<dt class="col-sm-3 fw-normal text-end">URL</dt>
|
||||
<dd class="col-sm-9">{{ toast.error.url }}</dd>
|
||||
<dt class="col-sm-3 fw-normal text-end" i18n>Status</dt>
|
||||
<dd class="col-sm-9">{{ toast.error.status }} <em>{{ toast.error.statusText }}</em></dd>
|
||||
<dt class="col-sm-3 fw-normal text-end" i18n>Error</dt>
|
||||
<dd class="col-sm-9">{{ getErrorText(toast.error) }}</dd>
|
||||
</dl>
|
||||
<div class="row">
|
||||
<div class="col offset-sm-3">
|
||||
<button class="btn btn-sm btn-outline-dark" (click)="copyError(toast.error)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use *ngIf="!copied" xlink:href="assets/bootstrap-icons.svg#clipboard" />
|
||||
<use *ngIf="copied" xlink:href="assets/bootstrap-icons.svg#clipboard-check" />
|
||||
</svg> <ng-container i18n>Copy Raw Error</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@for (toast of toasts; track toast) {
|
||||
<ngb-toast
|
||||
[autohide]="true" [delay]="toast.delay"
|
||||
[class]="toast.classname"
|
||||
[class.mb-2]="true"
|
||||
(shown)="onShow(toast)"
|
||||
(hidden)="toastService.closeToast(toast)">
|
||||
<ngb-progressbar class="position-absolute h-100 w-100 top-90 start-0 bottom-0 end-0 pe-none" type="dark" [max]="toast.delay" [value]="toast.delayRemaining"></ngb-progressbar>
|
||||
<span class="visually-hidden">{{ toast.delayRemaining / 1000 | number: '1.0-0' }} seconds</span>
|
||||
<div class="d-flex align-items-top">
|
||||
<svg class="sidebaricon-sm mt-1 me-2 flex-shrink-0" fill="currentColor">
|
||||
@if (!toast.error) {
|
||||
<use xlink:href="assets/bootstrap-icons.svg#info-circle"/>
|
||||
}
|
||||
@if (toast.error) {
|
||||
<use xlink:href="assets/bootstrap-icons.svg#exclamation-triangle"/>
|
||||
}
|
||||
</svg>
|
||||
<div>
|
||||
<p class="mb-0">{{toast.content}}</p>
|
||||
@if (toast.error) {
|
||||
<details>
|
||||
<div class="mt-2">
|
||||
@if (isDetailedError(toast.error)) {
|
||||
<dl class="row mb-0">
|
||||
<dt class="col-sm-3 fw-normal text-end">URL</dt>
|
||||
<dd class="col-sm-9">{{ toast.error.url }}</dd>
|
||||
<dt class="col-sm-3 fw-normal text-end" i18n>Status</dt>
|
||||
<dd class="col-sm-9">{{ toast.error.status }} <em>{{ toast.error.statusText }}</em></dd>
|
||||
<dt class="col-sm-3 fw-normal text-end" i18n>Error</dt>
|
||||
<dd class="col-sm-9">{{ getErrorText(toast.error) }}</dd>
|
||||
</dl>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col offset-sm-3">
|
||||
<button class="btn btn-sm btn-outline-dark" (click)="copyError(toast.error)">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
@if (!copied) {
|
||||
<use xlink:href="assets/bootstrap-icons.svg#clipboard" />
|
||||
}
|
||||
@if (copied) {
|
||||
<use xlink:href="assets/bootstrap-icons.svg#clipboard-check" />
|
||||
}
|
||||
</svg> <ng-container i18n>Copy Raw Error</ng-container>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
}
|
||||
@if (toast.action) {
|
||||
<p class="mb-0 mt-2"><button class="btn btn-sm btn-outline-secondary" (click)="toastService.closeToast(toast); toast.action()">{{toast.actionName}}</button></p>
|
||||
}
|
||||
</div>
|
||||
</details>
|
||||
<p class="mb-0 mt-2" *ngIf="toast.action"><button class="btn btn-sm btn-outline-secondary" (click)="toastService.closeToast(toast); toast.action()">{{toast.actionName}}</button></p>
|
||||
</div>
|
||||
<button type="button" class="btn-close ms-auto flex-shrink-0" data-bs-dismiss="toast" aria-label="Close" (click)="toastService.closeToast(toast);"></button>
|
||||
</div>
|
||||
</ngb-toast>
|
||||
<button type="button" class="btn-close ms-auto flex-shrink-0" data-bs-dismiss="toast" aria-label="Close" (click)="toastService.closeToast(toast);"></button>
|
||||
</div>
|
||||
</ngb-toast>
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ import { Clipboard } from '@angular/cdk/clipboard'
|
||||
})
|
||||
export class ToastsComponent implements OnInit, OnDestroy {
|
||||
constructor(
|
||||
private toastService: ToastService,
|
||||
public toastService: ToastService,
|
||||
private clipboard: Clipboard
|
||||
) {}
|
||||
|
||||
|
Reference in New Issue
Block a user