-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to create environment from lockfile #395
Changes from 9 commits
5a58b86
823df49
0df29c4
4929d0a
ab08669
37efaa7
78da64d
c71fce3
b25f773
d2a7e9a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,13 +24,20 @@ export const channelsSlice = createSlice({ | |
{ | ||
payload: { | ||
data: { | ||
specification: { | ||
spec: { channels } | ||
} | ||
specification: { spec } | ||
} | ||
} | ||
} | ||
) => { | ||
// channels can be undefined if a lockfile specification is provided, | ||
// try getting channels from metadata in that case | ||
const channels = | ||
spec?.channels ?? | ||
spec?.lockfile?.metadata?.channels?.map( | ||
(channel: any) => channel?.url | ||
) ?? | ||
[]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This and similar code for deps is what populates GUI channels and dependencies lists on env save. |
||
|
||
state.channels = channels; | ||
} | ||
); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,24 +13,34 @@ import { | |
environmentCreateStateCleared | ||
} from "../../environmentCreateSlice"; | ||
import { getStylesForStyleType } from "../../../../utils/helpers"; | ||
import Select, { SelectChangeEvent } from "@mui/material/Select"; | ||
import MenuItem from "@mui/material/MenuItem"; | ||
import FormControl from "@mui/material/FormControl"; | ||
|
||
export const SpecificationCreate = ({ onCreateEnvironment }: any) => { | ||
const dispatch = useAppDispatch(); | ||
const { channels, requestedPackages, environmentVariables } = useAppSelector( | ||
state => state.environmentCreate | ||
); | ||
const [show, setShow] = useState(false); | ||
const [specificationType, setSpecificationType] = | ||
React.useState("specification"); | ||
const [editorContent, setEditorContent] = useState<{ | ||
channels: string[]; | ||
dependencies: string[]; | ||
variables: Record<string, string>; | ||
}>({ channels: [], dependencies: [], variables: {} }); | ||
const [editorContentLockfile, setEditorContentLockfile] = useState<any>({}); | ||
|
||
const buttonStyles = getStylesForStyleType( | ||
{ padding: "5px 60px" }, | ||
{ padding: "5px 48px" } | ||
); | ||
|
||
const onUpdateSpecificationType = (event: SelectChangeEvent) => { | ||
setSpecificationType(event.target.value as string); | ||
}; | ||
|
||
const onUpdateChannels = useCallback((channels: string[]) => { | ||
dispatch(channelsChanged(channels)); | ||
}, []); | ||
|
@@ -71,15 +81,22 @@ export const SpecificationCreate = ({ onCreateEnvironment }: any) => { | |
setEditorContent(code); | ||
}; | ||
|
||
const onUpdateEditorLockfile = (lockfile: any) => { | ||
setEditorContentLockfile(lockfile); | ||
}; | ||
|
||
const onToggleEditorView = (value: boolean) => { | ||
if (show) { | ||
dispatch( | ||
editorCodeUpdated({ | ||
channels: editorContent.channels, | ||
dependencies: editorContent.dependencies, | ||
variables: editorContent.variables | ||
}) | ||
); | ||
if (specificationType === "specification") { | ||
dispatch( | ||
editorCodeUpdated({ | ||
channels: editorContent.channels, | ||
dependencies: editorContent.dependencies, | ||
variables: editorContent.variables | ||
}) | ||
); | ||
} | ||
// Do nothing when specificationType === lockfile | ||
} else { | ||
setEditorContent({ | ||
dependencies: requestedPackages, | ||
|
@@ -103,16 +120,36 @@ export const SpecificationCreate = ({ onCreateEnvironment }: any) => { | |
return stringify({ channels, dependencies, variables }); | ||
}; | ||
|
||
const formatCodeLockfile = () => { | ||
return stringify({ | ||
version: 1, | ||
metadata: {}, | ||
package: [] | ||
}); | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just to hint to the user which lockfile format is expected. Similar idea to |
||
|
||
const handleSubmit = () => { | ||
const code = show | ||
? editorContent | ||
: { | ||
dependencies: requestedPackages, | ||
variables: environmentVariables, | ||
channels | ||
}; | ||
|
||
onCreateEnvironment(code); | ||
let code; | ||
let is_lockfile; | ||
|
||
if (show) { | ||
if (specificationType === "specification") { | ||
code = editorContent; | ||
is_lockfile = false; | ||
} else { | ||
code = editorContentLockfile; | ||
is_lockfile = true; | ||
} | ||
} else { | ||
code = { | ||
dependencies: requestedPackages, | ||
variables: environmentVariables, | ||
channels | ||
}; | ||
is_lockfile = false; | ||
} | ||
|
||
onCreateEnvironment(code, is_lockfile); | ||
}; | ||
|
||
useEffect(() => { | ||
|
@@ -129,18 +166,41 @@ export const SpecificationCreate = ({ onCreateEnvironment }: any) => { | |
> | ||
<Box> | ||
{show ? ( | ||
<CodeEditor | ||
code={formatCode(channels, requestedPackages, environmentVariables)} | ||
onChangeEditor={onUpdateEditor} | ||
/> | ||
<> | ||
<FormControl sx={{ m: 1, minWidth: 120 }}> | ||
<Select | ||
value={specificationType} | ||
onChange={onUpdateSpecificationType} | ||
displayEmpty | ||
> | ||
<MenuItem value="specification">specification</MenuItem> | ||
<MenuItem value="lockfile">unified lockfile</MenuItem> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MenuItem values here match those we show in the admin interface (see the companion conda-store PR). |
||
</Select> | ||
</FormControl> | ||
{specificationType === "specification" ? ( | ||
<CodeEditor | ||
code={formatCode( | ||
channels, | ||
requestedPackages, | ||
environmentVariables | ||
)} | ||
onChangeEditor={onUpdateEditor} | ||
/> | ||
) : ( | ||
<CodeEditor | ||
code={formatCodeLockfile()} | ||
onChangeEditor={onUpdateEditorLockfile} | ||
/> | ||
)} | ||
</> | ||
) : ( | ||
<> | ||
<Box sx={{ marginBottom: "30px" }}> | ||
<CreateEnvironmentPackages | ||
requestedPackages={requestedPackages} | ||
/> | ||
</Box> | ||
<Box sx={{ margiBottom: "30px" }}> | ||
<Box sx={{ marginBottom: "30px" }}> | ||
peytondmurray marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<ChannelsEdit | ||
channelsList={channels} | ||
updateChannels={onUpdateChannels} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to rely on any particular format here since it might change upstream.