antd#Steps TypeScript Examples
The following examples show how to use
antd#Steps.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: FormWizardStepStatus.tsx From jmix-frontend with Apache License 2.0 | 7 votes |
FormWizardStepStatus = observer(({onSelectStep}: FormWizardStepStatusProps) => {
const {formWizardStore} = useFormWizard();
const {formatMessage} = useIntl()
return (
<Steps
style={{marginBottom: 12}}
size="small"
current={formWizardStore.stepIndex}
onChange={onSelectStep}
>
{formWizardStore.steps.map((step, index) => (
<Steps.Step
disabled={step.status === 'wait'}
key={step.name}
title={formatMessage({id: 'formWizard.stepTitle'}, {index: index + 1})}
status={step.status}
/>
))}
</Steps>
);
})
Example #2
Source File: index.tsx From posthog-foss with MIT License | 5 votes |
{ Step } = Steps
Example #3
Source File: index.tsx From metaplex with Apache License 2.0 | 5 votes |
Sidebar = ({
step,
setStep,
submit,
isValidStep,
buttonLoading,
}: SidebarProps) => {
const { connected } = useWallet();
const { isLoading } = useMeta();
const { width } = useWindowDimensions();
const isFinalStep = step === CreatePackSteps.ReviewAndMint;
const shouldDisable =
!isValidStep || !connected || isLoading || buttonLoading;
const handleContinue = (): void => {
if (isFinalStep) {
return submit();
}
setStep(step + 1);
};
return (
<div className="sidebar-wrapper">
<Steps
className="sidebar-steps"
direction={width < 768 ? 'horizontal' : 'vertical'}
current={step}
>
{Object.entries(STEPS_TITLES).map(([step, title]) => (
<Step title={title} key={step} />
))}
</Steps>
<Button
className="sidebar-btn secondary-btn"
onClick={handleContinue}
disabled={shouldDisable}
>
{buttonLoading ? <Spin /> : CONTINUE_TITLES[step]}
</Button>
{step !== CreatePackSteps.SelectItems && (
<Button
type="text"
className="sidebar-btn"
onClick={() => setStep(step - 1)}
>
Back
</Button>
)}
</div>
);
}
Example #4
Source File: questionnaire.tsx From RareCamp with Apache License 2.0 | 5 votes |
{ Step } = Steps
Example #5
Source File: index.tsx From metaplex with Apache License 2.0 | 5 votes |
{ Step } = Steps
Example #6
Source File: index.tsx From metaplex with Apache License 2.0 | 5 votes |
{ Step } = Steps
Example #7
Source File: UpdateForm.tsx From ui-visualization with MIT License | 5 votes |
{ Step } = Steps
Example #8
Source File: SourceEditorViewSteps.tsx From jitsu with MIT License | 5 votes |
SourceEditorViewSteps: React.FC<SourceEditorTabsViewProps> = ({
steps,
controlsDisabled,
handleBringSourceData,
setInitialSourceData,
handleLeaveEditor,
}) => {
const [currentStep, setCurrentStep] = useState<number>(0)
const [currentStepIsLoading, setCurrentStepIsLoading] = useState<boolean>(false)
const proceedButtonTitle = steps[currentStep].proceedButtonTitle ?? "Next"
const handleCompleteStep = () => {
setInitialSourceData(handleBringSourceData())
}
const handleGoToNextStep: AsyncUnknownFunction = async () => {
handleCompleteStep()
setCurrentStepIsLoading(true)
try {
await steps[currentStep].proceedAction?.()
setCurrentStep(step => step + 1)
} catch (error) {
actionNotification.error(`${error}`)
} finally {
setCurrentStepIsLoading(false)
}
}
const handleStepBack: AsyncUnknownFunction = async () => {
handleCompleteStep()
setCurrentStep(step => step - 1)
}
return (
<>
<div className={cn("flex flex-col items-stretch flex-grow-0 flex-shrink h-full min-h-0")}>
<div className="flex-shrink-0 flex-grow-0 mb-4">
<Steps current={currentStep}>
{steps.map(({ key, title, description }, idx) => (
<Steps.Step
key={key}
title={title}
description={description}
icon={idx === currentStep && currentStepIsLoading ? <LoadingOutlined spin /> : undefined}
/>
))}
</Steps>
</div>
<div className={cn("flex-grow flex-shrink min-h-0 overflow-y-auto pr-4")}>
<fieldset disabled={currentStepIsLoading}>{steps[currentStep]?.render}</fieldset>
</div>
<div className="flex items-center flex-shrink flex-grow-0 border-t py-2">
<SourceEditorViewControls
mainButton={{
title: proceedButtonTitle,
loading: currentStepIsLoading,
handleClick: handleGoToNextStep,
}}
secondaryButton={{
title: "Back",
hide: currentStep === 0,
handleClick: handleStepBack,
}}
dangerButton={{
title: "Cancel",
handleClick: handleLeaveEditor,
}}
controlsDisabled={controlsDisabled}
/>
</div>
</div>
</>
)
}
Example #9
Source File: control.tsx From leek with Apache License 2.0 | 5 votes |
{ Step } = Steps
Example #10
Source File: index.tsx From metaplex with Apache License 2.0 | 5 votes |
{ Step } = Steps
Example #11
Source File: index.tsx From amiya with MIT License | 4 votes |
export default function Demo() {
// 商品选择是否可见
const [currStep, setCurrStep] = useState(0)
// 提交的数据
const [submitValues, setSubmitValues] = useState<AnyKeyProps>({})
// 提交的数据
const [submitTagValues, setSubmitTagValues] = useState<AnyKeyProps>({})
return (
<Card className="step-form">
<Steps current={currStep} className="steps">
<Steps.Step title="基础信息" />
<Steps.Step title="能力选择" />
<Steps.Step title="录入完成" />
</Steps>
{currStep === 0 && (
<AyForm
formLayout="vertical"
onConfirm={values => {
setSubmitValues(values)
setCurrStep(1)
}}
>
<AyFields>
<AyField title="昵称" key="nickname" required help="你在平台展示的名称。" defaultValue="一只兔子" />
<AyField title="真实姓名" key="name" required help="仅用于认证,不会在界面展示。" defaultValue="阿米娅" />
<AyField title="证件信息" key="__card" type="input-group" required>
<AyField
type="select"
key="cardType"
style={{ width: 130 }}
defaultValue={2}
required
options={[
{ label: '居民身份证', value: 1 },
{ label: '出生证', value: 2 },
{ label: '护照', value: 3 }
]}
/>
<AyField
title="证件号码"
key="cardNo"
required
style={{ width: 370 }}
defaultValue="A1R2K3N4I5G6H7T8S9"
/>
</AyField>
<AyField
title="简介"
key="memo"
type="textarea"
placeholder="介绍一下自己"
defaultValue="正在努力奋斗中..."
/>
</AyFields>
<AyButton htmlType="submit" type="primary">
下一步
</AyButton>
</AyForm>
)}
{currStep === 1 && (
<AyForm
formLayout="vertical"
onConfirm={values => {
setSubmitTagValues(values)
setCurrStep(2)
}}
>
<AyFields>
<AyField
title="资质"
key="type"
type="card-group"
options={[
{ label: '高级资深干员', value: 3 },
{ label: '资深干员', value: 2 },
{ label: '新手', value: 1 }
]}
required
defaultValue={1}
/>
<AyField title="星级" key="level" type="rate" count={6} required defaultValue={5} />
<AyField
title="能力"
key="tags"
type="checkbox-group"
options={[
{ label: '控场', value: 1 },
{ label: '爆发', value: 2 },
{ label: '治疗', value: 3 },
{ label: '支援', value: 4 },
{ label: '费用回复', value: 5 },
{ label: '输出', value: 6 }
]}
required
defaultValue={[2, 6]}
/>
</AyFields>
<Space>
<AyButton onClick={() => setCurrStep(currStep - 1)}>上一步</AyButton>
<AyButton htmlType="submit" type="primary">
下一步
</AyButton>
</Space>
</AyForm>
)}
{currStep == 2 && (
<Result
status="success"
title="录入完成"
subTitle="信息录入已完成,可以选择再次录入。"
extra={[
<AyButton
type="primary"
onClick={() => {
setCurrStep(0)
setSubmitValues({})
setSubmitTagValues({})
}}
>
再次录入
</AyButton>
]}
/>
)}
{submitValues.name && <pre>{JSON.stringify(submitValues, null, 2)}</pre>}
{submitTagValues.type && <pre>{JSON.stringify(submitTagValues, null, 2)}</pre>}
</Card>
)
}
Example #12
Source File: index.tsx From metaplex with Apache License 2.0 | 4 votes |
AuctionCreateView = () => {
const connection = useConnection();
const wallet = useWallet();
const { whitelistedCreatorsByCreator, storeIndexer } = useMeta();
const { step_param }: { step_param: string } = useParams();
const history = useHistory();
const mint = useMint(QUOTE_MINT);
const { width } = useWindowDimensions();
const [step, setStep] = useState<number>(0);
const [stepsVisible, setStepsVisible] = useState<boolean>(true);
const [auctionObj, setAuctionObj] = useState<
| {
vault: StringPublicKey;
auction: StringPublicKey;
auctionManager: StringPublicKey;
}
| undefined
>(undefined);
const [attributes, setAttributes] = useState<AuctionState>({
reservationPrice: 0,
items: [],
category: AuctionCategory.Open,
auctionDurationType: 'minutes',
gapTimeType: 'minutes',
winnersCount: 1,
startSaleTS: undefined,
startListTS: undefined,
quoteMintAddress: '',
//@ts-ignore
quoteMintInfo: undefined,
//@ts-ignore
quoteMintInfoExtended: undefined,
});
const [tieredAttributes, setTieredAttributes] = useState<TieredAuctionState>({
items: [],
tiers: [],
});
useEffect(() => {
if (step_param) setStep(parseInt(step_param));
else gotoNextStep(0);
}, [step_param]);
const gotoNextStep = (_step?: number) => {
const nextStep = _step === undefined ? step + 1 : _step;
history.push(`/auction/create/${nextStep.toString()}`);
};
const createAuction = async () => {
let winnerLimit: WinnerLimit;
//const mint = attributes.quoteMintInfo
if (
attributes.category === AuctionCategory.InstantSale &&
attributes.instantSaleType === InstantSaleType.Open
) {
const { items, instantSalePrice } = attributes;
if (items.length > 0 && items[0].participationConfig) {
items[0].participationConfig.fixedPrice = new BN(
toLamports(instantSalePrice, mint) || 0,
);
}
winnerLimit = new WinnerLimit({
type: WinnerLimitType.Unlimited,
usize: ZERO,
});
} else if (attributes.category === AuctionCategory.InstantSale) {
const { items, editions } = attributes;
if (items.length > 0) {
const item = items[0];
if (!editions) {
item.winningConfigType = WinningConfigType.TokenOnlyTransfer;
}
item.amountRanges = [
new AmountRange({
amount: new BN(1),
length: new BN(editions || 1),
}),
];
}
winnerLimit = new WinnerLimit({
type: WinnerLimitType.Capped,
usize: new BN(editions || 1),
});
} else if (attributes.category === AuctionCategory.Open) {
if (
attributes.items.length > 0 &&
attributes.items[0].participationConfig
) {
attributes.items[0].participationConfig.fixedPrice = new BN(
toLamports(attributes.participationFixedPrice, mint) || 0,
);
}
winnerLimit = new WinnerLimit({
type: WinnerLimitType.Unlimited,
usize: ZERO,
});
} else if (
attributes.category === AuctionCategory.Limited ||
attributes.category === AuctionCategory.Single
) {
if (attributes.items.length > 0) {
const item = attributes.items[0];
if (
attributes.category == AuctionCategory.Single &&
item.masterEdition
) {
item.winningConfigType = WinningConfigType.TokenOnlyTransfer;
}
item.amountRanges = [
new AmountRange({
amount: new BN(1),
length:
attributes.category === AuctionCategory.Single
? new BN(1)
: new BN(attributes.editions || 1),
}),
];
}
winnerLimit = new WinnerLimit({
type: WinnerLimitType.Capped,
usize:
attributes.category === AuctionCategory.Single
? new BN(1)
: new BN(attributes.editions || 1),
});
if (
attributes.participationNFT &&
attributes.participationNFT.participationConfig
) {
attributes.participationNFT.participationConfig.fixedPrice = new BN(
toLamports(attributes.participationFixedPrice, mint) || 0,
);
}
} else {
const tiers = tieredAttributes.tiers;
tiers.forEach(
c =>
(c.items = c.items.filter(
i => (i as TierDummyEntry).winningConfigType !== undefined,
)),
);
const filteredTiers = tiers.filter(
i => i.items.length > 0 && i.winningSpots.length > 0,
);
tieredAttributes.items.forEach((config, index) => {
let ranges: AmountRange[] = [];
filteredTiers.forEach(tier => {
const tierRangeLookup: Record<number, AmountRange> = {};
const tierRanges: AmountRange[] = [];
const item = tier.items.find(
i => (i as TierDummyEntry).safetyDepositBoxIndex == index,
);
if (item) {
config.winningConfigType = (
item as TierDummyEntry
).winningConfigType;
const sorted = tier.winningSpots.sort();
sorted.forEach((spot, i) => {
if (tierRangeLookup[spot - 1]) {
tierRangeLookup[spot] = tierRangeLookup[spot - 1];
tierRangeLookup[spot].length = tierRangeLookup[spot].length.add(
new BN(1),
);
} else {
tierRangeLookup[spot] = new AmountRange({
amount: new BN((item as TierDummyEntry).amount),
length: new BN(1),
});
// If the first spot with anything is winner spot 1, you want a section of 0 covering winning
// spot 0.
// If we have a gap, we want a gap area covered with zeroes.
const zeroLength = i - 1 > 0 ? spot - sorted[i - 1] - 1 : spot;
if (zeroLength > 0) {
tierRanges.push(
new AmountRange({
amount: new BN(0),
length: new BN(zeroLength),
}),
);
}
tierRanges.push(tierRangeLookup[spot]);
}
});
// Ok now we have combined ranges from this tier range. Now we merge them into the ranges
// at the top level.
const oldRanges = ranges;
ranges = [];
let oldRangeCtr = 0,
tierRangeCtr = 0;
while (
oldRangeCtr < oldRanges.length ||
tierRangeCtr < tierRanges.length
) {
let toAdd = new BN(0);
if (
tierRangeCtr < tierRanges.length &&
tierRanges[tierRangeCtr].amount.gt(new BN(0))
) {
toAdd = tierRanges[tierRangeCtr].amount;
}
if (oldRangeCtr == oldRanges.length) {
ranges.push(
new AmountRange({
amount: toAdd,
length: tierRanges[tierRangeCtr].length,
}),
);
tierRangeCtr++;
} else if (tierRangeCtr == tierRanges.length) {
ranges.push(oldRanges[oldRangeCtr]);
oldRangeCtr++;
} else if (
oldRanges[oldRangeCtr].length.gt(
tierRanges[tierRangeCtr].length,
)
) {
oldRanges[oldRangeCtr].length = oldRanges[
oldRangeCtr
].length.sub(tierRanges[tierRangeCtr].length);
ranges.push(
new AmountRange({
amount: oldRanges[oldRangeCtr].amount.add(toAdd),
length: tierRanges[tierRangeCtr].length,
}),
);
tierRangeCtr += 1;
// dont increment oldRangeCtr since i still have length to give
} else if (
tierRanges[tierRangeCtr].length.gt(
oldRanges[oldRangeCtr].length,
)
) {
tierRanges[tierRangeCtr].length = tierRanges[
tierRangeCtr
].length.sub(oldRanges[oldRangeCtr].length);
ranges.push(
new AmountRange({
amount: oldRanges[oldRangeCtr].amount.add(toAdd),
length: oldRanges[oldRangeCtr].length,
}),
);
oldRangeCtr += 1;
// dont increment tierRangeCtr since they still have length to give
} else if (
tierRanges[tierRangeCtr].length.eq(
oldRanges[oldRangeCtr].length,
)
) {
ranges.push(
new AmountRange({
amount: oldRanges[oldRangeCtr].amount.add(toAdd),
length: oldRanges[oldRangeCtr].length,
}),
);
// Move them both in this degen case
oldRangeCtr++;
tierRangeCtr++;
}
}
}
});
console.log('Ranges');
config.amountRanges = ranges;
});
winnerLimit = new WinnerLimit({
type: WinnerLimitType.Capped,
usize: new BN(attributes.winnersCount),
});
if (
attributes.participationNFT &&
attributes.participationNFT.participationConfig
) {
attributes.participationNFT.participationConfig.fixedPrice = new BN(
toLamports(attributes.participationFixedPrice, mint) || 0,
);
}
console.log('Tiered settings', tieredAttributes.items);
}
const isInstantSale =
attributes.instantSalePrice &&
attributes.priceFloor === attributes.instantSalePrice;
const LAMPORTS_PER_TOKEN =
attributes.quoteMintAddress == WRAPPED_SOL_MINT.toBase58()
? LAMPORTS_PER_SOL
: Math.pow(10, attributes.quoteMintInfo.decimals || 0);
const auctionSettings: IPartialCreateAuctionArgs = {
winners: winnerLimit,
endAuctionAt: isInstantSale
? null
: new BN(
(attributes.auctionDuration || 0) *
(attributes.auctionDurationType == 'days'
? 60 * 60 * 24 // 1 day in seconds
: attributes.auctionDurationType == 'hours'
? 60 * 60 // 1 hour in seconds
: 60), // 1 minute in seconds
), // endAuctionAt is actually auction duration, poorly named, in seconds
auctionGap: isInstantSale
? null
: new BN(
(attributes.gapTime || 0) *
(attributes.gapTimeType == 'days'
? 60 * 60 * 24 // 1 day in seconds
: attributes.gapTimeType == 'hours'
? 60 * 60 // 1 hour in seconds
: 60), // 1 minute in seconds
),
priceFloor: new PriceFloor({
type: attributes.priceFloor
? PriceFloorType.Minimum
: PriceFloorType.None,
minPrice: new BN((attributes.priceFloor || 0) * LAMPORTS_PER_TOKEN),
}),
tokenMint: attributes.quoteMintAddress,
gapTickSizePercentage: attributes.tickSizeEndingPhase || null,
tickSize: attributes.priceTick
? new BN(attributes.priceTick * LAMPORTS_PER_TOKEN)
: null,
instantSalePrice: attributes.instantSalePrice
? new BN((attributes.instantSalePrice || 0) * LAMPORTS_PER_TOKEN)
: null,
name: null,
};
const isOpenEdition =
attributes.category === AuctionCategory.Open ||
attributes.instantSaleType === InstantSaleType.Open;
const safetyDepositDrafts = isOpenEdition
? []
: attributes.category !== AuctionCategory.Tiered
? attributes.items
: tieredAttributes.items;
const participationSafetyDepositDraft = isOpenEdition
? attributes.items[0]
: attributes.participationNFT;
const _auctionObj = await createAuctionManager(
connection,
wallet,
whitelistedCreatorsByCreator,
auctionSettings,
safetyDepositDrafts,
participationSafetyDepositDraft,
attributes.quoteMintAddress,
storeIndexer,
);
setAuctionObj(_auctionObj);
};
const categoryStep = (
<CategoryStep
confirm={(category: AuctionCategory) => {
setAttributes({
...attributes,
category,
});
gotoNextStep();
}}
/>
);
const instantSaleStep = (
<InstantSaleStep
attributes={attributes}
setAttributes={setAttributes}
confirm={() => gotoNextStep()}
/>
);
const copiesStep = (
<CopiesStep
attributes={attributes}
setAttributes={setAttributes}
confirm={() => gotoNextStep()}
/>
);
const winnersStep = (
<NumberOfWinnersStep
attributes={attributes}
setAttributes={setAttributes}
confirm={() => gotoNextStep()}
/>
);
const priceAuction = (
<PriceAuction
attributes={attributes}
setAttributes={setAttributes}
confirm={() => gotoNextStep()}
/>
);
const initialStep = (
<InitialPhaseStep
attributes={attributes}
setAttributes={setAttributes}
confirm={() => gotoNextStep()}
/>
);
const endingStep = (
<EndingPhaseAuction
attributes={attributes}
setAttributes={setAttributes}
confirm={() => gotoNextStep()}
/>
);
const participationStep = (
<ParticipationStep
attributes={attributes}
setAttributes={setAttributes}
confirm={() => gotoNextStep()}
/>
);
const tierTableStep = (
<TierTableStep
attributes={tieredAttributes}
setAttributes={setTieredAttributes}
maxWinners={attributes.winnersCount}
confirm={() => gotoNextStep()}
/>
);
const reviewStep = (
<ReviewStep
attributes={attributes}
setAttributes={setAttributes}
confirm={() => {
setStepsVisible(false);
gotoNextStep();
}}
connection={connection}
/>
);
const waitStep = (
<WaitingStep createAuction={createAuction} confirm={() => gotoNextStep()} />
);
const congratsStep = <Congrats auction={auctionObj} />;
const stepsByCategory = {
[AuctionCategory.InstantSale]: [
['Category', categoryStep],
['Instant Sale', instantSaleStep],
['Review', reviewStep],
['Publish', waitStep],
[undefined, congratsStep],
],
[AuctionCategory.Limited]: [
['Category', categoryStep],
['Copies', copiesStep],
['Price', priceAuction],
['Initial Phase', initialStep],
['Ending Phase', endingStep],
['Participation NFT', participationStep],
['Review', reviewStep],
['Publish', waitStep],
[undefined, congratsStep],
],
[AuctionCategory.Single]: [
['Category', categoryStep],
['Copies', copiesStep],
['Price', priceAuction],
['Initial Phase', initialStep],
['Ending Phase', endingStep],
['Participation NFT', participationStep],
['Review', reviewStep],
['Publish', waitStep],
[undefined, congratsStep],
],
[AuctionCategory.Open]: [
['Category', categoryStep],
['Copies', copiesStep],
['Price', priceAuction],
['Initial Phase', initialStep],
['Ending Phase', endingStep],
['Review', reviewStep],
['Publish', waitStep],
[undefined, congratsStep],
],
[AuctionCategory.Tiered]: [
['Category', categoryStep],
['Winners', winnersStep],
['Tiers', tierTableStep],
['Price', priceAuction],
['Initial Phase', initialStep],
['Ending Phase', endingStep],
['Participation NFT', participationStep],
['Review', reviewStep],
['Publish', waitStep],
[undefined, congratsStep],
],
};
return (
<>
<Row className="creator-base-page" style={{ paddingTop: 50 }}>
{stepsVisible && (
<Col span={24} md={4}>
<Steps
progressDot
direction={width < 768 ? 'horizontal' : 'vertical'}
current={step}
style={{
width: 'fit-content',
margin: '0 auto 30px auto',
overflowX: 'auto',
maxWidth: '100%',
}}
>
{stepsByCategory[attributes.category]
.filter(_ => !!_[0])
.map((step, idx) => (
<Step title={step[0]} key={idx} />
))}
</Steps>
</Col>
)}
<Col span={24} {...(stepsVisible ? { md: 20 } : { md: 24 })}>
{stepsByCategory[attributes.category][step][1]}
{0 < step && stepsVisible && (
<div style={{ margin: 'auto', width: 'fit-content' }}>
<Button onClick={() => gotoNextStep(step - 1)}>Back</Button>
</div>
)}
</Col>
</Row>
</>
);
}
Example #13
Source File: index.tsx From metaplex with Apache License 2.0 | 4 votes |
WaitingStep = (props: {
mint: Function;
minting: boolean;
confirm: Function;
step: number;
}) => {
useEffect(() => {
const func = async () => {
await props.mint();
props.confirm();
};
func();
}, []);
const setIconForStep = (currentStep: number, componentStep) => {
if (currentStep === componentStep) {
return <LoadingOutlined />;
}
return null;
};
return (
<div
style={{
marginTop: 70,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Spin size="large" />
<Card>
<Steps direction="vertical" current={props.step}>
<Step
className={'white-description'}
title="Minting"
description="Starting Mint Process"
icon={setIconForStep(props.step, 0)}
/>
<Step
className={'white-description'}
title="Preparing Assets"
icon={setIconForStep(props.step, 1)}
/>
<Step
className={'white-description'}
title="Signing Metadata Transaction"
description="Approve the transaction from your wallet"
icon={setIconForStep(props.step, 2)}
/>
<Step
className={'white-description'}
title="Sending Transaction to Solana"
description="This will take a few seconds."
icon={setIconForStep(props.step, 3)}
/>
<Step
className={'white-description'}
title="Waiting for Initial Confirmation"
icon={setIconForStep(props.step, 4)}
/>
<Step
className={'white-description'}
title="Waiting for Final Confirmation"
icon={setIconForStep(props.step, 5)}
/>
<Step
className={'white-description'}
title="Uploading to Arweave"
icon={setIconForStep(props.step, 6)}
/>
<Step
className={'white-description'}
title="Updating Metadata"
icon={setIconForStep(props.step, 7)}
/>
<Step
className={'white-description'}
title="Signing Token Transaction"
description="Approve the final transaction from your wallet"
icon={setIconForStep(props.step, 8)}
/>
</Steps>
</Card>
</div>
);
}
Example #14
Source File: index.tsx From metaplex with Apache License 2.0 | 4 votes |
ArtCreateView = () => {
const connection = useConnection();
const { endpoint } = useConnectionConfig();
const wallet = useWallet();
const [alertMessage, setAlertMessage] = useState<string>();
const { step_param }: { step_param: string } = useParams();
const history = useHistory();
const { width } = useWindowDimensions();
const [nftCreateProgress, setNFTcreateProgress] = useState<number>(0);
const [step, setStep] = useState<number>(0);
const [stepsVisible, setStepsVisible] = useState<boolean>(true);
const [isMinting, setMinting] = useState<boolean>(false);
const [nft, setNft] = useState<
{ metadataAccount: StringPublicKey } | undefined
>(undefined);
const [files, setFiles] = useState<File[]>([]);
const [isCollection, setIsCollection] = useState<boolean>(false);
const [attributes, setAttributes] = useState<IMetadataExtension>({
name: '',
symbol: '',
collection: '',
description: '',
external_url: '',
image: '',
animation_url: undefined,
attributes: undefined,
seller_fee_basis_points: 0,
creators: [],
properties: {
files: [],
category: MetadataCategory.Image,
},
});
const gotoStep = useCallback(
(_step: number) => {
history.push(`/art/create/${_step.toString()}`);
if (_step === 0) setStepsVisible(true);
},
[history],
);
useEffect(() => {
if (step_param) setStep(parseInt(step_param));
else gotoStep(0);
}, [step_param, gotoStep]);
// store files
const mint = async () => {
const metadata = {
name: attributes.name,
symbol: attributes.symbol,
creators: attributes.creators,
collection: attributes.collection,
description: attributes.description,
sellerFeeBasisPoints: attributes.seller_fee_basis_points,
image: attributes.image,
animation_url: attributes.animation_url,
attributes: attributes.attributes,
external_url: attributes.external_url,
properties: {
files: attributes.properties.files,
category: attributes.properties?.category,
},
};
setStepsVisible(false);
setMinting(true);
try {
const _nft = await mintNFT(
connection,
wallet,
endpoint.name,
files,
metadata,
setNFTcreateProgress,
attributes.properties?.maxSupply,
);
if (_nft) setNft(_nft);
setAlertMessage('');
} catch (e: any) {
setAlertMessage(e.message);
} finally {
setMinting(false);
}
};
return (
<>
<Row className={'creator-base-page'} style={{ paddingTop: 50 }}>
{stepsVisible && (
<Col span={24} md={4}>
<Steps
progressDot
direction={width < 768 ? 'horizontal' : 'vertical'}
current={step}
style={{
width: 'fit-content',
margin: '0 auto 30px auto',
overflowX: 'auto',
maxWidth: '100%',
}}
>
<Step title="Category" />
<Step title="Upload" />
<Step title="Info" />
<Step title="Royalties" />
<Step title="Launch" />
</Steps>
</Col>
)}
<Col span={24} {...(stepsVisible ? { md: 20 } : { md: 24 })}>
{step === 0 && (
<CategoryStep
confirm={(category: MetadataCategory) => {
setAttributes({
...attributes,
properties: {
...attributes.properties,
category,
},
});
gotoStep(1);
}}
/>
)}
{step === 1 && (
<UploadStep
attributes={attributes}
setAttributes={setAttributes}
files={files}
setFiles={setFiles}
confirm={() => gotoStep(2)}
/>
)}
{step === 2 && (
<InfoStep
attributes={attributes}
files={files}
isCollection={isCollection}
setIsCollection={setIsCollection}
setAttributes={setAttributes}
confirm={() => gotoStep(3)}
/>
)}
{step === 3 && (
<RoyaltiesStep
attributes={attributes}
confirm={() => gotoStep(4)}
setAttributes={setAttributes}
/>
)}
{step === 4 && (
<LaunchStep
attributes={attributes}
files={files}
confirm={() => gotoStep(5)}
connection={connection}
/>
)}
{step === 5 && (
<WaitingStep
mint={mint}
minting={isMinting}
step={nftCreateProgress}
confirm={() => gotoStep(6)}
/>
)}
{0 < step && step < 5 && (
<div style={{ margin: 'auto', width: 'fit-content' }}>
<Button onClick={() => gotoStep(step - 1)}>Back</Button>
</div>
)}
</Col>
</Row>
<MetaplexOverlay visible={step === 6}>
<Congrats nft={nft} alert={alertMessage} />
</MetaplexOverlay>
</>
);
}
Example #15
Source File: control.tsx From leek with Apache License 2.0 | 4 votes |
ControlPage = () => {
const [current, setCurrent] = useState(0);
const [command, setCommand] = useState<string>("revoke");
const { currentApp, currentEnv } = useApplication();
const service = new ControlService();
const metricsService = new MetricsService();
const [broadcasting, setBroadcasting] = useState<boolean>();
const [seenTasks, setSeenTasks] = useState([]);
const [taskName, setTaskName] = useState<string>();
const [terminate, setTerminate] = useState<boolean>(false);
const [signal, setSignal] = useState<string>("SIGTERM");
const [revocationCount, setRevocationCount] = useState<number>(0);
const [seenTasksFetching, setSeenTasksFetching] = useState<boolean>();
const next = () => {
if (command === "revoke" && current === 1)
revoke("true").then(() => {
setCurrent(current + 1);
});
else setCurrent(current + 1);
};
const prev = () => {
setCurrent(current - 1);
};
const memoizedTaskNameOptions = useMemo(() => {
// memoize this because it's common to have many different task names, which causes the dropdown to be very laggy.
// This is a known problem in Ant Design
return seenTasks.map((task, key) => badgedOption(task));
}, [seenTasks]);
function revoke(dry_run) {
if (!currentApp || !currentEnv || !taskName) return;
setBroadcasting(true);
return service
.revokeTasksByName(
currentApp,
currentEnv,
taskName,
terminate,
signal,
dry_run
)
.then(handleAPIResponse)
.then((result: any) => {
setRevocationCount(result.revocation_count);
if (dry_run !== "true") {
setCurrent(0);
pendingRevocation(result);
}
}, handleAPIError)
.catch(handleAPIError)
.finally(() => setBroadcasting(false));
}
function broadcastCommand() {
if (command === "revoke") revoke("false");
}
function pendingRevocation(result) {
confirm({
title: "Tasks pending revocation!",
icon: <CheckCircleOutlined style={{ color: "#00BFA6" }} />,
content: (
<>
<Typography.Paragraph>
Revocation command queued for {result.revocation_count} tasks!
</Typography.Paragraph>
</>
),
okText: "Ok",
cancelButtonProps: { style: { display: "none" } },
});
}
function getSeenTasks(open) {
if (!currentApp || !open) return;
setSeenTasksFetching(true);
metricsService
.getSeenTasks(currentApp, currentEnv, {})
.then(handleAPIResponse)
.then((result: any) => {
setSeenTasks(result.aggregations.seen_tasks.buckets);
}, handleAPIError)
.catch(handleAPIError)
.finally(() => setSeenTasksFetching(false));
}
return (
<>
<Helmet>
<html lang="en" />
<title>Control</title>
<meta name="description" content="Control commands" />
<meta name="keywords" content="celery, commands" />
</Helmet>
{/* Steps */}
<Row style={{ marginTop: 20 }}>
<Card style={{ width: "100%" }}>
<Steps current={current}>
<Step title="Command" description="Choose command" />
<Step title="Setup" description="Setup command args" />
<Step title="Broadcast" description="Broadcast command" />
</Steps>
</Card>
</Row>
{/* Tabs Containers */}
<Row style={{ marginTop: 20, marginBottom: 20 }}>
<Card style={{ width: "100%", alignItems: "center" }}>
{current == 0 && (
<Row justify="center" style={{ width: "100%" }}>
<Row style={{ width: "100%" }} justify="center">
<Typography.Title level={5}>
What control command you want to broadcast?
</Typography.Title>
</Row>
<Row style={{ width: "100%" }} justify="center">
<Select
style={{ width: "200" }}
defaultValue="revoke"
onSelect={(value) => setCommand(value)}
>
<Option value="revoke">Revoke</Option>
</Select>
</Row>
</Row>
)}
{current == 1 && command === "revoke" && (
<Row justify="center" style={{ width: "100%" }}>
<Typography.Paragraph>
Revoking tasks works by sending a broadcast message to all the
workers, the workers then keep a list of revoked tasks in
memory. When a worker receives a task in the list, it will skip
executing the task.
</Typography.Paragraph>
<Select
placeholder="Task name"
style={{ width: "100%" }}
allowClear
showSearch
dropdownMatchSelectWidth={false}
onDropdownVisibleChange={getSeenTasks}
notFoundContent={seenTasksFetching ? loadingIndicator : null}
// @ts-ignore
onSelect={(value) => setTaskName(value)}
>
{memoizedTaskNameOptions}
</Select>
<Row align="middle" style={{ marginTop: 16, width: "100%" }}>
<Checkbox onChange={(e) => setTerminate(e.target.checked)}>
{" "}
Terminate already started tasks with
</Checkbox>
<Select
style={{ width: 90 }}
// @ts-ignore
onSelect={(value) => setSignal(value)}
defaultValue="SIGTERM"
>
<Option value="SIGTERM">SIGTERM</Option>
<Option value="SIGKILL">SIGKILL</Option>
</Select>
</Row>
<Row justify="start" style={{ width: "100%", marginTop: 10 }}>
<Typography.Paragraph type="secondary">
The worker won’t terminate an already executing task unless
the terminate option is set.
</Typography.Paragraph>
</Row>
<Divider />
<Row justify="start" style={{ width: "100%" }}>
<Typography.Text type="secondary">
<Typography.Text strong type="warning">
Caveats:
</Typography.Text>
<ul>
<li>
When a worker starts up it will synchronize revoked tasks
with other workers in the cluster unless you have disabled
synchronization using worker arg
<Typography.Text code>--without-mingle</Typography.Text>.
</li>
<li>
If The list of revoked tasks is in-memory and if all
workers restart the list of revoked ids will also vanish.
If you want to preserve this list between restarts you
need to specify a file for these to be stored in by using
the <Typography.Text code>–statedb</Typography.Text>{" "}
argument to celery worker.
</li>
</ul>
</Typography.Text>
</Row>
</Row>
)}
{current == 2 && command === "revoke" && (
<>
<Row justify="center" style={{ width: "100%" }}>
<Typography.Paragraph>
Found{" "}
<Typography.Text code>{revocationCount}</Typography.Text>{" "}
pending ( <TaskState state="QUEUED" />{" "}
<TaskState state="RECEIVED" /> <TaskState state="STARTED" />)
instances of task{" "}
<Typography.Text code>{taskName}</Typography.Text>. Are you
sure you want to revoke them all?
</Typography.Paragraph>
</Row>
{terminate && (
<Row justify="center" style={{ width: "100%" }}>
<Typography.Paragraph type="secondary">
If an instance is already <TaskState state="STARTED" /> it
will be terminated using{" "}
<Typography.Text code>{signal}</Typography.Text> signal!
</Typography.Paragraph>
</Row>
)}
</>
)}
</Card>
</Row>
{/* Controls */}
<Row justify="end">
{current > 0 && (
<Button style={{ margin: "0 8px" }} onClick={() => prev()}>
Previous
</Button>
)}
{current < 2 && (
<Button type="primary" onClick={() => next()}>
Next
</Button>
)}
{current === 2 && (
<Button
type="primary"
onClick={broadcastCommand}
loading={broadcasting}
>
Broadcast
</Button>
)}
</Row>
</>
);
}
Example #16
Source File: UpdateForm.tsx From ui-visualization with MIT License | 4 votes |
UpdateForm: React.FC<UpdateFormProps> = (props) => {
const [formVals, setFormVals] = useState<FormValueType>({
name: props.values.name,
desc: props.values.desc,
key: props.values.key,
target: '0',
template: '0',
type: '1',
time: '',
frequency: 'month',
});
const [currentStep, setCurrentStep] = useState<number>(0);
const [form] = Form.useForm();
const {
onSubmit: handleUpdate,
onCancel: handleUpdateModalVisible,
updateModalVisible,
values,
} = props;
const forward = () => setCurrentStep(currentStep + 1);
const backward = () => setCurrentStep(currentStep - 1);
const handleNext = async () => {
const fieldsValue = await form.validateFields();
setFormVals({ ...formVals, ...fieldsValue });
if (currentStep < 2) {
forward();
} else {
handleUpdate({ ...formVals, ...fieldsValue });
}
};
const renderContent = () => {
if (currentStep === 1) {
return (
<>
<FormItem name="target" label="监控对象">
<Select style={{ width: '100%' }}>
<Option value="0">表一</Option>
<Option value="1">表二</Option>
</Select>
</FormItem>
<FormItem name="template" label="规则模板">
<Select style={{ width: '100%' }}>
<Option value="0">规则模板一</Option>
<Option value="1">规则模板二</Option>
</Select>
</FormItem>
<FormItem name="type" label="规则类型">
<RadioGroup>
<Radio value="0">强</Radio>
<Radio value="1">弱</Radio>
</RadioGroup>
</FormItem>
</>
);
}
if (currentStep === 2) {
return (
<>
<FormItem
name="time"
label="开始时间"
rules={[{ required: true, message: '请选择开始时间!' }]}
>
<DatePicker
style={{ width: '100%' }}
showTime
format="YYYY-MM-DD HH:mm:ss"
placeholder="选择开始时间"
/>
</FormItem>
<FormItem name="frequency" label="调度周期">
<Select style={{ width: '100%' }}>
<Option value="month">月</Option>
<Option value="week">周</Option>
</Select>
</FormItem>
</>
);
}
return (
<>
<FormItem
name="name"
label="规则名称"
rules={[{ required: true, message: '请输入规则名称!' }]}
>
<Input placeholder="请输入" />
</FormItem>
<FormItem
name="desc"
label="规则描述"
rules={[{ required: true, message: '请输入至少五个字符的规则描述!', min: 5 }]}
>
<TextArea rows={4} placeholder="请输入至少五个字符" />
</FormItem>
</>
);
};
const renderFooter = () => {
if (currentStep === 1) {
return (
<>
<Button style={{ float: 'left' }} onClick={backward}>
上一步
</Button>
<Button onClick={() => handleUpdateModalVisible(false, values)}>取消</Button>
<Button type="primary" onClick={() => handleNext()}>
下一步
</Button>
</>
);
}
if (currentStep === 2) {
return (
<>
<Button style={{ float: 'left' }} onClick={backward}>
上一步
</Button>
<Button onClick={() => handleUpdateModalVisible(false, values)}>取消</Button>
<Button type="primary" onClick={() => handleNext()}>
完成
</Button>
</>
);
}
return (
<>
<Button onClick={() => handleUpdateModalVisible(false, values)}>取消</Button>
<Button type="primary" onClick={() => handleNext()}>
下一步
</Button>
</>
);
};
return (
<Modal
width={640}
bodyStyle={{ padding: '32px 40px 48px' }}
destroyOnClose
title="规则配置"
visible={updateModalVisible}
footer={renderFooter()}
onCancel={() => handleUpdateModalVisible()}
>
<Steps style={{ marginBottom: 28 }} size="small" current={currentStep}>
<Step title="基本信息" />
<Step title="配置规则属性" />
<Step title="设定调度周期" />
</Steps>
<Form
{...formLayout}
form={form}
initialValues={{
target: formVals.target,
template: formVals.template,
type: formVals.type,
frequency: formVals.frequency,
name: formVals.name,
desc: formVals.desc,
}}
>
{renderContent()}
</Form>
</Modal>
);
}
Example #17
Source File: groupSave.tsx From jetlinks-ui-antd with MIT License | 4 votes |
groupSave: React.FC<Props> = props => {
const {
form: {getFieldDecorator},
form,
} = props;
const initState: State = {
currentStep: 0,
deviceId: [],
groupData: props.data
};
const [currentStep, setCurrentStep] = useState<number>(initState.currentStep);
const [deviceId, setDeviceId] = useState(initState.deviceId);
const [groupData, setGroupData] = useState(initState.groupData);
let taskByIdPush: any;
useEffect(() => {
props.data.devices?.map((item: any) => {
deviceId.push(item.id);
});
return () => {
taskByIdPush && taskByIdPush.unsubscribe();
};
}, []);
const submitData = () => {
form.validateFields((err, fileValue) => {
if (err) return;
if (props.data.id) {
apis.deviceGroup.saveOrUpdate(fileValue)
.then((response: any) => {
if (response.status === 200) {
message.success("保存成功");
setCurrentStep(Number(currentStep + 1));
}
}).catch(() => {
})
} else {
apis.deviceGroup.save(fileValue)
.then((response: any) => {
if (response.status === 200) {
message.success("保存成功");
setCurrentStep(Number(currentStep + 1));
setGroupData(response.result);
}
}).catch(() => {
})
}
});
};
const groupBindDevice = () => {
apis.deviceGroup._bind(groupData.id, deviceId)
.then((response: any) => {
if (response.status === 200) {
message.success('绑定成功');
setCurrentStep(Number(currentStep + 1));
}
}).catch(() => {
});
};
return (
<Modal
title={`${props.data?.id ? '编辑' : '新建'}设备分组`}
visible
okText={currentStep === 2 ? '完成' : '下一步'}
cancelText={currentStep === 0 ? '取消' : '上一步'}
onOk={() => {
if (currentStep === 2) {
props.close();
} else if (currentStep === 1) {
groupBindDevice();
} else {
submitData();
}
}}
width='50%'
onCancel={(event) => {
if (event.target.tagName === 'BUTTON') {
if (currentStep === 0) {
props.close();
} else {
setCurrentStep(Number(currentStep - 1));
}
} else {
props.close();
}
}}
>
<Steps current={currentStep} size="small" className={styles.steps} style={{paddingBottom: 24}}>
<Steps.Step title="基本信息"/>
<Steps.Step title="绑定设备"/>
<Steps.Step title="完成"/>
</Steps>
<div>
{currentStep === 0 && (
<Form labelCol={{span: 5}} wrapperCol={{span: 15}} key="groupForm">
<Form.Item key="id" label="分组标识">
{getFieldDecorator('id', {
rules: [
{required: true, message: '请输入分组标识'},
{max: 64, message: '分组标识不超过64个字符'},
{pattern: new RegExp(/^[0-9a-zA-Z_\-]+$/, "g"), message: '分组标识只能由数字、字母、下划线、中划线组成'}
],
initialValue: props.data?.id,
})(<Input placeholder="输入分组ID" disabled={!!props.data.id}/>)}
</Form.Item>
<Form.Item key="name" label="分组名称">
{getFieldDecorator('name', {
rules: [
{required: true, message: '请输入分组名称'},
{max: 200, message: '分组名称不超过200个字符'}
],
initialValue: props.data?.name,
})(<Input placeholder="输入分组名称"/>)}
</Form.Item>
<Form.Item key='description' label="描述">
{getFieldDecorator('description', {
initialValue: props.data?.description,
})(<Input.TextArea rows={4}/>)}
</Form.Item>
</Form>
)}
{/* {currentStep === 1 && (
<div>
<Card style={{maxHeight: 500, overflowY: 'auto', overflowX: 'hidden'}}>
<ChoiceDevice deviceList={deviceId} save={(item: any[]) => {
setDeviceId(item);
}}/>
</Card>
</div>
)} */}
{currentStep === 2 && (
<Result
status="success"
title="操作成功"
className={styles.result}
>
</Result>
)}
</div>
</Modal>
);
}
Example #18
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
Save: React.FC<Props> = props => {
const {
form: { getFieldDecorator },
form,
} = props;
const initState: State = {
currentStep: 0,
upgradeData: props.data,
releaseType: '',
deviceId: [],
speedProgress: {
waiting: 0,
processing: 0,
},
};
const [currentStep, setCurrentStep] = useState<number>(initState.currentStep);
const [upgradeData, setUpgradeData] = useState(initState.upgradeData);
const [releaseType, setReleaseType] = useState(initState.releaseType);
const [deviceId, setDeviceId] = useState(initState.deviceId);
const [speedProgress, setSpeedProgress] = useState(initState.speedProgress);
const [progressConditions, setProgressConditions] = useState(false);
const [resultSpinning, setResultSpinning] = useState(false);
let taskByIdPush: any;
const historyCount = () => {
apis.firmware._count(
encodeQueryParam({ terms: { taskId: upgradeData.id, state: 'waiting' } }),
).then((response: any) => {
if (response.status === 200) {
speedProgress.waiting = response.result;
setSpeedProgress({ ...speedProgress });
apis.firmware._count(
encodeQueryParam({ terms: { taskId: upgradeData.id, state: 'processing' } }),
).then((response: any) => {
if (response.status === 200) {
speedProgress.processing = response.result;
setSpeedProgress({ ...speedProgress });
setProgressConditions(true);
taskPush();
} else {
setResultSpinning(false);
}
}).catch(() => {
});
} else {
setResultSpinning(false);
}
}).catch(() => {
});
};
useEffect(() => {
return () => {
taskByIdPush && taskByIdPush.unsubscribe();
};
}, []);
const submitData = () => {
form.validateFields((err, fileValue) => {
if (err) return;
let params = {
...fileValue,
id: props.data.id,
productId: props.productId,
firmwareId: props.firmwareId,
};
if (upgradeData.id) {
apis.firmware.updateUpgrade(params)
.then((response: any) => {
if (response.status === 200) {
message.success('保存成功');
if (props.data.id) {
setCurrentStep(2);
} else {
setCurrentStep(Number(currentStep + 1));
}
}
}).catch(() => {
});
} else {
apis.firmware.saveUpgrade(params)
.then((response: any) => {
if (response.status === 200) {
message.success('保存成功');
setUpgradeData(response.result);
setCurrentStep(Number(currentStep + 1));
}
}).catch(() => {
});
}
});
};
const taskRelease = () => {
if (releaseType === '' || releaseType === null) {
message.error('请选择发布方式');
return;
}
if (releaseType === 'all') {
apis.firmware._deployAll(upgradeData.id)
.then((response: any) => {
if (response.status === 200) {
message.success('任务发布成功');
setCurrentStep(Number(currentStep + 1));
}
}).catch(() => {
});
} else {
apis.firmware._deploy(deviceId, upgradeData.id)
.then((response: any) => {
if (response.status === 200) {
message.success('任务发布成功');
setCurrentStep(Number(currentStep + 1));
}
}).catch(() => {
});
}
};
const taskPush = () => {
if (taskByIdPush) {
taskByIdPush.unsubscribe();
}
setResultSpinning(false);
taskByIdPush = getWebsocket(
`firmware-push-upgrade-by-taskId`,
`/device-firmware/publish`,
{
taskId: upgradeData.id,
},
).subscribe((resp: any) => {
const { payload } = resp;
if (payload.success) {
speedProgress.processing = (speedProgress.processing + 1);
speedProgress.waiting = (speedProgress.waiting - 1);
setSpeedProgress({ ...speedProgress });
}
});
};
const extra = (
<>
{upgradeData.mode?.value === 'push' && (
<Button type="primary" onClick={() => {
setResultSpinning(false);
historyCount();
}}>
推送升级
</Button>
)}
</>
);
const progressDisplay = (
<div className={styles.information} style={{ textAlign: 'center' }}>
<Descriptions column={1}>
<Descriptions.Item label="等待升级">{speedProgress.waiting}</Descriptions.Item>
<Descriptions.Item label="升级中"> {speedProgress.processing}</Descriptions.Item>
</Descriptions>
</div>
);
return (
<Modal
title={`${props.data?.id ? '编辑' : '新建'}固件版本`}
visible
okText={currentStep === 2 ? '完成' : '下一步'}
cancelText={currentStep === 0 ? '取消' : '上一步'}
onOk={() => {
if (currentStep === 2) {
props.close();
} else if (currentStep === 1) {
taskRelease();
} else {
submitData();
}
}}
/*cancelButtonProps={currentStep === 2 ? { disabled: true } : { disabled: false }}*/
width='60%'
onCancel={(event) => {
if (event.target.tagName === 'BUTTON') {
if (currentStep === 0) {
props.close();
} else {
setCurrentStep(Number(currentStep - 1));
}
} else {
props.close();
}
}}
>
<Steps current={currentStep} className={styles.steps}>
<Steps.Step title="任务信息"/>
<Steps.Step title="发布任务"/>
<Steps.Step title="完成"/>
</Steps>
{currentStep === 0 && (
<Form labelCol={{ span: 3 }} wrapperCol={{ span: 20 }} key="firmwareForm">
<Form.Item key="name" label="任务名称">
{getFieldDecorator('name', {
rules: [{ required: true, message: '任务名称必填' }],
initialValue: props.data.name,
})(<Input placeholder="输入任务名称"/>)}
</Form.Item>
<Form.Item key="timeoutSeconds" label="超时时间">
{getFieldDecorator('timeoutSeconds', {
rules: [{ required: true, message: '超时时间必填' }],
initialValue: props.data.timeoutSeconds,
})(<Input placeholder="输入超时时间/秒"/>)}
</Form.Item>
<Form.Item key="mode" label="推送方式">
{getFieldDecorator('mode', {
rules: [{ required: true, message: '推送方式必填' }],
initialValue: props.data.mode?.value,
})(<Select placeholder="选择推送方式">
<Select.Option value='push'>平台推送</Select.Option>
<Select.Option value='pull'>设备拉取</Select.Option>
</Select>)}
</Form.Item>
<Form.Item label="描述">
{getFieldDecorator('description', {
initialValue: props.data.description,
})(<Input.TextArea rows={4}/>)}
</Form.Item>
</Form>
)}
{currentStep === 1 && (
<div>
<Form labelCol={{ span: 3 }} wrapperCol={{ span: 20 }} key="releaseForm">
<Form.Item key="releaseType" label="发布方式">
{getFieldDecorator('releaseType', {
rules: [{ required: true, message: '选择发布方式' }],
})(<Select placeholder="选择发布方式" onChange={(value: string) => {
setReleaseType(value);
}}>
<Select.Option value='all'>所有设备</Select.Option>
<Select.Option value='part'>选择设备</Select.Option>
</Select>)}
</Form.Item>
</Form>
{releaseType === 'part' && (
<Form.Item wrapperCol={{ span: 20 }} labelCol={{ span: 3 }} label='选择设备'>
<Card style={{ maxHeight: 500, overflowY: 'auto', overflowX: 'hidden' }}>
<ChoiceDevice productId={props.productId} save={(item: any[]) => {
setDeviceId(item);
}}/>
</Card>
</Form.Item>
)}
</div>
)}
{currentStep === 2 && (
<Spin spinning={resultSpinning} tip="加载中...">
<Result status="success" title="操作成功" extra={extra} className={styles.result}>
{progressConditions && (progressDisplay)}
</Result>
</Spin>
)}
</Modal>
);
}
Example #19
Source File: SaveTask.tsx From jetlinks-ui-antd with MIT License | 4 votes |
Save: React.FC<Props> = props => {
const {
form: {getFieldDecorator},
form,
} = props;
const initState: State = {
currentStep: props.appointStep,
upgradeData: props.data,
releaseType: 'all',
deviceId: [],
taskStatus: {
waiting: 0,
waitingSpinning: true,
processing: 0,
processingSpinning: true,
success: 0,
successSpinning: true,
failed: 0,
failedSpinning: true,
},
};
const [currentStep, setCurrentStep] = useState<number>(initState.currentStep);
const [upgradeData, setUpgradeData] = useState(initState.upgradeData);
const [releaseType, setReleaseType] = useState(initState.releaseType);
const [deviceId, setDeviceId] = useState(initState.deviceId);
const [taskStatus, setTaskStatus] = useState(initState.taskStatus);
const [spinning, setSpinning] = useState(false);
const [pushOrSuspend, setPushOrSuspend] = useState(false);
const [taskByIdPush, setTaskByIdPush] = useState<any>();
useEffect(() => {
return () => {
taskByIdPush && taskByIdPush.unsubscribe();
};
}, [taskByIdPush]);
const taskStatusProcessing = () => {
apis.firmware._count(
encodeQueryParam({terms: {taskId: upgradeData.id, state: 'processing'}}),
).then((response: any) => {
if (response.status === 200) {
taskStatus.processing = response.result;
taskStatus.processingSpinning = false;
setTaskStatus({...taskStatus});
}
}).catch(() => {
});
};
const taskStatusWaiting = () => {
apis.firmware._count(
encodeQueryParam({terms: {taskId: upgradeData.id, state: 'waiting'}}),
).then((response: any) => {
if (response.status === 200) {
taskStatus.waiting = response.result;
taskStatus.waitingSpinning = false;
setTaskStatus({...taskStatus});
}
}).catch(() => {
});
};
const taskStatusFailed = () => {
apis.firmware._count(
encodeQueryParam({terms: {taskId: upgradeData.id, state: 'failed'}}),
).then((response: any) => {
if (response.status === 200) {
taskStatus.failed = response.result;
taskStatus.failedSpinning = false;
setTaskStatus({...taskStatus});
}
}).catch(() => {
});
};
const taskStatusSuccess = () => {
apis.firmware._count(
encodeQueryParam({terms: {taskId: upgradeData.id, state: 'success'}}),
).then((response: any) => {
if (response.status === 200) {
taskStatus.success = response.result;
taskStatus.successSpinning = false;
setTaskStatus({...taskStatus});
}
}).catch(() => {
});
};
useEffect(() => {
if (currentStep === 2) {
taskStatusWaiting();
taskStatusProcessing();
taskStatusSuccess();
taskStatusFailed();
}
}, [currentStep]);
const submitData = () => {
form.validateFields((err, fileValue) => {
if (err) return;
let params = {
...fileValue,
id: upgradeData.id,
productId: props.productId,
firmwareId: props.firmwareId,
};
if (upgradeData.id) {
apis.firmware.updateUpgrade(params)
.then((response: any) => {
if (response.status === 200) {
message.success('保存成功');
setSpinning(false);
if (props.data.id) {
setCurrentStep(2);
} else {
setCurrentStep(Number(currentStep + 1));
}
}
}).catch(() => {
});
} else {
apis.firmware.saveUpgrade(params)
.then((response: any) => {
if (response.status === 200) {
message.success('保存成功');
setUpgradeData(response.result);
setSpinning(false);
setCurrentStep(Number(currentStep + 1));
}
}).catch(() => {
});
}
});
};
const taskRelease = () => {
if (releaseType === '' || releaseType === null) {
message.error('请选择发布方式');
setSpinning(false);
return;
}
if (releaseType === 'all') {
apis.firmware._deployAll(upgradeData.id)
.then((response: any) => {
if (response.status === 200) {
message.success('任务发布成功');
setSpinning(false);
setCurrentStep(Number(currentStep + 1));
}
}).catch(() => {
});
} else {
apis.firmware._deploy(deviceId, upgradeData.id)
.then((response: any) => {
if (response.status === 200) {
message.success('任务发布成功');
setSpinning(false);
setCurrentStep(Number(currentStep + 1));
}
}).catch(() => {
});
}
};
const taskPush = () => {
if (taskByIdPush) {
taskByIdPush.unsubscribe();
}
let taskPush = getWebsocket(
`firmware-push-upgrade-by-taskId`,
`/device-firmware/publish`,
{
taskId: upgradeData.id,
},
).subscribe(() => {
taskStatus.processing = (taskStatus.processing + 1);
taskStatus.waiting = (taskStatus.waiting - 1);
setTaskStatus({...taskStatus});
});
setTaskByIdPush(taskPush);
};
return (
<Card style={{padding: 5}}>
<Steps current={currentStep} size="small" className={styles.steps} style={{paddingBottom: 24}}>
<Steps.Step title="任务信息"/>
<Steps.Step title="发布任务"/>
<Steps.Step title="完成"/>
</Steps>
<Spin spinning={spinning}>
<div>
{currentStep === 0 && (
<Form labelCol={{span: 9}} wrapperCol={{span: 7}} key="firmwareForm">
<Form.Item key="name" label="任务名称">
{getFieldDecorator('name', {
rules: [
{required: true, message: '请输入任务名称'},
{max: 200, message: '任务名称不超过200个字符'}
],
initialValue: upgradeData.name,
})(<Input placeholder="输入任务名称"/>)}
</Form.Item>
<Form.Item key="timeoutSeconds" label="超时时间">
{getFieldDecorator('timeoutSeconds', {
rules: [{required: true, message: '请输入超时时间'}],
initialValue: upgradeData.timeoutSeconds,
})(<InputNumber min={0} step={1} style={{width:'100%'}} placeholder="请输入超时时间"/>)}
</Form.Item>
<Form.Item key="mode" label="推送方式">
{getFieldDecorator('mode', {
rules: [{required: true, message: '推送方式必填'}],
initialValue: upgradeData.mode?.value,
})(<Select placeholder="选择推送方式">
<Select.Option value='push'>平台推送</Select.Option>
<Select.Option value='pull'>设备拉取</Select.Option>
</Select>)}
</Form.Item>
<Form.Item label="描述">
{getFieldDecorator('description', {
initialValue: upgradeData.description,
})(<Input.TextArea rows={4}/>)}
</Form.Item>
</Form>
)}
{currentStep === 1 && (
<div>
<Form labelCol={{span: 4}} wrapperCol={{span: 17}} key="releaseForm">
<Form.Item key="releaseType" label="发布方式">
{getFieldDecorator('releaseType', {
rules: [{required: true, message: '选择发布方式'}],
initialValue: releaseType,
})(
<Radio.Group buttonStyle="solid" onChange={(event) => {
setReleaseType(event.target.value);
}}>
<Radio.Button value="all">所有设备</Radio.Button>
<Radio.Button value="part">选择设备</Radio.Button>
</Radio.Group>,
)}
</Form.Item>
</Form>
{releaseType === 'part' && (
<Form.Item labelCol={{span: 4}} wrapperCol={{span: 17}} label='选择设备'>
<Card style={{maxHeight: 500, overflowY: 'auto', overflowX: 'hidden'}}>
<ChoiceDevice productId={props.productId} save={(item: any[]) => {
setDeviceId(item);
}}/>
</Card>
</Form.Item>
)}
</div>
)}
{currentStep === 2 && (
<div style={{padding: '0 15% 0 15%'}}>
<Row gutter={24}>
<Col {...topColResponsiveProps}>
<Spin spinning={taskStatus.waitingSpinning}>
<ChartCard title={<Badge status="warning" text='等待升级'/>}
total={<AutoHide title={taskStatus.waiting} style={{width: '313%'}}/>}
action={
<div>
<Icon title='刷新' type="sync" onClick={() => {
taskStatus.waitingSpinning = true;
setTaskStatus({...taskStatus});
taskStatusWaiting();
}}/>
</div>
}
>
<a style={{float: 'right', marginLeft: 8}}
onClick={() => {
props.close({type: 'history', taskId: props.data.id, state: 'waiting'});
}}>
查看
</a>
{upgradeData.mode?.value === 'push' && (
<>
{pushOrSuspend ? (
<Popconfirm title="确定暂停此次推送任务?请谨慎操作" onConfirm={() => {
taskByIdPush && taskByIdPush.unsubscribe();
setPushOrSuspend(false);
message.success('已暂停');
}}>
<a style={{float: 'right'}}>
暂停推送
</a>
</Popconfirm>
) : (
<Popconfirm title="确定推送此升级任务至设备?请谨慎操作" onConfirm={() => {
setPushOrSuspend(true);
taskPush();
}}>
<a style={{float: 'right'}}>
推送升级
</a>
</Popconfirm>
)}
</>
)}
</ChartCard>
</Spin>
</Col>
<Col {...topColResponsiveProps}>
<Spin spinning={taskStatus.processingSpinning}>
<ChartCard title={<Badge status="processing" text='升级中'/>}
total={<AutoHide title={taskStatus.processing} style={{width: '313%'}}/>}
action={
<div>
<Icon title='刷新' type="sync" onClick={() => {
taskStatus.processingSpinning = true;
setTaskStatus({...taskStatus});
taskStatusProcessing();
}}/>
</div>
}
>
<a style={{float: 'right'}}
onClick={() => {
props.close({type: 'history', taskId: props.data.id, state: 'processing'});
}}>
查看
</a>
</ChartCard>
</Spin>
</Col>
<Col {...topColResponsiveProps}>
<Spin spinning={taskStatus.successSpinning}>
<ChartCard title={<Badge status="success" text='升级完成'/>}
total={<AutoHide title={taskStatus.success} style={{width: '313%'}}/>}
action={
<div>
<Icon title='刷新' type="sync" onClick={() => {
taskStatus.successSpinning = true;
setTaskStatus({...taskStatus});
taskStatusSuccess();
}}/>
</div>
}
>
<a style={{float: 'right'}}
onClick={() => {
props.close({type: 'history', taskId: props.data.id, state: 'success'});
}}>
查看
</a>
</ChartCard>
</Spin>
</Col>
<Col {...topColResponsiveProps}>
<Spin spinning={taskStatus.failedSpinning}>
<ChartCard title={<Badge status="error" text='升级失败'/>}
total={<AutoHide title={taskStatus.failed} style={{width: '313%'}}/>}
action={
<div>
<Icon title='刷新' type="sync" onClick={() => {
taskStatus.failedSpinning = true;
setTaskStatus({...taskStatus});
taskStatusFailed();
}}/>
</div>
}
>
<a style={{float: 'right'}}
onClick={() => {
props.close({type: 'history', taskId: props.data.id, state: 'failed'});
}}>
查看
</a>
</ChartCard>
</Spin>
</Col>
</Row>
</div>
)}
<div style={{textAlign: 'center'}}>
{currentStep === 0 ? (<Button onClick={() => {
props.close({type: 'task'});
}}>
返回
</Button>) : (<Button onClick={() => {
setCurrentStep(Number(currentStep - 1));
}}>
上一步
</Button>
)}
{currentStep === 2 ? (
<Button type="primary" style={{marginLeft: 8}} onClick={() => {
props.close({type: 'task'});
}}>
完成
</Button>
) : (<Button type="primary" style={{marginLeft: 8}} onClick={() => {
setSpinning(true);
if (currentStep === 0) {
submitData();
} else {
taskRelease();
}
}}>
下一步
</Button>)}
</div>
</div>
</Spin>
</Card>
);
}
Example #20
Source File: questionnaire.tsx From RareCamp with Apache License 2.0 | 4 votes |
export default function questionnaire() {
const [current, setCurrent] = React.useState(0)
const [formValues, setFormValues] = React.useState({})
const [feasibility, setFeasibility] = React.useState({
isFeasible: false,
assessmentFinished: false,
answers: {},
})
const [content, setContent] = React.useState({
imgURL: '/eligibility_2.png',
description:
"Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs. The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De",
})
React.useEffect(() => {
if (current === 0)
setContent({
imgURL: '/eligibility_2.png',
description:
"Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs. The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De",
})
else if (current === 1)
setContent({
imgURL: '/eligibility_4.png',
description:
"Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs. The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De",
})
else
setContent({
imgURL: '/eligibility_3.png',
description:
"Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs. The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De",
})
}, [current])
const [form] = Form.useForm()
useEffect(() => {
setFormValues({ ...formValues, ...form.getFieldsValue() })
}, [form])
async function handleFormSubmit(values: Questionnaire) {
const isFeasible = isGeneTherapyFeasible(values)
setFeasibility({
isFeasible,
assessmentFinished: true,
answers: values,
})
}
const nextStep = () =>
form.validateFields().then(() => setCurrent(current + 1))
const title = 'Determine eligibility for AAV-based gene therapy'
const subTitle =
'Complete this short questionnaire to help our team determine your eligibility.'
return (
<AppLayout title="" selectedKey="programs">
<SubHeader title={<h3>{title}</h3>} subTitle={subTitle} />
<QuestionnaireContainer>
<div className="questionnaire-form">
{feasibility.assessmentFinished ? (
<QuestionnaireResult
isFeasible={feasibility.isFeasible}
answers={feasibility.answers as Questionnaire}
/>
) : (
<>
<Steps current={current}>
{steps.map((item, index) => (
<Step
className={index === 0 ? 'first-step' : ''}
key={item.title}
title={item.title}
/>
))}
</Steps>
<OFForm
onFinish={handleFormSubmit}
initialValues={{
proteinSize: ProteinSize.LESS_THAN_1100,
mutationType: MutationType.LEADS_TO_LOSS,
}}
layout="vertical"
form={form}
>
<div className="steps-content">
{steps.map((item, index) => (
<div
key={item.title}
style={{
display: index === current ? 'block' : 'none',
}}
>
{item.content}
</div>
))}
</div>
<div className="steps-action">
{current > 0 && (
<Button
style={{ margin: '0 8px' }}
onClick={() => setCurrent(current - 1)}
>
Back
</Button>
)}
{current < steps.length - 1 && (
<Button type="primary" onClick={nextStep}>
Next
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" htmlType="submit">
Check Eligibility
</Button>
)}
</div>
</OFForm>
</>
)}
</div>
<QuestionnaireIllustration
feasibility={feasibility}
className="questionnaire-illustration"
imgURL={content.imgURL}
description={content.description}
/>
</QuestionnaireContainer>
</AppLayout>
)
}
Example #21
Source File: index.tsx From posthog-foss with MIT License | 4 votes |
export function PreflightCheck(): JSX.Element {
const { preflight, preflightLoading, preflightMode } = useValues(preflightLogic)
const { setPreflightMode } = useActions(preflightLogic)
const isReady =
preflight &&
preflight.django &&
preflight.db &&
preflight.redis &&
preflight.celery &&
(preflightMode === 'experimentation' || preflight.plugins)
const checks = [
{
id: 'database',
name: 'Database (Postgres)',
status: preflight?.db,
},
{
id: 'backend',
name: 'Backend server (Django)',
status: preflight?.django,
},
{
id: 'redis',
name: 'Cache & queue (Redis)',
status: preflight?.redis,
},
{
id: 'celery',
name: 'Background jobs (Celery)',
status: preflight?.celery,
},
{
id: 'plugins',
name: 'Plugin server (Node)',
status: preflight?.plugins,
caption: preflightMode === 'experimentation' ? 'Required in production environments' : '',
failedState: preflightMode === 'experimentation' ? 'warning' : 'error',
},
{
id: 'frontend',
name: 'Frontend build (Webpack)',
status: true, // If this code is ran, the front-end is already built
},
{
id: 'tls',
name: 'SSL/TLS certificate',
status: window.location.protocol === 'https:',
caption:
preflightMode === 'experimentation'
? 'Not required for development or testing'
: 'Install before ingesting real user data',
failedState: preflightMode === 'experimentation' ? 'not-required' : 'warning',
},
] as CheckInterface[]
const handlePreflightFinished = (): void => {
router.actions.push(urls.signup())
}
return (
<div style={{ minHeight: '100vh' }}>
<Row
style={{
display: 'flex',
justifyContent: 'center',
paddingTop: 32,
paddingBottom: 32,
backgroundColor: '#eeefe9',
}}
>
<img src={posthogLogo} style={{ width: 157, height: 30 }} />
</Row>
<Row style={{ display: 'flex', justifyContent: 'center', paddingBottom: 16 }}>
<PageHeader title="Lets get started..." />
</Row>
<Row style={{ display: 'flex', justifyContent: 'center' }}>
<div style={{ width: 960 }}>
<Steps current={0}>
<Step title="Preflight check" subTitle="1 min" description="Prepare your instance" />
<Step
title="Event capture"
subTitle="15 mins"
description="Set up your app to capture events"
/>
<Step
title="Setup your team"
subTitle="5 mins"
description="Invite your team and start discovering insights"
/>
</Steps>
</div>
</Row>
<Row style={{ display: 'flex', justifyContent: 'center' }}>
<div style={{ display: 'flex', alignItems: 'center', flexDirection: 'column' }}>
<img src={suprisedHog} style={{ maxHeight: '100%', width: 320 }} />
<p>Any questions?</p>
<Button type="default" data-attr="support" data-source="preflight">
<a href="https://posthog.com/support" target="_blank" rel="noreferrer">
Get support
</a>
</Button>
</div>
<div
style={{
display: 'flex',
justifyContent: 'flex-start',
margin: '0 32px',
flexDirection: 'column',
paddingTop: 32,
}}
>
<Card style={{ width: '100%' }}>
<Row style={{ display: 'flex', justifyContent: 'space-between', lineHeight: '32px' }}>
{!preflightMode ? (
<b style={{ fontSize: 16 }}>Select launch mode</b>
) : (
<>
<b style={{ fontSize: 16 }}>
<span>
<span
style={{ color: blue.primary, cursor: 'pointer' }}
onClick={() => setPreflightMode(null)}
>
Select launch mode
</span>{' '}
> {capitalizeFirstLetter(preflightMode)}
</span>
</b>
<Button
type="default"
data-attr="preflight-refresh"
icon={<SyncOutlined />}
onClick={() => window.location.reload()}
disabled={preflightLoading || !preflight}
>
Refresh
</Button>
</>
)}
</Row>
{!preflightMode && (
<div>We're excited to have you here. What's your plan for this installation?</div>
)}
<div
className="text-center"
style={{ padding: '24px 0', display: 'flex', justifyContent: 'center', maxWidth: 533 }}
>
{!preflightMode && (
<>
<Button
type="default"
data-attr="preflight-experimentation"
size="large"
onClick={() => setPreflightMode('experimentation')}
icon={<ApiTwoTone />}
>
Just playing
</Button>
<Button
type="primary"
style={{ marginLeft: 16 }}
size="large"
data-attr="preflight-live"
onClick={() => setPreflightMode('live')}
icon={<RocketFilled />}
>
Live implementation
</Button>
</>
)}
{preflightMode && (
<>
<Row>
{checks.map((item) => (
<PreflightItem key={item.id} {...item} />
))}
</Row>
</>
)}
</div>
</Card>
{preflightMode && (
<>
<div className="space-top text-center" data-attr="preflightStatus">
{isReady ? (
<b style={{ color: green.primary }}>All systems go!</b>
) : (
<b>Checks in progress…</b>
)}
</div>
<div className="text-center" style={{ marginBottom: 64 }}>
<Button
type="primary"
data-attr="preflight-complete"
data-source={preflightMode}
disabled={!isReady}
onClick={handlePreflightFinished}
>
Continue
</Button>
</div>
</>
)}
</div>
</Row>
</div>
)
}