|
@@ -12,13 +12,15 @@ import { MemberId, Profile } from '@joystream/types/members';
|
|
|
import ProfilePreview from '@polkadot/joy-utils/MemberProfilePreview';
|
|
|
import { useTransport, usePromise } from '@polkadot/joy-utils/react/hooks';
|
|
|
import { Option, Bytes } from '@polkadot/types/';
|
|
|
+import { BlockNumber } from '@polkadot/types/interfaces';
|
|
|
import { formatBalance } from '@polkadot/util';
|
|
|
import { PromiseComponent } from '@polkadot/joy-utils/react/components';
|
|
|
import ReactMarkdown from 'react-markdown';
|
|
|
import { WorkingGroupOpeningPolicyCommitment, RewardPolicy } from '@joystream/types/working-group';
|
|
|
import {
|
|
|
ActivateOpeningAt,
|
|
|
- ActivateOpeningAtKeys
|
|
|
+ ActivateOpeningAtKeys,
|
|
|
+ StakingPolicy
|
|
|
} from '@joystream/types/hiring';
|
|
|
import { WorkingGroup, WorkingGroupKey } from '@joystream/types/common';
|
|
|
import { ApplicationsDetailsByOpening } from '@polkadot/joy-utils/react/components/working-groups/ApplicationDetails';
|
|
@@ -86,155 +88,201 @@ const ParsedHRT = styled.pre`
|
|
|
`;
|
|
|
|
|
|
type ParsedParamValue = string | number | JSX.Element;
|
|
|
-class FullWidthParam {
|
|
|
+
|
|
|
+class ParsedParam {
|
|
|
+ name: string;
|
|
|
value: ParsedParamValue;
|
|
|
- constructor (value: ParsedParamValue) {
|
|
|
+ fullWidth: boolean;
|
|
|
+
|
|
|
+ constructor (name: string, value: ParsedParamValue, fullWidth = false) {
|
|
|
+ this.name = name;
|
|
|
this.value = value;
|
|
|
+ this.fullWidth = fullWidth;
|
|
|
}
|
|
|
}
|
|
|
-type ParsedParams = { [paramName: string]: ParsedParamValue | FullWidthParam };
|
|
|
|
|
|
// The methods for parsing params by Proposal type.
|
|
|
-// They take the params as array and return { LABEL: VALUE } object.
|
|
|
-const paramParsers: { [x in ProposalType]: (params: any[]) => ParsedParams} = {
|
|
|
- Text: ([content]) => ({
|
|
|
- Content: new FullWidthParam(
|
|
|
- <ReactMarkdown className='TextProposalContent' source={content} linkTarget='_blank' />
|
|
|
+const paramParsers: { [x in ProposalType]: (params: any[]) => ParsedParam[]} = {
|
|
|
+ Text: ([content]) => [
|
|
|
+ new ParsedParam(
|
|
|
+ 'Content',
|
|
|
+ <ReactMarkdown className='TextProposalContent' source={content} linkTarget='_blank' />,
|
|
|
+ true
|
|
|
)
|
|
|
- }),
|
|
|
+ ],
|
|
|
RuntimeUpgrade: ([wasm]) => {
|
|
|
const buffer: Buffer = Buffer.from(wasm.replace('0x', ''), 'hex');
|
|
|
- return {
|
|
|
- 'Blake2b256 hash of WASM code': new FullWidthParam(blake2AsHex(buffer, 256)),
|
|
|
- 'File size': buffer.length + ' bytes'
|
|
|
- };
|
|
|
+ return [
|
|
|
+ new ParsedParam('Blake2b256 hash of WASM code', blake2AsHex(buffer, 256), true),
|
|
|
+ new ParsedParam('File size', buffer.length + ' bytes')
|
|
|
+ ];
|
|
|
},
|
|
|
- SetElectionParameters: ([params]) => ({
|
|
|
- 'Announcing period': params.announcing_period + ' blocks',
|
|
|
- 'Voting period': params.voting_period + ' blocks',
|
|
|
- 'Revealing period': params.revealing_period + ' blocks',
|
|
|
- 'Council size': params.council_size + ' members',
|
|
|
- 'Candidacy limit': params.candidacy_limit + ' members',
|
|
|
- 'New term duration': params.new_term_duration + ' blocks',
|
|
|
- 'Min. council stake': formatBalance(params.min_council_stake),
|
|
|
- 'Min. voting stake': formatBalance(params.min_voting_stake)
|
|
|
- }),
|
|
|
- Spending: ([amount, account]) => ({
|
|
|
- Amount: formatBalance(amount),
|
|
|
- Account: <ProposedAddress address={account} />
|
|
|
- }),
|
|
|
- SetLead: ([memberId, accountId]) => ({
|
|
|
- Member: <ProposedMember memberId={ memberId } />,
|
|
|
- 'Account id': <ProposedAddress address={accountId} />
|
|
|
- }),
|
|
|
- SetContentWorkingGroupMintCapacity: ([capacity]) => ({
|
|
|
- 'Mint capacity': formatBalance(capacity)
|
|
|
- }),
|
|
|
- EvictStorageProvider: ([accountId]) => ({
|
|
|
- 'Storage provider account': <ProposedAddress address={accountId} />
|
|
|
- }),
|
|
|
- SetValidatorCount: ([count]) => ({
|
|
|
- 'Validator count': count
|
|
|
- }),
|
|
|
- SetStorageRoleParameters: ([params]) => ({
|
|
|
- 'Min. stake': formatBalance(params.min_stake),
|
|
|
+ SetElectionParameters: ([params]) => [
|
|
|
+ new ParsedParam('Announcing period', params.announcing_period + ' blocks'),
|
|
|
+ new ParsedParam('Voting period', params.voting_period + ' blocks'),
|
|
|
+ new ParsedParam('Revealing period', params.revealing_period + ' blocks'),
|
|
|
+ new ParsedParam('Council size', params.council_size + ' members'),
|
|
|
+ new ParsedParam('Candidacy limit', params.candidacy_limit + ' members'),
|
|
|
+ new ParsedParam('New term duration', params.new_term_duration + ' blocks'),
|
|
|
+ new ParsedParam('Min. council stake', formatBalance(params.min_council_stake)),
|
|
|
+ new ParsedParam('Min. voting stake', formatBalance(params.min_voting_stake))
|
|
|
+ ],
|
|
|
+ Spending: ([amount, account]) => [
|
|
|
+ new ParsedParam('Amount', formatBalance(amount)),
|
|
|
+ new ParsedParam('Account', <ProposedAddress address={account} />)
|
|
|
+ ],
|
|
|
+ SetLead: ([memberId, accountId]) => [
|
|
|
+ new ParsedParam('Member', <ProposedMember memberId={ memberId } />),
|
|
|
+ new ParsedParam('Account id', <ProposedAddress address={accountId} />)
|
|
|
+ ],
|
|
|
+ SetContentWorkingGroupMintCapacity: ([capacity]) => [
|
|
|
+ new ParsedParam('Mint capacity', formatBalance(capacity))
|
|
|
+ ],
|
|
|
+ EvictStorageProvider: ([accountId]) => [
|
|
|
+ new ParsedParam('Storage provider account', <ProposedAddress address={accountId} />)
|
|
|
+ ],
|
|
|
+ SetValidatorCount: ([count]) => [
|
|
|
+ new ParsedParam('Validator count', count)
|
|
|
+ ],
|
|
|
+ SetStorageRoleParameters: ([params]) => [
|
|
|
+ new ParsedParam('Min. stake', formatBalance(params.min_stake)),
|
|
|
// "Min. actors": params.min_actors,
|
|
|
- 'Max. actors': params.max_actors,
|
|
|
- Reward: formatBalance(params.reward),
|
|
|
- 'Reward period': params.reward_period + ' blocks',
|
|
|
+ new ParsedParam('Max. actors', params.max_actors),
|
|
|
+ new ParsedParam('Reward', formatBalance(params.reward)),
|
|
|
+ new ParsedParam('Reward period', params.reward_period + ' blocks'),
|
|
|
// "Bonding period": params.bonding_period + " blocks",
|
|
|
- 'Unbonding period': params.unbonding_period + ' blocks',
|
|
|
+ new ParsedParam('Unbonding period', params.unbonding_period + ' blocks'),
|
|
|
// "Min. service period": params.min_service_period + " blocks",
|
|
|
// "Startup grace period": params.startup_grace_period + " blocks",
|
|
|
- 'Entry request fee': formatBalance(params.entry_request_fee)
|
|
|
- }),
|
|
|
+ new ParsedParam('Entry request fee', formatBalance(params.entry_request_fee))
|
|
|
+ ],
|
|
|
AddWorkingGroupLeaderOpening: ([{ activate_at, commitment, human_readable_text, working_group }]) => {
|
|
|
const workingGroup = new WorkingGroup(working_group);
|
|
|
const activateAt = new ActivateOpeningAt(activate_at);
|
|
|
const activateAtBlock = activateAt.type === ActivateOpeningAtKeys.ExactBlock ? activateAt.value : null;
|
|
|
const OPCommitment = new WorkingGroupOpeningPolicyCommitment(commitment);
|
|
|
const {
|
|
|
- application_staking_policy: aSP,
|
|
|
- role_staking_policy: rSP,
|
|
|
+ application_staking_policy: applicationSP,
|
|
|
+ role_staking_policy: roleSP,
|
|
|
application_rationing_policy: rationingPolicy
|
|
|
} = OPCommitment;
|
|
|
let HRT = bytesToString(new Bytes(human_readable_text));
|
|
|
try { HRT = JSON.stringify(JSON.parse(HRT), undefined, 4); } catch (e) { /* Do nothing */ }
|
|
|
- return {
|
|
|
- 'Working group': workingGroup.type,
|
|
|
- 'Activate at': `${activateAt.type}${activateAtBlock ? `(${activateAtBlock.toString()})` : ''}`,
|
|
|
- 'Application stake': aSP.isSome ? aSP.unwrap().amount_mode.type + `(${aSP.unwrap().amount})` : 'NONE',
|
|
|
- 'Role stake': rSP.isSome ? rSP.unwrap().amount_mode.type + `(${rSP.unwrap().amount})` : 'NONE',
|
|
|
- 'Max. applications': rationingPolicy.isSome ? rationingPolicy.unwrap().max_active_applicants.toNumber() : 'UNLIMITED',
|
|
|
- 'Terminate unstaking period (role stake)': OPCommitment.terminate_role_stake_unstaking_period.unwrapOr(0) + ' blocks',
|
|
|
- 'Exit unstaking period (role stake)': OPCommitment.exit_role_stake_unstaking_period.unwrapOr(0) + ' blocks',
|
|
|
+ const formatStake = (stake: Option<StakingPolicy>) => (
|
|
|
+ stake.isSome ? stake.unwrap().amount_mode.type + `(${stake.unwrap().amount})` : 'NONE'
|
|
|
+ );
|
|
|
+ const formatPeriod = (unstakingPeriod: Option<BlockNumber>) => (
|
|
|
+ unstakingPeriod.unwrapOr(0) + ' blocks'
|
|
|
+ );
|
|
|
+ return [
|
|
|
+ new ParsedParam('Working group', workingGroup.type),
|
|
|
+ new ParsedParam('Activate at', `${activateAt.type}${activateAtBlock ? `(${activateAtBlock.toString()})` : ''}`),
|
|
|
+ new ParsedParam('Application stake', formatStake(applicationSP)),
|
|
|
+ new ParsedParam('Role stake', formatStake(roleSP)),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Max. applications',
|
|
|
+ rationingPolicy.isSome ? rationingPolicy.unwrap().max_active_applicants.toNumber() : 'UNLIMITED'
|
|
|
+ ),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Terminate unstaking period (role stake)',
|
|
|
+ formatPeriod(OPCommitment.terminate_role_stake_unstaking_period)
|
|
|
+ ),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Exit unstaking period (role stake)',
|
|
|
+ formatPeriod(OPCommitment.exit_role_stake_unstaking_period)
|
|
|
+ ),
|
|
|
// <required_to_prevent_sneaking>
|
|
|
- 'Terminate unstaking period (appl. stake)': OPCommitment.terminate_application_stake_unstaking_period.unwrapOr(0) + ' blocks',
|
|
|
- 'Exit unstaking period (appl. stake)': OPCommitment.exit_role_application_stake_unstaking_period.unwrapOr(0) + ' blocks',
|
|
|
- 'Appl. accepted unstaking period (appl. stake)': OPCommitment.fill_opening_successful_applicant_application_stake_unstaking_period.unwrapOr(0) + ' blocks',
|
|
|
- 'Appl. failed unstaking period (role stake)': OPCommitment.fill_opening_failed_applicant_role_stake_unstaking_period.unwrapOr(0) + ' blocks',
|
|
|
- 'Appl. failed unstaking period (appl. stake)': OPCommitment.fill_opening_failed_applicant_application_stake_unstaking_period.unwrapOr(0) + ' blocks',
|
|
|
- 'Crowded out unstaking period (role stake)': ((rSP.isSome && rSP.unwrap().crowded_out_unstaking_period_length.unwrapOr(0)) || 0) + ' blocks',
|
|
|
- 'Review period expierd unstaking period (role stake)': ((rSP.isSome && rSP.unwrap().review_period_expired_unstaking_period_length.unwrapOr(0)) || 0) + ' blocks',
|
|
|
- 'Crowded out unstaking period (appl. stake)': ((aSP.isSome && aSP.unwrap().crowded_out_unstaking_period_length.unwrapOr(0)) || 0) + ' blocks',
|
|
|
- 'Review period expierd unstaking period (appl. stake)': ((aSP.isSome && aSP.unwrap().review_period_expired_unstaking_period_length.unwrapOr(0)) || 0) + ' blocks',
|
|
|
+ new ParsedParam(
|
|
|
+ 'Terminate unstaking period (appl. stake)',
|
|
|
+ formatPeriod(OPCommitment.terminate_application_stake_unstaking_period)
|
|
|
+ ),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Exit unstaking period (appl. stake)',
|
|
|
+ formatPeriod(OPCommitment.exit_role_application_stake_unstaking_period)
|
|
|
+ ),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Appl. accepted unstaking period (appl. stake)',
|
|
|
+ formatPeriod(OPCommitment.fill_opening_successful_applicant_application_stake_unstaking_period)
|
|
|
+ ),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Appl. failed unstaking period (role stake)',
|
|
|
+ formatPeriod(OPCommitment.fill_opening_failed_applicant_role_stake_unstaking_period)
|
|
|
+ ),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Appl. failed unstaking period (appl. stake)',
|
|
|
+ formatPeriod(OPCommitment.fill_opening_failed_applicant_application_stake_unstaking_period)
|
|
|
+ ),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Crowded out unstaking period (role stake)',
|
|
|
+ roleSP.isSome ? formatPeriod(roleSP.unwrap().crowded_out_unstaking_period_length) : '0 blocks'
|
|
|
+ ),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Review period expierd unstaking period (role stake)',
|
|
|
+ roleSP.isSome ? formatPeriod(roleSP.unwrap().review_period_expired_unstaking_period_length) : '0 blocks'
|
|
|
+ ),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Crowded out unstaking period (appl. stake)',
|
|
|
+ applicationSP.isSome ? formatPeriod(applicationSP.unwrap().crowded_out_unstaking_period_length) : '0 blocks'
|
|
|
+ ),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Review period expierd unstaking period (appl. stake)',
|
|
|
+ applicationSP.isSome ? formatPeriod(applicationSP.unwrap().review_period_expired_unstaking_period_length) : '0 blocks'
|
|
|
+ ),
|
|
|
// </required_to_prevent_sneaking>
|
|
|
- 'Human readable text': new FullWidthParam(<ParsedHRT>{ HRT }</ParsedHRT>)
|
|
|
- };
|
|
|
- },
|
|
|
- SetWorkingGroupMintCapacity: ([capacity, group]) => {
|
|
|
- return {
|
|
|
- 'Working group': (new WorkingGroup(group)).type,
|
|
|
- 'Mint capacity': formatBalance(capacity)
|
|
|
- };
|
|
|
- },
|
|
|
- BeginReviewWorkingGroupLeaderApplication: ([id, group]) => {
|
|
|
- return {
|
|
|
- 'Working group': (new WorkingGroup(group)).type,
|
|
|
- // TODO: Adjust the link to work with multiple groups after working-groups are normalized!
|
|
|
- 'Opening id': <Link to={`/working-groups/opportunities/storageProviders/${id}`}>#{id}</Link>
|
|
|
- };
|
|
|
+ new ParsedParam('Human readable text', <ParsedHRT>{ HRT }</ParsedHRT>, true)
|
|
|
+ ];
|
|
|
},
|
|
|
+ SetWorkingGroupMintCapacity: ([capacity, group]) => [
|
|
|
+ new ParsedParam('Working group', (new WorkingGroup(group)).type),
|
|
|
+ new ParsedParam('Mint capacity', formatBalance(capacity))
|
|
|
+ ],
|
|
|
+ BeginReviewWorkingGroupLeaderApplication: ([id, group]) => [
|
|
|
+ new ParsedParam('Working group', (new WorkingGroup(group)).type),
|
|
|
+ // TODO: Adjust the link to work with multiple groups after working-groups are normalized!
|
|
|
+ new ParsedParam('Opening id', <Link to={`/working-groups/opportunities/storageProviders/${id}`}>#{id}</Link>)
|
|
|
+ ],
|
|
|
FillWorkingGroupLeaderOpening: ([params]) => {
|
|
|
const { opening_id, successful_application_id, reward_policy, working_group } = params;
|
|
|
- const rp = reward_policy && new RewardPolicy(reward_policy);
|
|
|
- return {
|
|
|
- 'Working group': (new WorkingGroup(working_group)).type,
|
|
|
+ const rewardPolicy = reward_policy && new RewardPolicy(reward_policy);
|
|
|
+ return [
|
|
|
+ new ParsedParam('Working group', (new WorkingGroup(working_group)).type),
|
|
|
// TODO: Adjust the link to work with multiple groups after working-groups are normalized!
|
|
|
- 'Opening id': <Link to={`/working-groups/opportunities/storageProviders/${opening_id}`}>#{opening_id}</Link>,
|
|
|
- 'Reward policy': rp ? formatReward(rp, true) : 'NONE',
|
|
|
- Result: new FullWidthParam(
|
|
|
+ new ParsedParam('Opening id', <Link to={`/working-groups/opportunities/storageProviders/${opening_id}`}>#{opening_id}</Link>),
|
|
|
+ new ParsedParam('Reward policy', rewardPolicy ? formatReward(rewardPolicy, true) : 'NONE'),
|
|
|
+ new ParsedParam(
|
|
|
+ 'Result',
|
|
|
<ApplicationsDetailsByOpening
|
|
|
openingId={opening_id}
|
|
|
acceptedIds={[successful_application_id]}
|
|
|
- group={(new WorkingGroup(working_group)).type as WorkingGroupKey}/>
|
|
|
+ group={(new WorkingGroup(working_group)).type as WorkingGroupKey}/>,
|
|
|
+ true
|
|
|
)
|
|
|
- };
|
|
|
+ ];
|
|
|
},
|
|
|
- SlashWorkingGroupLeaderStake: ([leadId, amount, group]) => ({
|
|
|
- 'Working group': (new WorkingGroup(group)).type,
|
|
|
- 'Slash amount': formatBalance(amount),
|
|
|
- Lead: new FullWidthParam(<LeadInfoFromId group={(new WorkingGroup(group).type as WorkingGroupKey)} leadId={leadId}/>)
|
|
|
- }),
|
|
|
- DecreaseWorkingGroupLeaderStake: ([leadId, amount, group]) => ({
|
|
|
- 'Working group': (new WorkingGroup(group)).type,
|
|
|
- 'Decrease amount': formatBalance(amount),
|
|
|
- Lead: new FullWidthParam(<LeadInfoFromId group={(new WorkingGroup(group).type as WorkingGroupKey)} leadId={leadId}/>)
|
|
|
- }),
|
|
|
- SetWorkingGroupLeaderReward: ([leadId, amount, group]) => ({
|
|
|
- 'Working group': (new WorkingGroup(group)).type,
|
|
|
- 'New reward amount': formatBalance(amount),
|
|
|
- Lead: new FullWidthParam(<LeadInfoFromId group={(new WorkingGroup(group).type as WorkingGroupKey)} leadId={leadId}/>)
|
|
|
- }),
|
|
|
+ SlashWorkingGroupLeaderStake: ([leadId, amount, group]) => [
|
|
|
+ new ParsedParam('Working group', (new WorkingGroup(group)).type),
|
|
|
+ new ParsedParam('Slash amount', formatBalance(amount)),
|
|
|
+ new ParsedParam('Lead', <LeadInfoFromId group={(new WorkingGroup(group).type as WorkingGroupKey)} leadId={leadId}/>, true)
|
|
|
+ ],
|
|
|
+ DecreaseWorkingGroupLeaderStake: ([leadId, amount, group]) => [
|
|
|
+ new ParsedParam('Working group', (new WorkingGroup(group)).type),
|
|
|
+ new ParsedParam('Decrease amount', formatBalance(amount)),
|
|
|
+ new ParsedParam('Lead', <LeadInfoFromId group={(new WorkingGroup(group).type as WorkingGroupKey)} leadId={leadId}/>, true)
|
|
|
+ ],
|
|
|
+ SetWorkingGroupLeaderReward: ([leadId, amount, group]) => [
|
|
|
+ new ParsedParam('Working group', (new WorkingGroup(group)).type),
|
|
|
+ new ParsedParam('New reward amount', formatBalance(amount)),
|
|
|
+ new ParsedParam('Lead', <LeadInfoFromId group={(new WorkingGroup(group).type as WorkingGroupKey)} leadId={leadId}/>, true)
|
|
|
+ ],
|
|
|
TerminateWorkingGroupLeaderRole: ([params]) => {
|
|
|
const paramsObj = new TerminateRoleParameters(params);
|
|
|
const { working_group: workingGroup, rationale, worker_id: leadId, slash } = paramsObj;
|
|
|
- return {
|
|
|
- 'Working group': workingGroup.type,
|
|
|
- Rationale: new FullWidthParam(bytesToString(rationale)),
|
|
|
- 'Slash stake': slash.isTrue ? 'YES' : 'NO',
|
|
|
- Lead: new FullWidthParam(<LeadInfoFromId group={workingGroup.type as WorkingGroupKey} leadId={leadId.toNumber()}/>)
|
|
|
- };
|
|
|
+ return [
|
|
|
+ new ParsedParam('Working group', workingGroup.type),
|
|
|
+ new ParsedParam('Rationale', bytesToString(rationale), true),
|
|
|
+ new ParsedParam('Slash stake', slash.isTrue ? 'YES' : 'NO'),
|
|
|
+ new ParsedParam('Lead', <LeadInfoFromId group={workingGroup.type as WorkingGroupKey} leadId={leadId.toNumber()}/>, true)
|
|
|
+ ];
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -308,12 +356,10 @@ export default function Body ({
|
|
|
</StyledProposalDescription>
|
|
|
<ProposalParams>
|
|
|
<ParamsHeader>Parameters:</ParamsHeader>
|
|
|
- { Object.entries(parsedParams).map(([paramName, paramValue]) => (
|
|
|
- <ProposalParam key={paramName} fullWidth={paramValue instanceof FullWidthParam}>
|
|
|
- <ProposalParamName>{paramName}:</ProposalParamName>
|
|
|
- <ProposalParamValue>
|
|
|
- { paramValue instanceof FullWidthParam ? paramValue.value : paramValue}
|
|
|
- </ProposalParamValue>
|
|
|
+ { parsedParams.map(({ name, value, fullWidth }) => (
|
|
|
+ <ProposalParam key={name} fullWidth={fullWidth}>
|
|
|
+ <ProposalParamName>{name}:</ProposalParamName>
|
|
|
+ <ProposalParamValue>{value}</ProposalParamValue>
|
|
|
</ProposalParam>
|
|
|
))}
|
|
|
</ProposalParams>
|