diff --git a/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.css b/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.css index f4b0059b0..cd5227562 100644 --- a/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.css +++ b/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.css @@ -1,3 +1,12 @@ +:host { + display: block; + height: calc(100vh - 44px); + margin-bottom: -60px; + overflow: hidden; + position: relative; + z-index: 1; +} + :host app-alert:not(:empty) { --alert-margin: 0; @@ -5,13 +14,17 @@ margin-bottom: 16px; } -.drawer { +.actions-layout { + display: flex; height: 100%; } -.mat-drawer { - padding-bottom: 16px; +.actions-sidebar { width: clamp(200px, 18%, 320px); + padding-bottom: 16px; + border-right: 1px solid var(--mat-sidenav-container-divider-color); + overflow-y: auto; + flex-shrink: 0; } .drawer-header { @@ -25,16 +38,28 @@ margin: 0; } +.add-automation-button { + width: calc(100% - 24px); + margin: 8px 12px; +} + + .no-actions { display: flex; flex-direction: column; align-items: center; gap: 12px; - color: rgba(0, 0, 0, 0.5); + color: rgba(0, 0, 0, 0.64); padding: 1rem 0; text-align: center; } +@media (prefers-color-scheme: dark) { + .no-actions { + color: rgba(255, 255, 255, 0.64); + } +} + /* .new-action-input { background-color: transparent; margin-top: 12px; @@ -84,15 +109,43 @@ position: absolute; top: 44px; left: 0; - color: #e53935; + color: var(--color-error); font-size: 0.75em; width: 100%; } -.mat-drawer-content { +.actions-main { + flex: 1; + overflow-y: auto; display: flex; flex-direction: column; - padding: 20px 24px; + background-color: var(--mat-sidenav-content-background-color); +} + +.actions-main > app-alert, +.actions-main > app-breadcrumbs, +.actions-main > app-content-loader, +.actions-main > .creation-flow, +.actions-main > .empty-state { + padding-left: clamp(40px, 5vw, 100px); + padding-right: clamp(40px, 5vw, 100px); +} + +.actions-main > app-alert, +.actions-main > app-breadcrumbs, +.actions-main > app-content-loader { + padding-top: 20px; +} + +@media (width <= 600px) { + .actions-main > app-alert, + .actions-main > app-breadcrumbs, + .actions-main > app-content-loader, + .actions-main > .creation-flow, + .actions-main > .empty-state { + padding-left: 16px; + padding-right: 16px; + } } .rule { @@ -183,7 +236,8 @@ .code-snippet-box { position: relative; - border: 1px solid #b0b0b0; + border: 1px solid rgba(0, 0, 0, 0.12); + border-radius: 4px; margin-top: 8px; margin-bottom: 20px; max-width: 1100px; @@ -326,3 +380,446 @@ color: rgba(255, 255, 255, 0.64); } } + +/* ── Creation flow ── */ + +.creation-flow { + flex: 1; + margin-top: 20px; + max-width: 1400px; + width: 100%; + box-sizing: border-box; +} + +.creation-flow__form { + display: flex; + flex-direction: column; + gap: 24px; + min-height: 100%; +} + +.creation-flow__form > .actions { + margin-top: auto; +} + +.creation-flow__form .creation-card { + max-width: 900px; +} + +/* ── Card connector (line + arrow) ── */ + +.creation-card--trigger::after { + content: ''; + position: absolute; + bottom: -3px; + left: 50%; + transform: translateX(-50%); + width: 6px; + height: 6px; + border-radius: 50%; + background-color: var(--color-accentedPalette-300); + z-index: 1; +} + +.card-connector { + display: flex; + flex-direction: column; + align-items: center; + height: 36px; + margin: -18px 0; + max-width: 900px; +} + +.card-connector::before { + content: ''; + flex: 1; + border-left: 1px solid var(--color-accentedPalette-300); +} + +.card-connector::after { + content: ''; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--color-accentedPalette-300); +} + +.creation-flow__name-row { + display: flex; + align-items: center; + gap: 8px; + max-width: 900px; +} + +.creation-flow__name-row > button { + margin-left: auto; + margin-bottom: 22px; +} + +.creation-flow__name { + width: 50%; +} + +.actions { + position: sticky; + bottom: 0; + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + margin-left: calc(-1 * clamp(40px, 5vw, 100px)); + margin-right: calc(-1 * clamp(40px, 5vw, 100px)); + padding: 0 clamp(40px, 5vw, 100px); + background-color: var(--background-color); + box-shadow: var(--shadow); + height: 64px; + flex-shrink: 0; + z-index: 10; +} + +@media (prefers-color-scheme: dark) { + .actions { + --shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.5), 0 2px 2px 0 rgba(0, 0, 0, 0.64), 0 1px 5px 0 rgba(0, 0, 0, 0.85); + --background-color: var(--surface-dark-color); + } +} + +@media (prefers-color-scheme: light) { + .actions { + --shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + --background-color: #fff; + } +} + +@media (width <= 600px) { + .actions { + margin-left: -16px; + margin-right: -16px; + padding: 0 16px; + } +} + +/* ── Step badges ── */ + +.step-label__badge { + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 0.75em; + font-weight: 700; + letter-spacing: 0.05em; + padding: 2px 7px; + border-radius: 4px; + margin-right: 8px; +} + +.step-label__badge--when { + background-color: #3d2248; + color: #d1a3db; +} + +.step-label__badge--then { + background-color: #1a2d4a; + color: #82c4f8; +} + +@media (prefers-color-scheme: light) { + .step-label__badge--when { + background-color: #f3e5f5; + color: #7b1fa2; + } + + .step-label__badge--then { + background-color: #e3f2fd; + color: #1565c0; + } +} + +/* ── Cards ── */ + +.creation-card { + position: relative; + border: 1px solid rgba(0, 0, 0, 0.12); + border-radius: 8px; + padding: 20px 24px; +} + +@media (prefers-color-scheme: dark) { + .creation-card { + border-color: rgba(255, 255, 255, 0.12); + background-color: #1e1e1e; + } +} + +.creation-card--disabled { + opacity: 0.35; + pointer-events: none; +} + +.creation-card--highlight { + animation: card-pulse 1.5s ease; +} + +@keyframes card-pulse { + 0%, 100% { border-color: rgba(0, 0, 0, 0.12); } + 25%, 75% { border-color: var(--color-accentedPalette-500); } +} + +@media (prefers-color-scheme: dark) { + @keyframes card-pulse { + 0%, 100% { border-color: rgba(255, 255, 255, 0.12); } + 25%, 75% { border-color: var(--color-accentedPalette-500); } + } +} + +.creation-card__label { + font-weight: 500; + display: block; + margin-bottom: 16px; +} + +.creation-card__hint { + font-style: italic; + color: rgba(0, 0, 0, 0.45); +} + +@media (prefers-color-scheme: dark) { + .creation-card__hint { + color: rgba(255, 255, 255, 0.45); + } +} + +/* ── Trigger pills ── */ + +.trigger-pills { + display: flex; + align-items: center; + gap: 10px; + flex-wrap: wrap; +} + +.trigger-pills__or { + font-size: 11px; + font-weight: 500; + color: #5a5a70; + text-transform: uppercase; + letter-spacing: 0.03em; +} + +@media (prefers-color-scheme: light) { + .trigger-pills__or { + color: #94a3b8; + } +} + +.trigger-pill { + display: inline-flex; + align-items: center; + gap: 7px; + padding: 7px 14px; + border-radius: 8px; + border: 1px solid #2a2a3a; + background: #0f0f18; + font-size: 12px; + font-weight: 600; + cursor: pointer; + transition: border-color 0.2s, background-color 0.2s, box-shadow 0.2s; +} + +.trigger-pill__checkbox { + position: absolute; + opacity: 0; + pointer-events: none; +} + +.trigger-pill__icon { + font-size: 15px; + width: 15px; + height: 15px; +} + +/* Default colored text & icons per type (muted when not selected) */ +.trigger-pill--add-row { color: color-mix(in srgb, var(--success-color), transparent 40%); } +.trigger-pill--update-row { color: color-mix(in srgb, var(--info-color), transparent 40%); } +.trigger-pill--delete-row { color: color-mix(in srgb, var(--error-color), transparent 40%); } +.trigger-pill--custom { color: #8660b0; } + +/* Full saturation when active */ +.trigger-pill--add-row.trigger-pill--active { color: var(--success-color); } +.trigger-pill--update-row.trigger-pill--active { color: var(--info-color); } +.trigger-pill--delete-row.trigger-pill--active { color: var(--error-color); } +.trigger-pill--custom.trigger-pill--active { color: #c084fc; } + +.trigger-pill:hover { + border-color: #3a3a50; + background: #161620; +} + +/* Active states */ +.trigger-pill--add-row.trigger-pill--active { + border-color: var(--success-color); + background: color-mix(in srgb, var(--success-color), transparent 90%); + box-shadow: 0 0 0 1px color-mix(in srgb, var(--success-color), transparent 75%), 0 0 12px color-mix(in srgb, var(--success-color), transparent 92%); +} + +.trigger-pill--update-row.trigger-pill--active { + border-color: var(--info-color); + background: color-mix(in srgb, var(--info-color), transparent 90%); + box-shadow: 0 0 0 1px color-mix(in srgb, var(--info-color), transparent 75%), 0 0 12px color-mix(in srgb, var(--info-color), transparent 92%); +} + +.trigger-pill--delete-row.trigger-pill--active { + border-color: var(--error-color); + background: color-mix(in srgb, var(--error-color), transparent 90%); + box-shadow: 0 0 0 1px color-mix(in srgb, var(--error-color), transparent 75%), 0 0 12px color-mix(in srgb, var(--error-color), transparent 92%); +} + +.trigger-pill--custom.trigger-pill--active { + border-color: #c084fc; + background: #150820; + box-shadow: 0 0 0 1px rgba(192, 132, 252, 0.25), 0 0 12px rgba(192, 132, 252, 0.08); +} + +/* Light mode overrides */ +@media (prefers-color-scheme: light) { + .trigger-pill { + background: #ffffff; + border-color: #e2e8f0; + } + + .trigger-pill--add-row { color: color-mix(in srgb, var(--success-color), transparent 35%); } + .trigger-pill--update-row { color: color-mix(in srgb, var(--info-color), transparent 35%); } + .trigger-pill--delete-row { color: color-mix(in srgb, var(--error-color), transparent 35%); } + .trigger-pill--custom { color: #9878bf; } + + .trigger-pill--add-row.trigger-pill--active { color: var(--success-color); } + .trigger-pill--update-row.trigger-pill--active { color: var(--info-color); } + .trigger-pill--delete-row.trigger-pill--active { color: var(--error-color); } + .trigger-pill--custom.trigger-pill--active { color: #9333ea; } + + .trigger-pill:hover { + border-color: #cbd5e1; + background: #f8fafc; + } + + .trigger-pill--add-row.trigger-pill--active { + border-color: var(--success-color); + background: color-mix(in srgb, var(--success-color), transparent 92%); + box-shadow: 0 0 0 1px color-mix(in srgb, var(--success-color), transparent 75%); + } + + .trigger-pill--update-row.trigger-pill--active { + border-color: var(--info-color); + background: color-mix(in srgb, var(--info-color), transparent 92%); + box-shadow: 0 0 0 1px color-mix(in srgb, var(--info-color), transparent 75%); + } + + .trigger-pill--delete-row.trigger-pill--active { + border-color: var(--error-color); + background: color-mix(in srgb, var(--error-color), transparent 92%); + box-shadow: 0 0 0 1px color-mix(in srgb, var(--error-color), transparent 75%); + } + + .trigger-pill--custom.trigger-pill--active { + border-color: #9333ea; + background: #faf5ff; + box-shadow: 0 0 0 1px rgba(147, 51, 234, 0.25); + } +} + +/* Custom event inline */ +.custom-event-inline { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 16px; + margin-top: 16px; + padding-top: 16px; + border-top: 1px solid rgba(0, 0, 0, 0.08); +} + +.custom-event-inline app-icon-picker, +.custom-event-inline mat-checkbox { + margin-bottom: 22px; +} + +@media (prefers-color-scheme: dark) { + .custom-event-inline { + border-top-color: rgba(255, 255, 255, 0.08); + } +} + +/* ── Affects row ── */ + +.affects-row { + display: flex; + align-items: center; + gap: 16px; + margin-top: -8px; + width: 100%; +} + +.affects-row__label { + font-weight: 500; + font-size: 0.85em; + color: rgba(0, 0, 0, 0.64); +} + +@media (prefers-color-scheme: dark) { + .affects-row__label { + color: rgba(255, 255, 255, 0.64); + } +} + +/* ── Accented toggle groups (affects + action methods) ── */ + +.affects-row ::ng-deep .mat-button-toggle-checked, +.action-methods ::ng-deep .mat-button-toggle-checked { + background-color: var(--color-accentedPalette-100); + color: var(--color-accentedPalette-100-contrast); +} + +/* ── Action methods ── */ + +.action-methods { + margin-bottom: 16px; +} + +.action-methods ::ng-deep .mat-button-toggle-label-content { + display: flex; + align-items: center; + gap: 4px; +} + +.action-methods mat-icon { + font-size: 18px; + width: 18px; + height: 18px; +} + +/* ── Action fields ── */ + +.action-fields__input { + width: 60%; +} + +.action-fields__hint { + margin-top: -12px; + margin-bottom: 8px; + font-size: 0.85em; + color: rgba(0, 0, 0, 0.5); +} + +@media (prefers-color-scheme: dark) { + .action-fields__hint { + color: rgba(255, 255, 255, 0.5); + } +} + +@media screen and (max-width: 768px) { + .creation-flow__name, + .action-fields__input { + width: 100%; + } +} diff --git a/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.html b/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.html index 54e6ab93f..0334530b5 100644 --- a/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.html +++ b/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.html @@ -1,20 +1,12 @@ - - +
+

Automations

- -
-
+
No added automations
- + - - - {{actionNameError}} - - - + +
- +
-
-
- - Name - - -
- Trigger(s) -
-
-
- or - - Event - - - {{ availableEvent.label }} - - - - -
-
+
+ +
+ + Automation name + + + @if (isCreationMode) { + + } @else { + + }
-
- Custom event + +
+ WHEN Trigger + +
+ + or + + or + + or + +
-
+ @if (selectedRuleCustomEvent) { +
- Name - + Button label + - - Request confirmation +
+ Affects + + Single row + Multiple rows + +
- -
- - Affects - - Single row - - - Multiple rows - - -
+ }
-
-
- Action - - Actions type - - Email notification - Slack notification - URL webhook - - - - Action URL - - - - - Slack URL - - - - - Emails - - {{companyMember.name}} | {{companyMember.email}} - - -
+
+ + +
+ THEN Action + @if (!hasTriggersSelected) { + Add a trigger first + } @else { + + + link URL webhook + + + email Email + + + tag Slack + + + +
+ @if ($any(selectedRule.table_actions[0]).method === 'URL') { + + Webhook URL + + +

Use the code snippets below to verify requests.

+ +
+ + + + + + + +
+ } + + @if ($any(selectedRule.table_actions[0]).method === 'EMAIL') { + + Notification emails + + + {{companyMember.name}} | {{companyMember.email}} + + + + } -
- - - - - - - - + @if ($any(selectedRule.table_actions[0]).method === 'SLACK') { + + Slack webhook URL + + + }
+ }
-
- +
+ + Back +
-
+

Configure custom triggers and actions for database records React to standard operations like create, update, delete, or define your own. @@ -247,5 +271,5 @@

Automations

- - +
+
diff --git a/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.ts b/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.ts index 8c251ee7f..5f4ec10f7 100644 --- a/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.ts +++ b/frontend/src/app/components/dashboard/db-table-view/db-table-actions/db-table-actions.component.ts @@ -1,20 +1,22 @@ import { ClipboardModule } from '@angular/cdk/clipboard'; import { CommonModule } from '@angular/common'; import { HttpErrorResponse } from '@angular/common/http'; -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, ViewChild, ElementRef } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDialog, MatDialogModule } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; +import { MatButtonToggleModule } from '@angular/material/button-toggle'; import { MatListModule } from '@angular/material/list'; +import { MatMenuModule } from '@angular/material/menu'; import { MatRadioModule } from '@angular/material/radio'; import { MatSelectModule } from '@angular/material/select'; -import { MatSidenavModule } from '@angular/material/sidenav'; import { MatTabsModule } from '@angular/material/tabs'; import { MatTooltipModule } from '@angular/material/tooltip'; import { Title } from '@angular/platform-browser'; +import { RouterModule } from '@angular/router'; import { CodeEditorModule } from '@ngstack/code-editor'; import { Angulartics2, Angulartics2OnModule } from 'angulartics2'; import posthog from 'posthog-js'; @@ -43,14 +45,15 @@ import { ActionDeleteDialogComponent } from './action-delete-dialog/action-delet ClipboardModule, FormsModule, MatButtonModule, + MatButtonToggleModule, MatCheckboxModule, MatDialogModule, MatIconModule, MatInputModule, MatSelectModule, MatTooltipModule, - MatSidenavModule, MatListModule, + MatMenuModule, MatRadioModule, MatTabsModule, CodeEditorModule, @@ -59,6 +62,7 @@ import { ActionDeleteDialogComponent } from './action-delete-dialog/action-delet ContentLoaderComponent, IconPickerComponent, Angulartics2OnModule, + RouterModule, ], }) export class DbTableActionsComponent implements OnInit { @@ -73,6 +77,7 @@ export class DbTableActionsComponent implements OnInit { }; public rules: Rule[]; public submitting: boolean; + public isSaved = false; public selectedRule: Rule = null; public selectedRuleCustomEvent: CustomEvent = null; public customAction: CustomAction = null; @@ -96,6 +101,9 @@ export class DbTableActionsComponent implements OnInit { 'schedule', ]; + @ViewChild('newActionInput') newActionInput: ElementRef; + @ViewChild('ruleNameInput') ruleNameInput: ElementRef; + public signingKey: string; public codeViewerOptions = { @@ -111,8 +119,16 @@ export class DbTableActionsComponent implements OnInit { { value: EventType.DeleteRow, label: 'Delete row' }, { value: EventType.Custom, label: 'Custom' }, ]; + + public triggerMeta: Record = { + [EventType.AddRow]: { icon: 'add_circle_outline', desc: 'Fires when a new row is inserted', color: '#4caf50' }, + [EventType.UpdateRow]: { icon: 'edit', desc: 'Fires when an existing row is modified', color: '#2196f3' }, + [EventType.DeleteRow]: { icon: 'delete_outline', desc: 'Fires when a row is removed', color: '#e53935' }, + [EventType.Custom]: { icon: 'tune', desc: 'Manual trigger with custom button', color: '#9c27b0' }, + }; public selectedEvents: string[] = []; public codeEditorTheme: 'vs' | 'vs-dark' = 'vs-dark'; + public isCreationMode = false; constructor( private _connections: ConnectionsService, @@ -175,6 +191,24 @@ export class DbTableActionsComponent implements OnInit { }); } + get hasTriggersSelected(): boolean { + return this.selectedRule?.events?.some((e) => e.event !== null) ?? false; + } + + get saveDisabledReason(): string { + if (!this.selectedRuleTitle) return 'Enter automation name'; + if (!this.hasTriggersSelected) return 'Select at least one trigger'; + return ''; + } + + get activeTriggers() { + return this.selectedRule?.events?.filter((e) => e.event !== null) ?? []; + } + + get unusedTriggerOptions() { + return this.availableEvents.filter((e) => !this.selectedEvents.includes(e.value)); + } + get currentConnection() { // this.codeSnippets = codeSnippets(this._connections.currentConnection.signing_key); return this._connections.currentConnection; @@ -208,6 +242,7 @@ export class DbTableActionsComponent implements OnInit { setSelectedRule(rule: Rule) { this.selectedRule = rule; this.selectedRuleTitle = rule.title; + this.isCreationMode = !rule.id; if (this.selectedRule.events[this.selectedRule.events.length - 1].event !== null) this.selectedRule.events.push({ event: null }); this.selectedEvents = this.selectedRule.events.map((event) => event.event); @@ -224,6 +259,11 @@ export class DbTableActionsComponent implements OnInit { this.selectedRuleCustomEvent.icon = icon; } + setCustomEventType(type: string) { + this.selectedRuleCustomEvent.type = type as CustomActionType; + this.isSaved = false; + } + switchRulesView(rule: Rule) { this.setSelectedRule(rule); } @@ -247,7 +287,9 @@ export class DbTableActionsComponent implements OnInit { ], }; + this.rules.push(this.newRule); this.setSelectedRule(this.newRule); + this.isCreationMode = true; } addNewAction() { @@ -269,6 +311,7 @@ export class DbTableActionsComponent implements OnInit { this.selectedRuleTitle = this.selectedRule.title; this.rules.push(this.selectedRule); this.newRule = null; + this.isCreationMode = false; } else { this.actionNameError = 'You already have an action with this name.'; } @@ -276,7 +319,11 @@ export class DbTableActionsComponent implements OnInit { } undoRule() { + if (this.newRule) { + this.rules = this.rules.filter((r) => r !== this.newRule); + } this.newRule = null; + this.isCreationMode = false; if (this.rules.length) this.setSelectedRule(this.rules[0]); } @@ -298,6 +345,38 @@ export class DbTableActionsComponent implements OnInit { } handleRuleSubmitting() { + if (!this.selectedRuleTitle) { + this.ruleNameInput?.nativeElement?.focus(); + return; + } + + if (!this.hasTriggersSelected) { + const triggerCard = document.querySelector('.creation-card') as HTMLElement; + if (triggerCard) { + triggerCard.scrollIntoView({ behavior: 'smooth', block: 'center' }); + triggerCard.classList.add('creation-card--highlight'); + setTimeout(() => triggerCard.classList.remove('creation-card--highlight'), 1500); + } + return; + } + + const action = this.selectedRule.table_actions[0]; + if (action) { + const method = (action.method as string).toUpperCase(); + if (method === 'URL' && !action.url) { + (document.querySelector('input[name="action-url"]') as HTMLInputElement)?.focus(); + return; + } + if (method === 'EMAIL' && (!action.emails || action.emails.length === 0)) { + (document.querySelector('mat-select[name="notification-emails"]') as HTMLElement)?.click(); + return; + } + if (method === 'SLACK' && !(action as any).slack_url) { + (document.querySelector('input[name="action-slack-url"]') as HTMLInputElement)?.focus(); + return; + } + } + if (this.selectedRule.events.filter((event) => event.event !== null).length > 0) { if (this.selectedRule.id) { this.updateRule(); @@ -309,6 +388,8 @@ export class DbTableActionsComponent implements OnInit { addRule() { this.submitting = true; + if (this.selectedRuleTitle) this.selectedRule.title = this.selectedRuleTitle; + this.newRule = null; this.selectedRule.events = this.selectedRule.events.filter((event) => event.event !== null); this.selectedRule.events = this.selectedRule.events.map((event) => { if (event.event === 'CUSTOM') { @@ -329,6 +410,7 @@ export class DbTableActionsComponent implements OnInit { this.rules = undatedRulesData.action_rules; const currentRule = this.rules.find((rule: Rule) => rule.id === res.id); this.setSelectedRule(currentRule); + this.isSaved = true; } catch (error) { if (error instanceof HttpErrorResponse) { console.log(error.error.message); @@ -361,6 +443,7 @@ export class DbTableActionsComponent implements OnInit { this.rules = undatedRulesData.action_rules; const currentRule = this.rules.find((rule: Rule) => rule.id === res.id); this.setSelectedRule(currentRule); + this.isSaved = true; } catch (error) { if (error instanceof HttpErrorResponse) { console.log(error.error.message); @@ -412,6 +495,44 @@ export class DbTableActionsComponent implements OnInit { } } + toggleTriggerTile(eventType: EventType) { + this.isSaved = false; + const idx = this.selectedEvents.indexOf(eventType); + if (idx > -1) { + // Remove trigger + this.selectedRule.events = this.selectedRule.events.filter((e) => e.event !== eventType); + this.selectedEvents = this.selectedEvents.filter((e) => e !== eventType); + if (eventType === EventType.Custom) { + this.selectedRuleCustomEvent = null; + } + } else { + // Add trigger + this.selectedRule.events = this.selectedRule.events.filter((e) => e.event !== null); + this.selectedRule.events.push({ event: eventType }); + this.selectedEvents.push(eventType); + if (eventType === EventType.Custom) { + this.selectedRuleCustomEvent = { + event: EventType.Custom, + title: '', + type: CustomActionType.Single, + icon: '', + require_confirmation: false, + }; + } + } + // Keep trailing null for the old form + if (this.selectedRule.events[this.selectedRule.events.length - 1]?.event !== null) { + this.selectedRule.events.push({ event: null }); + } + } + + selectActionMethod(method: string) { + this.isSaved = false; + if (this.selectedRule.table_actions.length) { + this.selectedRule.table_actions[0].method = method as CustomActionMethod; + } + } + removeEvent(event: any) { this.selectedRule.events = this.selectedRule.events.filter((e) => e.event !== event); this.selectedEvents = this.selectedRule.events.map((event) => event.event); diff --git a/frontend/src/app/components/ui-components/alert/alert.component.css b/frontend/src/app/components/ui-components/alert/alert.component.css index d9262e252..7fb7d8b48 100644 --- a/frontend/src/app/components/ui-components/alert/alert.component.css +++ b/frontend/src/app/components/ui-components/alert/alert.component.css @@ -21,10 +21,6 @@ @media (prefers-color-scheme: dark) { .alert { - border-top: 1px solid var(--alert-dark-theme-color); - border-right: 1px solid var(--alert-dark-theme-color); - border-bottom: 1px solid var(--alert-dark-theme-color); - border-left: 12px solid var(--alert-dark-theme-color); backdrop-filter: blur(2px); } } @@ -37,27 +33,23 @@ } .alert_error { - --alert-theme-color: #b71c1c; - --alert-dark-theme-color: #e53935; - --bg-color: color-mix(in hsl, #b71c1c, transparent 95%); + --alert-theme-color: var(--error-color); + --bg-color: var(--error-background-color); } .alert_warning { - --alert-theme-color: #f79008; - --alert-dark-theme-color: #f79008; - --bg-color: color-mix(in hsl, #f79008, transparent 95%); + --alert-theme-color: var(--warning-color); + --bg-color: var(--warning-background-color); } .alert_info { - --alert-theme-color: #296ee9; - --alert-dark-theme-color: #296ee9; - --bg-color: color-mix(in hsl, #296ee9, transparent 95%); + --alert-theme-color: var(--info-color); + --bg-color: var(--info-background-color); } .alert_success { - --alert-theme-color: #1b5e20; - --alert-dark-theme-color: #4caf50; - --bg-color: color-mix(in hsl, #1b5e20, transparent 95%); + --alert-theme-color: var(--success-color); + --bg-color: var(--success-background-color); } .alert__icon { @@ -73,11 +65,6 @@ width: 36px; } -@media (prefers-color-scheme: dark) { - .alert__icon { - color: var(--alert-dark-theme-color); - } -} .alert__message { flex: 1; diff --git a/frontend/src/app/components/ui-components/banner/banner.component.css b/frontend/src/app/components/ui-components/banner/banner.component.css index bc86bce07..d84ff3d65 100644 --- a/frontend/src/app/components/ui-components/banner/banner.component.css +++ b/frontend/src/app/components/ui-components/banner/banner.component.css @@ -29,27 +29,23 @@ } .banner_error { - --alert-theme-color: #b71c1c; - --alert-dark-theme-color: #e53935; - --bg-color: color-mix(in hsl, #b71c1c, transparent 95%); + --alert-theme-color: var(--error-color); + --bg-color: var(--error-background-color); } .banner_warning { - --alert-theme-color: #f79008; - --alert-dark-theme-color: #f79008; - --bg-color: color-mix(in hsl, #f79008, transparent 95%); + --alert-theme-color: var(--warning-color); + --bg-color: var(--warning-background-color); } .banner_info { - --alert-theme-color: #296ee9; - --alert-dark-theme-color: #296ee9; - --bg-color: color-mix(in hsl, #296ee9, transparent 95%); + --alert-theme-color: var(--info-color); + --bg-color: var(--info-background-color); } .banner_success { - --alert-theme-color: #1b5e20; - --alert-dark-theme-color: #4caf50; - --bg-color: color-mix(in hsl, #1b5e20, transparent 95%); + --alert-theme-color: var(--success-color); + --bg-color: var(--success-background-color); } .banner-box { diff --git a/frontend/src/app/components/ui-components/icon-picker/icon-picker.component.html b/frontend/src/app/components/ui-components/icon-picker/icon-picker.component.html index 8061e54eb..08fbe63de 100644 --- a/frontend/src/app/components/ui-components/icon-picker/icon-picker.component.html +++ b/frontend/src/app/components/ui-components/icon-picker/icon-picker.component.html @@ -1,19 +1,11 @@ - - - -
diff --git a/frontend/src/custom-theme.scss b/frontend/src/custom-theme.scss index 4687ad29f..abb5bc346 100644 --- a/frontend/src/custom-theme.scss +++ b/frontend/src/custom-theme.scss @@ -27,6 +27,16 @@ html { --surface-dark-color: #202020 !important; --mat-toolbar-container-background-color: var(--surface-dark-color) !important; + + --error-color: var(--color-warnPalette-500); + --warning-color: #f79008; + --info-color: #296ee9; + --success-color: #1b5e20; + + --error-background-color: color-mix(in hsl, var(--error-color), transparent 95%); + --warning-background-color: color-mix(in hsl, var(--warning-color), transparent 95%); + --info-background-color: color-mix(in hsl, var(--info-color), transparent 95%); + --success-background-color: color-mix(in hsl, var(--success-color), transparent 95%); } @media (prefers-color-scheme: dark) { @@ -35,6 +45,11 @@ html { --mat-table-background-color: var(--surface-dark-color) !important; --mat-paginator-container-background-color: var(--surface-dark-color) !important; --mat-snack-bar-button-color: var(--color-accentedPalette-500) !important; + + --error-color: var(--color-warnDarkPalette-500); + --warning-color: #f79008; + --info-color: #296ee9; + --success-color: #4caf50; } .mat-datepicker-content {