Enhancement: shared icon & shared by me filter (#4859)

This commit is contained in:
shamoon
2023-12-19 12:45:04 -08:00
committed by GitHub
parent ad533429f7
commit 5e361b0e81
20 changed files with 394 additions and 126 deletions

View File

@@ -38,6 +38,16 @@
<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">

View File

@@ -145,6 +145,15 @@ describe('PermissionsFilterDropdownComponent', () => {
userID: null,
})
component.setFilter(OwnerFilterType.SHARED_BY_ME)
expect(ownerFilterSetResult).toEqual({
excludeUsers: [],
hideUnowned: false,
includeUsers: [],
ownerFilter: OwnerFilterType.SHARED_BY_ME,
userID: currentUserID,
})
component.setFilter(OwnerFilterType.UNOWNED)
expect(ownerFilterSetResult).toEqual({
excludeUsers: [],

View File

@@ -32,6 +32,7 @@ export enum OwnerFilterType {
NOT_SELF = 2,
OTHERS = 3,
UNOWNED = 4,
SHARED_BY_ME = 5,
}
@Component({
@@ -108,6 +109,13 @@ export class PermissionsFilterDropdownComponent extends ComponentWithPermissions
this.selectionModel.includeUsers = []
this.selectionModel.excludeUsers = []
this.selectionModel.hideUnowned = false
} else if (
this.selectionModel.ownerFilter === OwnerFilterType.SHARED_BY_ME
) {
this.selectionModel.userID = this.settingsService.currentUser.id
this.selectionModel.includeUsers = []
this.selectionModel.excludeUsers = []
this.selectionModel.hideUnowned = false
} else if (this.selectionModel.ownerFilter === OwnerFilterType.UNOWNED) {
this.selectionModel.userID = null
this.selectionModel.includeUsers = []

View File

@@ -112,6 +112,12 @@
</svg>
<small>{{document.owner | username}}</small>
</div>
<div *ngIf="document.is_shared_by_requester" class="list-group-item bg-light text-dark p-1 border-0">
<svg class="metadata-icon me-2 text-muted" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#people-fill"/>
</svg>
<small i18n>Shared</small>
</div>
<div *ngIf="document.__search_hit__?.score" class="list-group-item bg-light text-dark border-0 d-flex p-0 ps-4 search-score">
<small class="text-muted" i18n>Score:</small>
<ngb-progressbar [type]="searchScoreClass" [value]="document.__search_hit__.score" class="search-score-bar mx-2 mt-1" [max]="1"></ngb-progressbar>

View File

@@ -77,6 +77,12 @@
</svg>
<small>{{document.owner | username}}</small>
</div>
<div *ngIf="document.is_shared_by_requester" class="ps-0 p-1">
<svg class="metadata-icon me-2 text-muted" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#people-fill"/>
</svg>
<small i18n>Shared</small>
</div>
</div>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group w-100">

View File

@@ -47,6 +47,7 @@ import {
FILTER_OWNER_DOES_NOT_INCLUDE,
FILTER_OWNER_ISNULL,
FILTER_CUSTOM_FIELDS,
FILTER_SHARED_BY_USER,
} from 'src/app/data/filter-rule-type'
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'
@@ -826,6 +827,16 @@ describe('FilterEditorComponent', () => {
expect(component.permissionsSelectionModel.hideUnowned).toBeTruthy()
}))
it('should ingest filter rules for shared by me', fakeAsync(() => {
component.filterRules = [
{
rule_type: FILTER_SHARED_BY_USER,
value: '2',
},
]
expect(component.permissionsSelectionModel.userID).toEqual(2)
}))
// GET filterRules
it('should convert user input to correct filter rules on text field search title + content', fakeAsync(() => {
@@ -1453,13 +1464,28 @@ describe('FilterEditorComponent', () => {
])
}))
it('should convert user input to correct filter on permissions select unowned', fakeAsync(() => {
it('should convert user input to correct filter on permissions select shared by me', fakeAsync(() => {
const permissionsDropdown = fixture.debugElement.query(
By.directive(PermissionsFilterDropdownComponent)
)
const unownedButton = permissionsDropdown.queryAll(By.css('button'))[4]
unownedButton.triggerEventHandler('click')
fixture.detectChanges()
expect(component.filterRules).toEqual([
{
rule_type: FILTER_SHARED_BY_USER,
value: '1',
},
])
}))
it('should convert user input to correct filter on permissions select unowned', fakeAsync(() => {
const permissionsDropdown = fixture.debugElement.query(
By.directive(PermissionsFilterDropdownComponent)
)
const unownedButton = permissionsDropdown.queryAll(By.css('button'))[5]
unownedButton.triggerEventHandler('click')
fixture.detectChanges()
expect(component.filterRules).toEqual([
{
rule_type: FILTER_OWNER_ISNULL,

View File

@@ -49,6 +49,7 @@ import {
FILTER_OWNER_ISNULL,
FILTER_OWNER_ANY,
FILTER_CUSTOM_FIELDS,
FILTER_SHARED_BY_USER,
} from 'src/app/data/filter-rule-type'
import {
FilterableDropdownSelectionModel,
@@ -503,6 +504,12 @@ export class FilterEditorComponent implements OnInit, OnDestroy {
parseInt(rule.value, 10)
)
break
case FILTER_SHARED_BY_USER:
this.permissionsSelectionModel.ownerFilter =
OwnerFilterType.SHARED_BY_ME
if (rule.value)
this.permissionsSelectionModel.userID = parseInt(rule.value, 10)
break
case FILTER_OWNER_ISNULL:
if (rule.value === 'true' || rule.value === '1') {
this.permissionsSelectionModel.hideUnowned = false
@@ -801,6 +808,13 @@ export class FilterEditorComponent implements OnInit, OnDestroy {
rule_type: FILTER_OWNER_ANY,
value: this.permissionsSelectionModel.includeUsers?.join(','),
})
} else if (
this.permissionsSelectionModel.ownerFilter == OwnerFilterType.SHARED_BY_ME
) {
filterRules.push({
rule_type: FILTER_SHARED_BY_USER,
value: this.permissionsSelectionModel.userID.toString(),
})
} else if (
this.permissionsSelectionModel.ownerFilter == OwnerFilterType.UNOWNED
) {

View File

@@ -45,6 +45,7 @@ export const FILTER_OWNER = 32
export const FILTER_OWNER_ANY = 33
export const FILTER_OWNER_ISNULL = 34
export const FILTER_OWNER_DOES_NOT_INCLUDE = 35
export const FILTER_SHARED_BY_USER = 37
export const FILTER_CUSTOM_FIELDS = 36
@@ -273,6 +274,12 @@ export const FILTER_RULE_TYPES: FilterRuleType[] = [
datatype: 'number',
multi: true,
},
{
id: FILTER_SHARED_BY_USER,
filtervar: 'shared_by__id',
datatype: 'number',
multi: true,
},
{
id: FILTER_CUSTOM_FIELDS,
filtervar: 'custom_fields__icontains',

View File

@@ -17,4 +17,6 @@ export interface ObjectWithPermissions extends ObjectWithId {
permissions?: PermissionsObject
user_can_change?: boolean
is_shared_by_requester?: boolean
}