Skip to content
Open
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
359 changes: 287 additions & 72 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,18 @@
"@datadog/browser-rum": "^6.22.0",
"@datadog/browser-rum-react": "^6.22.0",
"@descope/react-sdk": "^2.16.1",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@estruyf/github-actions-reporter": "^1.9.2",
"@floating-ui/react": "^0.27.2",
"@formkit/auto-animate": "^0.8.2",
"@hookform/resolvers": "^3.9.1",
"@monaco-editor/react": "^4.6.0",
"@netlify/edge-functions": "^2.11.1",
"@sentry/react": "^8.47.0",
"@tanstack/react-table": "^8.21.3",
"@tanstack/react-virtual": "^3.13.12",
"@types/lodash": "^4.17.13",
"@types/pako": "^2.0.3",
"@uiw/react-json-view": "^2.0.0-alpha.30",
Expand Down
1 change: 1 addition & 0 deletions src/assets/image/icons/GripVertical.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/assets/image/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,5 @@ export { default as LinkIcon } from "@assets/image/icons/Link.svg?react";
export { default as InfoIconNoCircle } from "@assets/image/icons/InfoNoCircle.svg?react";
// Taken from: https://fontawesome.com/icons/file-zipper?f=classic&s=regular
export { default as ZipFileIcon } from "@assets/image/icons/ZipFile.svg?react";
// Taken from: https://tabler.io/icons/icon/grip-vertical
export { default as GripVerticalIcon } from "@assets/image/icons/GripVertical.svg?react";
2 changes: 1 addition & 1 deletion src/autokitteh
Submodule autokitteh updated 73 files
+32 −10 cmd/ak/cmd/connections/create.go
+9 −0 configs/opa_bundles/default/authz.rego
+2 −0 go.sum
+4 −0 internal/backend/auth/authsessions/store.go
+107 −0 internal/backend/auth/authz/ops.go
+6 −6 internal/backend/builds/builds.go
+33 −9 internal/backend/connections/connections.go
+2 −0 internal/backend/db/db.go
+23 −27 internal/backend/db/dbgorm/connections.go
+236 −2 internal/backend/db/dbgorm/connections_test.go
+7 −1 internal/backend/db/dbgorm/gorm_test.go
+21 −1 internal/backend/db/dbgorm/owner_org.go
+1 −1 internal/backend/db/dbgorm/owner_org_test.go
+12 −5 internal/backend/db/dbgorm/scheme/records.go
+29 −6 internal/backend/db/dbgorm/store.go
+7 −7 internal/backend/deployments/deployments.go
+2 −2 internal/backend/dispatcher/dispatcher.go
+3 −3 internal/backend/events/events.go
+3 −3 internal/backend/integrationsgrpcsvc/svc.go
+11 −11 internal/backend/orgs/orgs.go
+12 −12 internal/backend/projects/projects.go
+8 −8 internal/backend/sessions/sessions.go
+7 −0 internal/backend/sessions/sessionworkflows/workflow.go
+70 −16 internal/backend/store/store.go
+23 −2 internal/backend/store/store_test.go
+20 −0 internal/backend/storegrpcsvc/svc.go
+1 −1 internal/backend/svc/svc.go
+5 −5 internal/backend/triggers/triggers.go
+4 −4 internal/backend/users/users.go
+6 −6 internal/backend/vars/vars.go
+1 −2 internal/manifest/exec.go
+27 −0 migrations/postgres/20251124123331_org-level-connections.sql
+2 −1 migrations/postgres/atlas.sum
+27 −0 migrations/postgres/enterprise/20251124123252_org-level-connections.sql
+2 −1 migrations/postgres/enterprise/atlas.sum
+56 −0 migrations/sqlite/20251124090942_connection-unique-index.sql
+2 −1 migrations/sqlite/atlas.sum
+2 −0 proto/autokitteh/connections/v1/connection.proto
+8 −0 proto/autokitteh/store/v1/svc.proto
+10 −0 proto/autokitteh/user_code/v1/handler_svc.proto
+44 −34 proto/gen/go/autokitteh/connections/v1/connection.pb.go
+30 −4 proto/gen/go/autokitteh/store/v1/storev1connect/svc.connect.go
+177 −44 proto/gen/go/autokitteh/store/v1/svc.pb.go
+478 −333 proto/gen/go/autokitteh/user_code/v1/handler_svc.pb.go
+38 −0 proto/gen/go/autokitteh/user_code/v1/handler_svc_grpc.pb.go
+6 −6 proto/gen/py/autokitteh_pb/connections/v1/connection_pb2.py
+4 −2 proto/gen/py/autokitteh_pb/connections/v1/connection_pb2.pyi
+2 −2 proto/gen/py/autokitteh_pb/store/v1/__init__.py
+9 −3 proto/gen/py/autokitteh_pb/store/v1/svc_pb2.py
+12 −0 proto/gen/py/autokitteh_pb/store/v1/svc_pb2.pyi
+33 −0 proto/gen/py/autokitteh_pb/store/v1/svc_pb2_grpc.py
+6 −0 proto/gen/ts/autokitteh/connections/v1/connection_pb.ts
+10 −1 proto/gen/ts/autokitteh/store/v1/svc_connect.ts
+74 −0 proto/gen/ts/autokitteh/store/v1/svc_pb.ts
+4 −0 runtimes/pythonrt/py-sdk/autokitteh/__init__.py
+20 −0 runtimes/pythonrt/py-sdk/autokitteh/store.py
+1 −1 runtimes/pythonrt/py-sdk/docs/requirements.txt
+2 −2 runtimes/pythonrt/py-sdk/pyproject.toml
+37 −33 runtimes/pythonrt/runner/pb/autokitteh/user_code/v1/handler_svc_pb2.py
+14 −0 runtimes/pythonrt/runner/pb/autokitteh/user_code/v1/handler_svc_pb2.pyi
+43 −0 runtimes/pythonrt/runner/pb/autokitteh/user_code/v1/handler_svc_pb2_grpc.py
+7 −0 runtimes/pythonrt/runner/syscalls.py
+18 −0 runtimes/pythonrt/worker_grpc_handler.go
+16 −0 sdk/sdkclients/sdkstoreclient/client.go
+4 −3 sdk/sdkservices/runtimes.go
+1 −0 sdk/sdkservices/store.go
+17 −1 sdk/sdktypes/connection.go
+7 −0 sdk/sdktypes/event.go
+3 −6 tests/system/testdata/connections/create.txtar
+2 −1 tests/system/testdata/connections/get.txtar
+6 −4 tests/system/testdata/connections/list.txtar
+2 −1 tests/system/testdata/manifest/apply.txtar
+4 −2 tests/system/testdata/store/store.txtar
7 changes: 7 additions & 0 deletions src/components/molecules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,10 @@ export { PlanComparisonTable } from "@components/molecules/planComparisonTable";
export { DiffNavigationToolbar } from "@components/molecules/diffNavigationToolbar";
export { InfoPopover } from "@components/molecules/infoPopover";
export { AddButton } from "@components/molecules/configListAddButton";
export {
TableTanstack,
THeadTanstack,
ThTanstack,
TableRowTanstack,
FilterTableTanstack,
} from "@components/molecules/table";
62 changes: 62 additions & 0 deletions src/components/molecules/table/filterTanstack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { useMemo } from "react";

