Browse Source

Enable to order projects by name, created_at, created_by, and project_type

pull/1985/head
Hironsan 2 years ago
parent
commit
adc4f27736
6 changed files with 62 additions and 23 deletions
  1. 2
      backend/projects/views/project.py
  2. 29
      frontend/components/project/ProjectList.vue
  3. 23
      frontend/domain/models/project/projectRepository.ts
  4. 14
      frontend/repositories/project/apiProjectRepository.ts
  5. 9
      frontend/services/application/project/projectApplicationService.ts
  6. 8
      frontend/services/application/project/projectData.ts

2
backend/projects/views/project.py

@ -13,7 +13,7 @@ class ProjectList(generics.ListCreateAPIView):
serializer_class = ProjectPolymorphicSerializer
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
search_fields = ("name", "description")
ordering_fields = "__all__"
ordering_fields = ["name", "created_at", "created_by", "project_type"]
ordering = ["-created_at"]
def get_permissions(self):

29
frontend/components/project/ProjectList.vue

@ -88,14 +88,14 @@ export default Vue.extend({
},
computed: {
headers() {
headers(): { text: any; value: string; sortable?: boolean }[] {
return [
{ text: this.$t('generic.name'), value: 'name' },
{ text: this.$t('generic.description'), value: 'description' },
{ text: this.$t('generic.description'), value: 'description', sortable: false },
{ text: this.$t('generic.type'), value: 'projectType' },
{ text: 'Created', value: 'createdAt' },
{ text: 'Author', value: 'author' },
{ text: 'Tags', value: 'tags' }
{ text: 'Tags', value: 'tags', sortable: false }
]
}
},
@ -103,32 +103,35 @@ export default Vue.extend({
watch: {
options: {
handler() {
const self: any = this
self.updateQuery({
this.updateQuery({
query: {
limit: self.options.itemsPerPage.toString(),
offset: ((self.options.page - 1) * self.options.itemsPerPage).toString(),
q: self.search
limit: this.options.itemsPerPage.toString(),
offset: ((this.options.page - 1) * this.options.itemsPerPage).toString(),
q: this.search
}
})
},
deep: true
},
search() {
const self: any = this
self.updateQuery({
this.updateQuery({
query: {
limit: self.options.itemsPerPage.toString(),
limit: this.options.itemsPerPage.toString(),
offset: '0',
q: self.search
q: this.search
}
})
self.options.page = 1
this.options.page = 1
}
},
methods: {
updateQuery(payload: any) {
const { sortBy, sortDesc } = this.options
if (sortBy.length === 1 && sortDesc.length === 1) {
payload.query.sortBy = sortBy[0]
payload.query.sortDesc = sortDesc[0]
}
this.$emit('update:query', payload)
}
}

23
frontend/domain/models/project/projectRepository.ts

@ -1,9 +1,28 @@
import { ProjectReadItem, ProjectWriteItem, ProjectItemList } from '~/domain/models/project/project'
export type SearchOption = { [key: string]: string | (string | null)[] }
const sortableFieldList = ['name', 'projectType', 'createdAt', 'author'] as const
type SortableFields = typeof sortableFieldList[number]
export class SearchQuery {
readonly limit: number = 10
readonly offset: number = 0
readonly q: string = ''
readonly sortBy: SortableFields = 'createdAt'
readonly sortDesc: boolean = false
constructor(_limit: string, _offset: string, _q?: string, _sortBy?: string, _sortDesc?: string) {
this.limit = /^\d+$/.test(_limit) ? parseInt(_limit) : 10
this.offset = /^\d+$/.test(_offset) ? parseInt(_offset) : 0
this.q = _q || ''
this.sortBy = (
_sortBy && sortableFieldList.includes(_sortBy as SortableFields) ? _sortBy : 'createdAt'
) as SortableFields
this.sortDesc = _sortDesc === 'true'
}
}
export interface ProjectRepository {
list({ limit, offset, q }: SearchOption): Promise<ProjectItemList>
list(query: SearchQuery): Promise<ProjectItemList>
findById(id: string): Promise<ProjectReadItem>

14
frontend/repositories/project/apiProjectRepository.ts

@ -1,5 +1,5 @@
import ApiService from '@/services/api.service'
import { ProjectRepository, SearchOption } from '@/domain/models/project/projectRepository'
import { ProjectRepository, SearchQuery } from '@/domain/models/project/projectRepository'
import { ProjectReadItem, ProjectWriteItem, ProjectItemList } from '@/domain/models/project/project'
function toModel(item: { [key: string]: any }): ProjectReadItem {
@ -50,8 +50,16 @@ function toPayload(item: ProjectWriteItem): { [key: string]: any } {
export class APIProjectRepository implements ProjectRepository {
constructor(private readonly request = ApiService) {}
async list({ limit = '10', offset = '0', q = '' }: SearchOption): Promise<ProjectItemList> {
const url = `/projects?limit=${limit}&offset=${offset}&q=${q}`
async list(query: SearchQuery): Promise<ProjectItemList> {
const fieldMapper = {
name: 'name',
createdAt: 'created_at',
projectType: 'project_type',
author: 'created_by'
}
const sortBy = fieldMapper[query.sortBy]
const ordering = query.sortDesc ? `-${sortBy}` : `${sortBy}`
const url = `/projects?limit=${query.limit}&offset=${query.offset}&q=${query.q}&ordering=${ordering}`
const response = await this.request.get(url)
return new ProjectItemList(
response.data.count,

9
frontend/services/application/project/projectApplicationService.ts

@ -1,13 +1,14 @@
import { ProjectDTO, ProjectWriteDTO, ProjectListDTO } from './projectData'
import { ProjectRepository, SearchOption } from '~/domain/models/project/projectRepository'
import { ProjectDTO, ProjectWriteDTO, ProjectListDTO, SearchQueryData } from './projectData'
import { ProjectRepository, SearchQuery } from '~/domain/models/project/projectRepository'
import { ProjectWriteItem } from '~/domain/models/project/project'
export class ProjectApplicationService {
constructor(private readonly repository: ProjectRepository) {}
public async list(options: SearchOption): Promise<ProjectListDTO> {
public async list(q: SearchQueryData): Promise<ProjectListDTO> {
try {
const items = await this.repository.list(options)
const query = new SearchQuery(q.limit, q.offset, q.q, q.sortBy, q.sortDesc)
const items = await this.repository.list(query)
return new ProjectListDTO(items)
} catch (e: any) {
throw new Error(e.response.data.detail)

8
frontend/services/application/project/projectData.ts

@ -80,3 +80,11 @@ export class ProjectListDTO {
this.items = item.items.map((_) => new ProjectDTO(_))
}
}
export interface SearchQueryData {
limit: string
offset: string
q?: string
sortBy?: string
sortDesc?: string
}
Loading…
Cancel
Save