Skip to content
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

feat: namananand/ins 3605 add realease switch dropdown, share and delete button to view pipeline page #942

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
2 changes: 1 addition & 1 deletion packages/toolkit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@instill-ai/toolkit",
"version": "0.80.4-rc.11",
"version": "0.80.4-rc.13",
"description": "Instill AI's frontend toolkit",
"repository": "https://github.com/instill-ai/design-system.git",
"bugs": "https://github.com/instill-ai/design-system/issues",
Expand Down
2 changes: 1 addition & 1 deletion packages/toolkit/src/components/card-pipeline/Head.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const Head = ({
<div className="flex flex-row p-3">
<div className="mr-auto flex flex-row gap-x-2">
<EntityAvatar
src={pipeline.owner?.profile?.avatar ?? null}
src={pipeline.owner?.profile_avatar ?? null}
className="h-8 w-8"
entityName={ownerID}
fallbackImg={
Expand Down
1 change: 1 addition & 0 deletions packages/toolkit/src/lib/vdp-sdk/pipeline/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export type PipelineRelease = {
visibility: Visibility;
openapi_schema: OpenAPIV3.Document;
metadata: GeneralRecord;
alias?: string;
};

export type PipelineTrace = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export const TabShare = () => {
<div className="flex flex-row">
<div className="mr-auto flex flex-row gap-x-2">
<EntityAvatar
src={pipeline.data?.owner?.profile.avatar ?? null}
src={pipeline.data?.owner?.profile_avatar ?? null}
entityName={pipeline.data?.owner_name ?? ""}
className="h-[30px] w-[30px]"
fallbackImg={
Expand Down
185 changes: 172 additions & 13 deletions packages/toolkit/src/view/pipeline/view-pipeline/Head.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ import {
Tag,
TabMenu,
Skeleton,
Popover,
ScrollArea,
toast,
} from "@instill-ai/design-system";
import {
InstillStore,
Nullable,
isPublicPipeline,
toastInstillError,
useDeleteUserPipeline,
useEntity,
useInstillStore,
useOrganization,
Expand All @@ -22,19 +27,31 @@ import {
} from "../../../lib";
import { ClonePipelineDialog, EntityAvatar } from "../../../components";
import { EditMetadataDialog } from "./EditMetadataDialog";
import cn from "clsx";
import { Menu } from "./Menu";

const selector = (store: InstillStore) => ({
accessToken: store.accessToken,
enabledQuery: store.enabledQuery,
});

export const Head = () => {
type HeadProps = {
handleVersion: (version: string) => void;
currentVersion: string;
};

export const Head = (props: HeadProps) => {
const { accessToken, enabledQuery } = useInstillStore(useShallow(selector));

const { currentVersion, handleVersion } = props;

const router = useRouter();
const { id, entity } = router.query;
const [selectedTab, setSelectedTab] =
React.useState<Nullable<string>>("overview");

const [isOpen, setIsOpen] = React.useState<boolean>(false);

const entityObject = useEntity();

const user = useUser({
Expand Down Expand Up @@ -75,6 +92,29 @@ export const Head = () => {
enabledQuery: enabledQuery && entityObject.isSuccess,
});

const deletePipeline = useDeleteUserPipeline();
async function handleDeletePipeline() {
try {
await deletePipeline.mutateAsync({
pipelineName: pipeline.data?.name || "",
accessToken: accessToken ? accessToken : null,
});

toast({
title: "Pipeline deleted",
variant: "alert-success",
size: "large",
});
router.push(`/${entityObject.entity}/pipelines`);
} catch (error) {
toastInstillError({
title: "Something went wrong when delete the pipeline",
error,
toast,
});
}
}

return (
<React.Fragment>
<style jsx>{`
Expand All @@ -96,7 +136,7 @@ export const Head = () => {
<EntityAvatar
src={organization.data?.profile?.avatar ?? null}
entityName={organization.data?.name ?? ""}
className="h-6 w-6"
className="my-auto h-6 w-6"
fallbackImg={
<div className="flex h-6 w-6 rounded-full bg-semantic-bg-secondary">
<Icons.User02 className="m-auto h-4 w-4 stroke-semantic-fg-disabled" />
Expand All @@ -107,7 +147,7 @@ export const Head = () => {
<EntityAvatar
src={user.data?.profile?.avatar ?? null}
entityName={user.data?.name ?? ""}
className="h-6 w-6"
className="my-auto h-6 w-6"
fallbackImg={
<div className="flex h-6 w-6 rounded-full bg-semantic-bg-secondary">
<Icons.User02 className="m-auto h-4 w-4 stroke-semantic-fg-disabled" />
Expand All @@ -119,9 +159,9 @@ export const Head = () => {
<Skeleton className="h-6 w-6 rounded-full" />
)}

{pipeline.isSuccess ? (
{releases && pipeline.isSuccess ? (
<React.Fragment>
<div className="product-headings-heading-4">
<div className="my-auto product-headings-heading-4">
<span
onClick={() => {
router.push(`/${entity}`);
Expand All @@ -133,20 +173,97 @@ export const Head = () => {
<span className="text-semantic-fg-disabled">/</span>
<span className="text-semantic-fg-primary">{id}</span>
</div>

{releases.length && pipeline.isSuccess ? (
<Popover.Root
onOpenChange={() => setIsOpen(!isOpen)}
open={isOpen}
>
<Popover.Trigger asChild={true} className="my-auto">
<Button
className={cn(
"!h-8 !w-[145px] gap-x-1 !rounded-sm !border border-[#E1E6EF] !py-1 px-3 !transition-opacity !duration-300 !ease-in-out",
isOpen
? "border-opacity-100 !bg-semantic-accent-bg "
: "border-opacity-0"
)}
size="sm"
variant="tertiaryColour"
type="button"
onClick={() => setIsOpen(true)}
>
<Tag
size="sm"
variant="darkPurple"
className="h-6 gap-x-2"
>
Version{" "}
{currentVersion === "latest"
? releases[0]?.id
: currentVersion}
</Tag>
<Icons.ChevronDown className="h-4 w-4 stroke-semantic-fg-primary" />
</Button>
</Popover.Trigger>
<Popover.Content
side="top"
sideOffset={4}
align="start"
className="flex h-[180px] w-[145px] flex-col !rounded-sm !p-0"
>
<ScrollArea.Root>
<div className="flex flex-col gap-y-1 px-1.5 py-1">
{releases.length > 0 ? (
<React.Fragment>
{releases.map((release) => (
<VersionButton
key={release.id}
id={release.id}
currentVersion={
currentVersion === "latest"
? releases[0].id
: currentVersion
}
createTime={release.create_time}
onClick={() => {
handleVersion(release.id);
setIsOpen(false);
}}
/>
))}
</React.Fragment>
) : (
<div className="p-2 text-semantic-fg-disabled product-body-text-4-medium">
This pipeline has no released versions.
</div>
)}
</div>
</ScrollArea.Root>
</Popover.Content>
</Popover.Root>
) : null}
{pipeline.isSuccess ? (
<Tag className="!py-0" variant="darkBlue" size="sm">
{isPublicPipeline(pipeline.data) ? "Public" : "Private"}
<Tag
className="my-auto h-6 !border-0 !py-0"
variant="lightNeutral"
size="sm"
>
{isPublicPipeline(pipeline.data) ? (
<div className="flex flex-row gap-x-1">
<span className="my-auto">Public</span>
</div>
) : (
<div className="flex flex-row gap-x-1">
<span className="my-auto">Private</span>
<Icons.Lock03 className="my-auto h-3 w-3 stroke-semantic-fg-primary" />
</div>
)}
</Tag>
) : null}
</React.Fragment>
) : (
<PipelineNameSkeleton />
)}
{releases[0] ? (
<Tag className="!py-0" size="sm" variant="darkBlue">
{releases[0]?.id}
</Tag>
) : null}
</div>
</div>
{pipeline.isSuccess ? (
Expand All @@ -161,7 +278,7 @@ export const Head = () => {
/>
</div>
) : (
<div className="flex w-full flex-row items-center gap-x-2">
<div className="flex w-full flex-row items-center gap-x-2 p-1">
<p className="font-mono text-xs italic text-semantic-fg-disabled">
This is a placeholder brief of this pipeline
</p>
Expand Down Expand Up @@ -190,6 +307,13 @@ export const Head = () => {
</TabMenu.Root>
</div>
<div className="mt-auto flex flex-row gap-x-2 pb-1">
{pipeline.isSuccess ? (
<Menu
pipeline={pipeline.data}
handleDeletePipeline={handleDeletePipeline}
/>
) : null}

{pipeline.isSuccess ? (
<React.Fragment>
{me.isSuccess ? (
Expand Down Expand Up @@ -259,3 +383,38 @@ const HeaderControllerSkeleton = () => {
</React.Fragment>
);
};

const VersionButton = ({
id,
currentVersion,
onClick,
createTime,
}: {
id: string;
currentVersion: Nullable<string>;
createTime?: string;
onClick: () => void;
}) => {
return (
<Button
key={id}
className={cn(
"w-full !px-2 !py-1.5",
currentVersion === id ? "!bg-semantic-bg-secondary" : ""
)}
variant={"tertiaryColour"}
onClick={onClick}
>
<div className="flex w-full flex-row gap-x-2">
<div className="my-auto h-2 w-[9px] rounded-full bg-semantic-secondary-default"></div>
<p
className={cn(
"w-full text-left text-semantic-fg-secondary product-body-text-3-medium"
)}
>
Version {id}
</p>
</div>
</Button>
);
};
24 changes: 18 additions & 6 deletions packages/toolkit/src/view/pipeline/view-pipeline/InOutPut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
Skeleton,
useToast,
} from "@instill-ai/design-system";
import { recursiveHelpers } from "../../pipeline-builder";
import { recursiveHelpers, useSortedReleases } from "../../pipeline-builder";
import { ComponentOutputs } from "../../pipeline-builder/components/ComponentOutputs";
import { getPipelineInputOutputSchema } from "../../pipeline-builder/lib/getPipelineInputOutputSchema";
import { LoadingSpin } from "../../../components";
Expand All @@ -34,7 +34,11 @@ const selector = (store: InstillStore) => ({
enabledQuery: store.enabledQuery,
});

export const InOutPut = () => {
type InOutPutProps = {
currentVersion: string;
};

export const InOutPut = ({ currentVersion }: InOutPutProps) => {
const { amplitudeIsInit } = useAmplitudeCtx();
const { accessToken, enabledQuery } = useInstillStore(useShallow(selector));
const router = useRouter();
Expand All @@ -53,13 +57,21 @@ export const InOutPut = () => {
accessToken,
});

const startComponent = React.useMemo(() => {
if (!pipeline.isSuccess) return null;
const releases = useSortedReleases({
pipelineName: entityObject.pipelineName,
accessToken,
enabledQuery: enabledQuery && entityObject.isSuccess,
});

const startComponent = React.useMemo(() => {
const pipelineVersion = releases.find(
(release) =>
release.id === currentVersion || release.alias === currentVersion
);
return (
pipeline.data.recipe.components.find((c) => c.id === "start") ?? null
pipelineVersion?.recipe.components.find((c) => c.id === "start") ?? null
);
}, [pipeline.isSuccess, pipeline.data]);
}, [releases, currentVersion]);

const { fields, form, Schema } = useStartOperatorTriggerPipelineForm({
mode: "demo",
Expand Down
Loading
Loading