import debounce from "lodash/debounce";

import { FilterTableTanstackProps, FilterVariantColumnTable, SelectOption } from "@interfaces/components";
import { Input } from "@src/components/atoms";

import { Select } from "@components/molecules";

export const FilterTableTanstack = <TData,>({ column }: FilterTableTanstackProps<TData>) => {
const { filterVariant } = (column.columnDef.meta || {}) as FilterVariantColumnTable;
const columnFilterValue = column.getFilterValue();

const sortedUniqueValues = useMemo(
() => Array.from(column.getFacetedUniqueValues().keys()).sort().slice(0, 5000),
[column]
);

const debouncedSetFilter = useMemo(
() =>
debounce((value: string) => {
column.setFilterValue(value);
}, 300),
[column]
);

if (filterVariant === "select") {
const options: SelectOption[] = sortedUniqueValues.map((value) => ({
label: String(value),
value: String(value),
}));

return (
<div className="rounded-md">
<Select
label="Filter..."
onChange={(selected) => column.setFilterValue(selected?.value)}
options={options}
value={
columnFilterValue
? { label: String(columnFilterValue), value: String(columnFilterValue) }
: null
}
/>
</div>
);
}

if (filterVariant === "search") {
return (
<Input
className="my-0.5 h-8 w-2/3 rounded-md"
label="Search..."
onChange={(e) => debouncedSetFilter(e.target.value)}
type="text"
value={columnFilterValue as string}
/>
);
}

return null;
};
5 changes: 5 additions & 0 deletions src/components/molecules/table/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { ThTanstack } from "@components/molecules/table/tH";
export { THeadTanstack } from "@components/molecules/table/tHead";
export { TableRowTanstack } from "@components/molecules/table/tRowTanstack";
export { TableTanstack } from "@components/molecules/table/tableTanstack";
export { FilterTableTanstack } from "@components/molecules/table/filterTanstack";
100 changes: 100 additions & 0 deletions src/components/molecules/table/tH.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { useId, useCallback } from "react";

