2a1273b683
* Added the new colours to the Tailwind config * Fixed Tsailwind compile errors * WIP Geist working in the app * WIP Storybook * Storybook is working again… ouch * Use Geist mono for CodeMirror * Some find/replace class changes * Resizable colours improved * WIP on primary button * Minor style improvements * Improve the side menu header styling * Improved v2 breadcrumbs * Account side menu tweaks * The page now works with the NavBar and UpgradePrompt * Removed unused import * Refactored the buttons to be dry-er * Removed the breadcrumbs * WIP on nav bar * WIP updating the button styles * Fix for the old test page * Fix for type errors * Removed console.log * Colour change in the resizable handle * New loading bar divider * Removed the design plugin * Creating our own storybook pages * Added some “storybook” pages * Added DetailCell storybook * WIP new animation for the loading page * Added the new loading divider * Fix for the time frame filter having a green border * Style improvements to the new test page * Small style improvements * Improvements to the list pagination components * Nav bar back button improved * Improvements to the run page * Lots of v2 style improvements * Help looks better * Improvements to the regenerate API key modal * More general improvements * Added section titles to our storybook * Added form stories * Fix for missing key prop * Loading bar is working * Fixed button submitting state * Fix for the test button icon * Code bg improved * Improved oauth buttons * Integration page header fix * Various improvements, mainly changing button variants * Segmented control style updates * Added an outline of 3px for the segment control * Fixes for the billing pages * More pricing improvements * Added dialog to storybook * Typography now in storybook * Free usage bar added to storybook * Added inline clode to storybook * Separated menu types into a sub section in storybook * NamedIcon now in storybook * Added page header to storybook * Added pricing callout to storybook * Added radio groups to storybook * Added segmented controllers to storybook * Added shortcuts to storybook * Added switches to storybook * Added toast to storybook * Added tooltips to storybook * Added tree view to storybook * Added usage charts to storybook * Tarted up the environment variables page * Fix for the FreePlanUsage panel bg colours * Added new badge variants * Added the <TaskPath /> to the tasks table * Span header improvements * Started work on the timeline * Started work on the timeline * Fix for the run page header * Timeline tick marks are working * Timeline working * Got the durations showing on hover * Button improvements * Experimenting with how the duration should be shown * Lots of refinements to the timeline * Much nicer API for the Timeline * The switch is now purple to match the design, with inverted thumb when on * Removed old stuff * Export the props * Added the span with duration back in * Simplified more and fixed the span durations * Put in some decent dummy data * Rendering defaults * Wip with the mouse cursor * Improvements to the story * Added Slider primitive * Integrated the icons into the slider * Lots of layout improvements * Cleaned up imports * “Root” indicator * Animated background on partials * Pull the styles through to the spans and log dots * Fixed some bugs in the TreeView when nodes get created or destroyed * Fix for incorrect parentTask reference * Added run streaming endpoint for live refreshing * Added the tabs to Storybook * Fix for status font size mismatch * Fix for the misaligned run filter status * Set a minimum duration on the timeline * The TreeView now re-calculates if the number of nodes has changed * Partials now render to the end * Improved the durations gutter * The duration is calculated using the current time if there are partial events * Added the environment label to storybook * Improved the environment label style * Removed bottom margin from badge * Button style improvements * Callouts style fits the new design better * Got the scrollbars to appear on the tree/timeline * Added scroll support * Synced scrolling working * Close button and exit icon for the detail panel * secure field shows start of env * Clipboard improvements * Latest lockfile * Fix for the durations wrapping --------- Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
435 lines
16 KiB
TypeScript
435 lines
16 KiB
TypeScript
import { Link } from "@remix-run/react";
|
||
import { Paragraph } from "~/components/primitives/Paragraph";
|
||
import { StepNumber } from "~/components/primitives/StepNumber";
|
||
import { useJob } from "~/hooks/useJob";
|
||
import { useOrganization } from "~/hooks/useOrganizations";
|
||
import { useProject } from "~/hooks/useProject";
|
||
import { docsPath, jobTestPath } from "~/utils/pathBuilder";
|
||
import { CodeBlock } from "../code/CodeBlock";
|
||
import { InlineCode } from "../code/InlineCode";
|
||
import { EnvironmentLabel } from "../environments/EnvironmentLabel";
|
||
import { HelpPanelProps } from "../integrations/ApiKeyHelp";
|
||
import { HelpInstall } from "../integrations/HelpInstall";
|
||
import { HelpSamples } from "../integrations/HelpSamples";
|
||
import { LinkButton } from "../primitives/Buttons";
|
||
import { Callout, variantClasses } from "../primitives/Callout";
|
||
import { Header2 } from "../primitives/Headers";
|
||
import { TextLink } from "../primitives/TextLink";
|
||
import integrationButton from "./integration-button.png";
|
||
import selectEnvironment from "./select-environment.png";
|
||
import selectExample from "./select-example.png";
|
||
import { StepContentContainer } from "../StepContentContainer";
|
||
import { TriggerDevCommand } from "../SetupCommands";
|
||
import { IntegrationIcon } from "~/assets/icons/IntegrationIcon";
|
||
import { BookOpenIcon } from "@heroicons/react/20/solid";
|
||
|
||
export function HowToRunYourJob() {
|
||
const organization = useOrganization();
|
||
const project = useProject();
|
||
const job = useJob();
|
||
|
||
return (
|
||
<>
|
||
<Paragraph spacing>There are two ways to run your Job:</Paragraph>
|
||
|
||
<StepNumber stepNumber="1" title="Trigger a test Run" />
|
||
<StepContentContainer>
|
||
<Paragraph spacing>
|
||
You can perform a Run with any payload you want, or use one of our examples, on the test
|
||
page.
|
||
</Paragraph>
|
||
<LinkButton
|
||
to={jobTestPath(organization, project, job)}
|
||
variant={"primary/small"}
|
||
LeadingIcon={"beaker"}
|
||
leadingIconClassName="text-text-bright"
|
||
>
|
||
Test
|
||
</LinkButton>
|
||
</StepContentContainer>
|
||
|
||
<StepNumber stepNumber="2" title="Trigger your Job for real" />
|
||
<StepContentContainer>
|
||
<Paragraph spacing>
|
||
Performing a real run depends on the type of Trigger your Job is using.
|
||
</Paragraph>
|
||
|
||
<LinkButton
|
||
to="https://trigger.dev/docs/documentation/guides/running-jobs"
|
||
variant={"tertiary/small"}
|
||
LeadingIcon={BookOpenIcon}
|
||
leadingIconClassName="text-text-bright"
|
||
>
|
||
How to run a Job
|
||
</LinkButton>
|
||
</StepContentContainer>
|
||
<Callout variant="info">
|
||
<Paragraph variant={"small"} className={variantClasses.info.textColor}>
|
||
Scheduled Triggers <strong>do not</strong> trigger Jobs in the DEV Environment. When
|
||
developing locally you should use the{" "}
|
||
<Link
|
||
to={jobTestPath(organization, project, job)}
|
||
className="underline underline-offset-2 transition hover:text-blue-100"
|
||
>
|
||
Test feature
|
||
</Link>{" "}
|
||
to trigger any scheduled Jobs.
|
||
</Paragraph>
|
||
</Callout>
|
||
</>
|
||
);
|
||
}
|
||
|
||
export function HowToConnectAnIntegration() {
|
||
return (
|
||
<>
|
||
<StepNumber stepNumber="1" title="Select an API from the list" />
|
||
<StepContentContainer>
|
||
<Paragraph>
|
||
APIs marked with a
|
||
<span className="mx-2 -mt-1 inline-flex" aria-label="Trigger.dev Integration icon">
|
||
<IntegrationIcon />
|
||
</span>
|
||
are Trigger.dev Integrations. These Integrations make connecting to the API easier by
|
||
offering OAuth or API key authentication. All APIs can also be used with fetch or an SDK.
|
||
</Paragraph>
|
||
<img src={integrationButton} className="mt-2 h-10" />
|
||
</StepContentContainer>
|
||
<StepNumber stepNumber="2" title="Choose how you want to connect" />
|
||
<StepContentContainer>
|
||
<Paragraph>
|
||
Follow the instructions for your chosen connection method in the popover form. If no
|
||
Integration exists yet, you can request one by clicking the "I want an Integration"
|
||
button.
|
||
</Paragraph>
|
||
</StepContentContainer>
|
||
<StepNumber stepNumber="3" title="Your connection will appear in the list" />
|
||
<StepContentContainer>
|
||
<Paragraph>
|
||
Once you've connected your API, it will appear in the list of Integrations below. You can
|
||
view details and manage your connection by selecting it from the table.
|
||
</Paragraph>
|
||
</StepContentContainer>
|
||
<Callout variant={"docs"} to="https://trigger.dev/docs/integrations/introduction">
|
||
View the Integration docs page for more information on connecting an API using an
|
||
Integration or other method.
|
||
</Callout>
|
||
</>
|
||
);
|
||
}
|
||
|
||
export function HowToUseThisIntegration({ integration, help, integrationClient }: HelpPanelProps) {
|
||
return (
|
||
<>
|
||
<StepNumber stepNumber="1" title="Install the package" />
|
||
<StepContentContainer>
|
||
<HelpInstall packageName={integration.packageName} />
|
||
</StepContentContainer>
|
||
{help && (
|
||
<>
|
||
<StepNumber stepNumber="2" title="Create a Job" />
|
||
<StepContentContainer>
|
||
<HelpSamples
|
||
help={help}
|
||
integration={integration}
|
||
integrationClient={integrationClient}
|
||
/>
|
||
</StepContentContainer>
|
||
</>
|
||
)}
|
||
</>
|
||
);
|
||
}
|
||
|
||
export function HowToDisableAJob({
|
||
id,
|
||
name,
|
||
version,
|
||
}: {
|
||
id: string;
|
||
name: string;
|
||
version: string;
|
||
}) {
|
||
return (
|
||
<>
|
||
<Paragraph spacing>
|
||
To disable a job, you need to set the <InlineCode>enabled</InlineCode> property to{" "}
|
||
<InlineCode>false</InlineCode>.
|
||
</Paragraph>
|
||
<StepNumber
|
||
stepNumber="1"
|
||
title={
|
||
<>
|
||
Set <InlineCode>enabled</InlineCode> to <InlineCode>false</InlineCode>
|
||
</>
|
||
}
|
||
/>
|
||
<StepContentContainer>
|
||
<CodeBlock
|
||
showLineNumbers={false}
|
||
className="mb-4"
|
||
code={`client.defineJob({
|
||
id: "${id}",
|
||
name: "${name}",
|
||
version: "${version}",
|
||
enabled: false,
|
||
// ...rest of your Job definition
|
||
});`}
|
||
/>
|
||
</StepContentContainer>
|
||
<StepNumber
|
||
stepNumber="2"
|
||
title={
|
||
<>
|
||
Run the <InlineCode>@trigger.dev/cli dev</InlineCode> command
|
||
</>
|
||
}
|
||
/>
|
||
<StepContentContainer>
|
||
<Paragraph spacing>
|
||
If you aren't already running the <InlineCode>dev</InlineCode> command, run it now.
|
||
</Paragraph>
|
||
<TriggerDevCommand />
|
||
</StepContentContainer>
|
||
</>
|
||
);
|
||
}
|
||
|
||
export function HowToUseApiKeysAndEndpoints() {
|
||
return (
|
||
<>
|
||
<Paragraph spacing>
|
||
Environments and Endpoints are used to connect your server to the Trigger.dev platform.
|
||
</Paragraph>
|
||
<Header2 spacing>Environments</Header2>
|
||
<Paragraph spacing>
|
||
Each environment has API Keys associated with it. The Server API Key is used to authenticate
|
||
your Jobs with the Trigger.dev platform.
|
||
</Paragraph>
|
||
<Paragraph spacing>
|
||
The Server API Key you use for your{" "}
|
||
<TextLink to="https://trigger.dev/docs/documentation/concepts/client-adaptors">
|
||
Client
|
||
</TextLink>{" "}
|
||
is how we know which environment to run your code against:
|
||
</Paragraph>
|
||
<CodeBlock
|
||
showLineNumbers={false}
|
||
className="mb-4"
|
||
code={`export const client = new TriggerClient({
|
||
id: "nextjs-example",
|
||
//this environment variable should be set to your Server DEV API Key locally,
|
||
//and your Server PROD API Key in production
|
||
apiKey: process.env.TRIGGER_API_KEY!,
|
||
});`}
|
||
/>
|
||
<StepNumber
|
||
stepNumber="→"
|
||
title={
|
||
<span className="flex items-center gap-x-2">
|
||
<span>Development</span>
|
||
<EnvironmentLabel environment={{ type: "DEVELOPMENT" }} />
|
||
</span>
|
||
}
|
||
/>
|
||
<StepContentContainer>
|
||
<Paragraph>
|
||
The <InlineCode>DEV</InlineCode> environment should only be used for local development.
|
||
It’s where you can test your Jobs before deploying them to servers.
|
||
</Paragraph>
|
||
<Callout variant="warning" className="my-2">
|
||
Scheduled Triggers do not trigger Jobs in the DEV Environment. When you’re working locally
|
||
you should use the Test feature to trigger any scheduled Jobs.
|
||
</Callout>
|
||
</StepContentContainer>
|
||
<StepNumber
|
||
stepNumber="→"
|
||
title={
|
||
<span className="flex items-center gap-x-2">
|
||
<span>Staging</span>
|
||
<EnvironmentLabel environment={{ type: "STAGING" }} />
|
||
</span>
|
||
}
|
||
/>
|
||
<StepContentContainer>
|
||
<Paragraph spacing>
|
||
The <InlineCode>STAGING</InlineCode> environment is where your Jobs will run in a staging
|
||
environment, meant to mirror your production environment.
|
||
</Paragraph>
|
||
</StepContentContainer>
|
||
<StepNumber
|
||
stepNumber="→"
|
||
title={
|
||
<span className="flex items-center gap-x-2">
|
||
<span>Production</span>
|
||
<EnvironmentLabel environment={{ type: "PRODUCTION" }} />
|
||
</span>
|
||
}
|
||
/>
|
||
<StepContentContainer>
|
||
<Paragraph spacing>
|
||
The <InlineCode>PROD</InlineCode> environment is where your Jobs will run in production.
|
||
It’s where you can run your Jobs against real data.
|
||
</Paragraph>
|
||
</StepContentContainer>
|
||
<Header2 spacing>Endpoints</Header2>
|
||
<Paragraph spacing>
|
||
An Endpoint is a URL on your server that Trigger.dev can connect to. This URL is used to
|
||
register Jobs, start them and orchestrate runs and retries.
|
||
</Paragraph>
|
||
<Paragraph spacing>
|
||
<InlineCode>DEV</InlineCode> has multiple endpoints associated with it – one for each team
|
||
member. This allows each team member to run their own Jobs, without interfering with each
|
||
other.
|
||
</Paragraph>
|
||
<Paragraph spacing>
|
||
All other environments have just a single endpoint (with a single URL) associated with them.
|
||
</Paragraph>
|
||
<Header2 spacing>Deployment</Header2>
|
||
<Paragraph spacing>
|
||
Deployment uses Environments and Endpoints to connect your Jobs to the Trigger.dev platform.
|
||
</Paragraph>
|
||
<Callout variant="docs" to="https://trigger.dev/docs/documentation/guides/deployment">
|
||
Read the deployment guide to learn more.
|
||
</Callout>
|
||
</>
|
||
);
|
||
}
|
||
|
||
export function WhatAreHttpEndpoints() {
|
||
return (
|
||
<>
|
||
<Paragraph spacing>
|
||
HTTP endpoints allow you to trigger your Jobs from any webhooks. They require a bit more
|
||
work than using <TextLink to={docsPath("integrations/introduction")}>Integrations</TextLink>{" "}
|
||
but allow you to connect to any API.
|
||
</Paragraph>
|
||
<Header2 spacing>Getting started</Header2>
|
||
<Paragraph spacing>
|
||
You need to define the HTTP endpoint in your code. To do this you use{" "}
|
||
<InlineCode>client.defineHttpEndpoint()</InlineCode>. This will create an HTTP endpoint.
|
||
</Paragraph>
|
||
<Paragraph spacing>
|
||
Then you can create a Trigger from this by calling <InlineCode>.onRequest()</InlineCode> on
|
||
the created HTTP endpoint.
|
||
</Paragraph>
|
||
<Callout variant="docs" to={docsPath("documentation/concepts/http-endpoints")}>
|
||
Read the HTTP endpoints guide to learn more.
|
||
</Callout>
|
||
<Header2 spacing className="mt-4">
|
||
An example: cal.com
|
||
</Header2>
|
||
<CodeBlock
|
||
code={`//create an HTTP endpoint
|
||
const caldotcom = client.defineHttpEndpoint({
|
||
id: "cal.com",
|
||
source: "cal.com",
|
||
icon: "caldotcom",
|
||
verify: async (request) => {
|
||
//this helper function makes verifying most webhooks easy
|
||
return await verifyRequestSignature({
|
||
request,
|
||
headerName: "X-Cal-Signature-256",
|
||
secret: process.env.CALDOTCOM_SECRET!,
|
||
algorithm: "sha256",
|
||
});
|
||
},
|
||
});
|
||
|
||
client.defineJob({
|
||
id: "http-caldotcom",
|
||
name: "HTTP Cal.com",
|
||
version: "1.0.0",
|
||
enabled: true,
|
||
//create a Trigger from the HTTP endpoint above. The filter is optional.
|
||
trigger: caldotcom.onRequest({ filter: { body: { triggerEvent: ["BOOKING_CANCELLED"] } } }),
|
||
run: async (request, io, ctx) => {
|
||
//note that when using HTTP endpoints, the first parameter is the request
|
||
//you need to get the body, usually it will be json so you do:
|
||
const body = await request.json();
|
||
await io.logger.info("Body", body);
|
||
},
|
||
});`}
|
||
/>
|
||
</>
|
||
);
|
||
}
|
||
|
||
export function HowToConnectHttpEndpoint() {
|
||
return (
|
||
<>
|
||
<Header2 spacing>Setting up your webhook</Header2>
|
||
<Paragraph spacing>
|
||
To start receiving data you need to enter the Endpoint URL and secret into the API service
|
||
you want to receive webhooks from.
|
||
</Paragraph>
|
||
|
||
<StepNumber stepNumber="1" title={<>Go to the relevant API dashboard</>} />
|
||
<StepContentContainer>
|
||
<Paragraph spacing>
|
||
For example, if you want to receive webhooks from Cal.com then you should login to your
|
||
Cal.com account and go to their Settings/Developer/Webhooks page.
|
||
</Paragraph>
|
||
</StepContentContainer>
|
||
|
||
<StepNumber stepNumber="2" title={<>Copy the Webhook URL and Secret</>} />
|
||
<StepContentContainer>
|
||
<Paragraph spacing>
|
||
A unique Webhook URL is created for each environment (Dev, Staging, and Prod). Jobs will
|
||
only be triggered from the relevant environment.
|
||
</Paragraph>
|
||
<Paragraph spacing>
|
||
Copy the relevant Endpoint URL and secret from the table opposite and paste it into the
|
||
correct place in the API dashboard you located in the previous step.
|
||
</Paragraph>
|
||
</StepContentContainer>
|
||
|
||
<StepNumber stepNumber="3" title={<>Add the Secret to your Environment variables</>} />
|
||
<StepContentContainer>
|
||
<Paragraph spacing>
|
||
You should also add the Secret to the Environment variables in your code and where you're
|
||
deploying. Usually in Node this means adding it to the .env file.
|
||
</Paragraph>
|
||
<Paragraph spacing>
|
||
Use the secret in the <InlineCode>verify()</InlineCode> function of HTTP Endpoint. This
|
||
ensures that someone can't just send a request to your Endpoint and trigger a Job.
|
||
Different APIs do this verification in different ways – a common way is to have a header
|
||
that has a hash of the payload and secret. Refer to the API's documentation for more
|
||
information.
|
||
</Paragraph>
|
||
</StepContentContainer>
|
||
|
||
<Header2 spacing>Triggering runs</Header2>
|
||
<StepNumber stepNumber="1" title="Ensure you're using the HTTP Endpoint in your code" />
|
||
<StepContentContainer>
|
||
<Paragraph spacing>
|
||
In your code, you should use the <InlineCode>.onRequest()</InlineCode> function in a Job
|
||
Trigger. You can filter so only data that matches your criteria triggers the Job.
|
||
</Paragraph>
|
||
</StepContentContainer>
|
||
<StepNumber stepNumber="2" title="Make sure your code is deployed (for Staging and Prod)" />
|
||
<StepContentContainer>
|
||
<Paragraph spacing>
|
||
If you're using the Staging or Prod environment, you need to make sure your code is
|
||
deployed. Deploy like you normally would –{" "}
|
||
<TextLink to={docsPath("documentation/guides/deployment")}>
|
||
read our deployment guide
|
||
</TextLink>
|
||
.
|
||
</Paragraph>
|
||
</StepContentContainer>
|
||
<StepNumber stepNumber="3" title="Perform an action that sends a webhook" />
|
||
<StepContentContainer>
|
||
<Paragraph spacing>
|
||
Now you need to actually perform an action on that third-party service that triggers the
|
||
webhook you've subscribed to. For example, add a new meeting using Cal.com.
|
||
</Paragraph>
|
||
</StepContentContainer>
|
||
|
||
<Callout variant="docs" to={docsPath("documentation/concepts/http-endpoints")}>
|
||
Read the HTTP endpoints guide to learn more.
|
||
</Callout>
|
||
</>
|
||
);
|
||
}
|