Proper data type enum

This commit is contained in:
shamoon 2024-04-03 00:07:49 -07:00
parent 117b0b44b3
commit 8cbb15bd90
5 changed files with 91 additions and 60 deletions

View File

@ -30,10 +30,10 @@
(click)="primaryAction(type, item); $event.stopPropagation()"
[disabled]="disablePrimaryButton(type, item)"
(mouseenter)="onButtonHover($event)">
@if (type === 'document') {
@if (type === DataType.Document) {
<i-bs width="1em" height="1em" name="pencil"></i-bs>
<span>&nbsp;<ng-container i18n>Open</ng-container></span>
} @else if (type === 'workflow' || type === 'customField' || type === 'group' || type === 'user') {
} @else if (type === DataType.Workflow || type === DataType.CustomField || type === DataType.Group || type === DataType.User) {
<i-bs width="1em" height="1em" name="pencil"></i-bs>
<span>&nbsp;<ng-container i18n>Edit</ng-container></span>
} @else {
@ -41,12 +41,12 @@
<span>&nbsp;<ng-container i18n>Filter documents</ng-container></span>
}
</button>
@if (type !== 'workflow' && type !== 'customField' && type !== 'group' && type !== 'user') {
@if (type !== DataType.Workflow && type !== DataType.CustomField && type !== DataType.Group && type !== DataType.User) {
<button #secondaryButton type="button" class="btn btn-sm btn-outline-primary d-flex"
(click)="secondaryAction(type, item); $event.stopPropagation()"
[disabled]="disableSecondaryButton(type, item)"
(mouseenter)="onButtonHover($event)">
@if (type === 'document') {
@if (type === DataType.Document) {
<i-bs width="1em" height="1em" name="download"></i-bs>
<span>&nbsp;<ng-container i18n>Download</ng-container></span>
} @else {
@ -66,63 +66,63 @@
@if (searchResults?.documents.length) {
<h6 class="dropdown-header" i18n="@@searchResults.documents">Documents</h6>
@for (document of searchResults.documents; track document.id) {
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: document, nameProp: 'title', type: 'document', icon: 'file-text', date: document.added}"></ng-container>
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: document, nameProp: 'title', type: DataType.Document, icon: 'file-text', date: document.added}"></ng-container>
}
}
@if (searchResults?.tags.length) {
<h6 class="dropdown-header" i18n="@@searchResults.tags">Tags</h6>
@for (tag of searchResults.tags; track tag.id) {
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: tag, nameProp: 'name', type: 'tag', icon: 'tag'}"></ng-container>
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: tag, nameProp: 'name', type: DataType.Tag, icon: 'tag'}"></ng-container>
}
}
@if (searchResults?.correspondents.length) {
<h6 class="dropdown-header" i18n="@@searchResults.correspondents">Correspondents</h6>
@for (correspondent of searchResults.correspondents; track correspondent.id) {
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: correspondent, nameProp: 'name', type: 'correspondent', icon: 'person'}"></ng-container>
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: correspondent, nameProp: 'name', type: DataType.Correspondent, icon: 'person'}"></ng-container>
}
}
@if (searchResults?.document_types.length) {
<h6 class="dropdown-header" i18n="@@searchResults.documentTypes">Document types</h6>
@for (documentType of searchResults.document_types; track documentType.id) {
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: documentType, nameProp: 'name', type: 'documentType', icon: 'file-earmark'}"></ng-container>
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: documentType, nameProp: 'name', type: DataType.DocumentType, icon: 'file-earmark'}"></ng-container>
}
}
@if (searchResults?.storage_paths.length) {
<h6 class="dropdown-header" i18n="@@searchResults.storagePaths">Storage paths</h6>
@for (storagePath of searchResults.storage_paths; track storagePath.id) {
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: storagePath, nameProp: 'name', type: 'storagePath', icon: 'folder'}"></ng-container>
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: storagePath, nameProp: 'name', type: DataType.StoragePath, icon: 'folder'}"></ng-container>
}
}
@if (searchResults?.users.length) {
<h6 class="dropdown-header" i18n="@@searchResults.users">Users</h6>
@for (user of searchResults.users; track user.id) {
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: user, nameProp: 'username', type: 'user', icon: 'person-square'}"></ng-container>
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: user, nameProp: 'username', type: DataType.User, icon: 'person-square'}"></ng-container>
}
}
@if (searchResults?.groups.length) {
<h6 class="dropdown-header" i18n="@@searchResults.groups">Groups</h6>
@for (group of searchResults.groups; track group.id) {
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: group, nameProp: 'name', type: 'group', icon: 'people'}"></ng-container>
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: group, nameProp: 'name', type: DataType.Group, icon: 'people'}"></ng-container>
}
}
@if (searchResults?.custom_fields.length) {
<h6 class="dropdown-header" i18n="@@searchResults.customFields">Custom fields</h6>
@for (customField of searchResults.custom_fields; track customField.id) {
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: customField, nameProp: 'name', type: 'customField', icon: 'ui-radios'}"></ng-container>
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: customField, nameProp: 'name', type: DataType.CustomField, icon: 'ui-radios'}"></ng-container>
}
}
@if (searchResults?.workflows.length) {
<h6 class="dropdown-header" i18n="@@searchResults.workflows">Workflows</h6>
@for (workflow of searchResults.workflows; track workflow.id) {
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: workflow, nameProp: 'name', type: 'workflow', icon: 'boxes'}"></ng-container>
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: workflow, nameProp: 'name', type: DataType.Workflow, icon: 'boxes'}"></ng-container>
}
}
}

