Files
Juergen Kunz 81ead52a72 feat(core): add table actions (edit, pause, delete confirmation) and global action log
- Add Edit and Pause/Resume actions to connections table
- Add delete confirmation modal to secrets table
- Add 'paused' status to connections with full backend support
- Skip paused connections in health checks and secrets scanning
- Add global ActionLog service with filesystem persistence
- Instrument all mutation handlers (connections, secrets, pipelines) with action logging
- Add Action Log view with entity type filtering to dashboard
2026-02-27 11:13:07 +00:00

102 lines
2.8 KiB
TypeScript

import * as plugins from '../../../plugins.js';
import * as appstate from '../../../appstate.js';
import { viewHostCss } from '../../shared/index.js';
import {
DeesElement,
customElement,
html,
state,
css,
cssManager,
type TemplateResult,
} from '@design.estate/dees-element';
@customElement('gitops-view-actionlog')
export class GitopsViewActionlog extends DeesElement {
@state()
accessor actionLogState: appstate.IActionLogState = {
entries: [],
total: 0,
};
@state()
accessor selectedEntityType: string = 'all';
private _autoRefreshHandler: () => void;
constructor() {
super();
const sub = appstate.actionLogStatePart
.select((s) => s)
.subscribe((s) => { this.actionLogState = s; });
this.rxSubscriptions.push(sub);
this._autoRefreshHandler = () => this.refresh();
document.addEventListener('gitops-auto-refresh', this._autoRefreshHandler);
}
public override disconnectedCallback() {
super.disconnectedCallback();
document.removeEventListener('gitops-auto-refresh', this._autoRefreshHandler);
}
public static styles = [
cssManager.defaultStyles,
viewHostCss,
];
public render(): TemplateResult {
const entityOptions = [
{ option: 'All', key: 'all' },
{ option: 'Connection', key: 'connection' },
{ option: 'Secret', key: 'secret' },
{ option: 'Pipeline', key: 'pipeline' },
];
return html`
<div class="view-title">Action Log</div>
<div class="view-description">Audit trail of all operations performed in the system</div>
<div class="toolbar">
<dees-input-dropdown
.label=${'Entity Type'}
.options=${entityOptions}
.selectedOption=${entityOptions.find((o) => o.key === this.selectedEntityType)}
@selectedOption=${(e: CustomEvent) => {
this.selectedEntityType = e.detail.key;
this.refresh();
}}
></dees-input-dropdown>
<dees-button @click=${() => this.refresh()}>Refresh</dees-button>
</div>
<dees-table
.heading1=${'Action Log'}
.heading2=${`${this.actionLogState.total} entries total`}
.data=${this.actionLogState.entries}
.displayFunction=${(item: any) => ({
Time: new Date(item.timestamp).toLocaleString(),
Action: item.actionType,
Entity: item.entityType,
Name: item.entityName,
Details: item.details,
User: item.username,
})}
.dataActions=${[]}
></dees-table>
`;
}
async firstUpdated() {
await this.refresh();
}
private async refresh() {
const entityType = this.selectedEntityType === 'all'
? undefined
: this.selectedEntityType as any;
await appstate.actionLogStatePart.dispatchAction(appstate.fetchActionLogAction, {
limit: 100,
entityType,
});
}
}