Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/dashboard/src/teams/variables/NamedOrganizationEnvvarItem.tsx
2501 views
1
/**
2
* Copyright (c) 2025 Gitpod GmbH. All rights reserved.
3
* Licensed under the GNU Affero General Public License (AGPL).
4
* See License.AGPL.txt in the project root for license information.
5
*/
6
7
import { OrganizationEnvironmentVariable } from "@gitpod/public-api/lib/gitpod/v1/envvar_pb";
8
import { useCallback, useState } from "react";
9
import { OrganizationRemoveEnvvarModal } from "./OrganizationRemoveEnvvarModal";
10
import { InputField } from "../../components/forms/InputField";
11
import { ReactComponent as Stack } from "../../icons/Repository.svg";
12
import { Button } from "@podkit/buttons/Button";
13
import { useCreateOrganizationEnvironmentVariable } from "../../data/organizations/org-envvar-queries";
14
import Modal, { ModalBody, ModalFooter, ModalFooterAlert, ModalHeader } from "../../components/Modal";
15
import { TextInputField } from "../../components/forms/TextInputField";
16
import { useToast } from "../../components/toasts/Toasts";
17
import { LoadingButton } from "@podkit/buttons/LoadingButton";
18
import { MiddleDot } from "../../components/typography/MiddleDot";
19
20
type Props = {
21
disabled?: boolean;
22
organizationId: string;
23
name: string;
24
variable: OrganizationEnvironmentVariable | undefined;
25
};
26
export const NamedOrganizationEnvvarItem = ({ disabled, organizationId, name, variable }: Props) => {
27
const [showRemoveModal, setShowRemoveModal] = useState<boolean>(false);
28
const [showAddModal, setShowAddModal] = useState<boolean>(false);
29
30
const value = variable ? "*****" : "not set";
31
32
return (
33
<>
34
{variable && showRemoveModal && (
35
<OrganizationRemoveEnvvarModal
36
variable={variable}
37
organizationId={organizationId}
38
onClose={() => setShowRemoveModal(false)}
39
/>
40
)}
41
42
{showAddModal && (
43
<AddOrgEnvironmentVariableModal
44
organizationId={organizationId}
45
staticName={name}
46
onClose={() => setShowAddModal(false)}
47
/>
48
)}
49
50
<InputField disabled={disabled} className="w-full max-w-lg">
51
<div className="flex flex-col bg-pk-surface-secondary p-3 rounded-lg">
52
<div className="flex items-center justify-between">
53
<div className="flex-1 flex items-center overflow-hidden h-8 gap-2" title={value}>
54
<Stack className="w-5 h-5" />
55
<span className="truncate font-medium text-pk-content-secondary">{name}</span>
56
</div>
57
{!disabled && !variable && (
58
<Button variant="link" onClick={() => setShowAddModal(true)}>
59
Add
60
</Button>
61
)}
62
{!disabled && variable && (
63
<Button variant="link" onClick={() => setShowRemoveModal(true)}>
64
Delete
65
</Button>
66
)}
67
</div>
68
<div className="mx-7 text-pk-content-tertiary truncate">
69
{value}
70
{disabled && (
71
<>
72
<MiddleDot />
73
Requires <span className="font-medium">Owner</span> permissions to change
74
</>
75
)}
76
</div>
77
</div>
78
</InputField>
79
</>
80
);
81
};
82
83
type AddOrgEnvironmentVariableModalProps = {
84
organizationId: string;
85
staticName?: string;
86
onClose: () => void;
87
};
88
export const AddOrgEnvironmentVariableModal = ({
89
organizationId,
90
staticName,
91
onClose,
92
}: AddOrgEnvironmentVariableModalProps) => {
93
const { toast } = useToast();
94
95
const [name, setName] = useState(staticName || "");
96
const [value, setValue] = useState("");
97
const createVariable = useCreateOrganizationEnvironmentVariable();
98
99
const addVariable = useCallback(() => {
100
createVariable.mutateAsync(
101
{
102
organizationId,
103
name,
104
value,
105
},
106
{
107
onSuccess: () => {
108
toast("Variable added");
109
onClose();
110
},
111
},
112
);
113
}, [createVariable, organizationId, name, value, onClose, toast]);
114
115
return (
116
<Modal visible onClose={onClose} onSubmit={addVariable}>
117
<ModalHeader>Add a variable</ModalHeader>
118
<ModalBody>
119
<div>
120
<TextInputField
121
disabled={staticName !== undefined}
122
label="Name"
123
autoComplete={"off"}
124
className="w-full"
125
value={name}
126
placeholder="Variable name"
127
onChange={(name) => setName(name)}
128
autoFocus
129
required
130
/>
131
</div>
132
<div className="mt-4">
133
<TextInputField
134
label="Value"
135
autoComplete={"off"}
136
className="w-full"
137
value={value}
138
placeholder="Variable value"
139
onChange={(value) => setValue(value)}
140
required
141
/>
142
</div>
143
</ModalBody>
144
<ModalFooter
145
alert={
146
createVariable.isError ? (
147
<ModalFooterAlert type="danger">
148
{String(createVariable.error).replace(/Error: Request \w+ failed with message: /, "")}
149
</ModalFooterAlert>
150
) : null
151
}
152
>
153
<Button variant="secondary" onClick={onClose}>
154
Cancel
155
</Button>
156
<LoadingButton type="submit" loading={createVariable.isLoading}>
157
Add Variable
158
</LoadingButton>
159
</ModalFooter>
160
</Modal>
161
);
162
};
163
164