mirror of
https://github.com/directus/directus.git
synced 2026-02-19 10:14:33 -05:00
* Remove advanced filter sidebar detail So long, and thanks for all the fish. * Remove filter conversion logic * Start replacing/removing old skool filters * Add inline mode for usages in search bar * Make filter work in header bar * Emit empty string as null in filter * Move shared filter types to shared * Upgrade use-items * Fix manual sort on tabular * Cleanup styling in search bar usage * Tweak styling * Fix filtering issues * Update cards * Remove activeFilterCount from tabular * Update maps to work with new filters * Update calendar to new filter/sort structure * Fix activity module nav/search * Fix no-results message * Update file library filtering * Finalize user search * Allow filtering in drawer-collection * Handle cancelled responses semi-gracefully * Add loading start state timeout * Replace sort type in api * Last commit before redoing a bunch * Finish new visual style * Remove unused rounded prop from v-menu * Tweak sizing * Enough size tweaking for now * Count all filter operators instead of top * Fix archive casting * Fix api build * Add merge filters util * Split filter in user vs system * Fix export sidebar detail * Show field label on permissions configuration * Add migration for filter/sort * Use filters in insights
92 lines
2.7 KiB
TypeScript
92 lines
2.7 KiB
TypeScript
import { Knex } from 'knex';
|
|
import getDatabase from '../database';
|
|
import { ForbiddenException } from '../exceptions';
|
|
import { AbstractServiceOptions, SchemaOverview } from '../types';
|
|
import { Accountability, Query } from '@directus/shared/types';
|
|
import { applyFilter, applySearch } from '../utils/apply-query';
|
|
import { parseFilter } from '@directus/shared/utils';
|
|
|
|
export class MetaService {
|
|
knex: Knex;
|
|
accountability: Accountability | null;
|
|
schema: SchemaOverview;
|
|
|
|
constructor(options: AbstractServiceOptions) {
|
|
this.knex = options.knex || getDatabase();
|
|
this.accountability = options.accountability || null;
|
|
this.schema = options.schema;
|
|
}
|
|
|
|
async getMetaForQuery(collection: string, query: any): Promise<Record<string, any> | undefined> {
|
|
if (!query || !query.meta) return;
|
|
|
|
const results = await Promise.all(
|
|
query.meta.map((metaVal: string) => {
|
|
if (metaVal === 'total_count') return this.totalCount(collection);
|
|
if (metaVal === 'filter_count') return this.filterCount(collection, query);
|
|
})
|
|
);
|
|
|
|
return results.reduce((metaObject: Record<string, any>, value, index) => {
|
|
return {
|
|
...metaObject,
|
|
[query.meta![index]]: value,
|
|
};
|
|
}, {});
|
|
}
|
|
|
|
async totalCount(collection: string): Promise<number> {
|
|
const dbQuery = this.knex(collection).count('*', { as: 'count' }).first();
|
|
|
|
if (this.accountability?.admin !== true) {
|
|
const permissionsRecord = this.schema.permissions.find((permission) => {
|
|
return permission.action === 'read' && permission.collection === collection;
|
|
});
|
|
|
|
if (!permissionsRecord) throw new ForbiddenException();
|
|
|
|
const permissions = parseFilter(permissionsRecord.permissions, this.accountability);
|
|
|
|
applyFilter(this.knex, this.schema, dbQuery, permissions, collection);
|
|
}
|
|
|
|
const result = await dbQuery;
|
|
|
|
return Number(result?.count ?? 0);
|
|
}
|
|
|
|
async filterCount(collection: string, query: Query): Promise<number> {
|
|
const dbQuery = this.knex(collection).count('*', { as: 'count' });
|
|
|
|
let filter = query.filter || {};
|
|
|
|
if (this.accountability?.admin !== true) {
|
|
const permissionsRecord = this.schema.permissions.find((permission) => {
|
|
return permission.action === 'read' && permission.collection === collection;
|
|
});
|
|
|
|
if (!permissionsRecord) throw new ForbiddenException();
|
|
|
|
const permissions = parseFilter(permissionsRecord.permissions, this.accountability);
|
|
|
|
if (Object.keys(filter).length > 0) {
|
|
filter = { _and: [permissions, filter] };
|
|
} else {
|
|
filter = permissions;
|
|
}
|
|
}
|
|
|
|
if (Object.keys(filter).length > 0) {
|
|
applyFilter(this.knex, this.schema, dbQuery, filter, collection);
|
|
}
|
|
|
|
if (query.search) {
|
|
applySearch(this.schema, dbQuery, query.search, collection);
|
|
}
|
|
|
|
const records = await dbQuery;
|
|
|
|
return Number(records[0].count);
|
|
}
|
|
}
|