1- import { For , type Signal , createSignal } from "solid-js" ;
1+ import { For , Show , type Signal , createEffect , createSignal } from "solid-js" ;
22import { TrashIcon } from "@deploy-cat/heroicons-solid/24/solid/esm" ;
3+ import { cache , createAsync } from "@solidjs/router" ;
4+ import { getUser } from "~/lib/auth" ;
5+ import { k8sCore } from "~/lib/k8s" ;
6+ import { CircleStackIcon } from "@deploy-cat/heroicons-solid/24/solid/esm" ;
7+
8+ const getDatabseSecrets = cache ( async ( ) => {
9+ "use server" ;
10+ try {
11+ const user = await getUser ( ) ;
12+ const secrets = await k8sCore . listNamespacedSecret (
13+ user . name ,
14+ undefined ,
15+ undefined ,
16+ undefined ,
17+ undefined ,
18+ "cnpg.io/cluster"
19+ ) ;
20+ return secrets . body . items . map ( ( { data, metadata : { name, labels } } ) => ( {
21+ name,
22+ labels,
23+ values : Object . keys ( data ) ,
24+ } ) ) ;
25+ } catch ( e ) {
26+ console . error ( e ) ;
27+ }
28+ } , "db-secrets" ) ;
329
430const parseClipboard = ( text : string ) =>
531 text
@@ -14,13 +40,46 @@ const parseClipboard = (text: string) =>
1440 } ) ;
1541
1642export const EnvVarsInput = ( { data } ) => {
43+ const dbSecrets = createAsync ( ( ) => getDatabseSecrets ( ) ) ;
44+
1745 const [ env , setEnv ] = createSignal (
1846 ( data &&
19- Object . entries ( data ) . map ( ( [ key , value ] ) => ( {
20- key : createSignal ( key ) ,
21- value : createSignal ( value ) ,
22- } ) ) ) ??
23- ( [ ] as Array < { key : Signal < string > ; value : Signal < string > } > )
47+ Object . entries ( data ) . map ( ( [ k , v ] ) => {
48+ if ( typeof v == "string" ) {
49+ return {
50+ key : createSignal ( k ) ,
51+ value : createSignal ( v ) ,
52+ } ;
53+ }
54+
55+ const value = createSignal ( {
56+ secretKeyRef : {
57+ name : v . valueFrom . secretKeyRef . name ,
58+ key : v . valueFrom . secretKeyRef . key ,
59+ } ,
60+ } as any ) ;
61+ const secretName = createSignal ( v . valueFrom . secretKeyRef . name ) ;
62+ const secretKey = createSignal ( v . valueFrom . secretKeyRef . key ) ;
63+
64+ createEffect ( ( ) => {
65+ value [ 1 ] ( {
66+ valueFrom : {
67+ secretKeyRef : {
68+ name : secretName [ 0 ] ( ) ,
69+ key : secretKey [ 0 ] ( ) ,
70+ } ,
71+ } ,
72+ } ) ;
73+ } ) ;
74+ return {
75+ key : createSignal ( k ) ,
76+ value,
77+ type : "secret" ,
78+ secretName,
79+ secretKey,
80+ } ;
81+ } ) ) ??
82+ ( [ ] as Array < { key : Signal < string > ; value : Signal < string | any > } > )
2483 ) ;
2584
2685 return (
@@ -53,32 +112,95 @@ export const EnvVarsInput = ({ data }) => {
53112 </ div >
54113 }
55114 >
56- { ( { key, value } , index ) => (
57- < div class = "join my-1" >
58- < input
59- type = "text"
60- value = { key [ 0 ] ( ) }
61- onInput = { ( event ) => key [ 1 ] ( event . target . value ) }
62- class = "input input-bordered join-item w-32"
63- placeholder = "Env"
64- required
65- />
66- < input
67- type = "text"
68- name = { `env-${ key [ 0 ] ( ) } }` }
69- value = { value [ 0 ] ( ) }
70- onInput = { ( event ) => value [ 1 ] ( event . target . value ) }
71- class = "input select-bordered join-item w-full"
72- placeholder = "Value"
73- />
74- < div
75- class = "btn btn-error join-item"
76- tabindex = { 0 }
77- onClick = { ( ) => setEnv ( env ( ) . filter ( ( _ , i ) => i !== index ( ) ) ) }
78- >
79- < TrashIcon class = "flex-shrink-0 w-5 h-5" />
80- </ div >
81- </ div >
115+ { ( { key, value, type, secretKey, secretName } , index ) => (
116+ < >
117+ < Show when = { ! type } >
118+ < div class = "join my-1" >
119+ < input
120+ type = "text"
121+ value = { key [ 0 ] ( ) }
122+ onInput = { ( event ) => key [ 1 ] ( event . target . value ) }
123+ class = "input input-bordered join-item w-32"
124+ placeholder = "Env"
125+ required
126+ />
127+ < input
128+ type = "text"
129+ name = { `env-${ key [ 0 ] ( ) } }` }
130+ value = { value [ 0 ] ( ) }
131+ onInput = { ( event ) => value [ 1 ] ( event . target . value ) }
132+ class = "input select-bordered join-item w-full"
133+ placeholder = "Value"
134+ />
135+ < div
136+ class = "btn btn-error join-item"
137+ tabindex = { 0 }
138+ onClick = { ( ) =>
139+ setEnv ( env ( ) . filter ( ( _ , i ) => i !== index ( ) ) )
140+ }
141+ >
142+ < TrashIcon class = "flex-shrink-0 w-5 h-5" />
143+ </ div >
144+ </ div >
145+ </ Show >
146+ < Show when = { type === "secret" } >
147+ < div class = "join my-1" >
148+ < input
149+ type = "text"
150+ value = { key [ 0 ] ( ) }
151+ onInput = { ( event ) => key [ 1 ] ( event . target . value ) }
152+ class = "input input-bordered join-item w-32"
153+ placeholder = "Env"
154+ required
155+ />
156+ < select
157+ onchange = { ( event ) => secretName [ 1 ] ( event . target . value ) }
158+ class = "select select-bordered join-item"
159+ >
160+ < For each = { dbSecrets ( ) } >
161+ { ( secret ) => (
162+ < option
163+ selected = { value === secretName [ 0 ] ( ) }
164+ value = { secret . name }
165+ >
166+ { secret . labels [ "cnpg.io/cluster" ] } (cnpg)
167+ </ option >
168+ ) }
169+ </ For >
170+ </ select >
171+ < select
172+ onchange = { ( event ) => secretKey [ 1 ] ( event . target . value ) }
173+ class = "select select-bordered join-item w-full"
174+ >
175+ < For
176+ each = {
177+ dbSecrets ( ) ?. find (
178+ ( secret ) => secret . name === secretName [ 0 ] ( )
179+ ) ?. values
180+ }
181+ >
182+ { ( value ) => (
183+ < option
184+ selected = { value === secretKey [ 0 ] ( ) }
185+ value = { value }
186+ >
187+ { value }
188+ </ option >
189+ ) }
190+ </ For >
191+ </ select >
192+ < div
193+ class = "btn btn-error join-item"
194+ tabindex = { 0 }
195+ onClick = { ( ) =>
196+ setEnv ( env ( ) . filter ( ( _ , i ) => i !== index ( ) ) )
197+ }
198+ >
199+ < TrashIcon class = "flex-shrink-0 w-5 h-5" />
200+ </ div >
201+ </ div >
202+ </ Show >
203+ </ >
82204 ) }
83205 </ For >
84206
@@ -98,6 +220,38 @@ export const EnvVarsInput = ({ data }) => {
98220 >
99221 Add Variable
100222 </ div >
223+ < div
224+ class = "btn btn-outline btn-secondary join-item"
225+ tabindex = { 0 }
226+ onClick = { ( ) => {
227+ const value = createSignal ( "" ) ;
228+ const secretName = createSignal ( dbSecrets ( ) ?. [ 0 ] ?. name ) ;
229+ const secretKey = createSignal ( "" ) ;
230+
231+ createEffect ( ( ) => {
232+ value [ 1 ] ( {
233+ valueFrom : {
234+ secretKeyRef : {
235+ name : secretName [ 0 ] ( ) ,
236+ key : secretKey [ 0 ] ( ) ,
237+ } ,
238+ } ,
239+ } ) ;
240+ } ) ;
241+ setEnv ( [
242+ ...env ( ) ,
243+ {
244+ key : createSignal ( "" ) ,
245+ value,
246+ type : "secret" ,
247+ secretName,
248+ secretKey,
249+ } ,
250+ ] ) ;
251+ } }
252+ >
253+ Add Secret
254+ </ div >
101255 { /* <div
102256 class="btn btn-outline btn-secondary join-item"
103257 onClick={async () =>
@@ -107,6 +261,20 @@ export const EnvVarsInput = ({ data }) => {
107261 Paste Env File
108262 </div> */ }
109263 </ div >
264+ { /* <div class="join">
265+ <select class="select select-bordered join-item">
266+ <For each={dbSecrets()}>
267+ {(secret) => (
268+ <option value={secret.name}>
269+ {secret.labels["cnpg.io/cluster"]}
270+ </option>
271+ )}
272+ </For>
273+ </select>
274+ <button class="btn join-item btn-info btn-outline">
275+ Connect Postgres
276+ </button>
277+ </div> */ }
110278 </ div >
111279 </ >
112280 ) ;
0 commit comments