mirror of
https://github.com/pezkuwichain/pezkuwi-apps.git
synced 2026-06-16 19:01:04 +00:00
feat: initial Pezkuwi Apps rebrand from polkadot-apps
Rebranded terminology: - Polkadot → Pezkuwi - Kusama → Dicle - Westend → Zagros - Rococo → PezkuwiChain - Substrate → Bizinikiwi - parachain → teyrchain Custom logos with Kurdistan brand colors (#e6007a → #86e62a): - bizinikiwi-hexagon.svg - sora-bizinikiwi.svg - hezscanner.svg - heztreasury.svg - pezkuwiscan.svg - pezkuwistats.svg - pezkuwiassembly.svg - pezkuwiholic.svg
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
// Copyright 2017-2025 @pezkuwi/app-scheduler authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { DeriveDispatch } from '@pezkuwi/api-derive/types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import PreImageButton from '@pezkuwi/app-democracy/Overview/PreImageButton';
|
||||
import ProposalCell from '@pezkuwi/app-democracy/Overview/ProposalCell';
|
||||
import { LinkExternal, Table } from '@pezkuwi/react-components';
|
||||
import { useBestNumber } from '@pezkuwi/react-hooks';
|
||||
import { BlockToTime } from '@pezkuwi/react-query';
|
||||
import { formatNumber } from '@pezkuwi/util';
|
||||
|
||||
interface Props {
|
||||
value: DeriveDispatch;
|
||||
}
|
||||
|
||||
function DispatchEntry ({ value: { at, image, imageHash, index } }: Props): React.ReactElement<Props> {
|
||||
const bestNumber = useBestNumber();
|
||||
|
||||
return (
|
||||
<tr>
|
||||
<Table.Column.Id value={index} />
|
||||
<ProposalCell
|
||||
imageHash={imageHash}
|
||||
proposal={image?.proposal}
|
||||
/>
|
||||
<td className='number together'>
|
||||
{bestNumber && (
|
||||
<>
|
||||
<BlockToTime value={at.sub(bestNumber)} />
|
||||
#{formatNumber(at)}
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<td className='button'>
|
||||
{!image?.proposal && (
|
||||
<PreImageButton
|
||||
imageHash={imageHash}
|
||||
isImminent
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='links media--1000'>
|
||||
<LinkExternal
|
||||
data={index}
|
||||
type='democracyReferendum'
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(DispatchEntry);
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2017-2025 @pezkuwi/app-scheduler authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { DeriveDispatch } from '@pezkuwi/api-derive/types';
|
||||
|
||||
import React, { useMemo, useRef } from 'react';
|
||||
|
||||
import { Table } from '@pezkuwi/react-components';
|
||||
import { useApi, useBestNumber, useCall } from '@pezkuwi/react-hooks';
|
||||
|
||||
import DispatchEntry from './DispatchEntry.js';
|
||||
import { useTranslation } from './translate.js';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function DispatchQueue ({ className }: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const bestNumber = useBestNumber();
|
||||
const queued = useCall<DeriveDispatch[]>(api.derive.democracy.dispatchQueue);
|
||||
|
||||
const filtered = useMemo(
|
||||
() => bestNumber && queued?.filter(({ at }) => at.gte(bestNumber)).sort((a, b) => a.at.cmp(b.at)),
|
||||
[bestNumber, queued]
|
||||
);
|
||||
|
||||
const headerRef = useRef<([React.ReactNode?, string?, number?] | false)[]>([
|
||||
[t('dispatch queue'), 'start', 2],
|
||||
[t('enact')],
|
||||
[],
|
||||
[undefined, 'media--1000']
|
||||
]);
|
||||
|
||||
return (
|
||||
<Table
|
||||
className={className}
|
||||
empty={filtered && t('Nothing queued for execution')}
|
||||
header={headerRef.current}
|
||||
>
|
||||
{filtered?.map((entry): React.ReactNode => (
|
||||
<DispatchEntry
|
||||
key={entry.index.toString()}
|
||||
value={entry}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(DispatchQueue);
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright 2017-2025 @pezkuwi/app-scheduler authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { BlockNumber } from '@pezkuwi/types/interfaces';
|
||||
import type { ScheduledExt } from './types.js';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Hash from '@pezkuwi/app-preimages/Preimages/Hash';
|
||||
import { usePreimage, useStakingAsyncApis } from '@pezkuwi/react-hooks';
|
||||
import { CallExpander } from '@pezkuwi/react-params';
|
||||
import { BlockToTime } from '@pezkuwi/react-query';
|
||||
import { formatNumber } from '@pezkuwi/util';
|
||||
|
||||
interface Props {
|
||||
bestNumber?: BlockNumber;
|
||||
className?: string;
|
||||
value: ScheduledExt;
|
||||
}
|
||||
|
||||
function Scheduled ({ bestNumber, className = '', value: { blockNumber, call, maybeId, maybePeriodic, preimageHash } }: Props): React.ReactElement<Props> {
|
||||
const { isStakingAsync, rcApi } = useStakingAsyncApis();
|
||||
const preimage = usePreimage(preimageHash);
|
||||
const period = maybePeriodic.unwrapOr(null);
|
||||
const name = maybeId.unwrapOr(null);
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='all'>
|
||||
<CallExpander value={call || preimage?.proposal} />
|
||||
</td>
|
||||
{name
|
||||
? name.isAscii
|
||||
? <td className='start'>{name.toUtf8()}</td>
|
||||
: <Hash value={name.toHex()} />
|
||||
: <td />
|
||||
}
|
||||
<td className='number together'>
|
||||
{bestNumber && (
|
||||
<>
|
||||
<BlockToTime
|
||||
api={isStakingAsync ? rcApi : undefined}
|
||||
value={blockNumber.sub(bestNumber)}
|
||||
/>
|
||||
#{formatNumber(blockNumber)}
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<td className='number together'>
|
||||
{period && (
|
||||
formatNumber(period[0])
|
||||
)}
|
||||
</td>
|
||||
<td className='number together'>
|
||||
{period && (
|
||||
formatNumber(period[1])
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Scheduled);
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright 2017-2025 @pezkuwi/app-scheduler authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { ApiPromise } from '@pezkuwi/api';
|
||||
import type { Bytes, Option, u8, u32 } from '@pezkuwi/types';
|
||||
import type { BlockNumber, Call, Hash, Scheduled } from '@pezkuwi/types/interfaces';
|
||||
import type { FrameSupportPreimagesBounded, PalletSchedulerScheduled } from '@pezkuwi/types/lookup';
|
||||
import type { Codec, ITuple } from '@pezkuwi/types/types';
|
||||
import type { ScheduledExt } from './types.js';
|
||||
|
||||
import React, { useMemo, useRef } from 'react';
|
||||
|
||||
import { Table } from '@pezkuwi/react-components';
|
||||
import { useApi, useBestNumberRelay, useCall } from '@pezkuwi/react-hooks';
|
||||
|
||||
import ScheduledView from './Scheduled.js';
|
||||
import { useTranslation } from './translate.js';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
// included here for backwards compat
|
||||
interface PalletSchedulerScheduledV3 extends Codec {
|
||||
maybeId: Option<Bytes>;
|
||||
priority: u8;
|
||||
call: FrameSupportScheduleMaybeHashed;
|
||||
maybePeriodic: Option<ITuple<[u32, u32]>>;
|
||||
origin: Codec;
|
||||
}
|
||||
|
||||
// included here for backwards compat
|
||||
interface FrameSupportScheduleMaybeHashed extends Codec {
|
||||
// added here since we use it for detection
|
||||
inner: Codec;
|
||||
// enum features
|
||||
isHash: boolean;
|
||||
isValue: boolean;
|
||||
asValue: Call;
|
||||
asHash: Hash;
|
||||
}
|
||||
|
||||
const OPT_SCHED = {
|
||||
transform: (entries: [{ args: [BlockNumber] }, Option<Scheduled | PalletSchedulerScheduled | PalletSchedulerScheduledV3>[]][], api: ApiPromise): ScheduledExt[] => {
|
||||
return entries
|
||||
.filter(([, all]) => all.some((o) => o.isSome))
|
||||
.reduce((items: ScheduledExt[], [key, all]): ScheduledExt[] => {
|
||||
const blockNumber = key.args[0];
|
||||
|
||||
return all
|
||||
.filter((o) => o.isSome)
|
||||
.map((o) => o.unwrap())
|
||||
.reduce((items: ScheduledExt[], { call: callOrEnum, maybeId, maybePeriodic, priority }, index) => {
|
||||
let call: Call | null = null;
|
||||
let preimageHash: FrameSupportPreimagesBounded | undefined;
|
||||
|
||||
if ((callOrEnum as unknown as FrameSupportScheduleMaybeHashed).inner) {
|
||||
if ((callOrEnum as unknown as FrameSupportScheduleMaybeHashed).isValue) {
|
||||
call = (callOrEnum as unknown as FrameSupportScheduleMaybeHashed).asValue;
|
||||
} else if ((callOrEnum as unknown as FrameSupportPreimagesBounded).isInline) {
|
||||
try {
|
||||
call = api.registry.createType('Call', (callOrEnum as unknown as FrameSupportPreimagesBounded).asInline.toHex());
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
} else if ((callOrEnum as unknown as FrameSupportPreimagesBounded).isLookup) {
|
||||
preimageHash = (callOrEnum as unknown as FrameSupportPreimagesBounded);
|
||||
}
|
||||
} else {
|
||||
call = callOrEnum as Call;
|
||||
}
|
||||
|
||||
items.push({ blockNumber, call, key: `${blockNumber.toString()}-${index}`, maybeId, maybePeriodic, preimageHash, priority });
|
||||
|
||||
return items;
|
||||
}, items);
|
||||
}, []);
|
||||
}
|
||||
};
|
||||
|
||||
function Schedule ({ className = '' }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const bestNumber = useBestNumberRelay();
|
||||
const items = useCall<ScheduledExt[]>(api.query.scheduler.agenda.entries, undefined, OPT_SCHED);
|
||||
|
||||
const filtered = useMemo(
|
||||
() => bestNumber && items?.filter(({ blockNumber }) => blockNumber.gte(bestNumber)).sort((a, b) => a.blockNumber.cmp(b.blockNumber)),
|
||||
[bestNumber, items]
|
||||
);
|
||||
|
||||
const headerRef = useRef<[React.ReactNode?, string?, number?][]>([
|
||||
[t('scheduled'), 'start'],
|
||||
[t('id'), 'start'],
|
||||
[t('remaining')],
|
||||
[t('period')],
|
||||
[t('count')]
|
||||
]);
|
||||
|
||||
return (
|
||||
<Table
|
||||
className={className}
|
||||
empty={filtered && t('No active schedules')}
|
||||
header={headerRef.current}
|
||||
>
|
||||
{filtered?.map((value): React.ReactNode => (
|
||||
<ScheduledView
|
||||
bestNumber={bestNumber}
|
||||
key={value.key}
|
||||
value={value}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Schedule);
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2017-2025 @pezkuwi/app-scheduler authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import { Tabs } from '@pezkuwi/react-components';
|
||||
import { useApi } from '@pezkuwi/react-hooks';
|
||||
|
||||
import DispatchQueue from './DispatchQueue.js';
|
||||
import Scheduler from './Scheduler.js';
|
||||
import { useTranslation } from './translate.js';
|
||||
|
||||
interface Props {
|
||||
basePath: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function App ({ basePath, className }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
|
||||
const tabs = useMemo(
|
||||
() => [
|
||||
{
|
||||
isRoot: true,
|
||||
name: 'overview',
|
||||
text: t('Overview')
|
||||
}
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
return (
|
||||
<main className={className}>
|
||||
<Tabs
|
||||
basePath={basePath}
|
||||
items={tabs}
|
||||
/>
|
||||
{api.query.democracy && (
|
||||
<DispatchQueue />
|
||||
)}
|
||||
{api.query.scheduler && (
|
||||
<Scheduler />
|
||||
)}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(App);
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright 2017-2025 @pezkuwi/app-explorer authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { useTranslation as useTranslationBase } from 'react-i18next';
|
||||
|
||||
export function useTranslation (): { t: (key: string, options?: { replace: Record<string, unknown> }) => string } {
|
||||
return useTranslationBase('app-scheduler');
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright 2017-2025 @pezkuwi/app-scheduler authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { Bytes, Option } from '@pezkuwi/types';
|
||||
import type { BlockNumber, Call, SchedulePeriod, SchedulePriority } from '@pezkuwi/types/interfaces';
|
||||
import type { FrameSupportPreimagesBounded } from '@pezkuwi/types/lookup';
|
||||
|
||||
export interface ScheduledExt {
|
||||
blockNumber: BlockNumber;
|
||||
call: Call | null;
|
||||
key: string;
|
||||
maybeId: Option<Bytes>;
|
||||
maybePeriodic: Option<SchedulePeriod>;
|
||||
priority: SchedulePriority;
|
||||
preimageHash?: FrameSupportPreimagesBounded;
|
||||
}
|
||||
Reference in New Issue
Block a user