mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-07-13 17:25:48 +00:00
Add Pezkuwi SDK UI - Polkadot.js Apps clone
- Clone Polkadot.js Apps repository - Update package.json with Pezkuwi branding - Add Pezkuwi endpoint to production chains (wss://pezkuwichain.app:9944) - Create comprehensive README for SDK UI - Set up project structure with all packages Next steps: - Apply Kurdistan colors (Kesk, Sor, Zer, Spi + Black) to UI theme - Replace logos with Pezkuwi branding - Test build and deployment
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
// Copyright 2017-2025 @polkadot/react-components authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { DropdownOptions } from '../util/types.js';
|
||||
import type { ConstValueBase } from './types.js';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Dropdown from '../Dropdown.js';
|
||||
import { filterDropdownItems } from '../util/index.js';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
isError?: boolean;
|
||||
onChange: (value: ConstValueBase) => void;
|
||||
options: DropdownOptions;
|
||||
value: ConstValueBase;
|
||||
}
|
||||
|
||||
function transform ({ value }: Props): (method: string) => ConstValueBase {
|
||||
return (method: string): ConstValueBase => {
|
||||
const section = value.section;
|
||||
|
||||
return {
|
||||
method,
|
||||
section
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function SelectKey (props: Props): React.ReactElement<Props> | null {
|
||||
const { className = '', isError, onChange, options, value } = props;
|
||||
|
||||
if (!options.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
className={`${className} ui--DropdownLinked-Items`}
|
||||
isError={isError}
|
||||
onChange={onChange}
|
||||
onSearch={filterDropdownItems}
|
||||
options={options}
|
||||
transform={transform(props)}
|
||||
value={value.method}
|
||||
withLabel={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(SelectKey);
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2017-2025 @polkadot/react-components authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { DropdownOptions } from '../util/types.js';
|
||||
import type { ConstValueBase, StorageEntryPromise } from './types.js';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Dropdown from '../Dropdown.js';
|
||||
import { filterDropdownItems } from '../util/index.js';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
defaultValue?: StorageEntryPromise;
|
||||
isError?: boolean;
|
||||
onChange: (value: string) => void;
|
||||
options: DropdownOptions;
|
||||
value: ConstValueBase;
|
||||
}
|
||||
|
||||
function SelectSection ({ className = '', defaultValue, isError, onChange, options, value: { section } }: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<Dropdown
|
||||
className={`${className} ui--DropdownLinked-Sections`}
|
||||
defaultValue={defaultValue}
|
||||
isError={isError}
|
||||
onChange={onChange}
|
||||
onSearch={filterDropdownItems}
|
||||
options={options}
|
||||
value={section}
|
||||
withLabel={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(SelectSection);
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright 2017-2025 @polkadot/react-components authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { ApiPromise } from '@polkadot/api';
|
||||
import type { ConstantCodec } from '@polkadot/types/metadata/decorate/types';
|
||||
import type { DropdownOptions } from '../util/types.js';
|
||||
import type { ConstValue, ConstValueBase } from './types.js';
|
||||
|
||||
import React, { useCallback, useState } from 'react';
|
||||
|
||||
import { useApi } from '@polkadot/react-hooks';
|
||||
|
||||
import LinkedWrapper from '../InputExtrinsic/LinkedWrapper.js';
|
||||
import keyOptions from './options/key.js';
|
||||
import sectionOptions from './options/section.js';
|
||||
import SelectKey from './SelectKey.js';
|
||||
import SelectSection from './SelectSection.js';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
defaultValue: ConstValueBase;
|
||||
isError?: boolean;
|
||||
label: React.ReactNode;
|
||||
onChange?: (value: ConstValue) => void;
|
||||
withLabel?: boolean;
|
||||
}
|
||||
|
||||
function getValue (api: ApiPromise, { method, section }: ConstValueBase): ConstValue {
|
||||
const firstSec = Object.keys(api.consts)[0];
|
||||
const firstMet = Object.keys(api.consts[firstSec])[0];
|
||||
const value = api.consts[section]?.[method]
|
||||
? { method, section }
|
||||
: { method: firstMet, section: firstSec };
|
||||
|
||||
return {
|
||||
...value,
|
||||
meta: (api.consts[value.section][value.method] as ConstantCodec).meta
|
||||
};
|
||||
}
|
||||
|
||||
function InputConsts ({ className = '', defaultValue, label, onChange, withLabel }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const [optionsMethod, setOptionsMethod] = useState<DropdownOptions>(() => keyOptions(api, defaultValue.section));
|
||||
const [optionsSection] = useState<DropdownOptions>(() => sectionOptions(api));
|
||||
const [value, setValue] = useState<ConstValue>(() => getValue(api, defaultValue));
|
||||
|
||||
const _onKeyChange = useCallback(
|
||||
(newValue: ConstValueBase): void => {
|
||||
if (value.section !== newValue.section || value.method !== newValue.method) {
|
||||
const { method, section } = newValue;
|
||||
const meta = (api.consts[section][method] as ConstantCodec).meta;
|
||||
const updated = { meta, method, section };
|
||||
|
||||
setValue(updated);
|
||||
onChange && onChange(updated);
|
||||
}
|
||||
},
|
||||
[api, onChange, value]
|
||||
);
|
||||
|
||||
const _onSectionChange = useCallback(
|
||||
(newSection: string): void => {
|
||||
if (newSection !== value.section) {
|
||||
const optionsMethod = keyOptions(api, newSection);
|
||||
|
||||
setOptionsMethod(optionsMethod);
|
||||
_onKeyChange({ method: optionsMethod[0].value, section: newSection });
|
||||
}
|
||||
},
|
||||
[_onKeyChange, api, value]
|
||||
);
|
||||
|
||||
return (
|
||||
<LinkedWrapper
|
||||
className={className}
|
||||
label={label}
|
||||
withLabel={withLabel}
|
||||
>
|
||||
<SelectSection
|
||||
className='small'
|
||||
onChange={_onSectionChange}
|
||||
options={optionsSection}
|
||||
value={value}
|
||||
/>
|
||||
<SelectKey
|
||||
className='large'
|
||||
onChange={_onKeyChange}
|
||||
options={optionsMethod}
|
||||
value={value}
|
||||
/>
|
||||
</LinkedWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(InputConsts);
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2017-2025 @polkadot/react-components authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { ApiPromise } from '@polkadot/api';
|
||||
import type { ConstantCodec } from '@polkadot/types/metadata/decorate/types';
|
||||
import type { DropdownOption, DropdownOptions } from '../../util/types.js';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { getSiName } from '@polkadot/types/metadata/util';
|
||||
|
||||
export default function createOptions (api: ApiPromise, sectionName: string): DropdownOptions {
|
||||
const section = api.consts[sectionName];
|
||||
|
||||
if (!section || Object.keys(section).length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Object
|
||||
.keys(section)
|
||||
.filter((s) => !s.startsWith('$'))
|
||||
.sort()
|
||||
.map((value): DropdownOption => {
|
||||
const method = (section[value] as ConstantCodec);
|
||||
|
||||
return {
|
||||
className: 'ui--DropdownLinked-Item',
|
||||
key: `${sectionName}_${value}`,
|
||||
text: [
|
||||
<div
|
||||
className='ui--DropdownLinked-Item-call'
|
||||
key={`${sectionName}_${value}:call`}
|
||||
>
|
||||
{value}: {getSiName(api.registry.lookup, method.meta.type)}
|
||||
</div>,
|
||||
<div
|
||||
className='ui--DropdownLinked-Item-text'
|
||||
key={`${sectionName}_${value}:text`}
|
||||
>
|
||||
{(method.meta.docs[0] || method.meta.name).toString()}
|
||||
</div>
|
||||
],
|
||||
value
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2017-2025 @polkadot/react-components authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { ApiPromise } from '@polkadot/api';
|
||||
import type { DropdownOptions } from '../../util/types.js';
|
||||
|
||||
export default function createOptions (api: ApiPromise): DropdownOptions {
|
||||
return Object
|
||||
.keys(api.consts)
|
||||
.filter((s) => !s.startsWith('$'))
|
||||
.sort()
|
||||
.filter((name): number => Object.keys(api.consts[name]).length)
|
||||
.map((name): { text: string; value: string } => ({
|
||||
text: name,
|
||||
value: name
|
||||
}));
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2017-2025 @polkadot/react-components authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { StorageEntryBase } from '@polkadot/api/types';
|
||||
import type { PalletConstantMetadataLatest } from '@polkadot/types/interfaces';
|
||||
import type { AnyTuple } from '@polkadot/types/types';
|
||||
|
||||
export type StorageEntryPromise = StorageEntryBase<'promise', any, AnyTuple>;
|
||||
|
||||
export interface ConstValueBase {
|
||||
method: string;
|
||||
section: string;
|
||||
}
|
||||
|
||||
export interface ConstValue extends ConstValueBase {
|
||||
meta: PalletConstantMetadataLatest;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2017-2025 @polkadot/react-components authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export class TokenUnit {
|
||||
public static abbr = 'Unit';
|
||||
|
||||
public static setAbbr (abbr: string = TokenUnit.abbr): void {
|
||||
TokenUnit.abbr = abbr;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user