Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
getStatusColor,
statusColor,
} from "~/app/[workspaceSlug]/(app)/(deploy)/_utils/status-color";
import { urls } from "~/app/urls";
import { api } from "~/trpc/react";

const ReleaseIcon: React.FC<{
Expand Down Expand Up @@ -191,14 +192,18 @@ export const DeploymentVersion: React.FC<{
[d.job, d.resource, d.job.message].every(isPresent),
);

const versionUrl = urls
.workspace(workspaceSlug)
.system(systemSlug)
.deployment(deploymentSlug)
.release(versionId)
.baseUrl();

return (
<div className="flex w-full items-center justify-between">
<HoverCard>
<HoverCardTrigger asChild>
<Link
href={`/${workspaceSlug}/systems/${systemSlug}/deployments/${deploymentSlug}/releases/${versionId}`}
className="flex w-full items-center gap-2"
>
<Link href={versionUrl} className="flex w-full items-center gap-2">
<ReleaseIcon statuses={statuses} />
<div className="w-full text-sm">
<div className="flex items-center gap-2">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Table, TableBody, TableCell, TableRow } from "@ctrlplane/ui/table";

import type { VariableData } from "./variable-data";
import { ResourceIcon } from "~/app/[workspaceSlug]/(app)/_components/resources/ResourceIcon";
import { urls } from "~/app/urls";
import { useMatchSorterWithSearch } from "~/utils/useMatchSorter";
import { VariableDropdown } from "./VariableDropdown";
import { VariableValueDropdown } from "./VariableValueDropdown";
Expand Down Expand Up @@ -59,6 +60,8 @@ export const VariableTable: React.FC<{
return newState;
});

const workspaceUrls = urls.workspace(workspaceSlug);

