Skip to content

Commit

Permalink
Merge pull request Joystream#379 from Lezek123/runtime-upgrade
Browse files Browse the repository at this point in the history
Proposal form: Runtime upgrade
  • Loading branch information
Francesco authored Apr 21, 2020
2 parents a27687e + b4def67 commit 5b94f1c
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 2 deletions.
3 changes: 2 additions & 1 deletion packages/joy-proposals/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
"maintainers": [],
"dependencies": {
"@babel/runtime": "^7.7.1",
"@polkadot/joy-utils": "^0.1.1",
"@polkadot/react-components": "0.37.0-beta.63",
"@polkadot/react-query": "0.37.0-beta.63",
"@polkadot/joy-utils": "^0.1.1"
"react-dropzone": "^10.2.2"
}
}
119 changes: 119 additions & 0 deletions packages/joy-proposals/src/forms/FileDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React, { useState } from "react";
import { FormikProps } from "formik";
import { Icon, Loader } from "semantic-ui-react";
import Dropzone from 'react-dropzone';

enum Status {
Accepted = 'accepted',
Rejected = 'rejected',
Active = 'active',
Parsing = 'parsing',
Default = 'default'
}

const determineStatus = (
acceptedFiles: File[],
rejectedFiles: File[],
error: string | undefined,
isDragActive: boolean,
parsing: boolean
): Status => {
if (parsing) return Status.Parsing;
if (error || rejectedFiles.length) return Status.Rejected;
if (acceptedFiles.length) return Status.Accepted;
if (isDragActive) return Status.Active;

return Status.Default;
}

// Get color by status (imporant to use #FFFFFF format, so we can easily swicth the opacity!)
const getStatusColor = (status:Status): string => {
switch(status) {
case Status.Accepted: return '#00DBB0';
case Status.Rejected: return '#FF3861';
case Status.Active:
case Status.Parsing:
return '#000000';
default: return '#333333';
}
}

const dropdownDivStyle = (status:Status): React.CSSProperties => {
let mainColor = getStatusColor(status);

return {
border: `1px solid ${ mainColor + '30' }`,
borderRadius: '3px',
padding: '1.5em',
color: mainColor,
fontWeight: 'bold',
transition: 'color 0.5s, border-color 0.5s'
};
}

const dropdownIconStyle = (): React.CSSProperties => {
return {
marginRight: '0.5em',
opacity: 0.5
};
}

const innerSpanStyle = (): React.CSSProperties => {
return {
display: 'flex',
alignItems: 'center'
};
}

// Here we define a way of coverting the file into string for Formik purposes
// This may change depnding on how we decide to actually send the data
const parseFile = async (file: File): Promise<string> => {
return await file.text();
}

type FileDropdownProps<FormValuesT> = {
error: string | undefined,
name: keyof FormValuesT & string,
setFieldValue: FormikProps<FormValuesT>["setFieldValue"],
acceptedFormats: string | string[],
defaultText: string
}

export default function FileDropdown<ValuesT = {}>(props: FileDropdownProps<ValuesT>) {
const [ parsing, setParsing ] = useState(false);
const { error, name, setFieldValue, acceptedFormats, defaultText } = props;
return (
<Dropzone
onDropAccepted={ async(acceptedFiles) => {
setParsing(true);
const fileAsString:string = await parseFile(acceptedFiles[0]);
setFieldValue(name, fileAsString, true);
setParsing(false);
} }
multiple={false}
accept={acceptedFormats}
>
{({getRootProps, getInputProps, acceptedFiles, rejectedFiles, isDragActive }) => {
const status = determineStatus(acceptedFiles, rejectedFiles, error, isDragActive, parsing);
return (
<section>
<div {...getRootProps({ style: dropdownDivStyle(status) })}>
<input {...getInputProps()}/>
{
<span style={ innerSpanStyle() }>
<Icon name="cloud upload" size="huge" style={ dropdownIconStyle() }/>
<p>
{ status === Status.Parsing && <><Loader style={{marginRight: '0.5em'}} size="small" inline active/> Uploading...</> }
{ status === Status.Rejected && (<>{ error || 'This is not a correct file!'}<br/></>) }
{ status === Status.Accepted && (<>{`Current file: ${ acceptedFiles[0].name }`}<br/></>) }
{ status !== Status.Parsing && defaultText }
</p>
</span>
}
</div>
</section>
);
}}
</Dropzone>
);
}
2 changes: 1 addition & 1 deletion packages/joy-proposals/src/forms/GenericProposalForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const genericFormDefaultOptions: DefaultGenericFormOptions = {
},
handleSubmit: (values, { setSubmitting, resetForm }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
console.log(JSON.stringify(values));
setSubmitting(false);
}, 1000);
},
Expand Down
58 changes: 58 additions & 0 deletions packages/joy-proposals/src/forms/RuntimeUpgradeForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from "react";
import { FormikProps } from "formik";
import { Form } from "semantic-ui-react";
import * as Yup from "yup";
import {
GenericProposalForm,
GenericFormValues,
genericFormDefaultOptions,
DefaultOuterFormProps,
genericFormDefaultValues
} from './GenericProposalForm';
import { withFormContainer } from "./FormContainer";
import "./forms.css";
import FileDropdown from './FileDropdown';

