mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 17:26:36 +00:00
Merge pull request #1678 from Infisical/daniel/workspace-endpoint-fix
FIx: Fetching workspaces with no environments
This commit is contained in:
@@ -126,13 +126,11 @@ export const projectDALFactory = (db: TDbClient) => {
|
|||||||
|
|
||||||
const findProjectById = async (id: string) => {
|
const findProjectById = async (id: string) => {
|
||||||
try {
|
try {
|
||||||
const workspaces = await db(TableName.ProjectMembership)
|
const workspaces = await db(TableName.Project)
|
||||||
.where(`${TableName.Project}.id`, id)
|
.where(`${TableName.Project}.id`, id)
|
||||||
.join(TableName.Project, `${TableName.ProjectMembership}.projectId`, `${TableName.Project}.id`)
|
.leftJoin(TableName.Environment, `${TableName.Environment}.projectId`, `${TableName.Project}.id`)
|
||||||
.join(TableName.Environment, `${TableName.Environment}.projectId`, `${TableName.Project}.id`)
|
|
||||||
.select(
|
.select(
|
||||||
selectAllTableCols(TableName.Project),
|
selectAllTableCols(TableName.Project),
|
||||||
db.ref("id").withSchema(TableName.Project).as("_id"),
|
|
||||||
db.ref("id").withSchema(TableName.Environment).as("envId"),
|
db.ref("id").withSchema(TableName.Environment).as("envId"),
|
||||||
db.ref("slug").withSchema(TableName.Environment).as("envSlug"),
|
db.ref("slug").withSchema(TableName.Environment).as("envSlug"),
|
||||||
db.ref("name").withSchema(TableName.Environment).as("envName")
|
db.ref("name").withSchema(TableName.Environment).as("envName")
|
||||||
@@ -141,10 +139,11 @@ export const projectDALFactory = (db: TDbClient) => {
|
|||||||
{ column: `${TableName.Project}.name`, order: "asc" },
|
{ column: `${TableName.Project}.name`, order: "asc" },
|
||||||
{ column: `${TableName.Environment}.position`, order: "asc" }
|
{ column: `${TableName.Environment}.position`, order: "asc" }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const project = sqlNestRelationships({
|
const project = sqlNestRelationships({
|
||||||
data: workspaces,
|
data: workspaces,
|
||||||
key: "id",
|
key: "id",
|
||||||
parentMapper: ({ _id, ...el }) => ({ _id, ...ProjectsSchema.parse(el) }),
|
parentMapper: ({ ...el }) => ({ _id: el.id, ...ProjectsSchema.parse(el) }),
|
||||||
childrenMapper: [
|
childrenMapper: [
|
||||||
{
|
{
|
||||||
key: "envId",
|
key: "envId",
|
||||||
@@ -174,14 +173,12 @@ export const projectDALFactory = (db: TDbClient) => {
|
|||||||
throw new BadRequestError({ message: "Organization ID is required when querying with slugs" });
|
throw new BadRequestError({ message: "Organization ID is required when querying with slugs" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const projects = await db(TableName.ProjectMembership)
|
const projects = await db(TableName.Project)
|
||||||
.where(`${TableName.Project}.slug`, slug)
|
.where(`${TableName.Project}.slug`, slug)
|
||||||
.where(`${TableName.Project}.orgId`, orgId)
|
.where(`${TableName.Project}.orgId`, orgId)
|
||||||
.join(TableName.Project, `${TableName.ProjectMembership}.projectId`, `${TableName.Project}.id`)
|
.leftJoin(TableName.Environment, `${TableName.Environment}.projectId`, `${TableName.Project}.id`)
|
||||||
.join(TableName.Environment, `${TableName.Environment}.projectId`, `${TableName.Project}.id`)
|
|
||||||
.select(
|
.select(
|
||||||
selectAllTableCols(TableName.Project),
|
selectAllTableCols(TableName.Project),
|
||||||
db.ref("id").withSchema(TableName.Project).as("_id"),
|
|
||||||
db.ref("id").withSchema(TableName.Environment).as("envId"),
|
db.ref("id").withSchema(TableName.Environment).as("envId"),
|
||||||
db.ref("slug").withSchema(TableName.Environment).as("envSlug"),
|
db.ref("slug").withSchema(TableName.Environment).as("envSlug"),
|
||||||
db.ref("name").withSchema(TableName.Environment).as("envName")
|
db.ref("name").withSchema(TableName.Environment).as("envName")
|
||||||
@@ -194,7 +191,7 @@ export const projectDALFactory = (db: TDbClient) => {
|
|||||||
const project = sqlNestRelationships({
|
const project = sqlNestRelationships({
|
||||||
data: projects,
|
data: projects,
|
||||||
key: "id",
|
key: "id",
|
||||||
parentMapper: ({ _id, ...el }) => ({ _id, ...ProjectsSchema.parse(el) }),
|
parentMapper: ({ ...el }) => ({ _id: el.id, ...ProjectsSchema.parse(el) }),
|
||||||
childrenMapper: [
|
childrenMapper: [
|
||||||
{
|
{
|
||||||
key: "envId",
|
key: "envId",
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
|
import { Button } from "../v2";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
projectId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NoEnvironmentsBanner = ({ projectId }: IProps) => {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-4 flex w-full flex-row items-center rounded-md border border-primary-600/70 bg-primary/[.07] p-4 text-base text-white">
|
||||||
|
<div className="flex w-full flex-col text-sm">
|
||||||
|
<span className="mb-2 text-lg font-semibold">
|
||||||
|
No environments in your project was found
|
||||||
|
</span>
|
||||||
|
<p className="prose">
|
||||||
|
In order to use integrations, you need to create at least one environment in your project.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="my-2">
|
||||||
|
<Button onClick={() => router.push(`/project/${projectId}/settings#environments`)}>
|
||||||
|
Add environments
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
+24
-3
@@ -1,10 +1,17 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { faCheck, faXmark } from "@fortawesome/free-solid-svg-icons";
|
import { faCheck, faXmark } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
|
import { NoEnvironmentsBanner } from "@app/components/integrations/NoEnvironmentsBanner";
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { DeleteActionModal, Skeleton, Tooltip } from "@app/components/v2";
|
import { DeleteActionModal, Skeleton, Tooltip } from "@app/components/v2";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub, useProjectPermission } from "@app/context";
|
import {
|
||||||
|
ProjectPermissionActions,
|
||||||
|
ProjectPermissionSub,
|
||||||
|
useProjectPermission,
|
||||||
|
useWorkspace
|
||||||
|
} from "@app/context";
|
||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
import { IntegrationAuth, TCloudIntegration } from "@app/hooks/api/types";
|
import { IntegrationAuth, TCloudIntegration } from "@app/hooks/api/types";
|
||||||
|
|
||||||
@@ -31,18 +38,32 @@ export const CloudIntegrationSection = ({
|
|||||||
"deleteConfirmation"
|
"deleteConfirmation"
|
||||||
] as const);
|
] as const);
|
||||||
const { permission } = useProjectPermission();
|
const { permission } = useProjectPermission();
|
||||||
|
const { currentWorkspace } = useWorkspace();
|
||||||
|
|
||||||
const isEmpty = !isLoading && !cloudIntegrations?.length;
|
const isEmpty = !isLoading && !cloudIntegrations?.length;
|
||||||
|
|
||||||
const sortedCloudIntegrations = cloudIntegrations.sort((a, b) => a.name.localeCompare(b.name));
|
const sortedCloudIntegrations = useMemo(() => {
|
||||||
|
const sortedIntegrations = cloudIntegrations.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
|
||||||
|
if (currentWorkspace?.environments.length === 0) {
|
||||||
|
return sortedIntegrations.map((integration) => ({ ...integration, isAvailable: false }));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortedIntegrations;
|
||||||
|
}, [cloudIntegrations, currentWorkspace?.environments]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<div className="px-5">
|
||||||
|
{currentWorkspace?.environments.length === 0 && (
|
||||||
|
<NoEnvironmentsBanner projectId={currentWorkspace.id} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<div className="m-4 mt-7 flex max-w-5xl flex-col items-start justify-between px-2 text-xl">
|
<div className="m-4 mt-7 flex max-w-5xl flex-col items-start justify-between px-2 text-xl">
|
||||||
<h1 className="text-3xl font-semibold">{t("integrations.cloud-integrations")}</h1>
|
<h1 className="text-3xl font-semibold">{t("integrations.cloud-integrations")}</h1>
|
||||||
<p className="text-base text-gray-400">{t("integrations.click-to-start")}</p>
|
<p className="text-base text-gray-400">{t("integrations.click-to-start")}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mx-6 grid grid-cols-2 gap-4 lg:grid-cols-3 2xl:grid-cols-4">
|
<div className="mx-6 grid grid-cols-2 gap-4 lg:grid-cols-3 2xl:grid-cols-4">
|
||||||
{isLoading &&
|
{isLoading &&
|
||||||
Array.from({ length: 12 }).map((_, index) => (
|
Array.from({ length: 12 }).map((_, index) => (
|
||||||
|
|||||||
Reference in New Issue
Block a user