Add event status trigger, improve test coverage, and UI enhancements
- Add event-status-changed trigger for SmoothSchedule Activepieces piece - Add comprehensive test coverage for payments, tickets, messaging, mobile - Add test coverage for core services, signals, consumers, and views - Improve Activepieces UI: templates, billing hooks, project hooks - Update marketing automation showcase and workflow visual components - Add public API endpoints for availability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,148 @@
|
||||
import { createTrigger, TriggerStrategy, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { smoothScheduleAuth, SmoothScheduleAuth } from '../../index';
|
||||
import { makeRequest } from '../common';
|
||||
|
||||
const TRIGGER_KEY = 'last_status_change_at';
|
||||
|
||||
// Event status options from SmoothSchedule backend
|
||||
const EVENT_STATUSES = [
|
||||
{ label: 'Any Status', value: '' },
|
||||
{ label: 'Scheduled', value: 'SCHEDULED' },
|
||||
{ label: 'En Route', value: 'EN_ROUTE' },
|
||||
{ label: 'In Progress', value: 'IN_PROGRESS' },
|
||||
{ label: 'Canceled', value: 'CANCELED' },
|
||||
{ label: 'Completed', value: 'COMPLETED' },
|
||||
{ label: 'Awaiting Payment', value: 'AWAITING_PAYMENT' },
|
||||
{ label: 'Paid', value: 'PAID' },
|
||||
{ label: 'No Show', value: 'NOSHOW' },
|
||||
];
|
||||
|
||||
export const eventStatusChangedTrigger = createTrigger({
|
||||
auth: smoothScheduleAuth,
|
||||
name: 'event_status_changed',
|
||||
displayName: 'Event Status Changed',
|
||||
description: 'Triggers when an event status changes (e.g., Scheduled → In Progress).',
|
||||
props: {
|
||||
oldStatus: Property.StaticDropdown({
|
||||
displayName: 'Previous Status (From)',
|
||||
description: 'Only trigger when changing from this status (optional)',
|
||||
required: false,
|
||||
options: {
|
||||
options: EVENT_STATUSES,
|
||||
},
|
||||
}),
|
||||
newStatus: Property.StaticDropdown({
|
||||
displayName: 'New Status (To)',
|
||||
description: 'Only trigger when changing to this status (optional)',
|
||||
required: false,
|
||||
options: {
|
||||
options: EVENT_STATUSES,
|
||||
},
|
||||
}),
|
||||
},
|
||||
type: TriggerStrategy.POLLING,
|
||||
async onEnable(context) {
|
||||
// Store the current timestamp as the starting point
|
||||
await context.store.put(TRIGGER_KEY, new Date().toISOString());
|
||||
},
|
||||
async onDisable(context) {
|
||||
await context.store.delete(TRIGGER_KEY);
|
||||
},
|
||||
async test(context) {
|
||||
const auth = context.auth as SmoothScheduleAuth;
|
||||
const { oldStatus, newStatus } = context.propsValue;
|
||||
|
||||
const queryParams: Record<string, string> = {
|
||||
limit: '5',
|
||||
};
|
||||
|
||||
if (oldStatus) {
|
||||
queryParams['old_status'] = oldStatus;
|
||||
}
|
||||
if (newStatus) {
|
||||
queryParams['new_status'] = newStatus;
|
||||
}
|
||||
|
||||
const statusChanges = await makeRequest<Array<Record<string, unknown>>>(
|
||||
auth,
|
||||
HttpMethod.GET,
|
||||
'/events/status_changes/',
|
||||
undefined,
|
||||
queryParams
|
||||
);
|
||||
|
||||
return statusChanges;
|
||||
},
|
||||
async run(context) {
|
||||
const auth = context.auth as SmoothScheduleAuth;
|
||||
const { oldStatus, newStatus } = context.propsValue;
|
||||
|
||||
const lastChangeAt = await context.store.get<string>(TRIGGER_KEY) || new Date(0).toISOString();
|
||||
|
||||
const queryParams: Record<string, string> = {
|
||||
changed_at__gt: lastChangeAt,
|
||||
};
|
||||
|
||||
if (oldStatus) {
|
||||
queryParams['old_status'] = oldStatus;
|
||||
}
|
||||
if (newStatus) {
|
||||
queryParams['new_status'] = newStatus;
|
||||
}
|
||||
|
||||
const statusChanges = await makeRequest<Array<{ changed_at: string } & Record<string, unknown>>>(
|
||||
auth,
|
||||
HttpMethod.GET,
|
||||
'/events/status_changes/',
|
||||
undefined,
|
||||
queryParams
|
||||
);
|
||||
|
||||
if (statusChanges.length > 0) {
|
||||
// Update the last change timestamp
|
||||
const maxChangedAt = statusChanges.reduce((max, c) =>
|
||||
c.changed_at > max ? c.changed_at : max,
|
||||
lastChangeAt
|
||||
);
|
||||
await context.store.put(TRIGGER_KEY, maxChangedAt);
|
||||
}
|
||||
|
||||
return statusChanges;
|
||||
},
|
||||
sampleData: {
|
||||
id: 1,
|
||||
event_id: 12345,
|
||||
event: {
|
||||
id: 12345,
|
||||
title: 'Consultation',
|
||||
start_time: '2024-12-01T10:00:00Z',
|
||||
end_time: '2024-12-01T11:00:00Z',
|
||||
status: 'IN_PROGRESS',
|
||||
service: {
|
||||
id: 1,
|
||||
name: 'Consultation',
|
||||
},
|
||||
customer: {
|
||||
id: 100,
|
||||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
email: 'john.doe@example.com',
|
||||
},
|
||||
resources: [
|
||||
{ id: 1, name: 'Dr. Smith', type: 'STAFF' },
|
||||
],
|
||||
},
|
||||
old_status: 'SCHEDULED',
|
||||
old_status_display: 'Scheduled',
|
||||
new_status: 'IN_PROGRESS',
|
||||
new_status_display: 'In Progress',
|
||||
changed_by: 'John Smith',
|
||||
changed_by_email: 'john@example.com',
|
||||
changed_at: '2024-12-01T10:05:00Z',
|
||||
notes: 'Started working on the job',
|
||||
source: 'mobile_app',
|
||||
latitude: 40.7128,
|
||||
longitude: -74.0060,
|
||||
},
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './event-created';
|
||||
export * from './event-updated';
|
||||
export * from './event-cancelled';
|
||||
export * from './event-status-changed';
|
||||
|
||||
Reference in New Issue
Block a user