Source

adminjs/src/backend/actions/list/list-action.ts

  1. import * as flat from 'flat'
  2. import { Action, ActionResponse } from '../action.interface'
  3. import sortSetter from '../../services/sort-setter/sort-setter'
  4. import Filter from '../../utils/filter/filter'
  5. import populator from '../../utils/populator/populator'
  6. import { RecordJSON } from '../../../frontend/interfaces'
  7. const PER_PAGE_LIMIT = 500
  8. /**
  9. * @implements Action
  10. * @category Actions
  11. * @module ListAction
  12. * @description
  13. * Returns selected Records in a list form
  14. * @private
  15. */
  16. export const ListAction: Action<ListActionResponse> = {
  17. name: 'list',
  18. isVisible: true,
  19. actionType: 'resource',
  20. showFilter: true,
  21. showInDrawer: false,
  22. /**
  23. * Responsible for returning data for all records.
  24. *
  25. * To invoke this action use {@link ApiClient#recordAction}
  26. *
  27. * @implements Action#handler
  28. * @memberof module:ListAction
  29. * @return {Promise<ListActionResponse>} records with metadata
  30. */
  31. handler: async (request, response, context) => {
  32. const { query } = request
  33. const { sortBy, direction, filters = {} } = flat.unflatten(query || {})
  34. const { resource } = context
  35. let { page, perPage } = flat.unflatten(query || {})
  36. if (perPage) {
  37. perPage = +perPage > PER_PAGE_LIMIT ? PER_PAGE_LIMIT : +perPage
  38. } else {
  39. perPage = 10 // default
  40. }
  41. page = Number(page) || 1
  42. const listProperties = resource.decorate().getListProperties()
  43. const firstProperty = listProperties.find(p => p.isSortable())
  44. let sort
  45. if (firstProperty) {
  46. sort = sortSetter(
  47. { sortBy, direction },
  48. firstProperty.name(),
  49. resource.decorate().options,
  50. )
  51. }
  52. const filter = await new Filter(filters, resource).populate()
  53. const records = await resource.find(filter, {
  54. limit: perPage,
  55. offset: (page - 1) * perPage,
  56. sort,
  57. })
  58. const populatedRecords = await populator(records)
  59. // eslint-disable-next-line no-param-reassign
  60. context.records = populatedRecords
  61. const total = await resource.count(filter)
  62. return {
  63. meta: {
  64. total,
  65. perPage,
  66. page,
  67. direction: sort?.direction,
  68. sortBy: sort?.sortBy,
  69. },
  70. records: populatedRecords.map(r => r.toJSON(context.currentAdmin)),
  71. }
  72. },
  73. }
  74. export default ListAction
  75. /**
  76. * Response returned by List action
  77. * @memberof module:ListAction
  78. * @alias ListAction
  79. */
  80. export type ListActionResponse = ActionResponse & {
  81. /**
  82. * Paginated collection of records
  83. */
  84. records: Array<RecordJSON>;
  85. /**
  86. * Pagination metadata
  87. */
  88. meta: {
  89. page: number;
  90. perPage: number;
  91. direction: 'asc' | 'desc';
  92. sortBy: string;
  93. total: number;
  94. };
  95. }