diff --git a/src-ui/src/app/app.module.ts b/src-ui/src/app/app.module.ts index 03ef89a8a..a5b9d2f2d 100644 --- a/src-ui/src/app/app.module.ts +++ b/src-ui/src/app/app.module.ts @@ -113,7 +113,8 @@ import localeSl from '@angular/common/locales/sl' import localeSr from '@angular/common/locales/sr' import localeSv from '@angular/common/locales/sv' import localeTr from '@angular/common/locales/tr' -import localeZh from '@angular/common/locales/zh' +import localeZh from '@angular/common/locales/zh'; +import { FolderCreateDialogComponent } from './components/common/create-dialog/folder-create-dialog/folder-create-dialog.component' registerLocaleData(localeAr) registerLocaleData(localeBe) @@ -215,6 +216,7 @@ function initializeApp(settings: SettingsService) { IfObjectPermissionsDirective, PermissionsDialogComponent, PermissionsFormComponent, + FolderCreateDialogComponent, ], imports: [ BrowserModule, diff --git a/src-ui/src/app/components/common/create-dialog/folder-create-dialog/folder-create-dialog.component.html b/src-ui/src/app/components/common/create-dialog/folder-create-dialog/folder-create-dialog.component.html new file mode 100644 index 000000000..a3540553a --- /dev/null +++ b/src-ui/src/app/components/common/create-dialog/folder-create-dialog/folder-create-dialog.component.html @@ -0,0 +1,47 @@ +
+ + + +
diff --git a/src-ui/src/app/components/common/create-dialog/folder-create-dialog/folder-create-dialog.component.scss b/src-ui/src/app/components/common/create-dialog/folder-create-dialog/folder-create-dialog.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src-ui/src/app/components/common/create-dialog/folder-create-dialog/folder-create-dialog.component.spec.ts b/src-ui/src/app/components/common/create-dialog/folder-create-dialog/folder-create-dialog.component.spec.ts new file mode 100644 index 000000000..940430ec8 --- /dev/null +++ b/src-ui/src/app/components/common/create-dialog/folder-create-dialog/folder-create-dialog.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FolderCreateDialogComponent } from './folder-create-dialog.component'; + +describe('FolderCreateDialogComponent', () => { + let component: FolderCreateDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FolderCreateDialogComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(FolderCreateDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src-ui/src/app/components/common/create-dialog/folder-create-dialog/folder-create-dialog.component.ts b/src-ui/src/app/components/common/create-dialog/folder-create-dialog/folder-create-dialog.component.ts new file mode 100644 index 000000000..5724c0048 --- /dev/null +++ b/src-ui/src/app/components/common/create-dialog/folder-create-dialog/folder-create-dialog.component.ts @@ -0,0 +1,57 @@ +import { Component, OnInit } from '@angular/core' +import { FormControl, FormGroup } from '@angular/forms' +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' +import { DEFAULT_MATCHING_ALGORITHM } from 'src/app/data/matching-model' +import { PaperlessStoragePath } from 'src/app/data/paperless-storage-path' +import { StoragePathService } from 'src/app/services/rest/storage-path.service' +import { UserService } from 'src/app/services/rest/user.service' +import { EditDialogComponent } from '../../edit-dialog/edit-dialog.component' +import { Subscription } from 'rxjs' + +@Component({ + selector: 'app-folder-create-dialog', + templateUrl: './folder-create-dialog.component.html', + styleUrls: ['./folder-create-dialog.component.scss'], +}) +export class FolderCreateDialogComponent + extends EditDialogComponent + implements OnInit +{ + nameSub: Subscription + + constructor( + service: StoragePathService, + activeModal: NgbActiveModal, + userService: UserService + ) { + super(service, activeModal, userService) + } + + ngOnInit(): void { + const nameField = this.objectForm.get('name') + const parentFolderPath = this.object?.path ?? '' + this.nameSub = nameField.valueChanges.subscribe(() => { + const fullPath = parentFolderPath + '/' + nameField.value + this.objectForm.get('path').patchValue(fullPath) + this.objectForm.get('slug').patchValue(fullPath) + }) + } + + submit(): void { + this.nameSub.unsubscribe() + this.objectForm.get('name').patchValue(this.objectForm.get('path').value) + this.save() + } + + getForm(): FormGroup { + return new FormGroup({ + name: new FormControl(''), + path: new FormControl(''), + slug: new FormControl(''), + matching_algorithm: new FormControl(DEFAULT_MATCHING_ALGORITHM), + match: new FormControl(''), + is_insensitive: new FormControl(true), + permissions_form: new FormControl(null), + }) + } +} diff --git a/src-ui/src/app/components/explorer/explorer.component.html b/src-ui/src/app/components/explorer/explorer.component.html index 7fb112576..08c37f2e7 100644 --- a/src-ui/src/app/components/explorer/explorer.component.html +++ b/src-ui/src/app/components/explorer/explorer.component.html @@ -169,7 +169,7 @@
-
+
{{ pathPart }} / @@ -182,6 +182,17 @@ [selectionData]="list.selectionData" #filterEditor > --> + +
+ +
+
diff --git a/src-ui/src/app/components/explorer/explorer.component.ts b/src-ui/src/app/components/explorer/explorer.component.ts index d09b39e43..dd4d50ed3 100644 --- a/src-ui/src/app/components/explorer/explorer.component.ts +++ b/src-ui/src/app/components/explorer/explorer.component.ts @@ -6,18 +6,9 @@ import { ViewChild, ViewChildren, } from '@angular/core' -import { ActivatedRoute, Router, convertToParamMap } from '@angular/router' +import { ActivatedRoute, Router } from '@angular/router' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' -import { - Subject, - filter, - first, - map, - switchMap, - take, - takeUntil, - tap, -} from 'rxjs' +import { Subject, takeUntil } from 'rxjs' import { FilterRule, filterRulesDiffer, @@ -26,6 +17,7 @@ import { import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type' import { PaperlessDocument } from 'src/app/data/paperless-document' import { PaperlessSavedView } from 'src/app/data/paperless-saved-view' +import { PaperlessStoragePath } from 'src/app/data/paperless-storage-path' import { SETTINGS_KEYS } from 'src/app/data/paperless-uisettings' import { SortEvent, @@ -41,9 +33,9 @@ import { SavedViewService } from 'src/app/services/rest/saved-view.service' import { SettingsService } from 'src/app/services/settings.service' import { StoragePathListViewService } from 'src/app/services/storage-path-list-view.service' import { ToastService } from 'src/app/services/toast.service' +import { FolderCreateDialogComponent } from '../common/create-dialog/folder-create-dialog/folder-create-dialog.component' import { ComponentWithPermissions } from '../with-permissions/with-permissions.component' import { FilterEditorComponent } from './filter-editor/filter-editor.component' -import { PaperlessStoragePath } from 'src/app/data/paperless-storage-path' @Component({ selector: 'app-explorer', @@ -169,9 +161,11 @@ export class ExplorerComponent } clickPathPart(index: number) { + if (index === 0) return this.router.navigate(['explorer']) const pathUntilPart = this.folderPath + .replace('DMS/', '') .split('/') - .slice(0, index + 1) + .slice(0, index) .join('/') this.list.getStoragePathByPath(pathUntilPart).subscribe((storagePath) => { this.router.navigate(['explorer'], { @@ -180,6 +174,19 @@ export class ExplorerComponent }) } + createFolder() { + var modal = this.modalService.open(FolderCreateDialogComponent, { + backdrop: 'static', + }) + modal.componentInstance.dialogMode = 'create' + modal.componentInstance.object = { + path: this.folderPath.replace('DMS/', ''), + } + modal.componentInstance.succeeded + .pipe(takeUntil(this.unsubscribeNotifier)) + .subscribe(() => this.list.reload()) + } + openDocumentDetail(storagePath: PaperlessStoragePath) { this.router.navigate(['explorer'], { queryParams: { spid: storagePath.id }, diff --git a/src-ui/src/app/services/rest/custom-storage-path.service.ts b/src-ui/src/app/services/rest/custom-storage-path.service.ts index d877d8eaa..3d2f5d3ad 100644 --- a/src-ui/src/app/services/rest/custom-storage-path.service.ts +++ b/src-ui/src/app/services/rest/custom-storage-path.service.ts @@ -51,7 +51,7 @@ export class CustomStoragePathService extends AbstractPaperlessService { - params.path__istartswith = storagePath.path + params.path__istartswith = storagePath.path + '/' return this.list(page, pageSize, sortField, sortReverse, params).pipe( map((results) => { results.results = results.results.filter((s) => { diff --git a/src-ui/src/app/services/storage-path-list-view.service.ts b/src-ui/src/app/services/storage-path-list-view.service.ts index 0b059a4c3..0e10b23df 100644 --- a/src-ui/src/app/services/storage-path-list-view.service.ts +++ b/src-ui/src/app/services/storage-path-list-view.service.ts @@ -1,18 +1,12 @@ import { Injectable } from '@angular/core' import { ParamMap, Router } from '@angular/router' import { Observable } from 'rxjs' -import { - FilterRule, - cloneFilterRules, - filterRulesDiffer, - isFullTextFilterRule, -} from '../data/filter-rule' +import { FilterRule, isFullTextFilterRule } from '../data/filter-rule' import { PaperlessDocument } from '../data/paperless-document' -import { PaperlessSavedView } from '../data/paperless-saved-view' import { PaperlessStoragePath } from '../data/paperless-storage-path' import { SETTINGS_KEYS } from '../data/paperless-uisettings' import { DOCUMENT_LIST_SERVICE } from '../data/storage-keys' -import { paramsFromViewState, paramsToViewState } from '../utils/query-params' +import { paramsToViewState } from '../utils/query-params' import { CustomStoragePathService } from './rest/custom-storage-path.service' import { DOCUMENT_SORT_FIELDS, SelectionData } from './rest/document.service' import { SettingsService } from './settings.service' @@ -136,29 +130,38 @@ export class StoragePathListViewService { if (queryParams.has('spid')) { newState.storagePathId = parseInt(queryParams.get('spid')) } + } else { + newState = this.defaultListViewState() } if (newState == undefined) newState = this.defaultListViewState() // if nothing in local storage + this.activeListViewState.filterRules = newState.filterRules + this.activeListViewState.sortField = newState.sortField + this.activeListViewState.sortReverse = newState.sortReverse + this.activeListViewState.currentPage = newState.currentPage + this.activeListViewState.storagePathId = newState.storagePathId + this.activeListViewState.parentStoragePath = newState.parentStoragePath + this.reload(null, isParamsEmpty) // only reload if things have changed - if ( - !this.initialized || - isParamsEmpty || - this.activeListViewState.sortField !== newState.sortField || - this.activeListViewState.sortReverse !== newState.sortReverse || - this.activeListViewState.currentPage !== newState.currentPage || - this.activeListViewState.storagePathId !== newState.storagePathId || - filterRulesDiffer( - this.activeListViewState.filterRules, - newState.filterRules - ) - ) { - this.activeListViewState.filterRules = newState.filterRules - this.activeListViewState.sortField = newState.sortField - this.activeListViewState.sortReverse = newState.sortReverse - this.activeListViewState.currentPage = newState.currentPage - this.activeListViewState.storagePathId = newState.storagePathId - this.reload(null, isParamsEmpty) // update the params if there arent any - } + // if ( + // !this.initialized || + // isParamsEmpty || + // this.activeListViewState.sortField !== newState.sortField || + // this.activeListViewState.sortReverse !== newState.sortReverse || + // this.activeListViewState.currentPage !== newState.currentPage || + // this.activeListViewState.storagePathId !== newState.storagePathId || + // filterRulesDiffer( + // this.activeListViewState.filterRules, + // newState.filterRules + // ) + // ) { + // this.activeListViewState.filterRules = newState.filterRules + // this.activeListViewState.sortField = newState.sortField + // this.activeListViewState.sortReverse = newState.sortReverse + // this.activeListViewState.currentPage = newState.currentPage + // this.activeListViewState.storagePathId = newState.storagePathId + // this.reload(null, isParamsEmpty) // update the params if there arent any + // } } getStoragePathByPath(path: string): Observable { @@ -297,7 +300,8 @@ export class StoragePathListViewService { } get currentFolderPath(): string { - return this.activeListViewState.parentStoragePath?.path || '/' + const path = this.activeListViewState.parentStoragePath?.path + return path ? 'DMS/' + path : 'DMS/' } setSort(field: string, reverse: boolean) {