View File

@ -34,6 +34,7 @@ import { CustomFieldEditDialogComponent } from '../../common/edit-dialog/custom-
import { WorkflowEditDialogComponent } from '../../common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component'
import { ElementRef } from '@angular/core'
import { ToastService } from 'src/app/services/toast.service'
import { DataType } from 'src/app/data/datatype'
const searchResults = {
total: 11,
@ -229,55 +230,55 @@ describe('GlobalSearchComponent', () => {
let modal: NgbModalRef
modalService.activeInstances.subscribe((m) => (modal = m[m.length - 1]))
component.primaryAction('document', object)
component.primaryAction(DataType.Document, object)
expect(routerSpy).toHaveBeenCalledWith(['/documents', object.id])
component.primaryAction('correspondent', object)
component.primaryAction(DataType.Correspondent, object)
expect(qfSpy).toHaveBeenCalledWith([
{ rule_type: FILTER_HAS_CORRESPONDENT_ANY, value: object.id.toString() },
])
component.primaryAction('documentType', object)
component.primaryAction(DataType.DocumentType, object)
expect(qfSpy).toHaveBeenCalledWith([
{ rule_type: FILTER_HAS_DOCUMENT_TYPE_ANY, value: object.id.toString() },
])
component.primaryAction('storagePath', object)
component.primaryAction(DataType.StoragePath, object)
expect(qfSpy).toHaveBeenCalledWith([
{ rule_type: FILTER_HAS_STORAGE_PATH_ANY, value: object.id.toString() },
])
component.primaryAction('tag', object)
component.primaryAction(DataType.Tag, object)
expect(qfSpy).toHaveBeenCalledWith([
{ rule_type: FILTER_HAS_ANY_TAG, value: object.id.toString() },
])
component.primaryAction('user', object)
component.primaryAction(DataType.User, object)
expect(modalSpy).toHaveBeenCalledWith(UserEditDialogComponent, {
size: 'lg',
})
component.primaryAction('group', object)
component.primaryAction(DataType.Group, object)
expect(modalSpy).toHaveBeenCalledWith(GroupEditDialogComponent, {
size: 'lg',
})
component.primaryAction('mailAccount', object)
component.primaryAction(DataType.MailAccount, object)
expect(modalSpy).toHaveBeenCalledWith(MailAccountEditDialogComponent, {
size: 'xl',
})
component.primaryAction('mailRule', object)
component.primaryAction(DataType.MailRule, object)
expect(modalSpy).toHaveBeenCalledWith(MailRuleEditDialogComponent, {
size: 'xl',
})
component.primaryAction('customField', object)
component.primaryAction(DataType.CustomField, object)
expect(modalSpy).toHaveBeenCalledWith(CustomFieldEditDialogComponent, {
size: 'md',
})
component.primaryAction('workflow', object)
component.primaryAction(DataType.Workflow, object)
expect(modalSpy).toHaveBeenCalledWith(WorkflowEditDialogComponent, {
size: 'xl',
})
@ -307,22 +308,28 @@ describe('GlobalSearchComponent', () => {
let modal: NgbModalRef
modalService.activeInstances.subscribe((m) => (modal = m[m.length - 1]))
component.secondaryAction('correspondent', correspondent)
component.secondaryAction(DataType.Correspondent, correspondent)
expect(modalSpy).toHaveBeenCalledWith(CorrespondentEditDialogComponent, {
size: 'md',
})
component.secondaryAction('documentType', searchResults.document_types[0])
component.secondaryAction(
DataType.DocumentType,
searchResults.document_types[0]
)
expect(modalSpy).toHaveBeenCalledWith(CorrespondentEditDialogComponent, {
size: 'md',
})
component.secondaryAction('storagePath', searchResults.storage_paths[0])
component.secondaryAction(
DataType.StoragePath,
searchResults.storage_paths[0]
)
expect(modalSpy).toHaveBeenCalledWith(CorrespondentEditDialogComponent, {
size: 'md',
})
component.secondaryAction('tag', searchResults.tags[0])
component.secondaryAction(DataType.Tag, searchResults.tags[0])
expect(modalSpy).toHaveBeenCalledWith(CorrespondentEditDialogComponent, {
size: 'md',
})

View File

@ -15,6 +15,7 @@ import {
FILTER_HAS_STORAGE_PATH_ANY,
FILTER_HAS_ANY_TAG,
} from 'src/app/data/filter-rule-type'
import { DataType } from 'src/app/data/datatype'
import { ObjectWithId } from 'src/app/data/object-with-id'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import {
@ -45,6 +46,7 @@ import { WorkflowEditDialogComponent } from '../../common/edit-dialog/workflow-e
styleUrl: './global-search.component.scss',
})
export class GlobalSearchComponent {
public DataType = DataType
public query: string
public queryDebounce: Subject<string>
public searchResults: GlobalSearchResult
@ -130,41 +132,41 @@ export class GlobalSearchComponent {
let editDialogComponent: any
let size: string = 'md'
switch (type) {
case 'document':
case DataType.Document:
this.router.navigate(['/documents', object.id])
return
case 'correspondent':
case DataType.Correspondent:
filterRuleType = FILTER_HAS_CORRESPONDENT_ANY
break
case 'documentType':
case DataType.DocumentType:
filterRuleType = FILTER_HAS_DOCUMENT_TYPE_ANY
break
case 'storagePath':
case DataType.StoragePath:
filterRuleType = FILTER_HAS_STORAGE_PATH_ANY
break
case 'tag':
case DataType.Tag:
filterRuleType = FILTER_HAS_ANY_TAG
break
case 'user':
case DataType.User:
editDialogComponent = UserEditDialogComponent
size = 'lg'
break
case 'group':
case DataType.Group:
editDialogComponent = GroupEditDialogComponent
size = 'lg'
break
case 'mailAccount':
case DataType.MailAccount:
editDialogComponent = MailAccountEditDialogComponent
size = 'xl'
break
case 'mailRule':
case DataType.MailRule:
editDialogComponent = MailRuleEditDialogComponent
size = 'xl'
break
case 'customField':
case DataType.CustomField:
editDialogComponent = CustomFieldEditDialogComponent
break
case 'workflow':
case DataType.Workflow:
editDialogComponent = WorkflowEditDialogComponent
size = 'xl'
break
@ -195,19 +197,19 @@ export class GlobalSearchComponent {
let editDialogComponent: any
let size: string = 'md'
switch (type) {
case 'document':
case DataType.Document:
window.open(this.documentService.getDownloadUrl(object.id))
break
case 'correspondent':
case DataType.Correspondent:
editDialogComponent = CorrespondentEditDialogComponent
break
case 'documentType':
case DataType.DocumentType:
editDialogComponent = DocumentTypeEditDialogComponent
break
case 'storagePath':
case DataType.StoragePath:
editDialogComponent = StoragePathEditDialogComponent
break
case 'tag':
case DataType.Tag:
editDialogComponent = TagEditDialogComponent
break
}
@ -287,8 +289,15 @@ export class GlobalSearchComponent {
}
}
public disablePrimaryButton(type: string, object: ObjectWithId): boolean {
if (['workflow', 'customField', 'group', 'user'].includes(type)) {
public disablePrimaryButton(type: DataType, object: ObjectWithId): boolean {
if (
[
DataType.Workflow,
DataType.CustomField,
DataType.Group,
DataType.User,
].includes(type)
) {
return !this.permissionsService.currentUserHasObjectPermissions(
PermissionAction.Change,
object
@ -298,8 +307,8 @@ export class GlobalSearchComponent {
return false
}
public disableSecondaryButton(type: string, object: ObjectWithId): boolean {
if ('document' === type) {
public disableSecondaryButton(type: DataType, object: ObjectWithId): boolean {
if (DataType.Document === type) {
return false
}

View File

@ -0,0 +1,13 @@
export enum DataType {
Document = 'document',
Correspondent = 'correspondent',
DocumentType = 'document_type',
StoragePath = 'storage_path',
Tag = 'tag',
User = 'user',
Group = 'group',
MailAccount = 'mail_account',
MailRule = 'mail_rule',
CustomField = 'custom_field',
Workflow = 'workflow',
}

View File

@ -1,3 +1,5 @@
import { DataType } from './datatype'
// These correspond to src/documents/models.py and changes here require a DB migration (and vice versa)
export const FILTER_TITLE = 0
export const FILTER_CONTENT = 1
@ -74,57 +76,57 @@ export const FILTER_RULE_TYPES: FilterRuleType[] = [
id: FILTER_CORRESPONDENT,
filtervar: 'correspondent__id',
isnull_filtervar: 'correspondent__isnull',
datatype: 'correspondent',
datatype: DataType.Correspondent,
multi: false,
},
{
id: FILTER_HAS_CORRESPONDENT_ANY,
filtervar: 'correspondent__id__in',
datatype: 'correspondent',
datatype: DataType.Correspondent,
multi: true,
},
{
id: FILTER_DOES_NOT_HAVE_CORRESPONDENT,
filtervar: 'correspondent__id__none',
datatype: 'correspondent',
datatype: DataType.Correspondent,
multi: true,
},
{
id: FILTER_STORAGE_PATH,
filtervar: 'storage_path__id',
isnull_filtervar: 'storage_path__isnull',
datatype: 'storage_path',
datatype: DataType.StoragePath,
multi: false,
},
{
id: FILTER_HAS_STORAGE_PATH_ANY,
filtervar: 'storage_path__id__in',
datatype: 'storage_path',
datatype: DataType.StoragePath,
multi: true,
},
{
id: FILTER_DOES_NOT_HAVE_STORAGE_PATH,
filtervar: 'storage_path__id__none',
datatype: 'storage_path',
datatype: DataType.StoragePath,
multi: true,
},
{
id: FILTER_DOCUMENT_TYPE,
filtervar: 'document_type__id',
isnull_filtervar: 'document_type__isnull',
datatype: 'document_type',
datatype: DataType.DocumentType,
multi: false,
},
{
id: FILTER_HAS_DOCUMENT_TYPE_ANY,
filtervar: 'document_type__id__in',
datatype: 'document_type',
datatype: DataType.DocumentType,
multi: true,
},
{
id: FILTER_DOES_NOT_HAVE_DOCUMENT_TYPE,
filtervar: 'document_type__id__none',
datatype: 'document_type',
datatype: DataType.DocumentType,
multi: true,
},
{
@ -137,19 +139,19 @@ export const FILTER_RULE_TYPES: FilterRuleType[] = [
{
id: FILTER_HAS_TAGS_ALL,
filtervar: 'tags__id__all',
datatype: 'tag',
datatype: DataType.Tag,
multi: true,
},
{
id: FILTER_HAS_TAGS_ANY,
filtervar: 'tags__id__in',
datatype: 'tag',
datatype: DataType.Tag,
multi: true,
},
{
id: FILTER_DOES_NOT_HAVE_TAG,
filtervar: 'tags__id__none',
datatype: 'tag',
datatype: DataType.Tag,
multi: true,
},
{