import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { flexRender } from "@tanstack/react-table";
import { useTranslation } from "react-i18next";

import { FilterVariantColumnTable, ThTanstackProps } from "@interfaces/components";
import { SortDirectionVariant } from "@src/enums/components";
import { SortDirection as SortDirectionType } from "@src/types/components";
import { cn } from "@src/utilities";

import { ResizeButton } from "@components/atoms";
import { SortButton } from "@components/molecules";
import { FilterTableTanstack } from "@components/molecules/table";

import { GripVerticalIcon } from "@assets/image/icons";

export const ThTanstack = <TData,>({ header, className, enableColumnDnD }: ThTanstackProps<TData>) => {
const { t } = useTranslation("table", { keyPrefix: "tableActions" });
const { filterVariant } = (header.column.columnDef.meta || {}) as FilterVariantColumnTable;
const resizeId = useId();

const isLastColumn = header.column.getIsLastColumn();
const isRowSelection = header.column.id === "rowSelection";
const isActions = header.column.id === "actions";
const enableResize = header.column.getCanResize();
const canSort = header.column.getCanSort();
const isSorted = header.column.getIsSorted() as boolean;
const sortDirection = header.column.getIsSorted() as SortDirectionType;

const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
id: header.column.id,
disabled: !enableColumnDnD,
});

const style = {
transform: transform ? CSS.Translate.toString({ ...transform, y: 0 }) : undefined,
transition,
};

const handleSort = useCallback(() => {
if (!canSort) return;
header.column.toggleSorting(sortDirection === SortDirectionVariant.ASC);
}, [canSort, header.column, sortDirection]);

const thClassName = cn(
"group relative cursor-pointer py-0.5 pr-4 font-normal first:rounded-tl-14 first:pl-4 last:rounded-tr-14",
{ "align-top": filterVariant },
className
);

