-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b568028
commit ee0892c
Showing
6 changed files
with
227 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
import { useState, useCallback, useEffect, useContext } from "react"; | ||
import styled from "styled-components"; | ||
import { Ed25519KeyIdentity } from "@dfinity/identity"; | ||
import { IDL } from "@dfinity/candid"; | ||
|
||
import { Modal } from "./shared/Modal"; | ||
import { CanisterInfo, deploy } from "../build"; | ||
import { ILoggingStore } from "./Logger"; | ||
import { Button } from "./shared/Button"; | ||
import { | ||
WorkerContext, | ||
WorkplaceState, | ||
ContainerContext, | ||
Origin, | ||
} from "../contexts/WorkplaceState"; | ||
import { didjs, backend } from "../config/actor"; | ||
import { Field } from "./shared/Field"; | ||
|
||
const assetWasmHash = | ||
"3a533f511b3960b4186e76cf9abfbd8222a2c507456a66ec55671204ee70cae3"; | ||
|
||
const ModalContainer = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: space-between; | ||
align-items: center; | ||
width: 46rem; | ||
`; | ||
|
||
const FormContainer = styled.div` | ||
width: 100%; | ||
margin-top: 2rem; | ||
`; | ||
|
||
const ButtonContainer = styled.div` | ||
display: flex; | ||
justify-content: center; | ||
width: 100%; | ||
margin-top: 3rem; | ||
`; | ||
|
||
const MyButton = styled(Button)` | ||
width: 12rem; | ||
`; | ||
|
||
interface FrontendDeployModalProps { | ||
state: WorkplaceState; | ||
isOpen: boolean; | ||
close: () => void; | ||
onDeploy: (string) => void; | ||
isDeploy: (tag: boolean) => void; | ||
canisters: Record<string, CanisterInfo>; | ||
logger: ILoggingStore; | ||
origin: Origin; | ||
} | ||
|
||
const MAX_CANISTERS = 3; | ||
|
||
export function FrontendDeployModal({ | ||
state, | ||
isOpen, | ||
close, | ||
onDeploy, | ||
isDeploy, | ||
canisters, | ||
logger, | ||
origin, | ||
}: FrontendDeployModalProps) { | ||
const [canisterName, setCanisterName] = useState("frontend"); | ||
const [buildDir, setBuildDir] = useState("dist"); | ||
const worker = useContext(WorkerContext); | ||
const container = useContext(ContainerContext); | ||
|
||
const exceedsLimit = Object.keys(canisters).length >= MAX_CANISTERS; | ||
|
||
async function deployClick(mode: string) { | ||
try { | ||
await close(); | ||
await isDeploy(true); | ||
var info: CanisterInfo | undefined = canisters[canisterName]; | ||
if (mode !== "upgrade") { | ||
const module_hash = assetWasmHash | ||
.match(/.{2}/g)! | ||
.map((byte) => parseInt(byte, 16)); | ||
info = await deploy( | ||
worker, | ||
canisterName, | ||
canisters[canisterName], | ||
new Uint8Array(IDL.encode([], [])), | ||
mode, | ||
new Uint8Array(module_hash), | ||
true, | ||
false, | ||
false, | ||
logger, | ||
origin, | ||
); | ||
const identity = Ed25519KeyIdentity.generate(); | ||
const principal = identity.getPrincipal(); | ||
const args = IDL.encode([IDL.Principal], [principal]); | ||
await backend.callForward(info!, "authorize", args); | ||
await container.container!.fs.writeFile( | ||
"utils/identity.json", | ||
JSON.stringify(identity.toJSON()), | ||
); | ||
logger.log(`Authorized asset canister with ${principal}`); | ||
if (info) { | ||
info.isFrontend = true; | ||
onDeploy(info); | ||
} | ||
} | ||
logger.log(`Uploading frontend...`); | ||
await container.run_cmd( | ||
"node", | ||
["uploadAsset.js", info!.id.toText(), `../user/${buildDir}`], | ||
{ cwd: "utils" }, | ||
); | ||
logger.log(`Frontend uploaded`); | ||
await isDeploy(false); | ||
} catch (err) { | ||
await isDeploy(false); | ||
throw err; | ||
} | ||
} | ||
const welcomeText = <p>Deploy your frontend to the IC</p>; | ||
const deployLabelText = "Select a canister name"; | ||
const newDeploy = ( | ||
<> | ||
<Field | ||
type="text" | ||
labelText={deployLabelText} | ||
list="canisters" | ||
value={canisterName} | ||
onChange={(e) => setCanisterName(e.target.value)} | ||
/> | ||
<datalist id="canisters"> | ||
{Object.keys(canisters).map((canister, i) => ( | ||
<option key={`${canister}${i}`}>{canister}</option> | ||
))} | ||
</datalist> | ||
</> | ||
); | ||
const selectDeploy = ( | ||
<Field | ||
required | ||
type="select" | ||
labelText={deployLabelText} | ||
value={canisterName} | ||
onChange={(e) => setCanisterName(e.target.value)} | ||
> | ||
{Object.keys(canisters).map((canister) => ( | ||
<option value={canister}>{canister}</option> | ||
))} | ||
</Field> | ||
); | ||
|
||
return ( | ||
<> | ||
<Modal | ||
isOpen={isOpen} | ||
close={close} | ||
label="Deploy Canister" | ||
shouldCloseOnEsc | ||
shouldCloseOnOverlayClick | ||
> | ||
<ModalContainer> | ||
<div style={{ maxHeight: 680, overflowY: "auto", width: "100%" }}> | ||
{welcomeText} | ||
<FormContainer> | ||
{exceedsLimit ? selectDeploy : newDeploy} | ||
<Field | ||
type="text" | ||
labelText="Build directory" | ||
value={buildDir} | ||
onChange={(e) => setBuildDir(e.target.value)} | ||
/> | ||
</FormContainer> | ||
</div> | ||
{canisterName ? ( | ||
<ButtonContainer> | ||
{canisters.hasOwnProperty(canisterName) ? ( | ||
<> | ||
<MyButton | ||
variant="primary" | ||
onClick={() => deployClick("upgrade")} | ||
> | ||
Upgrade | ||
</MyButton> | ||
<MyButton onClick={() => deployClick("reinstall")}> | ||
Reinstall | ||
</MyButton> | ||
</> | ||
) : ( | ||
<MyButton | ||
variant="primary" | ||
onClick={() => deployClick("install")} | ||
> | ||
Install | ||
</MyButton> | ||
)} | ||
<MyButton onClick={close}>Cancel</MyButton> | ||
</ButtonContainer> | ||
) : null} | ||
</ModalContainer> | ||
</Modal> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters