Skip to content

Commit

Permalink
Merge branch 'main' of github.com:Joystream/pioneer into main
Browse files Browse the repository at this point in the history
� Conflicts:
�	packages/ui/src/proposals/modals/AddNewProposal/components/SpecificParameters/DecreaseWorkingGroupLeadStake.tsx
�	packages/ui/src/proposals/modals/AddNewProposal/components/SpecificParameters/SlashWorkingGroupLead.tsx
�	packages/ui/src/working-groups/components/SelectWorkingGroup/OptionsListWorkingGroup.tsx
  • Loading branch information
nick-olizarenko committed Jul 27, 2021
2 parents 4c91898 + d2d0437 commit 716f423
Show file tree
Hide file tree
Showing 125 changed files with 4,324 additions and 4,106 deletions.
2 changes: 1 addition & 1 deletion packages/ui/dev/mocks/commands/createMembers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const createMembersCommand = async () => {
const members = memberData

const createMembers = members.map((member) => {
return api?.tx.members.buyMembership({
return api.tx.members.buyMembership({
handle: member.handle,
metadata: {
name: member.metadata.name,
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/dev/scripts/generateMocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { generateMembers } from './generators/generateMembers'
import { generateOpeningsAndUpcomingOpenings } from './generators/generateOpeningsAndUpcomingOpenings'
import { generateProposals } from './generators/generateProposals'
import { generateWithdrawnApplications, generateWorkers } from './generators/generateWorkers'
import { generateWorkingGroups, getWorkingGroupsWithLeader } from './generators/generateWorkingGroups'
import { generateWorkingGroups, getWorkingGroupsWithLead } from './generators/generateWorkingGroups'
import { Mocks } from './generators/types'
import { saveFile } from './helpers/saveFile'

Expand All @@ -25,7 +25,7 @@ const main = () => {
mocks.workingGroups = generateWorkingGroups()
Object.assign(mocks, generateOpeningsAndUpcomingOpenings(mocks))
Object.assign(mocks, generateWorkers(mocks))
mocks.workingGroups = getWorkingGroupsWithLeader(mocks)
mocks.workingGroups = getWorkingGroupsWithLead(mocks)
mocks.applications = [...mocks.applications, ...generateWithdrawnApplications(mocks)]
Object.assign(mocks, generateAllEvents(mocks))
mocks.proposals = generateProposals(mocks)
Expand Down
52 changes: 28 additions & 24 deletions packages/ui/dev/scripts/generators/generateEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const generateBudgetSpending = (mocks: Mocks) => () => {

const generateAppliedOnOpeningEvent = (mocks: Mocks) => () => {
const application = mocks.applications[randomFromRange(0, mocks.applications.length - 1)]
const opening = mocks.openings.find(opening => opening.id == application.openingId)
const opening = mocks.openings.find((opening) => opening.id == application.openingId)

return {
id: (nextAppliedOnOpeningEventId++).toString(),
Expand All @@ -52,9 +52,9 @@ const generateAppliedOnOpeningEvent = (mocks: Mocks) => () => {
}

const generateApplicationWithdrawnEvent = (mocks: Mocks) => () => {
const withdrawnApplications = mocks.applications.filter(application => application.status === 'withdrawn')
const withdrawnApplications = mocks.applications.filter((application) => application.status === 'withdrawn')
const application = withdrawnApplications[randomFromRange(0, withdrawnApplications.length - 1)]
const opening = mocks.openings.find(opening => opening.id == application.openingId)
const opening = mocks.openings.find((opening) => opening.id == application.openingId)

return {
id: (nextApplicationWithdrawnEventId++).toString(),
Expand All @@ -65,17 +65,17 @@ const generateApplicationWithdrawnEvent = (mocks: Mocks) => () => {
}

const generateStakeChanged = (mocks: Mocks) => () => {
const worker = mocks.workers[randomFromRange(0, mocks.workers.length -1)]
const worker = mocks.workers[randomFromRange(0, mocks.workers.length - 1)]
return {
createdAt: faker.date.recent(7),
groupId: worker?.groupId,
workerId: worker?.id,
amount: randomFromRange(100, 10000)
amount: randomFromRange(100, 10000),
}
}

const generateStakeSlashedEvent = (mocks: Mocks) => () => {
const worker = mocks.workers[randomFromRange(0, mocks.workers.length -1)]
const worker = mocks.workers[randomFromRange(0, mocks.workers.length - 1)]
return {
createdAt: faker.date.recent(7),
groupId: worker?.groupId,
Expand All @@ -87,21 +87,22 @@ const generateStakeSlashedEvent = (mocks: Mocks) => () => {
}

const generateOpeningFilledEvent = (mocks: Mocks) => () => {
const filled = mocks.openings.filter(o => o.status === 'filled')
const filled = mocks.openings.filter((o) => o.status === 'filled')
const opening = filled[randomFromRange(0, filled.length - 1)]
const workers = mocks.workers.filter(w => w && w.groupId === opening.groupId)
const workers = mocks.workers.filter((w) => w && w.groupId === opening.groupId)
return {
createdAt: faker.date.recent(7),
groupId: opening.groupId,
openingId: opening.id,
workersHiredIds: Array.from({ length: opening.metadata.hiringLimit })
.map(() => workers[randomFromRange(0, workers.length - 1)]?.id)
workersHiredIds: Array.from({ length: opening.metadata.hiringLimit }).map(
() => workers[randomFromRange(0, workers.length - 1)]?.id
),
}
}

const generateWorkerLeavingEvent = (mocks: Mocks, leftAlready?: boolean) => () => {
const status = leftAlready ? 'left' : 'active'
const workers = mocks.workers.filter(worker => worker && worker.status === status)
const workers = mocks.workers.filter((worker) => worker && worker.status === status)
const worker = workers[randomFromRange(0, workers.length - 1)]
return {
createdAt: faker.date.recent(7),
Expand All @@ -113,18 +114,18 @@ const generateWorkerLeavingEvent = (mocks: Mocks, leftAlready?: boolean) => () =
const generateStatusTextChangedEvents = (mocks: Mocks) => {
const groups = mocks.workingGroups
const openings = mocks.upcomingOpenings
return groups.map(group => ({
return groups.map((group) => ({
createdAt: faker.date.recent(7),
groupId: group.id,
upcomingworkinggroupopeningcreatedInEventIds: [openings.find(opening => opening.groupId == group.id)?.id],
upcomingworkinggroupopeningcreatedInEventIds: [openings.find((opening) => opening.groupId == group.id)?.id],
// assuming this controls the "status updated" activity, just the array being empty or non-empty matters
workinggroupmetadatasetInEventIds: Math.random() > .5 ? ['1'] : [],
workinggroupmetadatasetInEventIds: Math.random() > 0.5 ? ['1'] : [],
}))
}

const generateOpeningAddedEvent = (mocks: Mocks) => () => {
const opening = mocks.openings[randomFromRange(0, mocks.openings.length -1)]
const group = mocks.workingGroups.find(g => g.id === opening.groupId)
const opening = mocks.openings[randomFromRange(0, mocks.openings.length - 1)]
const group = mocks.workingGroups.find((g) => g.id === opening.groupId)
return {
createdAt: faker.date.recent(15),
groupId: group?.id,
Expand All @@ -133,9 +134,9 @@ const generateOpeningAddedEvent = (mocks: Mocks) => () => {
}

const generateOpeningCanceledEvent = (mocks: Mocks) => () => {
const openings = mocks.openings.filter(opening => opening.status === 'cancelled')
const openings = mocks.openings.filter((opening) => opening.status === 'cancelled')
const opening = openings[randomFromRange(0, openings.length - 1)]
const group = mocks.workingGroups.find(g => g.id === opening.groupId)
const group = mocks.workingGroups.find((g) => g.id === opening.groupId)
return {
createdAt: faker.date.recent(7),
groupId: group?.id,
Expand All @@ -153,7 +154,7 @@ const generateBudgetSetEvent = (mocks: Mocks) => () => {
}

const generateTerminatedEvent = (mocks: Mocks) => () => {
const workers = mocks.workers.filter(worker => worker?.status === 'terminated')
const workers = mocks.workers.filter((worker) => worker?.status === 'terminated')
const worker = workers[randomFromRange(0, workers.length - 1)]
return {
createdAt: faker.date.recent(30),
Expand All @@ -165,7 +166,7 @@ const generateTerminatedEvent = (mocks: Mocks) => () => {

const generateWorkerRewardAccountUpdatedEvent = (mocks: Mocks) => () => {
const worker = mocks.workers[randomFromRange(0, mocks.workers.length - 1)]
const member = mocks.members.find(member => member.id === worker!.membershipId.toString())
const member = mocks.members.find((member) => member.id === worker!.membershipId.toString())
return {
createdAt: faker.date.recent(30),
groupId: worker?.groupId,
Expand Down Expand Up @@ -194,20 +195,23 @@ export const eventGenerators = {
stakeSlashedEvents: (mocks: Mocks) => Array.from({ length: 10 }).map(generateStakeSlashedEvent(mocks)),
openingFilledEvents: (mocks: Mocks) => Array.from({ length: 15 }).map(generateOpeningFilledEvent(mocks)),
workerExitedEvents: (mocks: Mocks) => Array.from({ length: 10 }).map(generateWorkerLeavingEvent(mocks, true)),
workerStartedLeavingEvents: (mocks: Mocks) => Array.from({ length: 10 }).map(generateWorkerLeavingEvent(mocks)),
statusTextChangedEvents: (mocks: Mocks) => generateStatusTextChangedEvents(mocks),
openingAddedEvents: (mocks: Mocks) => Array.from({ length: 10 }).map(generateOpeningAddedEvent(mocks)),
openingCanceledEvents: (mocks: Mocks) => Array.from({ length: 10 }).map(generateOpeningCanceledEvent(mocks)),
budgetSetEvents: (mocks: Mocks) => Array.from({ length: 10 }).map(generateBudgetSetEvent(mocks)),
terminatedWorkerEvents: (mocks: Mocks) => Array.from({ length: 10 }).map(generateTerminatedEvent(mocks)),
terminatedLeaderEvents: (mocks: Mocks) => Array.from({ length: 5 }).map(generateTerminatedEvent(mocks)),
workerRewardAccountUpdatedEvents: (mocks: Mocks) => Array.from({ length: 10 }).map(generateWorkerRewardAccountUpdatedEvent(mocks)),
workerRewardAmountUpdatedEvents: (mocks: Mocks) => Array.from({ length: 10 }).map(generateWorkerRewardAmountUpdatedEvent(mocks)),
workerRewardAccountUpdatedEvents: (mocks: Mocks) =>
Array.from({ length: 10 }).map(generateWorkerRewardAccountUpdatedEvent(mocks)),
workerRewardAmountUpdatedEvents: (mocks: Mocks) =>
Array.from({ length: 10 }).map(generateWorkerRewardAmountUpdatedEvent(mocks)),
}

export const generateAllEvents = (mocks: Mocks) => {
const newMocks: { [key: string]: any[] } = {}
Object.entries(eventGenerators).forEach(([key, generator]) => { newMocks[key] = generator(mocks) })
Object.entries(eventGenerators).forEach(([key, generator]) => {
newMocks[key] = generator(mocks)
})

return newMocks
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ const generateBaseOpening = (groupId: string) => {
}

const generateOpening = (status: string, groupId: string) => () => {
const isLeader = Math.random() > 0.9
const isLead = Math.random() > 0.9
const isInPast = status !== 'open'
return {
...generateBaseOpening(groupId),
type: isLeader ? 'LEADER' : 'REGULAR',
type: isLead ? 'LEAD' : 'REGULAR',
status,
unstakingPeriod: randomFromRange(5, 10),
unstakingPeriod: randomFromRange(14400, 40000),
metadata: {
...generateOpeningMetadata(),
expectedEnding: isInPast ? faker.date.recent(90) : faker.date.soon(10),
Expand Down
10 changes: 5 additions & 5 deletions packages/ui/dev/scripts/generators/generateWorkingGroups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const generateWorkingGroup = (groupName: string) => ({
id: groupName,
name: groupName,
workers: [],
leaderId: null,
leadId: null,
budget: randomFromRange(1000, 5000),
metadata: {
name: faker.lorem.words(2),
Expand All @@ -31,7 +31,7 @@ export interface WorkingGroupMock {
id: string
name: string
workers: never[]
leaderId: string | null
leadId: string | null
budget: number
metadata: ReturnType<typeof generateWorkingGroup>['metadata']
}
Expand All @@ -40,8 +40,8 @@ export const generateWorkingGroups = () => {
return WORKING_GROUPS.map(generateWorkingGroup)
}

export const getWorkingGroupsWithLeader = (mocks: Mocks) => {
const getLeader = (groupId: string) => {
export const getWorkingGroupsWithLead = (mocks: Mocks) => {
const getLead = (groupId: string) => {
if (groupId === 'membershipWorkingGroup') {
return null
}
Expand All @@ -53,6 +53,6 @@ export const getWorkingGroupsWithLeader = (mocks: Mocks) => {

return mocks.workingGroups.map((group) => ({
...group,
leaderId: getLeader(group.id),
leadId: getLead(group.id),
}))
}
4 changes: 2 additions & 2 deletions packages/ui/src/accounts/hooks/useBalance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { Address } from '@/common/types'
import { Balances } from '../types'

export const useBalance = (address?: Address): Balances | null => {
const { api } = useApi()
const { api, connectionState } = useApi()

const balances = useObservable(address ? api?.derive.balances.all(address) : undefined, [api, address])
const balances = useObservable(address ? api.derive.balances.all(address) : undefined, [connectionState, address])

if (balances === undefined) {
return null
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/accounts/hooks/useMyBalances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function useMyBalances() {
const addresses = allAccounts.map((account) => account.address)
const balancesObs = api ? addresses.map((address) => api.derive.balances.all(address).pipe(map(toBalances))) : []

const result = useObservable(combineLatest(balancesObs), [api, JSON.stringify(addresses)])
const result = useObservable(combineLatest(balancesObs), [isConnected, JSON.stringify(addresses)])

if (hasAccounts && isConnected && result) {
return result.reduce((acc, balance, index) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface Props {

export const RecoverBalanceSignModal = ({ onClose, service }: Props) => {
const balances = useMyTotalBalances()
const { api } = useApi()
const { api, connectionState } = useApi()
const amount = balances.recoverable
const { active } = useMyMemberships()

Expand All @@ -28,7 +28,7 @@ export const RecoverBalanceSignModal = ({ onClose, service }: Props) => {
}

return api.tx.council.releaseCandidacyStake(active.id)
}, [api, active?.id, JSON.stringify(balances)])
}, [connectionState, active?.id, JSON.stringify(balances)])

const { paymentInfo, sign, isReady } = useSignAndSendTransaction({
transaction,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function TransferSignModal({ onClose, from, amount, to, service }: Props)
const balanceFrom = useBalance(fromAddress)
const balanceTo = useBalance(toAddress)
const { api } = useApi()
const transaction = useMemo(() => api?.tx?.balances?.transfer(toAddress, amount), [toAddress, amount])
const transaction = useMemo(() => api.tx?.balances?.transfer(toAddress, amount), [toAddress, amount])
const { paymentInfo, sign, isReady } = useSignAndSendTransaction({ transaction, signer: fromAddress, service })

return (
Expand Down
68 changes: 41 additions & 27 deletions packages/ui/src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React from 'react'
import React, { ReactNode } from 'react'
import { Redirect, Route, Switch } from 'react-router-dom'

import { ConnectionStatus } from '@/common/components/ConnectionStatus'
import { Loading } from '@/common/components/Loading'
import { Page } from '@/common/components/page/Page'
import { useApi } from '@/common/hooks/useApi'
import { ProposalsRoutes } from '@/proposals/constants/routes'

import { ExtensionWarning } from './components/ExtensionWarning'
Expand All @@ -27,33 +29,45 @@ import { Providers } from './Providers'

export const App = () => (
<Providers>
<Page>
<SideBar />
<Switch>
<Route exact path="/profile" component={MyAccounts} />
<Route exact path="/profile/memberships" component={MyMemberships} />
<Route exact path="/working-groups" component={WorkingGroups} />
<Route exact path="/working-groups/openings" component={WorkingGroupsOpenings} />
<Route exact path="/working-groups/my-applications" component={MyApplications} />
<Route exact path="/working-groups/my-roles" component={MyRoles} />
<Route exact path="/working-groups/my-roles/:id" component={MyRole} />
<Route exact path="/working-groups/:name" component={WorkingGroup} />
<Route exact path="/working-groups/openings/:id" component={WorkingGroupOpening} />
<Route exact path="/working-groups/upcoming-openings/:id" component={UpcomingOpening} />
<Route exact path={ProposalsRoutes.current} component={Proposals} />
<Route exact path={ProposalsRoutes.past} component={PastProposals} />
<Route exact path={ProposalsRoutes.myproposals} />
<Route exact path={`${ProposalsRoutes.preview}/:id/vote/:voteId`} component={ProposalPreview} />
<Route exact path={`${ProposalsRoutes.preview}/:id/post/:postId`} component={ProposalPreview} />
<Route exact path={`${ProposalsRoutes.preview}/:id`} component={ProposalPreview} />
<Route exact path="/members" component={Members} />
<Route exact path="/members/:id" component={Members} />
<Route exact path="/settings" component={Settings} />
<Redirect exact from="/" to="/profile" />
</Switch>
</Page>
<WaitForAPI>
<Page>
<SideBar />
<Switch>
<Route exact path="/profile" component={MyAccounts} />
<Route exact path="/profile/memberships" component={MyMemberships} />
<Route exact path="/working-groups" component={WorkingGroups} />
<Route exact path="/working-groups/openings" component={WorkingGroupsOpenings} />
<Route exact path="/working-groups/my-applications" component={MyApplications} />
<Route exact path="/working-groups/my-roles" component={MyRoles} />
<Route exact path="/working-groups/my-roles/:id" component={MyRole} />
<Route exact path="/working-groups/:name" component={WorkingGroup} />
<Route exact path="/working-groups/openings/:id" component={WorkingGroupOpening} />
<Route exact path="/working-groups/upcoming-openings/:id" component={UpcomingOpening} />
<Route exact path={ProposalsRoutes.current} component={Proposals} />
<Route exact path={ProposalsRoutes.past} component={PastProposals} />
<Route exact path={ProposalsRoutes.myproposals} />
<Route exact path={`${ProposalsRoutes.preview}/:id/vote/:voteId`} component={ProposalPreview} />
<Route exact path={`${ProposalsRoutes.preview}/:id/post/:postId`} component={ProposalPreview} />
<Route exact path={`${ProposalsRoutes.preview}/:id`} component={ProposalPreview} />
<Route exact path="/members" component={Members} />
<Route exact path="/members/:id" component={Members} />
<Route exact path="/settings" component={Settings} />
<Redirect exact from="/" to="/profile" />
</Switch>
</Page>
<GlobalModals />
</WaitForAPI>
<ConnectionStatus />
<ExtensionWarning />
<GlobalModals />
</Providers>
)

export const WaitForAPI = ({ children }: { children: ReactNode }) => {
const { connectionState } = useApi()

if (connectionState === 'connecting') {
return <Loading text="Waiting for API initialization" />
}

return <>{children}</>
}
2 changes: 1 addition & 1 deletion packages/ui/src/app/pages/Proposals/ProposalPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const ProposalPreview = () => {

const votingRounds = useVotingRounds(proposal?.votes, proposal?.proposalStatusUpdates)
const [currentVotingRound, setVotingRound] = useState(0)
const votes = votingRounds[currentVotingRound]
const votes = votingRounds[currentVotingRound] ?? votingRounds[0]

useEffect(() => setVotingRound(Math.max(0, votingRounds.length - 1)), [votingRounds.length])

Expand Down
Loading

0 comments on commit 716f423

Please sign in to comment.