return (
<th
className={thClassName}
colSpan={header.colSpan}
key={header.id}
onClick={handleSort}
ref={setNodeRef}
style={style}
>
<div className="flex items-center">
{flexRender(header.column.columnDef.header, header.getContext())}
{canSort ? (
<SortButton
ariaLabel={`${t("sortBy")} ${header.column.columnDef.header}`}
className="opacity-0 group-hover:opacity-100"
isActive={isSorted}
sortDirection={sortDirection}
/>
) : null}
{enableColumnDnD && !isRowSelection && !isActions ? (
<button
className="ml-auto cursor-grab opacity-0 transition-opacity duration-200 group-hover:opacity-100"
{...attributes}
{...listeners}
type="button"
>
<GripVerticalIcon className="size-5" />
</button>
) : null}
</div>
{filterVariant ? <FilterTableTanstack column={header.column} /> : null}
{!isLastColumn && !isRowSelection && enableResize ? (
<button
className="absolute right-0 top-0 h-full w-px cursor-ew-resize"
onMouseDown={header.getResizeHandler()}
onTouchStart={header.getResizeHandler()}
type="button"
>
<ResizeButton
className="absolute m-0 size-full p-0 hover:bg-gray-1050"
direction="horizontal"
resizeId={resizeId}
/>
</button>
) : null}
</th>
);
};
37 changes: 37 additions & 0 deletions src/components/molecules/table/tHead.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { useMemo } from "react";

import { ThTanstack } from "./tH";
import { FilterVariantColumnTable, THeadTanstackProps } from "@interfaces/components";
import { cn } from "@utilities";

export const THeadTanstack = <TData,>({ headerGroups, className, enableColumnDnD }: THeadTanstackProps<TData>) => {
const hasAnyFilter = useMemo(
() =>
headerGroups.some((headerGroup) =>
headerGroup.headers.some(
(header) => (header.column.columnDef.meta as FilterVariantColumnTable)?.filterVariant
)
),
[headerGroups]
);

const headStyle = cn(
"sticky top-0 z-10 h-9.5 border-b-2 border-gray-1050 bg-gray-1250 text-left text-gray-500",
{
"align-top leading-7": hasAnyFilter,
},
className
);

return (
<thead className={headStyle}>
{headerGroups.map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<ThTanstack enableColumnDnD={enableColumnDnD} header={header} key={header.id} />
))}
</tr>
))}
</thead>
);
};
32 changes: 32 additions & 0 deletions src/components/molecules/table/tRowTanstack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";

import { flexRender } from "@tanstack/react-table";

import { TableRowTanstackProps } from "@interfaces/components";
import { cn } from "@utilities";

export const TableRowTanstack = <TData,>({ row, className, onRowSelect }: TableRowTanstackProps<TData>) => {
const trStyle = cn(
"cursor-pointer border-y border-transparent hover:bg-gray-1300",
{
"bg-gray-1250/55 border-y border-gray-1200": row.getIsSelected(),
},
className
);

return (
<tr className={trStyle} onClick={() => onRowSelect(row)}>
{row.getVisibleCells().map((cell) => (
<td
className={cn("py-0.5 text-white first:pl-4 last:pr-4")}
key={cell.id}
style={{
width: cell.column.getSize(),
}}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
);
};
41 changes: 41 additions & 0 deletions src/components/molecules/table/tableActions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React, { useMemo } from "react";

import { RowData } from "@tanstack/react-table";
import { useTranslation } from "react-i18next";

import { TableActionsProps } from "@interfaces/components";

import { Button } from "@components/atoms";

export const TableActionsTanstack = <TData extends RowData>({
selectedRows,
actions,
onReset,
}: TableActionsProps<TData>) => {
const { t } = useTranslation("table", { keyPrefix: "tableActions" });

const isShowActions = useMemo(() => {
return selectedRows.length > 0;
}, [selectedRows]);

return (
<div className="flex items-center gap-4">
<div className="flex gap-2">
<Button className="rounded-md bg-black text-white" disabled={!isShowActions} onClick={onReset}>
{t("resetAll")}
</Button>
{isShowActions
? actions?.map((action, index) => (
<Button
className="rounded-md bg-gray-1000 text-white hover:bg-gray-1000/60"
key={index}
onClick={() => action.onClick(selectedRows)}
>
{action.label} ({selectedRows.length})
</Button>
))
: null}
</div>
</div>
);
};
Loading
Loading