return (
<>
<div className="mb-[1px]">
Expand Down Expand Up @@ -227,10 +230,11 @@ export const VariableTable: React.FC<{
<TableCell
className="h-10 cursor-pointer py-0 pl-[56px]"
colSpan={2}
// onClick={() => setResourceId(r.id)}
>
<Link
href={`/${workspaceSlug}/resources/${r.id}`}
href={workspaceUrls
.resource(r.id)
.baseUrl()}
target="_blank"
rel="noopener noreferrer"
className="flex h-full items-center border-l border-neutral-800 pl-7"
Expand Down Expand Up @@ -262,7 +266,7 @@ export const VariableTable: React.FC<{
<div className="flex h-full items-center border-l border-neutral-800 pl-7 text-muted-foreground hover:text-white">
<Link
className="flex h-full items-center gap-2 border-l border-neutral-800 pl-6"
href={`/${workspaceSlug}/resources?filter=${v.filterHash}`}
href={`${workspaceUrls.resources().baseUrl()}?filter=${v.filterHash}`}
target="_blank"
>
<IconDotsVertical className="h-4 w-4" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
import { PageHeader } from "~/app/[workspaceSlug]/(app)/_components/PageHeader";
import { SidebarLink } from "~/app/[workspaceSlug]/(app)/resources/(sidebar)/SidebarLink";
import { Sidebars } from "~/app/[workspaceSlug]/sidebars";
import { urls } from "~/app/urls";
import { api } from "~/trpc/server";
import { DailyResourceCountGraph } from "./insights/DailyResourcesCountGraph";

Expand All @@ -36,8 +37,8 @@ export default async function EnvironmentLayout(props: {
environmentId: string;
}>;
}) {
const params = await props.params;
const environment = await api.environment.byId(params.environmentId);
const { workspaceSlug, systemSlug, environmentId } = await props.params;
const environment = await api.environment.byId(environmentId);
if (environment == null) notFound();

const endDate = new Date();
Expand All @@ -49,8 +50,8 @@ export default async function EnvironmentLayout(props: {
endDate,
});

const url = (tab: string) =>
`/${params.workspaceSlug}/systems/${params.systemSlug}/environments/${params.environmentId}/${tab}`;
const systemUrls = urls.workspace(workspaceSlug).system(systemSlug);
const environmentUrls = systemUrls.environment(environmentId);
return (
<SidebarProvider
className="flex h-full w-full flex-col"
Expand All @@ -59,18 +60,14 @@ export default async function EnvironmentLayout(props: {
>
<PageHeader className="justify-between">
<div className="flex shrink-0 items-center gap-4">
<Link
href={`/${params.workspaceSlug}/systems/${params.systemSlug}/deployments`}
>
<Link href={systemUrls.deployments()}>
<IconArrowLeft className="size-5" />
</Link>
<Separator orientation="vertical" className="h-4" />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink
href={`/${params.workspaceSlug}/systems/${params.systemSlug}/environments`}
>
<BreadcrumbLink href={systemUrls.environments()}>
Environments
</BreadcrumbLink>
</BreadcrumbItem>
Expand All @@ -92,10 +89,18 @@ export default async function EnvironmentLayout(props: {
<SidebarContent>
<SidebarGroup>
<SidebarMenu>
<SidebarLink href={url("deployments")}>Deployments</SidebarLink>
<SidebarLink href={url("policies")}>Policies</SidebarLink>
<SidebarLink href={url("resources")}>Resources</SidebarLink>
<SidebarLink href={url("variables")}>Variables</SidebarLink>
<SidebarLink href={environmentUrls.deployments()}>
Deployments
</SidebarLink>
<SidebarLink href={environmentUrls.policies()}>
Policies
</SidebarLink>
<SidebarLink href={environmentUrls.resources()}>
Resources
</SidebarLink>
<SidebarLink href={environmentUrls.variables()}>
Variables
</SidebarLink>
</SidebarMenu>
</SidebarGroup>
</SidebarContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Tabs,
TabsList,
} from "~/app/[workspaceSlug]/(app)/_components/navigation/Tabs";
import { urls } from "~/app/urls";

const getActiveTab = (url: string) => {
if (url.endsWith("/approval")) return "approval";
Expand All @@ -27,7 +28,11 @@ export const PolicyTabs: React.FC = () => {

const pathname = usePathname();
const activeTab = getActiveTab(pathname);
const baseUrl = `/${workspaceSlug}/systems/${systemSlug}/environments/${environmentId}/policies`;
const baseUrl = urls
.workspace(workspaceSlug)
.system(systemSlug)
.environment(environmentId)
.policies();

return (
<Tabs>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from "@ctrlplane/ui/command";
import { Popover, PopoverContent, PopoverTrigger } from "@ctrlplane/ui/popover";

import { urls } from "../../../../../../../../../../../urls";
import { useUpdatePolicy } from "../useUpdatePolicy";

type Deployment = RouterOutputs["deployment"]["bySystemId"][number];
Expand Down Expand Up @@ -43,14 +44,20 @@ const DeploymentSelect: React.FC<DeploymentSelectProps> = ({
updateDeploymentVersionChannel(deployment.id, channelId);

const { workspaceSlug, systemSlug } = useParams<{
workspaceSlug?: string;
systemSlug?: string;
workspaceSlug: string;
systemSlug: string;
}>();

const sortedDeploymentVersionChannels = deployment.versionChannels.sort(
(a, b) => a.name.localeCompare(b.name),
);

const releaseChannelsUrl = urls
.workspace(workspaceSlug)
.system(systemSlug)
.deployment(deployment.slug)
.channels();

return (
<div className="flex items-center gap-2">
<span className="w-40 truncate text-sm">{deployment.name}</span>
Expand All @@ -75,7 +82,7 @@ const DeploymentSelect: React.FC<DeploymentSelectProps> = ({
{sortedDeploymentVersionChannels.length === 0 && (
<CommandItem>
<Link
href={`/${workspaceSlug}/systems/${systemSlug}/deployments/${deployment.slug}/release-channels`}
href={releaseChannelsUrl}
className="w-full hover:text-blue-300"
>
<IconPlus className="h-4 w-4" /> Create version channel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
TableRow,
} from "@ctrlplane/ui/table";

import { urls } from "~/app/urls";
import { api } from "~/trpc/server";

export default async function VariablesPage(props: {
Expand All @@ -22,6 +23,12 @@ export default async function VariablesPage(props: {

const variableSets = await api.variableSet.byEnvironmentId(environmentId);

const variablesUrl = urls
.workspace(workspaceSlug)
.system(systemSlug)
.environment(environmentId)
.variables();

return (
<Table>
<TableHeader>
Expand All @@ -40,7 +47,7 @@ export default async function VariablesPage(props: {
<TableCell>{val.value}</TableCell>
<TableCell>
<Link
href={`/${workspaceSlug}/systems/${systemSlug}/environments/${environmentId}/variables?variable_set_id=${v.variableSet.id}`}
href={`${variablesUrl}?variable_set_id=${v.variableSet.id}`}
className="underline-offset-2 hover:underline"
>
{v.variableSet.name}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { cn } from "@ctrlplane/ui";
import { Button } from "@ctrlplane/ui/button";
import { Skeleton } from "@ctrlplane/ui/skeleton";

import { urls } from "~/app/urls";
import { api } from "~/trpc/react";
import { EnvironmentDropdown } from "./EnvironmentDropdown";

Expand Down Expand Up @@ -79,10 +80,16 @@ export const EnvironmentRow: React.FC<{
systemSlug: string;
}>();

const environmentUrl = urls
.workspace(workspaceSlug)
.system(systemSlug)
.environment(environment.id)
.baseUrl();

return (
<Link
className="flex items-center border-b p-4 hover:bg-muted/50"
href={`/${workspaceSlug}/systems/${systemSlug}/environments/${environment.id}`}
href={environmentUrl}
>
<div className="flex-1">{environment.name}</div>
<div className="flex-1">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
TooltipTrigger,
} from "@ctrlplane/ui/tooltip";

import { urls } from "~/app/urls";
import { api } from "~/trpc/react";

type UniqueFilterResult = {
Expand Down Expand Up @@ -96,6 +97,7 @@ export const ResourceFilterUniquenessIndicator: FC<{
currentNode: Node;
}> = ({ nodes, workspaceId, workspaceSlug, currentNode }) => {
const result = useResourceFilterUniqueness(nodes, workspaceId, currentNode);
const resourcesUrl = urls.workspace(workspaceSlug).resources().baseUrl();

if (!currentNode.data.resourceFilter)
return (
Expand Down Expand Up @@ -159,7 +161,7 @@ export const ResourceFilterUniquenessIndicator: FC<{
</span>{" "}
<span className="text-muted-foreground">has</span>{" "}
<Link
href={`/${workspaceSlug}/resources?${new URLSearchParams({
href={`${resourcesUrl}?${new URLSearchParams({
filter: compressedFilter,
})}`}
className="text-muted-foreground underline"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,43 @@ import { IconBook } from "@tabler/icons-react";

import { Button } from "@ctrlplane/ui/button";

import { urls } from "~/app/urls";

export const RunbookGettingStarted: React.FC<{
workspaceSlug: string;
systemSlug: string;
}> = ({ workspaceSlug, systemSlug }) => {
return (
<div className="h-full w-full p-20">
<div className="container m-auto max-w-xl space-y-6 p-20">
<div className="relative -ml-1 text-neutral-500">
<IconBook className="h-10 w-10" strokeWidth={0.5} />
</div>
<div className="font-semibold">Runbooks</div>
<div className="prose prose-invert text-sm text-muted-foreground">
<p>
Runbooks in Ctrlplane trigger pipelines that you can control and
manage in one centralized place. They allow you to select specific
resources for pipeline execution and can be scheduled to run
automatically, streamlining your operational processes. This
centralized approach to pipeline management enhances efficiency and
provides greater control over your automated workflows.
</p>
</div>
<div className="flex items-center gap-2">
<Link
href={`/${workspaceSlug}/systems/${systemSlug}/runbooks/create`}
passHref
>
<Button size="sm">Create Runbook</Button>
</Link>
<Button size="sm" variant="secondary">
Documentation
</Button>
</div>
}> = ({ workspaceSlug, systemSlug }) => (
<div className="h-full w-full p-20">
<div className="container m-auto max-w-xl space-y-6 p-20">
<div className="relative -ml-1 text-neutral-500">
<IconBook className="h-10 w-10" strokeWidth={0.5} />
</div>
<div className="font-semibold">Runbooks</div>
<div className="prose prose-invert text-sm text-muted-foreground">
<p>
Runbooks in Ctrlplane trigger pipelines that you can control and
manage in one centralized place. They allow you to select specific
resources for pipeline execution and can be scheduled to run
automatically, streamlining your operational processes. This
centralized approach to pipeline management enhances efficiency and
provides greater control over your automated workflows.
</p>
</div>
<div className="flex items-center gap-2">
<Link
href={urls
.workspace(workspaceSlug)
.system(systemSlug)
.runbooks()
.create()}
passHref
>
<Button size="sm">Create Runbook</Button>
</Link>
<Button size="sm" variant="secondary">
Documentation
</Button>
</div>
</div>
);
};
</div>
);
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { buttonVariants } from "@ctrlplane/ui/button";
import { PageHeader } from "~/app/[workspaceSlug]/(app)/_components/PageHeader";
import { api } from "~/trpc/server";
import { SystemBreadcrumb } from "../_components/SystemBreadcrumb";
import { urls } from "../../../../../../../../urls";
import { RunbookGettingStarted } from "./RunbookGettingStarted";
import { RunbookRow } from "./RunbookRow";

Expand All @@ -18,13 +19,19 @@ export default async function RunbooksPage(props: {
const system = await api.system.bySlug(params).catch(notFound);
const runbooks = await api.runbook.bySystemId(system.id);
const jobAgents = await api.job.agent.byWorkspaceId(workspace.id);
const createRunbookUrl = urls
.workspace(params.workspaceSlug)
.system(params.systemSlug)
.runbooks()
.create();

return (
<div>
<PageHeader className="flex w-full items-center justify-between">
<SystemBreadcrumb system={system} page="Runbooks" />

<Link
href={`/${params.workspaceSlug}/systems/${params.systemSlug}/runbooks/create`}
href={createRunbookUrl}
className={buttonVariants({ variant: "outline", size: "sm" })}
>
Create Runbook
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default async function Layout(props: {
const workspaceUrls = urls.workspace(workspaceSlug);
const deploymentsUrl = workspaceUrls.deployments();
const systemsUrl = workspaceUrls.systems();
const agentsUrl = workspaceUrls.agents();
const agentsUrl = workspaceUrls.agents().baseUrl();
return (
<div className="relative">
<SidebarProvider sidebarNames={[Sidebars.Deployments]}>
Expand Down
Loading
Loading