Combine custom component and ngx-file-drop
This commit is contained in:
parent
9588f899f9
commit
86cba60755
@ -1,16 +1,10 @@
|
|||||||
<pngx-toasts></pngx-toasts>
|
<pngx-toasts></pngx-toasts>
|
||||||
|
|
||||||
<ngx-file-drop dropZoneClassName="main-dropzone" contentClassName="main-content" [disabled]="!dragDropEnabled"
|
<pngx-file-drop>
|
||||||
(onFileDrop)="dropped($event)" (onFileOver)="fileOver()" (onFileLeave)="fileLeave()">
|
<ng-container content>
|
||||||
<ng-template ngx-file-drop-content-tmp>
|
<router-outlet></router-outlet>
|
||||||
<div class="global-dropzone-overlay">
|
</ng-container>
|
||||||
<h2 i18n>Drop files to begin upload</h2>
|
</pngx-file-drop>
|
||||||
</div>
|
|
||||||
<div class="main-wrapper">
|
|
||||||
<router-outlet></router-outlet>
|
|
||||||
</div>
|
|
||||||
</ng-template>
|
|
||||||
</ngx-file-drop>
|
|
||||||
|
|
||||||
<tour-step-template>
|
<tour-step-template>
|
||||||
<ng-template #tourStep let-step="step">
|
<ng-template #tourStep let-step="step">
|
||||||
|
@ -5,10 +5,8 @@ import {
|
|||||||
fakeAsync,
|
fakeAsync,
|
||||||
tick,
|
tick,
|
||||||
} from '@angular/core/testing'
|
} from '@angular/core/testing'
|
||||||
import { By } from '@angular/platform-browser'
|
|
||||||
import { Router } from '@angular/router'
|
import { Router } from '@angular/router'
|
||||||
import { RouterTestingModule } from '@angular/router/testing'
|
import { RouterTestingModule } from '@angular/router/testing'
|
||||||
import { NgxFileDropEntry, NgxFileDropModule } from 'ngx-file-drop'
|
|
||||||
import { TourService, TourNgBootstrapModule } from 'ngx-ui-tour-ng-bootstrap'
|
import { TourService, TourNgBootstrapModule } from 'ngx-ui-tour-ng-bootstrap'
|
||||||
import { Subject } from 'rxjs'
|
import { Subject } from 'rxjs'
|
||||||
import { routes } from './app-routing.module'
|
import { routes } from './app-routing.module'
|
||||||
@ -20,8 +18,9 @@ import {
|
|||||||
} from './services/consumer-status.service'
|
} from './services/consumer-status.service'
|
||||||
import { PermissionsService } from './services/permissions.service'
|
import { PermissionsService } from './services/permissions.service'
|
||||||
import { ToastService, Toast } from './services/toast.service'
|
import { ToastService, Toast } from './services/toast.service'
|
||||||
import { UploadDocumentsService } from './services/upload-documents.service'
|
|
||||||
import { SettingsService } from './services/settings.service'
|
import { SettingsService } from './services/settings.service'
|
||||||
|
import { FileDropComponent } from './components/file-drop/file-drop.component'
|
||||||
|
import { NgxFileDropModule } from 'ngx-file-drop'
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
let component: AppComponent
|
let component: AppComponent
|
||||||
@ -32,11 +31,10 @@ describe('AppComponent', () => {
|
|||||||
let toastService: ToastService
|
let toastService: ToastService
|
||||||
let router: Router
|
let router: Router
|
||||||
let settingsService: SettingsService
|
let settingsService: SettingsService
|
||||||
let uploadDocumentsService: UploadDocumentsService
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [AppComponent, ToastsComponent],
|
declarations: [AppComponent, ToastsComponent, FileDropComponent],
|
||||||
providers: [],
|
providers: [],
|
||||||
imports: [
|
imports: [
|
||||||
HttpClientTestingModule,
|
HttpClientTestingModule,
|
||||||
@ -52,7 +50,6 @@ describe('AppComponent', () => {
|
|||||||
settingsService = TestBed.inject(SettingsService)
|
settingsService = TestBed.inject(SettingsService)
|
||||||
toastService = TestBed.inject(ToastService)
|
toastService = TestBed.inject(ToastService)
|
||||||
router = TestBed.inject(Router)
|
router = TestBed.inject(Router)
|
||||||
uploadDocumentsService = TestBed.inject(UploadDocumentsService)
|
|
||||||
fixture = TestBed.createComponent(AppComponent)
|
fixture = TestBed.createComponent(AppComponent)
|
||||||
component = fixture.componentInstance
|
component = fixture.componentInstance
|
||||||
})
|
})
|
||||||
@ -142,43 +139,4 @@ describe('AppComponent', () => {
|
|||||||
fileStatusSubject.next(new FileStatus())
|
fileStatusSubject.next(new FileStatus())
|
||||||
expect(toastSpy).toHaveBeenCalled()
|
expect(toastSpy).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should enable drag-drop if user has permissions', () => {
|
|
||||||
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
|
|
||||||
expect(component.dragDropEnabled).toBeTruthy()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should disable drag-drop if user does not have permissions', () => {
|
|
||||||
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(false)
|
|
||||||
expect(component.dragDropEnabled).toBeFalsy()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should support drag drop', fakeAsync(() => {
|
|
||||||
expect(settingsService.globalDropzoneActive).toBeFalsy()
|
|
||||||
component.fileOver()
|
|
||||||
tick(1)
|
|
||||||
fixture.detectChanges()
|
|
||||||
expect(settingsService.globalDropzoneActive).toBeTruthy()
|
|
||||||
const dropzone = fixture.debugElement.query(
|
|
||||||
By.css('.global-dropzone-overlay')
|
|
||||||
)
|
|
||||||
expect(dropzone).not.toBeNull()
|
|
||||||
tick(700)
|
|
||||||
fixture.detectChanges()
|
|
||||||
// drop
|
|
||||||
const toastSpy = jest.spyOn(toastService, 'show')
|
|
||||||
const uploadSpy = jest.spyOn(uploadDocumentsService, 'onNgxFileDrop')
|
|
||||||
component.dropped([
|
|
||||||
{
|
|
||||||
fileEntry: {
|
|
||||||
isFile: true,
|
|
||||||
file: () => {},
|
|
||||||
},
|
|
||||||
} as unknown as NgxFileDropEntry,
|
|
||||||
])
|
|
||||||
expect(settingsService.globalDropzoneActive).toBeFalsy()
|
|
||||||
tick(3000)
|
|
||||||
expect(toastSpy).toHaveBeenCalled()
|
|
||||||
expect(uploadSpy).toHaveBeenCalled()
|
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
|
@ -5,8 +5,6 @@ import { Router } from '@angular/router'
|
|||||||
import { Subscription, first } from 'rxjs'
|
import { Subscription, first } from 'rxjs'
|
||||||
import { ConsumerStatusService } from './services/consumer-status.service'
|
import { ConsumerStatusService } from './services/consumer-status.service'
|
||||||
import { ToastService } from './services/toast.service'
|
import { ToastService } from './services/toast.service'
|
||||||
import { NgxFileDropEntry } from 'ngx-file-drop'
|
|
||||||
import { UploadDocumentsService } from './services/upload-documents.service'
|
|
||||||
import { TasksService } from './services/tasks.service'
|
import { TasksService } from './services/tasks.service'
|
||||||
import { TourService } from 'ngx-ui-tour-ng-bootstrap'
|
import { TourService } from 'ngx-ui-tour-ng-bootstrap'
|
||||||
import {
|
import {
|
||||||
@ -30,7 +28,6 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
private consumerStatusService: ConsumerStatusService,
|
private consumerStatusService: ConsumerStatusService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private uploadDocumentsService: UploadDocumentsService,
|
|
||||||
private tasksService: TasksService,
|
private tasksService: TasksService,
|
||||||
public tourService: TourService,
|
public tourService: TourService,
|
||||||
private renderer: Renderer2,
|
private renderer: Renderer2,
|
||||||
@ -246,29 +243,4 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public get dragDropEnabled(): boolean {
|
|
||||||
return (
|
|
||||||
this.settings.globalDropzoneEnabled &&
|
|
||||||
this.permissionsService.currentUserCan(
|
|
||||||
PermissionAction.Add,
|
|
||||||
PermissionType.Document
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fileOver() {
|
|
||||||
this.settings.globalDropzoneActive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
public fileLeave() {
|
|
||||||
this.settings.globalDropzoneActive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
public dropped(files: NgxFileDropEntry[]) {
|
|
||||||
this.fileLeave()
|
|
||||||
this.uploadDocumentsService.onNgxFileDrop(files)
|
|
||||||
if (files.length > 0)
|
|
||||||
this.toastService.showInfo($localize`Initiating upload...`, 3000)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,7 @@ import { ConsumptionTemplateEditDialogComponent } from './components/common/edit
|
|||||||
import { MailComponent } from './components/manage/mail/mail.component'
|
import { MailComponent } from './components/manage/mail/mail.component'
|
||||||
import { UsersAndGroupsComponent } from './components/admin/users-groups/users-groups.component'
|
import { UsersAndGroupsComponent } from './components/admin/users-groups/users-groups.component'
|
||||||
import { DndModule } from 'ngx-drag-drop'
|
import { DndModule } from 'ngx-drag-drop'
|
||||||
|
import { FileDropComponent } from './components/file-drop/file-drop.component'
|
||||||
|
|
||||||
import localeAf from '@angular/common/locales/af'
|
import localeAf from '@angular/common/locales/af'
|
||||||
import localeAr from '@angular/common/locales/ar'
|
import localeAr from '@angular/common/locales/ar'
|
||||||
@ -242,6 +243,7 @@ function initializeApp(settings: SettingsService) {
|
|||||||
ConsumptionTemplateEditDialogComponent,
|
ConsumptionTemplateEditDialogComponent,
|
||||||
MailComponent,
|
MailComponent,
|
||||||
UsersAndGroupsComponent,
|
UsersAndGroupsComponent,
|
||||||
|
FileDropComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
14
src-ui/src/app/components/file-drop/file-drop.component.html
Normal file
14
src-ui/src/app/components/file-drop/file-drop.component.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<div [class.inert]="fileIsOver">
|
||||||
|
<ng-content select="[content]"></ng-content>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="global-dropzone-overlay fade" [class.show]="fileIsOver" [class.hide]="hidden">
|
||||||
|
<h2 class="pe-none" i18n>Drop files to begin upload</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ngx-file-drop
|
||||||
|
dropZoneClassName="visually-hidden"
|
||||||
|
contentClassName="visually-hidden"
|
||||||
|
(onFileDrop)="dropped($event)"
|
||||||
|
#ngxFileDrop>
|
||||||
|
</ngx-file-drop>
|
148
src-ui/src/app/components/file-drop/file-drop.component.spec.ts
Normal file
148
src-ui/src/app/components/file-drop/file-drop.component.spec.ts
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
import { HttpClientTestingModule } from '@angular/common/http/testing'
|
||||||
|
import {
|
||||||
|
ComponentFixture,
|
||||||
|
TestBed,
|
||||||
|
discardPeriodicTasks,
|
||||||
|
fakeAsync,
|
||||||
|
tick,
|
||||||
|
} from '@angular/core/testing'
|
||||||
|
import { By } from '@angular/platform-browser'
|
||||||
|
import { PermissionsService } from 'src/app/services/permissions.service'
|
||||||
|
import { SettingsService } from 'src/app/services/settings.service'
|
||||||
|
import { ToastService } from 'src/app/services/toast.service'
|
||||||
|
import { UploadDocumentsService } from 'src/app/services/upload-documents.service'
|
||||||
|
import { ToastsComponent } from '../common/toasts/toasts.component'
|
||||||
|
import { FileDropComponent } from './file-drop.component'
|
||||||
|
import { NgxFileDropEntry, NgxFileDropModule } from 'ngx-file-drop'
|
||||||
|
|
||||||
|
describe('FileDropComponent', () => {
|
||||||
|
let component: FileDropComponent
|
||||||
|
let fixture: ComponentFixture<FileDropComponent>
|
||||||
|
let permissionsService: PermissionsService
|
||||||
|
let toastService: ToastService
|
||||||
|
let settingsService: SettingsService
|
||||||
|
let uploadDocumentsService: UploadDocumentsService
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [FileDropComponent, ToastsComponent],
|
||||||
|
providers: [],
|
||||||
|
imports: [HttpClientTestingModule, NgxFileDropModule],
|
||||||
|
}).compileComponents()
|
||||||
|
|
||||||
|
permissionsService = TestBed.inject(PermissionsService)
|
||||||
|
settingsService = TestBed.inject(SettingsService)
|
||||||
|
toastService = TestBed.inject(ToastService)
|
||||||
|
uploadDocumentsService = TestBed.inject(UploadDocumentsService)
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(FileDropComponent)
|
||||||
|
component = fixture.componentInstance
|
||||||
|
fixture.detectChanges()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should enable drag-drop if user has permissions', () => {
|
||||||
|
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
|
||||||
|
expect(component.dragDropEnabled).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should disable drag-drop if user does not have permissions', () => {
|
||||||
|
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(false)
|
||||||
|
expect(component.dragDropEnabled).toBeFalsy()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should disable drag-drop if disabled in settings', fakeAsync(() => {
|
||||||
|
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
|
||||||
|
settingsService.globalDropzoneEnabled = false
|
||||||
|
expect(component.dragDropEnabled).toBeFalsy()
|
||||||
|
|
||||||
|
component.onDragOver(new Event('dragover') as DragEvent)
|
||||||
|
tick(1)
|
||||||
|
fixture.detectChanges()
|
||||||
|
expect(component.fileIsOver).toBeFalsy()
|
||||||
|
const dropzone = fixture.debugElement.query(
|
||||||
|
By.css('.global-dropzone-overlay')
|
||||||
|
)
|
||||||
|
expect(dropzone.classes['hide']).toBeTruthy()
|
||||||
|
component.onDragLeave(new Event('dragleave') as DragEvent)
|
||||||
|
tick(700)
|
||||||
|
fixture.detectChanges()
|
||||||
|
// drop
|
||||||
|
const uploadSpy = jest.spyOn(uploadDocumentsService, 'uploadFiles')
|
||||||
|
const dragEvent = new Event('drop')
|
||||||
|
dragEvent['dataTransfer'] = {
|
||||||
|
files: {
|
||||||
|
item: () => {},
|
||||||
|
length: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
component.onDrop(dragEvent as DragEvent)
|
||||||
|
tick(3000)
|
||||||
|
expect(uploadSpy).not.toHaveBeenCalled()
|
||||||
|
}))
|
||||||
|
|
||||||
|
it('should support drag drop, initiate upload', fakeAsync(() => {
|
||||||
|
jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true)
|
||||||
|
expect(component.fileIsOver).toBeFalsy()
|
||||||
|
component.onDragOver(new Event('dragover') as DragEvent)
|
||||||
|
tick(1)
|
||||||
|
fixture.detectChanges()
|
||||||
|
expect(component.fileIsOver).toBeTruthy()
|
||||||
|
const dropzone = fixture.debugElement.query(
|
||||||
|
By.css('.global-dropzone-overlay')
|
||||||
|
)
|
||||||
|
component.onDragLeave(new Event('dragleave') as DragEvent)
|
||||||
|
tick(700)
|
||||||
|
fixture.detectChanges()
|
||||||
|
expect(dropzone.classes['hide']).toBeTruthy()
|
||||||
|
// drop
|
||||||
|
const toastSpy = jest.spyOn(toastService, 'show')
|
||||||
|
const uploadSpy = jest.spyOn(
|
||||||
|
UploadDocumentsService.prototype as any,
|
||||||
|
'uploadFile'
|
||||||
|
)
|
||||||
|
const dragEvent = new Event('drop')
|
||||||
|
dragEvent['dataTransfer'] = {
|
||||||
|
files: {
|
||||||
|
item: () => {
|
||||||
|
return new File(
|
||||||
|
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||||
|
'file.pdf'
|
||||||
|
)
|
||||||
|
},
|
||||||
|
length: 1,
|
||||||
|
} as unknown as FileList,
|
||||||
|
}
|
||||||
|
component.onDrop(dragEvent as DragEvent)
|
||||||
|
component.dropped([
|
||||||
|
{
|
||||||
|
fileEntry: {
|
||||||
|
isFile: true,
|
||||||
|
file: (callback) => {
|
||||||
|
callback(
|
||||||
|
new File(
|
||||||
|
[new Blob(['testing'], { type: 'application/pdf' })],
|
||||||
|
'file.pdf'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as unknown as NgxFileDropEntry,
|
||||||
|
])
|
||||||
|
tick(3000)
|
||||||
|
expect(toastSpy).toHaveBeenCalled()
|
||||||
|
expect(uploadSpy).toHaveBeenCalled()
|
||||||
|
discardPeriodicTasks()
|
||||||
|
}))
|
||||||
|
|
||||||
|
it('should ignore events if disabled', fakeAsync(() => {
|
||||||
|
settingsService.globalDropzoneEnabled = false
|
||||||
|
expect(settingsService.globalDropzoneActive).toBeFalsy()
|
||||||
|
component.onDragOver(new Event('dragover') as DragEvent)
|
||||||
|
expect(settingsService.globalDropzoneActive).toBeFalsy()
|
||||||
|
settingsService.globalDropzoneActive = true
|
||||||
|
component.onDragLeave(new Event('dragleave') as DragEvent)
|
||||||
|
expect(settingsService.globalDropzoneActive).toBeTruthy()
|
||||||
|
component.onDrop(new Event('drop') as DragEvent)
|
||||||
|
expect(settingsService.globalDropzoneActive).toBeTruthy()
|
||||||
|
}))
|
||||||
|
})
|
89
src-ui/src/app/components/file-drop/file-drop.component.ts
Normal file
89
src-ui/src/app/components/file-drop/file-drop.component.ts
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import { Component, HostListener, ViewChild } from '@angular/core'
|
||||||
|
import { NgxFileDropComponent, NgxFileDropEntry } from 'ngx-file-drop'
|
||||||
|
import {
|
||||||
|
PermissionsService,
|
||||||
|
PermissionAction,
|
||||||
|
PermissionType,
|
||||||
|
} from 'src/app/services/permissions.service'
|
||||||
|
import { SettingsService } from 'src/app/services/settings.service'
|
||||||
|
import { ToastService } from 'src/app/services/toast.service'
|
||||||
|
import { UploadDocumentsService } from 'src/app/services/upload-documents.service'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'pngx-file-drop',
|
||||||
|
templateUrl: './file-drop.component.html',
|
||||||
|
styleUrls: ['./file-drop.component.scss'],
|
||||||
|
})
|
||||||
|
export class FileDropComponent {
|
||||||
|
private fileLeaveTimeoutID: any
|
||||||
|
fileIsOver: boolean = false
|
||||||
|
hidden: boolean = true
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private settings: SettingsService,
|
||||||
|
private toastService: ToastService,
|
||||||
|
private uploadDocumentsService: UploadDocumentsService,
|
||||||
|
private permissionsService: PermissionsService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public get dragDropEnabled(): boolean {
|
||||||
|
return (
|
||||||
|
this.settings.globalDropzoneEnabled &&
|
||||||
|
this.permissionsService.currentUserCan(
|
||||||
|
PermissionAction.Add,
|
||||||
|
PermissionType.Document
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewChild('ngxFileDrop') ngxFileDrop: NgxFileDropComponent
|
||||||
|
|
||||||
|
@HostListener('dragover', ['$event ']) onDragOver(event: DragEvent) {
|
||||||
|
if (!this.dragDropEnabled) return
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopImmediatePropagation()
|
||||||
|
this.settings.globalDropzoneActive = true
|
||||||
|
// allows transition
|
||||||
|
setTimeout(() => {
|
||||||
|
this.fileIsOver = true
|
||||||
|
}, 1)
|
||||||
|
this.hidden = false
|
||||||
|
// stop fileLeave timeout
|
||||||
|
clearTimeout(this.fileLeaveTimeoutID)
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('dragleave', ['$event']) public onDragLeave(
|
||||||
|
event: DragEvent,
|
||||||
|
immediate: boolean = false
|
||||||
|
) {
|
||||||
|
if (!this.dragDropEnabled) return
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopImmediatePropagation()
|
||||||
|
this.settings.globalDropzoneActive = false
|
||||||
|
|
||||||
|
const ms = immediate ? 0 : 500
|
||||||
|
|
||||||
|
this.fileLeaveTimeoutID = setTimeout(() => {
|
||||||
|
this.fileIsOver = false
|
||||||
|
// await transition completed
|
||||||
|
setTimeout(() => {
|
||||||
|
this.hidden = true
|
||||||
|
}, 150)
|
||||||
|
}, ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('drop', ['$event']) public onDrop(event: DragEvent) {
|
||||||
|
if (!this.dragDropEnabled) return
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopImmediatePropagation()
|
||||||
|
this.onDragLeave(event, true)
|
||||||
|
// pass event onto ngx-file-drop to handle files
|
||||||
|
this.ngxFileDrop.dropFiles(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
public dropped(files: NgxFileDropEntry[]) {
|
||||||
|
this.uploadDocumentsService.onNgxFileDrop(files)
|
||||||
|
if (files.length > 0)
|
||||||
|
this.toastService.showInfo($localize`Initiating upload...`, 3000)
|
||||||
|
}
|
||||||
|
}
|
@ -505,8 +505,6 @@ table.table {
|
|||||||
user-select: none !important;
|
user-select: none !important;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 25%;
|
padding-top: 25%;
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.05s linear;
|
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
color: var(--pngx-primary-text-contrast)
|
color: var(--pngx-primary-text-contrast)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user