mirror of
https://github.com/Dvorinka/Primora.git
synced 2026-10-28 07:41:23 +00:00
feat: integration/webhook counts in project overview
ProjectOverview gains integration_count + webhook_count (enabled only); dashboard Resources list gets an Integrations row linking to the new view. Covers the "dashboard widget if cheap" Phase 4 item. Authored By: TDvorak <[email protected]>
This commit is contained in:
1 parent
e25eb92339
commit
23186e38b8
8 files changed
+71
-2
No files matched your search
@@ -136,7 +136,18 @@ SELECT
|
|||||||
SELECT MAX(al.created_at)::TIMESTAMPTZ
|
SELECT MAX(al.created_at)::TIMESTAMPTZ
|
||||||
FROM core.audit_logs al
|
FROM core.audit_logs al
|
||||||
WHERE al.project_id = p.id
|
WHERE al.project_id = p.id
|
||||||
) AS last_audit_at
|
) AS last_audit_at,
|
||||||
|
(
|
||||||
|
SELECT COUNT(*)::BIGINT
|
||||||
|
FROM core.integrations i
|
||||||
|
WHERE i.project_id = p.id
|
||||||
|
) AS integration_count,
|
||||||
|
(
|
||||||
|
SELECT COUNT(*)::BIGINT
|
||||||
|
FROM core.webhooks w
|
||||||
|
WHERE w.project_id = p.id
|
||||||
|
AND w.enabled
|
||||||
|
) AS webhook_count
|
||||||
FROM core.projects p
|
FROM core.projects p
|
||||||
WHERE p.id = $1;
|
WHERE p.id = $1;
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,18 @@ SELECT
|
|||||||
SELECT MAX(al.created_at)::TIMESTAMPTZ
|
SELECT MAX(al.created_at)::TIMESTAMPTZ
|
||||||
FROM core.audit_logs al
|
FROM core.audit_logs al
|
||||||
WHERE al.project_id = p.id
|
WHERE al.project_id = p.id
|
||||||
) AS last_audit_at
|
) AS last_audit_at,
|
||||||
|
(
|
||||||
|
SELECT COUNT(*)::BIGINT
|
||||||
|
FROM core.integrations i
|
||||||
|
WHERE i.project_id = p.id
|
||||||
|
) AS integration_count,
|
||||||
|
(
|
||||||
|
SELECT COUNT(*)::BIGINT
|
||||||
|
FROM core.webhooks w
|
||||||
|
WHERE w.project_id = p.id
|
||||||
|
AND w.enabled
|
||||||
|
) AS webhook_count
|
||||||
FROM core.projects p
|
FROM core.projects p
|
||||||
WHERE p.id = $1
|
WHERE p.id = $1
|
||||||
`
|
`
|
||||||
@@ -235,6 +246,8 @@ type GetProjectOverviewRow struct {
|
|||||||
PendingInvitationCount int64 `json:"pending_invitation_count"`
|
PendingInvitationCount int64 `json:"pending_invitation_count"`
|
||||||
AuditEvents24h int64 `json:"audit_events_24h"`
|
AuditEvents24h int64 `json:"audit_events_24h"`
|
||||||
LastAuditAt pgtype.Timestamptz `json:"last_audit_at"`
|
LastAuditAt pgtype.Timestamptz `json:"last_audit_at"`
|
||||||
|
IntegrationCount int64 `json:"integration_count"`
|
||||||
|
WebhookCount int64 `json:"webhook_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetProjectOverview(ctx context.Context, id uuid.UUID) (GetProjectOverviewRow, error) {
|
func (q *Queries) GetProjectOverview(ctx context.Context, id uuid.UUID) (GetProjectOverviewRow, error) {
|
||||||
@@ -253,6 +266,8 @@ func (q *Queries) GetProjectOverview(ctx context.Context, id uuid.UUID) (GetProj
|
|||||||
&i.PendingInvitationCount,
|
&i.PendingInvitationCount,
|
||||||
&i.AuditEvents24h,
|
&i.AuditEvents24h,
|
||||||
&i.LastAuditAt,
|
&i.LastAuditAt,
|
||||||
|
&i.IntegrationCount,
|
||||||
|
&i.WebhookCount,
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,6 +179,8 @@ type ProjectOverview struct {
|
|||||||
PendingInvitationCount int64 `json:"pending_invitation_count"`
|
PendingInvitationCount int64 `json:"pending_invitation_count"`
|
||||||
AuditEvents24h int64 `json:"audit_events_24h"`
|
AuditEvents24h int64 `json:"audit_events_24h"`
|
||||||
LastAuditAt *time.Time `json:"last_audit_at,omitempty"`
|
LastAuditAt *time.Time `json:"last_audit_at,omitempty"`
|
||||||
|
IntegrationCount int64 `json:"integration_count"`
|
||||||
|
WebhookCount int64 `json:"webhook_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OrganizationMemberSummary struct {
|
type OrganizationMemberSummary struct {
|
||||||
@@ -586,6 +588,8 @@ func (s *PlatformService) GetProjectOverview(ctx context.Context, actor *models.
|
|||||||
PendingInvitationCount: row.PendingInvitationCount,
|
PendingInvitationCount: row.PendingInvitationCount,
|
||||||
AuditEvents24h: row.AuditEvents24h,
|
AuditEvents24h: row.AuditEvents24h,
|
||||||
LastAuditAt: projectOverviewLastAuditAt(row.LastAuditAt),
|
LastAuditAt: projectOverviewLastAuditAt(row.LastAuditAt),
|
||||||
|
IntegrationCount: row.IntegrationCount,
|
||||||
|
WebhookCount: row.WebhookCount,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1979,6 +1979,14 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
nullable: true
|
nullable: true
|
||||||
|
integration_count:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: Connectors attached to the project.
|
||||||
|
webhook_count:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: Enabled outbound webhooks.
|
||||||
required:
|
required:
|
||||||
- project_id
|
- project_id
|
||||||
- organization_id
|
- organization_id
|
||||||
@@ -1991,6 +1999,8 @@ components:
|
|||||||
- object_bytes_total
|
- object_bytes_total
|
||||||
- pending_invitation_count
|
- pending_invitation_count
|
||||||
- audit_events_24h
|
- audit_events_24h
|
||||||
|
- integration_count
|
||||||
|
- webhook_count
|
||||||
ProjectMember:
|
ProjectMember:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
IconMembers,
|
IconMembers,
|
||||||
IconAudit,
|
IconAudit,
|
||||||
IconCollections,
|
IconCollections,
|
||||||
|
IconIntegrations,
|
||||||
IconChevronRight,
|
IconChevronRight,
|
||||||
} from "./Icons";
|
} from "./Icons";
|
||||||
|
|
||||||
@@ -110,6 +111,12 @@ export function ProjectDashboard(props: ProjectDashboardProps) {
|
|||||||
icon: IconMembers,
|
icon: IconMembers,
|
||||||
view: "members",
|
view: "members",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Integrations",
|
||||||
|
sub: `${overview()?.integration_count ?? 0} connectors · ${overview()?.webhook_count ?? 0} webhooks`,
|
||||||
|
icon: IconIntegrations,
|
||||||
|
view: "integrations",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const audit = () => (props.recentAudit ?? []).slice(0, 6);
|
const audit = () => (props.recentAudit ?? []).slice(0, 6);
|
||||||
|
|||||||
@@ -511,6 +511,8 @@ class DemoService {
|
|||||||
pending_invitation_count: invitations.filter((i) => i.status === OrganizationInvitation.status.PENDING).length,
|
pending_invitation_count: invitations.filter((i) => i.status === OrganizationInvitation.status.PENDING).length,
|
||||||
audit_events_24h: auditLogs.length,
|
audit_events_24h: auditLogs.length,
|
||||||
last_audit_at: auditLogs[0]?.created_at ?? null,
|
last_audit_at: auditLogs[0]?.created_at ?? null,
|
||||||
|
integration_count: demoIntegrations.length,
|
||||||
|
webhook_count: demoWebhooks.filter((w) => w.enabled).length,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,5 +15,13 @@ export type ProjectOverview = {
|
|||||||
pending_invitation_count: number;
|
pending_invitation_count: number;
|
||||||
audit_events_24h: number;
|
audit_events_24h: number;
|
||||||
last_audit_at?: string | null;
|
last_audit_at?: string | null;
|
||||||
|
/**
|
||||||
|
* Connectors attached to the project.
|
||||||
|
*/
|
||||||
|
integration_count: number;
|
||||||
|
/**
|
||||||
|
* Enabled outbound webhooks.
|
||||||
|
*/
|
||||||
|
webhook_count: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -62,5 +62,17 @@ export const $ProjectOverview = {
|
|||||||
isNullable: true,
|
isNullable: true,
|
||||||
format: 'date-time',
|
format: 'date-time',
|
||||||
},
|
},
|
||||||
|
integration_count: {
|
||||||
|
type: 'number',
|
||||||
|
description: `Connectors attached to the project.`,
|
||||||
|
isRequired: true,
|
||||||
|
format: 'int64',
|
||||||
|
},
|
||||||
|
webhook_count: {
|
||||||
|
type: 'number',
|
||||||
|
description: `Enabled outbound webhooks.`,
|
||||||
|
isRequired: true,
|
||||||
|
format: 'int64',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
Reference in new issue
Block a user