type FormValues = GenericFormValues & {
WASM: string
};

const defaultValues:FormValues = {
...genericFormDefaultValues,
WASM: ''
}

type FormAdditionalProps = {};
type RuntimeUpgradeFormProps = FormikProps<FormValues> & FormAdditionalProps;

const RuntimeUpgradeForm: React.FunctionComponent<RuntimeUpgradeFormProps> = props => {
const { handleChange, handleSubmit, isSubmitting, errors, touched, setFieldValue } = props;
const passProps = { handleChange, errors, isSubmitting, touched, handleSubmit };
return (
<GenericProposalForm {...passProps}>
<Form.Field>
<FileDropdown<FormValues>
setFieldValue={setFieldValue}
defaultText="Drag-n-drop WASM bytecode of a runtime upgrade (*.wasm)"
acceptedFormats=".wasm"
name="WASM"
error={ errors.WASM }/>
</Form.Field>
</GenericProposalForm>
);
}

type OuterFormProps = DefaultOuterFormProps<FormAdditionalProps, FormValues>;

export default withFormContainer<OuterFormProps, FormValues>({
mapPropsToValues: (props:OuterFormProps) => ({
...defaultValues,
...(props.initialData || {})
}),
validationSchema: Yup.object().shape({
...genericFormDefaultOptions.validationSchema,
WASM: Yup.string().required('The file is empty!'),
}),
handleSubmit: genericFormDefaultOptions.handleSubmit,
displayName: "RuntimeUpgradeForm"
})(RuntimeUpgradeForm);
1 change: 1 addition & 0 deletions packages/joy-proposals/src/forms/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export { default as MintCapacityForm } from "./MintCapacityForm";
export { default as SetCouncilParamsForm } from "./SetCouncilParamsForm";
export { default as SetContentWorkingGroupLeadForm } from "./SetContentWorkingGroupLeadForm";
export { default as SetStorageRoleParamsForm } from "./SetStorageRoleParamsForm"
export { default as RuntimeUpgradeForm } from "./RuntimeUpgradeForm";
export { default as SetContentWorkingGroupMintCapForm } from './SetContentWorkingGroupMintCapForm';
export { default as SetCouncilMintCapForm } from './SetCouncilMintCapForm';
3 changes: 3 additions & 0 deletions packages/joy-proposals/src/stories/ProposalForms.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
SetCouncilParamsForm,
SetContentWorkingGroupLeadForm,
SetStorageRoleParamsForm,
RuntimeUpgradeForm,
SetContentWorkingGroupMintCapForm,
SetCouncilMintCapForm
} from "../forms";
Expand All @@ -27,6 +28,8 @@ export const SetContentWorkingGroupLead = () => <SetContentWorkingGroupLeadForm

export const SetStorageRoleParams = () => <SetStorageRoleParamsForm />;

export const RuntimeUpgrade = () => <RuntimeUpgradeForm />;

export const ContentWorkingGroupMintCap = () => <SetContentWorkingGroupMintCapForm />;

export const CouncilMintCap = () => <SetCouncilMintCapForm />;
Expand Down
9 changes: 9 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -16411,6 +16411,15 @@ react-dropzone@^10.1.10:
file-selector "^0.1.12"
prop-types "^15.7.2"

react-dropzone@^10.2.2:
version "10.2.2"
resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-10.2.2.tgz#67b4db7459589a42c3b891a82eaf9ade7650b815"
integrity sha512-U5EKckXVt6IrEyhMMsgmHQiWTGLudhajPPG77KFSvgsMqNEHSyGpqWvOMc5+DhEah/vH4E1n+J5weBNLd5VtyA==
dependencies:
attr-accept "^2.0.0"
file-selector "^0.1.12"
prop-types "^15.7.2"

react-error-overlay@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.3.tgz#c378c4b0a21e88b2e159a3e62b2f531fd63bf60d"
Expand Down

0 comments on commit 5b94f1c

Please sign in to comment.