Improve processing indicator
This commit is contained in:
parent
8090d4329f
commit
1cbb928778
@ -8,8 +8,3 @@
|
||||
@include scroll-bar;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.w-100 {
|
||||
min-width: 100px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
@ -17,10 +17,16 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-content">
|
||||
<span class="read-only flex-center" *ngIf="isReadOnly">
|
||||
<mat-icon svgIcon="red:read-only" class="red-white"></mat-icon>
|
||||
<span class="read-only-text" translate="readonly-pill"></span>
|
||||
</span>
|
||||
<div class="read-only d-flex" *ngIf="isReadOnly" [class.justify-center]="!isProcessing">
|
||||
<div class="flex-align-items-center" *ngIf="isProcessing">
|
||||
<span class="read-only-text" [translate]="fileData.fileStatus.status"></span>
|
||||
<mat-progress-bar class="w-100" [mode]="'indeterminate'"></mat-progress-bar>
|
||||
</div>
|
||||
<div class="flex-center">
|
||||
<mat-icon svgIcon="red:read-only" class="red-white"></mat-icon>
|
||||
<span class="read-only-text" translate="readonly"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="multiSelectActive" class="multi-select">
|
||||
<div class="selected-wrapper">
|
||||
<redaction-round-checkbox
|
||||
@ -84,17 +90,13 @@
|
||||
|
||||
<div style="overflow: hidden; width: 100%">
|
||||
<div attr.anotation-page-header="{{ activeViewerPage }}" class="page-separator">
|
||||
<span *ngIf="!!activeViewerPage" class="all-caps-label"
|
||||
><span translate="page"></span> {{ activeViewerPage }} -
|
||||
{{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }}
|
||||
<span *ngIf="!!activeViewerPage" class="all-caps-label">
|
||||
<span translate="page"></span> {{ activeViewerPage }} -
|
||||
{{ activeAnnotationsLength || 0 }}
|
||||
<span
|
||||
[translate]="
|
||||
displayedAnnotations[activeViewerPage]?.annotations?.length === 1
|
||||
? 'annotation'
|
||||
: 'annotations'
|
||||
"
|
||||
></span
|
||||
></span>
|
||||
[translate]="activeAnnotationsLength === 1 ? 'annotation' : 'annotations'"
|
||||
></span>
|
||||
</span>
|
||||
|
||||
<div *ngIf="multiSelectActive">
|
||||
<div (click)="selectAllOnActivePage()" class="all-caps-label primary pointer">
|
||||
@ -170,14 +172,9 @@
|
||||
<div>
|
||||
<strong>{{ annotation.typeLabel | translate }}</strong>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="
|
||||
annotation.dictionary &&
|
||||
annotation.dictionary !== 'manual'
|
||||
"
|
||||
>
|
||||
<strong
|
||||
><span>{{ annotation.descriptor | translate }}</span
|
||||
<div *ngIf="annotation?.dictionary !== 'manual'">
|
||||
<strong>
|
||||
<span>{{ annotation.descriptor | translate }}</span
|
||||
>: </strong
|
||||
>{{ annotation.dictionary | humanize: false }}
|
||||
</div>
|
||||
@ -200,25 +197,15 @@
|
||||
<div class="actions-wrapper">
|
||||
<div
|
||||
(click)="toggleExpandComments(annotation, $event)"
|
||||
[matTooltip]="
|
||||
(annotation.comments.length === 1
|
||||
? 'comments.comment'
|
||||
: 'comments.comments'
|
||||
)
|
||||
| translate
|
||||
: {
|
||||
count: annotation.comments.length
|
||||
}
|
||||
"
|
||||
[matTooltip]="commentsTooltip(annotation)"
|
||||
class="comments-counter"
|
||||
matTooltipPosition="above"
|
||||
>
|
||||
<mat-icon svgIcon="red:comment"></mat-icon>
|
||||
{{ annotation.comments.length }}
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="actions" *ngIf="!multiSelectActive">
|
||||
<ng-container
|
||||
*ngIf="!multiSelectActive"
|
||||
[ngTemplateOutletContext]="{ annotation: annotation }"
|
||||
[ngTemplateOutlet]="annotationActionsTemplate"
|
||||
></ng-container>
|
||||
|
||||
@ -2,12 +2,12 @@
|
||||
@import '../../../../../assets/styles/red-mixins';
|
||||
|
||||
.read-only {
|
||||
padding: 13px 0;
|
||||
padding: 13px 16px;
|
||||
background-color: $primary;
|
||||
color: $white;
|
||||
justify-content: space-between;
|
||||
|
||||
.read-only-text {
|
||||
padding-left: 8px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
line-height: 14px;
|
||||
@ -18,6 +18,18 @@
|
||||
mat-icon {
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
|
||||
&.red-white {
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
mat-progress-bar {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
&.justify-center {
|
||||
justify-content: center !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ import { FileDataModel } from '@models/file/file-data.model';
|
||||
import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model';
|
||||
import { CommentsComponent } from '../comments/comments.component';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape'];
|
||||
const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
||||
@ -57,7 +58,8 @@ export class FileWorkloadComponent {
|
||||
constructor(
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _annotationProcessingService: AnnotationProcessingService,
|
||||
private readonly _permissionsService: PermissionsService
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _translateService: TranslateService
|
||||
) {}
|
||||
|
||||
private _annotations: AnnotationWrapper[];
|
||||
@ -69,6 +71,14 @@ export class FileWorkloadComponent {
|
||||
|
||||
private _multiSelectActive = false;
|
||||
|
||||
get isProcessing(): boolean {
|
||||
return this.fileData.fileStatus.isProcessing;
|
||||
}
|
||||
|
||||
get activeAnnotationsLength(): number | undefined {
|
||||
return this.displayedAnnotations[this.activeViewerPage]?.annotations?.length;
|
||||
}
|
||||
|
||||
get isReadOnly(): boolean {
|
||||
return !this._permissionsService.canPerformAnnotationActions();
|
||||
}
|
||||
@ -105,6 +115,11 @@ export class FileWorkloadComponent {
|
||||
}
|
||||
}
|
||||
|
||||
commentsTooltip({ comments }: AnnotationWrapper): string {
|
||||
const i18nString = 'comments.' + (comments.length === 1 ? 'comment' : 'comments');
|
||||
return this._translateService.instant(i18nString, { count: comments.length });
|
||||
}
|
||||
|
||||
annotationIsSelected(annotation: AnnotationWrapper) {
|
||||
return this.selectedAnnotations?.find(a => a?.id === annotation.id);
|
||||
}
|
||||
|
||||
@ -209,7 +209,7 @@
|
||||
<div>
|
||||
<div class="filename-wrapper">
|
||||
<div
|
||||
[class.disabled]="fileStatus.isPending || fileStatus.isProcessing"
|
||||
[class.disabled]="fileStatus.isPending"
|
||||
[class.error]="fileStatus.isError"
|
||||
class="table-item-title text-overflow"
|
||||
>
|
||||
|
||||
@ -31,13 +31,15 @@
|
||||
|
||||
<div *ngIf="viewReady" class="flex-1 actions-container">
|
||||
<ng-container *ngIf="!appStateService.activeFile.isExcluded">
|
||||
<redaction-status-bar [config]="statusBarConfig" [small]="true">
|
||||
</redaction-status-bar>
|
||||
<ng-container *ngIf="!appStateService.activeFile.isProcessing">
|
||||
<redaction-status-bar [config]="statusBarConfig" [small]="true">
|
||||
</redaction-status-bar>
|
||||
|
||||
<div class="all-caps-label mr-16 ml-8">
|
||||
{{ status | translate }}
|
||||
<span *ngIf="isUnderReviewOrApproval">{{ 'by' | translate }}:</span>
|
||||
</div>
|
||||
<div class="all-caps-label mr-16 ml-8">
|
||||
{{ status | translate }}
|
||||
<span *ngIf="isUnderReviewOrApproval">{{ 'by' | translate }}:</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<redaction-initials-avatar
|
||||
*ngIf="!editingReviewer"
|
||||
@ -61,13 +63,7 @@
|
||||
(cancel)="editingReviewer = false"
|
||||
></redaction-assign-user-dropdown>
|
||||
|
||||
<div
|
||||
*ngIf="
|
||||
!editingReviewer &&
|
||||
(permissionsService.canAssignUser() || permissionsService.canAssignToSelf())
|
||||
"
|
||||
class="assign-actions-wrapper"
|
||||
>
|
||||
<div *ngIf="canAssign" class="assign-actions-wrapper">
|
||||
<redaction-circle-button
|
||||
(action)="editingReviewer = true"
|
||||
*ngIf="permissionsService.canAssignUser() && currentReviewer"
|
||||
@ -85,16 +81,11 @@
|
||||
></redaction-circle-button>
|
||||
</div>
|
||||
|
||||
<ng-container
|
||||
*ngIf="
|
||||
permissionsService.isApprover() &&
|
||||
!!appStateService.activeFile.fileStatus.lastReviewer
|
||||
"
|
||||
>
|
||||
<ng-container *ngIf="permissionsService.isApprover() && !!lastReviewer">
|
||||
<div class="vertical-line"></div>
|
||||
<div class="all-caps-label mr-16 ml-8" translate="file-preview.last-reviewer"></div>
|
||||
<redaction-initials-avatar
|
||||
[userId]="appStateService.activeFile.fileStatus.lastReviewer"
|
||||
[userId]="lastReviewer"
|
||||
[withName]="true"
|
||||
></redaction-initials-avatar>
|
||||
</ng-container>
|
||||
@ -196,17 +187,7 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<redaction-full-page-loading-indicator
|
||||
[displayed]="!viewReady"
|
||||
[showIndicator]="!this.loadingMessage"
|
||||
>
|
||||
<h1 *ngIf="loadingMessage" class="heading-l loading">{{ loadingMessage | translate }}</h1>
|
||||
<div *ngIf="loadingMessage" class="analysis-progress">
|
||||
<mat-progress-bar
|
||||
[mode]="indeterminateMode ? 'indeterminate' : 'determinate'"
|
||||
[value]="analysisProgress"
|
||||
></mat-progress-bar>
|
||||
</div>
|
||||
<redaction-full-page-loading-indicator [displayed]="!viewReady" [showIndicator]="!viewReady">
|
||||
</redaction-full-page-loading-indicator>
|
||||
|
||||
<ng-template #annotationActionsTemplate let-annotation="annotation">
|
||||
|
||||
@ -59,16 +59,12 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
fullScreen = false;
|
||||
editingReviewer = false;
|
||||
shouldDeselectAnnotationsOnPageChange = true;
|
||||
analysisProgressInSeconds = 0;
|
||||
analysisProgress: number;
|
||||
analysisInterval: number;
|
||||
fileData: FileDataModel;
|
||||
annotationData: AnnotationData;
|
||||
selectedAnnotations: AnnotationWrapper[];
|
||||
viewReady = false;
|
||||
primaryFilters: FilterModel[];
|
||||
secondaryFilters: FilterModel[];
|
||||
loadingMessage: string;
|
||||
canPerformAnnotationActions: boolean;
|
||||
filesAutoUpdateTimer: Subscription;
|
||||
fileReanalysedSubscription: Subscription;
|
||||
@ -141,24 +137,22 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
|
||||
get canSwitchToDeltaView() {
|
||||
return (
|
||||
this.fileData &&
|
||||
this.fileData.redactionChangeLog?.redactionLogEntry?.length > 0 &&
|
||||
this.fileData?.redactionChangeLog?.redactionLogEntry?.length > 0 &&
|
||||
!this.fileData.fileStatus.isExcluded
|
||||
);
|
||||
}
|
||||
|
||||
get canAssign(): boolean {
|
||||
return (
|
||||
!this.editingReviewer &&
|
||||
(this.permissionsService.canAssignUser() || this.permissionsService.canAssignToSelf())
|
||||
);
|
||||
}
|
||||
|
||||
get displayData() {
|
||||
return this.fileData?.fileData;
|
||||
}
|
||||
|
||||
get indeterminateMode() {
|
||||
return (
|
||||
this.analysisProgress > 100 ||
|
||||
this.appStateService.activeFile.analysisDuration < 3 * 1000
|
||||
// it takes longer than usual - switch to indeterminate
|
||||
); // on less than 3 seconds show indeterminate
|
||||
}
|
||||
|
||||
get dossierId() {
|
||||
return this.appStateService.activeDossierId;
|
||||
}
|
||||
@ -171,6 +165,10 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
return !!this._workloadComponent?.multiSelectActive;
|
||||
}
|
||||
|
||||
get lastReviewer(): string | undefined {
|
||||
return this.appStateService.activeFile.fileStatus.lastReviewer;
|
||||
}
|
||||
|
||||
updateViewMode() {
|
||||
const annotations = this._getAnnotations(a => a.getCustomData('redacto-manager'));
|
||||
const redactions = annotations.filter(a => a.getCustomData('redaction'));
|
||||
@ -239,6 +237,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
} catch (error) {}
|
||||
|
||||
this._subscribeToFileUpdates();
|
||||
this.viewReady = true;
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@ -254,9 +253,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
imported: true,
|
||||
force: true
|
||||
});
|
||||
} catch (error) {
|
||||
// nothing
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
console.log(
|
||||
'[REDACTION] Delete previous annotations time: ' +
|
||||
@ -438,9 +435,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
|
||||
case 'enable-analysis':
|
||||
case 'reanalyse':
|
||||
this.viewReady = false;
|
||||
this._startAnalysisTimer();
|
||||
this.loadingMessage = 'file-preview.reanalyse-file';
|
||||
await this._loadFileData();
|
||||
this._updateCanPerformActions();
|
||||
await this.appStateService.reloadActiveDossierFiles();
|
||||
@ -555,19 +549,13 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
|
||||
private _subscribeToFileUpdates(): void {
|
||||
this.filesAutoUpdateTimer = timer(0, 5000)
|
||||
.pipe(
|
||||
tap(async () => {
|
||||
await this.appStateService.reloadActiveFile();
|
||||
})
|
||||
)
|
||||
.pipe(tap(async () => await this.appStateService.reloadActiveFile()))
|
||||
.subscribe();
|
||||
this.fileReanalysedSubscription = this.appStateService.fileReanalysed.subscribe(
|
||||
async (fileStatus: FileStatusWrapper) => {
|
||||
if (fileStatus.fileId === this.fileId) {
|
||||
await this._loadFileData(true);
|
||||
this.viewReady = true;
|
||||
this.loadingMessage = null;
|
||||
this._stopAnalysisTimer();
|
||||
this._updateCanPerformActions();
|
||||
this._cleanupAndRedrawManualAnnotations();
|
||||
}
|
||||
@ -585,32 +573,26 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
this.permissionsService.canPerformAnnotationActions() && this.viewMode === 'STANDARD';
|
||||
}
|
||||
|
||||
private _loadFileData(performUpdate: boolean = false) {
|
||||
return this._fileDownloadService
|
||||
.loadActiveFileData()
|
||||
.pipe(
|
||||
tap(fileDataModel => {
|
||||
if (fileDataModel.fileStatus.isWorkable) {
|
||||
if (performUpdate) {
|
||||
this.fileData.redactionLog = fileDataModel.redactionLog;
|
||||
this.fileData.redactionChangeLog = fileDataModel.redactionChangeLog;
|
||||
this.fileData.fileStatus = fileDataModel.fileStatus;
|
||||
this.fileData.manualRedactions = fileDataModel.manualRedactions;
|
||||
this.rebuildFilters(true);
|
||||
} else {
|
||||
this.fileData = fileDataModel;
|
||||
this.rebuildFilters();
|
||||
}
|
||||
} else {
|
||||
if (fileDataModel.fileStatus.isError) {
|
||||
this._router.navigate(['/main/dossiers/' + this.dossierId]);
|
||||
} else {
|
||||
this.loadingMessage = 'file-preview.reanalyse-file';
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
.toPromise();
|
||||
private async _loadFileData(performUpdate: boolean = false): Promise<void> {
|
||||
const fileData = await this._fileDownloadService.loadActiveFileData().toPromise();
|
||||
if (!fileData.fileStatus.isPending && !fileData.fileStatus.isError) {
|
||||
if (performUpdate) {
|
||||
this.fileData.redactionLog = fileData.redactionLog;
|
||||
this.fileData.redactionChangeLog = fileData.redactionChangeLog;
|
||||
this.fileData.fileStatus = fileData.fileStatus;
|
||||
this.fileData.manualRedactions = fileData.manualRedactions;
|
||||
this.rebuildFilters(true);
|
||||
} else {
|
||||
this.fileData = fileData;
|
||||
this.rebuildFilters();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileData.fileStatus.isError) {
|
||||
await this._router.navigate(['/main/dossiers/' + this.dossierId]);
|
||||
}
|
||||
}
|
||||
|
||||
@debounce()
|
||||
@ -665,17 +647,20 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
const hasAnyFilterSet =
|
||||
this.primaryFilters.find(f => f.checked || f.indeterminate) ||
|
||||
this.secondaryFilters.find(f => f.checked || f.indeterminate);
|
||||
if (hasAnyFilterSet) {
|
||||
const oldPageSpecificFilters =
|
||||
this._annotationProcessingService.getAnnotationFilter(currentPageAnnotations);
|
||||
const newPageSpecificFilters =
|
||||
this._annotationProcessingService.getAnnotationFilter(newPageAnnotations);
|
||||
handleFilterDelta(oldPageSpecificFilters, newPageSpecificFilters, this.primaryFilters);
|
||||
this._workloadComponent.filtersChanged({
|
||||
primary: this.primaryFilters,
|
||||
secondary: this.secondaryFilters
|
||||
});
|
||||
|
||||
if (!hasAnyFilterSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldPageSpecificFilters =
|
||||
this._annotationProcessingService.getAnnotationFilter(currentPageAnnotations);
|
||||
const newPageSpecificFilters =
|
||||
this._annotationProcessingService.getAnnotationFilter(newPageAnnotations);
|
||||
handleFilterDelta(oldPageSpecificFilters, newPageSpecificFilters, this.primaryFilters);
|
||||
this._workloadComponent.filtersChanged({
|
||||
primary: this.primaryFilters,
|
||||
secondary: this.secondaryFilters
|
||||
});
|
||||
}
|
||||
|
||||
private _findAndDeleteAnnotation(id: string) {
|
||||
@ -688,33 +673,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
}
|
||||
}
|
||||
|
||||
private _startAnalysisTimer() {
|
||||
this._stopAnalysisTimer();
|
||||
|
||||
if (this.appStateService.activeFile.analysisDuration > 0) {
|
||||
this.analysisProgress = 0;
|
||||
this.analysisProgressInSeconds = 0;
|
||||
|
||||
this.analysisInterval = setInterval(() => {
|
||||
this.analysisProgressInSeconds += 1;
|
||||
this.analysisProgress =
|
||||
(this.analysisProgressInSeconds * 100) /
|
||||
(this.appStateService.activeFile.analysisDuration / 1000);
|
||||
}, 1000);
|
||||
} else {
|
||||
this.analysisInterval = 0;
|
||||
this.analysisProgress = 0;
|
||||
this.analysisProgressInSeconds = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private _stopAnalysisTimer() {
|
||||
if (this.analysisInterval) {
|
||||
clearInterval(this.analysisInterval);
|
||||
this.analysisInterval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* View in fullscreen */
|
||||
private _openFullScreen() {
|
||||
const documentElement = document.documentElement;
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { Color } from '@utils/types';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-status-bar',
|
||||
templateUrl: './status-bar.component.html',
|
||||
styleUrls: ['./status-bar.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class StatusBarComponent {
|
||||
@Input()
|
||||
@ -18,6 +19,4 @@ export class StatusBarComponent {
|
||||
|
||||
@Input()
|
||||
small = false;
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ export class PermissionsService {
|
||||
}
|
||||
|
||||
canOpenFile(fileStatus = this._activeFile): boolean {
|
||||
return !fileStatus?.isError && !fileStatus?.isProcessing && !fileStatus?.isPending;
|
||||
return !fileStatus?.isError && !fileStatus?.isPending;
|
||||
}
|
||||
|
||||
canUndoApproval(fileStatus = this._activeFile): boolean {
|
||||
|
||||
@ -519,7 +519,7 @@
|
||||
"number-of-analyses": "Anzahl der Analysen",
|
||||
"custom": "Benutzerdefiniert"
|
||||
},
|
||||
"readonly-pill": "Schreibgeschützt",
|
||||
"readonly": "Schreibgeschützt",
|
||||
"group": {
|
||||
"redactions": "Redaktionswörterbücher",
|
||||
"hints": "Tipp Wörterbücher"
|
||||
|
||||
@ -578,7 +578,7 @@
|
||||
"number-of-analyses": "Number of analyses",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"readonly-pill": "Read-only",
|
||||
"readonly": "Read only",
|
||||
"group": {
|
||||
"redactions": "Redaction Dictionaries",
|
||||
"hints": "Hint Dictionaries"
|
||||
|
||||
@ -265,6 +265,11 @@ section.settings {
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
.w-100 {
|
||||
min-width: 100px !important;
|
||||
width: 100px !important;
|
||||
}
|
||||
|
||||
.break-20 {
|
||||
height: 20px;
|
||||
background: transparent;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user