mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Allow disabling activity/revisions (#5112)
* Add accountability column * Add field info for accountability * Add accountability to collection type * Fetch accountability info from collection meta * Add field name translation for accountability field * Hide revisions drawer detail if revisions aren't available * Only save activity where accountability flag matches * Disable revisions for directus_presets Fixes #3767 * Tweak field option naming
This commit is contained in:
@@ -7,7 +7,7 @@ export async function up(knex: Knex) {
|
||||
}
|
||||
|
||||
export async function down(knex: Knex) {
|
||||
await knex.schema.alterTable('directus_presets', (table) => {
|
||||
await knex.schema.alterTable('directus_files', (table) => {
|
||||
table.integer('filesize').notNullable().defaultTo(0).alter();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Knex } from 'knex';
|
||||
|
||||
export async function up(knex: Knex) {
|
||||
await knex.schema.alterTable('directus_collections', (table) => {
|
||||
table.string('accountability').defaultTo('all');
|
||||
});
|
||||
|
||||
await knex('directus_collections').update({ accountability: 'all' });
|
||||
}
|
||||
|
||||
export async function down(knex: Knex) {
|
||||
await knex.schema.alterTable('directus_collections', (table) => {
|
||||
table.dropColumn('accountability');
|
||||
});
|
||||
}
|
||||
@@ -21,10 +21,10 @@ data:
|
||||
- collection: directus_files
|
||||
icon: folder
|
||||
note: Metadata for all managed file assets
|
||||
display_template: "{{ title }}"
|
||||
display_template: '{{ title }}'
|
||||
- collection: directus_folders
|
||||
note: Provides virtual directories for files
|
||||
display_template: "{{ name }}"
|
||||
display_template: '{{ name }}'
|
||||
- collection: directus_migrations
|
||||
note: What version of the database you're using
|
||||
- collection: directus_permissions
|
||||
@@ -33,6 +33,7 @@ data:
|
||||
- collection: directus_presets
|
||||
icon: bookmark_border
|
||||
note: Presets for collection defaults and bookmarks
|
||||
accountability: null
|
||||
- collection: directus_relations
|
||||
icon: merge_type
|
||||
note: Relationship configuration and metadata
|
||||
@@ -52,6 +53,6 @@ data:
|
||||
unarchive_value: draft
|
||||
icon: people_alt
|
||||
note: System users for the platform
|
||||
display_template: "{{ first_name }} {{ last_name }}"
|
||||
display_template: '{{ first_name }} {{ last_name }}'
|
||||
- collection: directus_webhooks
|
||||
note: Configuration for event-based HTTP requests
|
||||
|
||||
@@ -135,3 +135,25 @@ fields:
|
||||
- integer
|
||||
allowNone: true
|
||||
width: half
|
||||
|
||||
- field: accountability_divider
|
||||
special:
|
||||
- alias
|
||||
- no-data
|
||||
interface: divider
|
||||
options:
|
||||
icon: admin_panel_settings
|
||||
title: Accountability
|
||||
width: full
|
||||
|
||||
- field: accountability
|
||||
interface: dropdown
|
||||
options:
|
||||
choices:
|
||||
- text: '$t:field_options.directus_collections.track_activity_revisions'
|
||||
value: all
|
||||
- text: '$t:field_options.directus_collections.only_track_activity'
|
||||
value: activity
|
||||
- text: '$t:field_options.directus_collections.do_not_track_anything'
|
||||
value: null
|
||||
width: half
|
||||
|
||||
@@ -129,7 +129,7 @@ export class ItemsService<Item extends AnyItem = AnyItem> implements AbstractSer
|
||||
await payloadService.processO2M(payloads, key);
|
||||
}
|
||||
|
||||
if (this.accountability) {
|
||||
if (this.accountability && this.schema.collections[this.collection].accountability !== null) {
|
||||
const activityRecords = primaryKeys.map((key) => ({
|
||||
action: Action.CREATE,
|
||||
user: this.accountability!.user,
|
||||
@@ -153,16 +153,18 @@ export class ItemsService<Item extends AnyItem = AnyItem> implements AbstractSer
|
||||
activityPrimaryKeys.push(primaryKey);
|
||||
}
|
||||
|
||||
const revisionRecords = activityPrimaryKeys.map((key, index) => ({
|
||||
activity: key,
|
||||
collection: this.collection,
|
||||
item: primaryKeys[index],
|
||||
data: JSON.stringify(payloads[index]),
|
||||
delta: JSON.stringify(payloads[index]),
|
||||
}));
|
||||
if (this.schema.collections[this.collection].accountability === 'all') {
|
||||
const revisionRecords = activityPrimaryKeys.map((key, index) => ({
|
||||
activity: key,
|
||||
collection: this.collection,
|
||||
item: primaryKeys[index],
|
||||
data: JSON.stringify(payloads[index]),
|
||||
delta: JSON.stringify(payloads[index]),
|
||||
}));
|
||||
|
||||
if (revisionRecords.length > 0) {
|
||||
await trx.insert(revisionRecords).into('directus_revisions');
|
||||
if (revisionRecords.length > 0) {
|
||||
await trx.insert(revisionRecords).into('directus_revisions');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +337,7 @@ export class ItemsService<Item extends AnyItem = AnyItem> implements AbstractSer
|
||||
await payloadService.processO2M(payload, key);
|
||||
}
|
||||
|
||||
if (this.accountability) {
|
||||
if (this.accountability && this.schema.collections[this.collection].accountability !== null) {
|
||||
const activityRecords = keys.map((key) => ({
|
||||
action: Action.UPDATE,
|
||||
user: this.accountability!.user,
|
||||
@@ -357,24 +359,26 @@ export class ItemsService<Item extends AnyItem = AnyItem> implements AbstractSer
|
||||
activityPrimaryKeys.push(primaryKey);
|
||||
}
|
||||
|
||||
const itemsService = new ItemsService(this.collection, {
|
||||
knex: trx,
|
||||
schema: this.schema,
|
||||
});
|
||||
if (this.schema.collections[this.collection].accountability === 'all') {
|
||||
const itemsService = new ItemsService(this.collection, {
|
||||
knex: trx,
|
||||
schema: this.schema,
|
||||
});
|
||||
|
||||
const snapshots = await itemsService.readByKey(keys);
|
||||
const snapshots = await itemsService.readByKey(keys);
|
||||
|
||||
const revisionRecords = activityPrimaryKeys.map((key, index) => ({
|
||||
activity: key,
|
||||
collection: this.collection,
|
||||
item: keys[index],
|
||||
data:
|
||||
snapshots && Array.isArray(snapshots) ? JSON.stringify(snapshots?.[index]) : JSON.stringify(snapshots),
|
||||
delta: JSON.stringify(payloadWithoutAliasAndPK),
|
||||
}));
|
||||
const revisionRecords = activityPrimaryKeys.map((key, index) => ({
|
||||
activity: key,
|
||||
collection: this.collection,
|
||||
item: keys[index],
|
||||
data:
|
||||
snapshots && Array.isArray(snapshots) ? JSON.stringify(snapshots?.[index]) : JSON.stringify(snapshots),
|
||||
delta: JSON.stringify(payloadWithoutAliasAndPK),
|
||||
}));
|
||||
|
||||
if (revisionRecords.length > 0) {
|
||||
await trx.insert(revisionRecords).into('directus_revisions');
|
||||
if (revisionRecords.length > 0) {
|
||||
await trx.insert(revisionRecords).into('directus_revisions');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -502,7 +506,7 @@ export class ItemsService<Item extends AnyItem = AnyItem> implements AbstractSer
|
||||
await this.knex.transaction(async (trx) => {
|
||||
await trx(this.collection).whereIn(primaryKeyField, keys).delete();
|
||||
|
||||
if (this.accountability) {
|
||||
if (this.accountability && this.schema.collections[this.collection].accountability !== null) {
|
||||
const activityRecords = keys.map((key) => ({
|
||||
action: Action.DELETE,
|
||||
user: this.accountability!.user,
|
||||
|
||||
@@ -8,6 +8,7 @@ export type CollectionMeta = {
|
||||
singleton: boolean;
|
||||
icon: string | null;
|
||||
translations: Record<string, string>;
|
||||
accountability: 'all' | 'accountability' | null;
|
||||
};
|
||||
|
||||
export type Collection = {
|
||||
|
||||
@@ -9,6 +9,7 @@ type CollectionsOverview = {
|
||||
singleton: boolean;
|
||||
sortField: string | null;
|
||||
note: string | null;
|
||||
accountability: 'all' | 'activity' | null;
|
||||
fields: {
|
||||
[name: string]: {
|
||||
field: string;
|
||||
|
||||
@@ -68,7 +68,9 @@ export async function getSchema(options?: {
|
||||
const schemaOverview = await schemaInspector.overview();
|
||||
|
||||
const collections = [
|
||||
...(await database.select('collection', 'singleton', 'note', 'sort_field').from('directus_collections')),
|
||||
...(await database
|
||||
.select('collection', 'singleton', 'note', 'sort_field', 'accountability')
|
||||
.from('directus_collections')),
|
||||
...systemCollectionRows,
|
||||
];
|
||||
|
||||
@@ -87,6 +89,7 @@ export async function getSchema(options?: {
|
||||
collectionMeta?.singleton === true || collectionMeta?.singleton === 'true' || collectionMeta?.singleton === 1,
|
||||
note: collectionMeta?.note || null,
|
||||
sortField: collectionMeta?.sort_field || null,
|
||||
accountability: collectionMeta ? collectionMeta.accountability : 'all',
|
||||
fields: mapValues(schemaOverview[collection].columns, (column) => ({
|
||||
field: column.column_name,
|
||||
defaultValue: getDefaultValue(column) ?? null,
|
||||
|
||||
Reference in New Issue
Block a user