8000 feat: default email alert group by grutt · Pull Request #547 · hatchet-dev/hatchet · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: default email alert group #547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions api-contracts/openapi/components/schemas/tenant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ Tenant:
analyticsOptOut:
type: boolean
description: Whether the tenant has opted out of analytics.
alertMemberEmails:
type: boolean
description: Whether to alert tenant members.
required:
- metadata
- name
Expand All @@ -21,6 +24,15 @@ TenantAlertingSettings:
properties:
metadata:
$ref: "./metadata.yaml#/APIResourceMeta"
alertMemberEmails:
type: boolean
description: Whether to alert tenant members.
enableWorkflowRunFailureAlerts:
type: boolean
description: Whether to send alerts when workflow runs fail.
enableExpiringTokenAlerts:
type: boolean
description: Whether to enable alerts when tokens are approaching expiration.
maxAlertingFrequency:
type: string
description: The max frequency at which to alert.
Expand Down Expand Up @@ -58,6 +70,15 @@ UpdateTenantRequest:
analyticsOptOut:
type: boolean
description: Whether the tenant has opted out of analytics.
alertMemberEmails:
type: boolean
description: Whether to alert tenant members.
enableWorkflowRunFailureAlerts:
type: boolean
description: Whether to send alerts when workflow runs fail.
enableExpiringTokenAlerts:
type: boolean
description: Whether to enable alerts when tokens are approaching expiration.
maxAlertingFrequency:
type: string
description: The max frequency at which to alert.
Expand Down
13 changes: 11 additions & 2 deletions api/v1/server/handlers/tenants/update.go
ED4F
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ func (t *TenantService) TenantUpdate(ctx echo.Context, request gen.TenantUpdateR
updateOpts.AnalyticsOptOut = request.Body.AnalyticsOptOut
}

if request.Body.AlertMemberEmails != nil {
updateOpts.AlertMemberEmails = request.Body.AlertMemberEmails
}

if request.Body.Name != nil {
updateOpts.Name = request.Body.Name
}
Expand All @@ -37,11 +41,16 @@ func (t *TenantService) TenantUpdate(ctx echo.Context, request gen.TenantUpdateR
return nil, err
}

