Skip to content

Commit

Permalink
Lockfile upload (#401)
Browse files Browse the repository at this point in the history
* Support creating lockfile envs

* Remove redundant import

* Update state

* Remove workarounds that are no longer needed

* Handle `is_lockfile` in test

* Initial edit spec support

* Send updated spec to server

* Get channels from lockfile

* Get dependencies from lockfile

* gabs edits

* Add warning about no syncing between lockfile and GUI

* Revert unneeded changes

* Working proof of concept: lockfile upload

* Switch to lockfile/specification

* Show dependencies and channels for lockfile-built envs

* reset SpecificationEdit when switching builds

* Kim's suggestions

- On VIEW page for environment built from lockfile, show link to lockfile
- In specification mode of EDIT page for environment built from lockfile,
  show clean slate

* Show installed dependencies and channels on view environment built from lockfile

* lint

* yarn install

* yarn install (with correct version of yarn this time)

* note about file formats

* lint

* Three changes:

- pull info out from details/summary
- restyle cancel/continue buttons on alert dialog
- restyle "switch to" buttons and move up

* update yarn.lock

* Fix Docker Compose for GitHub Actions

---------

Co-authored-by: Nikita Karetnikov <[email protected]>
  • Loading branch information
gabalafou and nkaretnikov authored Aug 10, 2024
1 parent 5dabe4f commit 0885e02
Show file tree
Hide file tree
Showing 21 changed files with 3,202 additions and 4,237 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"date-fns-tz": "^1.3.7",
"lodash": "^4.17.21",
"match-sorter": "^6.3.1",
"mui-file-dropzone": "^4.0.2",
"react": "^18.0.0",
"react-beautiful-dnd": "^13.1.0",
"react-dom": "^18.0.0",
Expand Down
4 changes: 3 additions & 1 deletion src/common/models/CondaSpecification.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { CondaSpecificationPip } from "./CondaSpecificationPip";
import type { CondaSpecificationPip } from "./CondaSpecificationPip";
import type { Lockfile } from "./Lockfile";

export type CondaSpecification = {
name: string;
channels: string[];
dependencies: (string | CondaSpecificationPip)[];
variables: Record<string, string>;
prefix?: string | null;
lockfile?: Lockfile;
};
2 changes: 2 additions & 0 deletions src/common/models/Lockfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// TODO: define lockfile type better
export type Lockfile = Record<string, any>;
1 change: 1 addition & 0 deletions src/common/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export * from "./Artifact";
export * from "./BuildPackage";
export * from "./BuildArtifact";
export * from "./Namespace";
export * from "./Lockfile";
96 changes: 56 additions & 40 deletions src/components/BlockContainerEditMode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,23 @@ import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import { CodeIcon } from "../components";
import { StyledSwitch } from "../styles";
import Button from "@mui/material/Button";
import UploadFileRoundedIcon from "@mui/icons-material/UploadFileRounded";

interface IBlockContainerProps {
title: string;
children: React.ReactNode;
onToggleEditMode: (show: boolean) => void;
isEditMode: boolean;
setShowDialog: (show: boolean) => void;
}

export const BlockContainerEditMode = ({
title,
children,
onToggleEditMode,
isEditMode
isEditMode,
setShowDialog
}: IBlockContainerProps) => {
return (
<Box
Expand Down Expand Up @@ -44,46 +48,58 @@ export const BlockContainerEditMode = ({
>
{title}
</Typography>
<Grid
component="label"
container
spacing={1}
justifyContent={"center"}
sx={{ width: "auto" }}
>
<Grid item sx={{ alignSelf: "baseline" }}>
<Typography
data-testid="block-container-title"
sx={{
fontSize: "14px",
color: "#333",
fontWeight: isEditMode ? "400" : "600"
}}
>
GUI
</Typography>
</Grid>
<Grid item sx={{ alignSelf: "baseline" }}>
<StyledSwitch
checked={isEditMode}
onClick={e => onToggleEditMode(!isEditMode)}
icon={<CodeIcon />}
checkedIcon={<CodeIcon />}
/>
</Grid>
<Grid item sx={{ alignSelf: "baseline" }}>
<Typography
data-testid="block-container-title"
sx={{
fontSize: "14px",
color: "#333",
fontWeight: isEditMode ? "600" : "400"
}}
>
YAML
</Typography>
<Box display="flex" alignItems="center">
<Button
variant="outlined"
color="secondary"
size="small"
startIcon={<UploadFileRoundedIcon />}
onClick={() => setShowDialog(true)}
sx={{ mx: "1em" }}
>
Switch to Conda Lockfile Upload
</Button>{" "}
<Grid
component="label"
container
spacing={1}
justifyContent={"center"}
sx={{ width: "auto" }}
>
<Grid item sx={{ alignSelf: "baseline" }}>
<Typography
data-testid="block-container-title"
sx={{
fontSize: "14px",
color: "#333",
fontWeight: isEditMode ? "400" : "600"
}}
>
GUI
</Typography>
</Grid>
<Grid item sx={{ alignSelf: "baseline" }}>
<StyledSwitch
checked={isEditMode}
onClick={e => onToggleEditMode(!isEditMode)}
icon={<CodeIcon />}
checkedIcon={<CodeIcon />}
/>
</Grid>
<Grid item sx={{ alignSelf: "baseline" }}>
<Typography
data-testid="block-container-title"
sx={{
fontSize: "14px",
color: "#333",
fontWeight: isEditMode ? "600" : "400"
}}
>
YAML
</Typography>
</Grid>
</Grid>
</Grid>
</Box>
</Box>
</Box>
<Box
Expand Down
17 changes: 12 additions & 5 deletions src/components/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import Button from "@mui/material/Button";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
Expand All @@ -12,14 +13,16 @@ interface IAlertDialog {
isOpen: boolean;
closeAction: () => void;
confirmAction: () => void;
confirmText?: string;
}

export const AlertDialog = ({
title,
description,
isOpen,
closeAction,
confirmAction
confirmAction,
confirmText = "Delete"
}: IAlertDialog) => {
return (
<Dialog open={isOpen} onClose={closeAction}>
Expand All @@ -45,11 +48,15 @@ export const AlertDialog = ({
</DialogContentText>
</DialogContent>
<DialogActions>
<StyledButton color="primary" onClick={closeAction}>
<Button color="secondary" onClick={closeAction}>
Cancel
</StyledButton>
<StyledButton color="primary" onClick={() => confirmAction()}>
Delete
</Button>
<StyledButton
color="primary"
onClick={() => confirmAction()}
sx={{ textTransform: "uppercase" }}
>
{confirmText}
</StyledButton>
</DialogActions>
</Dialog>
Expand Down
18 changes: 18 additions & 0 deletions src/components/LockfileSupportInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from "react";
import Typography from "@mui/material/Typography";

export const LockfileSupportInfo = () => (
<Typography sx={{ fontSize: "12px" }}>
We currently only support the{" "}
<a
href="https://conda.github.io/conda-lock/"
target="_blank"
rel="noreferrer"
>
Conda lockfile
</a>{" "}
format. Other lockfile formats such as Poetry are not supported.
</Typography>
);

export default LockfileSupportInfo;
15 changes: 12 additions & 3 deletions src/features/channels/channelsSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,22 @@ export const channelsSlice = createSlice({
{
payload: {
data: {
specification: {
spec: { channels }
}
specification: { spec }
}
}
}
) => {
let channels = [];

if (spec.channels) {
channels = spec.channels;
} else if (spec.lockfile?.metadata?.channels) {
channels = spec.lockfile.metadata.channels.map(
// Note: in the lockfile spec, a channel URL can be a string identifier like "conda-forge"
(channel: { url: string }) => channel.url
);
}

state.channels = channels;
}
);
Expand Down
5 changes: 4 additions & 1 deletion src/features/dependencies/components/Dependencies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ export const Dependencies = ({
<StyledAccordionSummary expandIcon={<ArrowIcon />}>
<StyledAccordionTitle sx={{ color: "primary.main" }}>
Installed Packages{" "}
<Tooltip title="Includes requested packages and their dependencies">
<Tooltip
title="Includes requested packages and their dependencies"
tabIndex={0}
>
<InfoOutlinedIcon
sx={{
fontSize: "20px",
Expand Down
27 changes: 20 additions & 7 deletions src/features/environmentCreate/components/EnvironmentCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,27 @@ export const EnvironmentCreate = () => {
dispatch(descriptionChanged(value));
}, 300);

const createEnvironment = async (code: ICreateEnvironmentArgs) => {
const createEnvironment = async (code: ICreateEnvironmentArgs | string) => {
const namespace = newEnvironment?.namespace;
const environmentInfo = {
namespace,
specification: `${stringify(
code
)}\ndescription: '${description}'\nname: ${name}\nprefix: null`
};
const isLockfile = typeof code === "string";

let environmentInfo;
if (isLockfile) {
environmentInfo = {
namespace,
specification: code,
environment_name: name,
environment_description: description,
is_lockfile: true
};
} else {
environmentInfo = {
namespace,
specification: `${stringify(
code
)}\ndescription: '${description}'\nname: ${name}\nprefix: null`
};
}

try {
const { data } = await createOrUpdate(environmentInfo).unwrap();
Expand Down
Loading

0 comments on commit 0885e02

Please sign in to comment.