77 onCleanup ,
88} from "solid-js" ;
99import { unwrap } from "solid-js/store" ;
10- import { Button , buttonVariants } from "~/components/ui/button" ;
10+ import { Button } from "~/components/ui/button" ;
1111import { createArchive , toConfigBlob } from "~/lib/download" ;
1212import { findPresetByName } from "~/lib/presets" ;
1313import {
@@ -20,12 +20,17 @@ import {
2020import { ExperimentConfigForm } from "./ExperimentConfigForm" ;
2121import { ObservationsList } from "./ObservationsList" ;
2222import { PermutationsList } from "./PermutationsList" ;
23- import { MdiCog , MdiContentCopy , MdiDelete , MdiDownload } from "./icons" ;
23+ import {
24+ MdiCog ,
25+ MdiContentCopy ,
26+ MdiDelete ,
27+ MdiDotsHorizontal ,
28+ MdiDownload ,
29+ } from "./icons" ;
2430import {
2531 Card ,
2632 CardContent ,
2733 CardDescription ,
28- CardFooter ,
2934 CardHeader ,
3035 CardTitle ,
3136} from "./ui/card" ;
@@ -41,6 +46,10 @@ import {
4146 DropdownMenu ,
4247 DropdownMenuContent ,
4348 DropdownMenuItem ,
49+ DropdownMenuPortal ,
50+ DropdownMenuSub ,
51+ DropdownMenuSubContent ,
52+ DropdownMenuSubTrigger ,
4453 DropdownMenuTrigger ,
4554} from "./ui/dropdown-menu" ;
4655
@@ -203,27 +212,6 @@ function DownloadExperimentArchive(props: { experiment: Experiment }) {
203212 ) ;
204213}
205214
206- function DownloadExperiment ( props : { experiment : Experiment } ) {
207- return (
208- < DropdownMenu >
209- < DropdownMenuTrigger
210- class = { buttonVariants ( { variant : "outline" } ) }
211- title = "Download"
212- >
213- < MdiDownload />
214- </ DropdownMenuTrigger >
215- < DropdownMenuContent >
216- < DropdownMenuItem >
217- < DownloadExperimentConfiguration experiment = { props . experiment } />
218- </ DropdownMenuItem >
219- < DropdownMenuItem >
220- < DownloadExperimentArchive experiment = { props . experiment } />
221- </ DropdownMenuItem >
222- </ DropdownMenuContent >
223- </ DropdownMenu >
224- ) ;
225- }
226-
227215export function ExperimentCard ( props : {
228216 experiment : Experiment ;
229217 experimentIndex : number ;
@@ -234,58 +222,92 @@ export function ExperimentCard(props: {
234222 const descriptionId = `${ id } -description` ;
235223 return (
236224 < Card
237- class = "w-[380px ]"
225+ class = "min- w-[320px ]"
238226 role = "article"
239227 aria-labelledby = { id }
240228 aria-describedby = { descriptionId }
241229 >
242- < CardHeader >
230+ < CardHeader class = "flex-row items-center justify-between gap-4 py-2" >
231+ { /* Card title and buttons */ }
243232 < CardTitle id = { id } > { experiment ( ) . config . reference . name } </ CardTitle >
244- < CardDescription id = { descriptionId } >
245- { experiment ( ) . config . reference . description }
246- </ CardDescription >
233+ < div class = "flex gap-1" >
234+ < Show
235+ when = { ! experiment ( ) . output . running }
236+ fallback = {
237+ < RunningIndicator progress = { experiment ( ) . output . running } />
238+ }
239+ >
240+ < ExperimentSettingsDialog
241+ experiment = { experiment ( ) }
242+ experimentIndex = { experimentIndex ( ) }
243+ />
244+ < DropdownMenu >
245+ < DropdownMenuTrigger as = { Button } variant = "outline" >
246+ < MdiDotsHorizontal />
247+ </ DropdownMenuTrigger >
248+ < DropdownMenuContent >
249+ < DropdownMenuSub overlap >
250+ < DropdownMenuSubTrigger >
251+ { " " }
252+ < div class = "flex items-end gap-1" >
253+ < MdiDownload />
254+ Download{ " " }
255+ </ div > { " " }
256+ </ DropdownMenuSubTrigger >
257+ < DropdownMenuPortal >
258+ < DropdownMenuSubContent >
259+ < DropdownMenuItem >
260+ < DownloadExperimentConfiguration
261+ experiment = { props . experiment }
262+ />
263+ </ DropdownMenuItem >
264+ < DropdownMenuItem >
265+ < DownloadExperimentArchive
266+ experiment = { props . experiment }
267+ />
268+ </ DropdownMenuItem >
269+ </ DropdownMenuSubContent >
270+ </ DropdownMenuPortal >
271+ </ DropdownMenuSub >
272+ < DropdownMenuItem
273+ class = "flex gap-2"
274+ onSelect = { ( ) => {
275+ duplicateExperiment ( experimentIndex ( ) ) ;
276+ } }
277+ >
278+ < MdiContentCopy />
279+ Duplicate experiment
280+ </ DropdownMenuItem >
281+ < DropdownMenuItem
282+ class = "flex gap-2"
283+ onSelect = { ( ) => {
284+ if (
285+ window . confirm (
286+ "Are you sure you want to delete this experiment?" ,
287+ )
288+ ) {
289+ deleteExperiment ( experimentIndex ( ) ) ;
290+ }
291+ } }
292+ >
293+ < MdiDelete />
294+ Delete experiment
295+ </ DropdownMenuItem >
296+ </ DropdownMenuContent >
297+ </ DropdownMenu >
298+ </ Show >
299+ </ div >
247300 </ CardHeader >
248301 < CardContent class = "text-left" >
302+ < CardDescription class = "pb-4 text-left" id = { descriptionId } >
303+ { experiment ( ) . config . reference . description }
304+ </ CardDescription >
249305 < PermutationsList
250306 experiment = { experiment ( ) }
251307 experimentIndex = { experimentIndex ( ) }
252308 />
253309 < ObservationsList observations = { experiment ( ) . config . observations } />
254310 </ CardContent >
255- < CardFooter class = "gap-1" >
256- < Show
257- when = { ! experiment ( ) . output . running }
258- fallback = { < RunningIndicator progress = { experiment ( ) . output . running } /> }
259- >
260- < DownloadExperiment experiment = { experiment ( ) } />
261- < ExperimentSettingsDialog
262- experiment = { experiment ( ) }
263- experimentIndex = { experimentIndex ( ) }
264- />
265- < Button
266- variant = "outline"
267- title = "Duplicate experiment"
268- onClick = { ( ) => duplicateExperiment ( experimentIndex ( ) ) }
269- >
270- < MdiContentCopy />
271- </ Button >
272- < Button
273- variant = "outline"
274- title = "Delete experiment"
275- onClick = { ( ) => {
276- if (
277- window . confirm (
278- "Are you sure you want to delete this experiment?" ,
279- )
280- ) {
281- deleteExperiment ( experimentIndex ( ) ) ;
282- }
283- } }
284- >
285- < MdiDelete />
286- </ Button >
287- </ Show >
288- </ CardFooter >
289311 </ Card >
290312 ) ;
291313}
0 commit comments