if request.Body.MaxAlertingFrequency != nil {
if request.Body.MaxAlertingFrequency != nil ||
request.Body.EnableExpiringTokenAlerts != nil ||
request.Body.EnableWorkflowRunFailureAlerts != nil {

_, err = t.config.APIRepository.TenantAlertingSettings().UpsertTenantAlertingSettings(
tenant.ID,
&repository.UpsertTenantAlertingSettingsOpts{
MaxFrequency: request.Body.MaxAlertingFrequency,
MaxFrequency: request.Body.MaxAlertingFrequency,
EnableExpiringTokenAlerts: request.Body.EnableExpiringTokenAlerts,
EnableWorkflowRunFailureAlerts: request.Body.EnableWorkflowRunFailureAlerts,
},
)

Expand Down
328 changes: 175 additions & 153 deletions api/v1/server/oas/gen/openapi.gen.go

Large diffs are not rendered by default.

15 changes: 9 additions & 6 deletions api/v1/server/oas/transformers/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@ import (

func ToTenant(tenant *db.TenantModel) *gen.Tenant {
return &gen.Tenant{
Metadata: *toAPIMetadata(tenant.ID, tenant.CreatedAt, tenant.UpdatedAt),
Name: tenant.Name,
Slug: tenant.Slug,
AnalyticsOptOut: &tenant.AnalyticsOptOut,
Metadata: *toAPIMetadata(tenant.ID, tenant.CreatedAt, tenant.UpdatedAt),
Name: tenant.Name,
Slug: tenant.Slug,
AnalyticsOptOut: &tenant.AnalyticsOptOut,
AlertMemberEmails: &tenant.AlertMemberEmails,
}
}

func ToTenantAlertingSettings(alerting *db.TenantAlertingSettingsModel) *gen.TenantAlertingSettings {
res := &gen.TenantAlertingSettings{
Metadata: *toAPIMetadata(alerting.ID, alerting.CreatedAt, alerting.UpdatedAt),
MaxAlertingFrequency: alerting.MaxFrequency,
Metadata: *toAPIMetadata(alerting.ID, alerting.CreatedAt, alerting.UpdatedAt),
MaxAlertingFrequency: alerting.MaxFrequency,
EnableExpiringTokenAlerts: &alerting.EnableExpiringTokenAlerts,
EnableWorkflowRunFailureAlerts: &alerting.EnableWorkflowRunFailureAlerts,
}

if lastAlertedAt, ok := alerting.LastAlertedAt(); ok {
Expand Down
14 changes: 14 additions & 0 deletions frontend/app/src/lib/api/generated/data-contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ export interface Tenant {
slug: string;
/** Whether the tenant has opted out of analytics. */
analyticsOptOut?: boolean;
/** Whether to alert tenant members. */
alertMemberEmails?: boolean;
}

export interface TenantMember {
Expand Down Expand Up @@ -231,6 +233,12 @@ export interface UpdateTenantInviteRequest {

export interface TenantAlertingSettings {
metadata: APIResourceMeta;
/** Whether to alert tenant members. */
alertMemberEmails?: boolean;
/** Whether to send alerts when workflow runs fail. */
enableWorkflowRunFailureAlerts?: boolean;
/** Whether to enable alerts when tokens are approaching expiration. */
enableExpiringTokenAlerts?: boolean;
/** The max frequency at which to alert. */
maxAlertingFrequency: string;
/**
Expand Down Expand Up @@ -318,6 +326,12 @@ export interface UpdateTenantRequest {
name?: string;
/** Whether the tenant has opted out of analytics. */
analyticsOptOut?: boolean;
/** Whether to alert tenant members. */
alertMemberEmails?: boolean;
/** Whether to send alerts when workflow runs fail. */
enableWorkflowRunFailureAlerts?: boolean;
/** Whether to enable alerts when tokens are approaching expiration. */
enableExpiringTokenAlerts?: boolean;
/** The max frequency at which to alert. */
maxAlertingFrequency?: string;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ import { Badge } from '@/components/ui/badge';
import RelativeDate from '@/components/molecules/relative-date';

export const columns = ({
alertTenantEmailsSet,
onDeleteClick,
onToggleMembersClick,
}: {
alertTenantEmailsSet: boolean;
onDeleteClick: (row: TenantAlertEmailGroup) => void;
onToggleMembersClick: (val: boolean) => void;
}): ColumnDef<TenantAlertEmailGroup>[] => {
return [
{
Expand All @@ -18,6 +22,11 @@ export const columns = ({
),
cell: ({ row }) => (
<div>
{row.original.metadata.id == 'default' && (
<Badge className="mr-2" variant="secondary">
All Tenant Members
</Badge>
)}
{row.original.emails.map((email, index) => (
<Badge key={index} className="mr-2" variant="outline">
{email}
Expand All @@ -35,22 +44,43 @@ export const columns = ({
),
cell: ({ row }) => (
<div>
<RelativeDate date={row.original.metadata.createdAt} />
{row.original.metadata.id != 'default' && (
<RelativeDate date={row.original.metadata.createdAt} />
)}
</div>
),
},
{
id: 'enabled',
cell: ({ row }) => (
<div className="flex items-center space-x-2 justify-end">
{row.original.metadata.id != 'default' || alertTenantEmailsSet ? (
<Badge variant="successful">Enabled</Badge>
) : (
<Badge variant="destructive">Disabled</Badge>
)}
</div>
),
},
{
id: 'actions',
cell: ({ row }) => (
<DataTableRowActions
row={row}
actions={[
{
label: 'Delete',
onClick: () => onDeleteClick(row.original),
},
]}
/>
<div className="flex items-center space-x-2 justify-end mr-4">
<DataTableRowActions
row={row}
actions={[
row.original.metadata.id != 'default'
? {
label: 'Delete',
onClick: () => onDeleteClick(row.original),
}
: {
label: alertTenantEmailsSet ? 'Disable' : 'Enable',
onClick: () => onToggleMembersClick(!alertTenantEmailsSet),
},
]}
/>
</div>
),
},
];
Expand Down
10000
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ import {
SelectValue,
} from '@/components/ui/select';
import { TenantAlertingSettings } from '@/lib/api';
import { useState } from 'react';
import { Switch } from '@/components/ui/switch';

const schema = z.object({
maxAlertingFrequency: z.string(),
enableWorkflowRunFailureAlerts: z.boolean().optional(),
enableExpiringTokenAlerts: z.boolean().optional(),
});

interface UpdateTenantAlertingSettingsProps {
Expand All @@ -30,6 +34,13 @@ export function UpdateTenantAlertingSettings({
className,
...props
}: UpdateTenantAlertingSettingsProps) {
const [enabledWorkflowAlerting, setEnabledWorkflowAlerting] = useState(
props.alertingSettings.enableWorkflowRunFailureAlerts,
);

const [enabledExpiringTokenAlerting, setEnabledExpiringTokenAlerting] =
useState(props.alertingSettings.enableExpiringTokenAlerts);

const {
handleSubmit,
control,
Expand All @@ -45,40 +56,74 @@ export function UpdateTenantAlertingSettings({
errors.maxAlertingFrequency?.message?.toString() || props.fieldErrors?.role;

return (
<div className={cn('grid gap-6', className)}>
<div>
<form
=> {
props.onSubmit(d);
props.onSubmit({
...d,
enableWorkflowRunFailureAlerts: enabledWorkflowAlerting,
enableExpiringTokenAlerts: enabledExpiringTokenAlerting,
});
})}
className={cn('grid gap-6', className)}
>
<div className="flex items-center space-x-2">
<Switch
id="eta"
checked={enabledExpiringTokenAlerting}
=> {
setEnabledExpiringTokenAlerting((checkedState) => !checkedState);
}}
/>
<Label htmlFor="eta" className="text-sm">
Enable Expiring Token Alerts
</Label>
</div>
<div className="flex items-center space-x-2">
<Switch
id="awrf"
checked={enabledWorkflowAlerting}
=> {
setEnabledWorkflowAlerting((checkedState) => !checkedState);
}}
/>
<Label htmlFor="awrf" className="text-sm">
Enable Workflow Run Failure Alerts
</Label>
</div>

<div className="grid gap-4">
<div className="grid gap-2">
<Label htmlFor="maxAlertingFrequency">Max Alerting Frequency</Label>
<Controller
control={control}
name="maxAlertingFrequency"
render={({ field }) => {
return (
<Select {...field}>
<SelectTrigger className="w-[180px]">
<SelectValue
id="maxAlertingFrequency"
placeholder="Frequency..."
/>
</SelectTrigger>
<SelectContent>
<SelectItem value="5m">5 minutes</SelectItem>
<SelectItem value="1h">1 hour</SelectItem>
<SelectItem value="24h">24 hours</SelectItem>
</SelectContent>
</Select>
);
}}
/>
{freqError && (
<div className="text-sm text-red-500">{freqError}</div>
)}
</div>
{enabledWorkflowAlerting && (
<div className="grid gap-2">
<Label htmlFor="maxAlertingFrequency">
Max Workflow Run Failure Alerting Frequency
</Label>
<Controller
control={control}
name="maxAlertingFrequency"
render={({ field }) => {
return (
<Select {...field}>
<SelectTrigger className="w-[180px]">
<SelectValue
id="maxAlertingFrequency"
placeholder="Frequency..."
/>
</SelectTrigger>
<SelectContent>
<SelectItem value="5m">5 minutes</SelectItem>
<SelectItem value="1h">1 hour</SelectItem>
<SelectItem value="24h">24 hours</SelectItem>
</SelectContent>
</Select>
);
}}
/>
{freqError && (
<div className="text-sm text-red-500">{freqError}</div>
)}
</div>
)}
<Button disabled={props.isLoading}>
{props.isLoading && <Spinner />}
Update
Expand Down
Loading
Loading
0