mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-08-08 07:45:40 +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,54 @@
|
||||
// Copyright 2017-2025 @polkadot/react-components authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { ApiPromise } from '@polkadot/api';
|
||||
import type { QueryableStorageEntry } from '@polkadot/api/types';
|
||||
import type { DropdownOptions } from '../util/types.js';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { useApi } from '@polkadot/react-hooks';
|
||||
|
||||
import Dropdown from '../Dropdown.js';
|
||||
import { filterDropdownItems } from '../util/index.js';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
isError?: boolean;
|
||||
onChange: (value: QueryableStorageEntry<'promise'>) => void;
|
||||
options: DropdownOptions;
|
||||
value: QueryableStorageEntry<'promise'>;
|
||||
}
|
||||
|
||||
function transform (api: ApiPromise, { value }: Props): (method: string) => QueryableStorageEntry<'promise'> {
|
||||
return function (method: string): QueryableStorageEntry<'promise'> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return api.query[value.creator.section]
|
||||
? api.query[value.creator.section][method] as any
|
||||
: value;
|
||||
};
|
||||
}
|
||||
|
||||
function SelectKey (props: Props): React.ReactElement<Props> | null {
|
||||
const { api } = useApi();
|
||||
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(api, props)}
|
||||
value={value.creator.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 { QueryableStorageEntry } from '@polkadot/api/types';
|
||||
import type { DropdownOptions } from '../util/types.js';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Dropdown from '../Dropdown.js';
|
||||
import { filterDropdownItems } from '../util/index.js';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
defaultValue?: QueryableStorageEntry<'promise'>;
|
||||
isError?: boolean;
|
||||
onChange: (value: string) => void;
|
||||
options: DropdownOptions;
|
||||
value: QueryableStorageEntry<'promise'>;
|
||||
}
|
||||
|
||||
function SelectSection ({ className = '', defaultValue, isError, onChange, options, value: { creator: { 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,79 @@
|
||||
// Copyright 2017-2025 @polkadot/react-components authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// TODO: We have a lot shared between this and InputExtrinsic
|
||||
|
||||
import type { QueryableStorageEntry } from '@polkadot/api/types';
|
||||
import type { DropdownOptions } from '../util/types.js';
|
||||
|
||||
import React, { useCallback, useState } from 'react';
|
||||
|
||||
import { useApi } from '@polkadot/react-hooks';
|
||||
|
||||
import LinkedWrapper from '../InputExtrinsic/LinkedWrapper.js';
|
||||
import { keyOptions, sectionOptions } from './options/index.js';
|
||||
import SelectKey from './SelectKey.js';
|
||||
import SelectSection from './SelectSection.js';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
defaultValue: QueryableStorageEntry<'promise'>;
|
||||
isError?: boolean;
|
||||
label: React.ReactNode;
|
||||
onChange?: (value: QueryableStorageEntry<'promise'>) => void;
|
||||
withLabel?: boolean;
|
||||
}
|
||||
|
||||
function InputStorage ({ className = '', defaultValue, label, onChange, withLabel }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const [optionsMethod, setOptionsMethod] = useState<DropdownOptions>(() => keyOptions(api, defaultValue.creator.section));
|
||||
const [optionsSection] = useState<DropdownOptions>(() => sectionOptions(api));
|
||||
const [value, setValue] = useState<QueryableStorageEntry<'promise'>>(() => defaultValue);
|
||||
|
||||
const _onKeyChange = useCallback(
|
||||
(newValue: QueryableStorageEntry<'promise'>): void => {
|
||||
if (value !== newValue) {
|
||||
// set via callback
|
||||
setValue(() => newValue);
|
||||
onChange && onChange(newValue);
|
||||
}
|
||||
},
|
||||
[onChange, value]
|
||||
);
|
||||
|
||||
const _onSectionChange = useCallback(
|
||||
(section: string): void => {
|
||||
if (section !== value.creator.section) {
|
||||
const optionsMethod = keyOptions(api, section);
|
||||
|
||||
setOptionsMethod(optionsMethod);
|
||||
_onKeyChange(api.query[section][optionsMethod[0].value]);
|
||||
}
|
||||
},
|
||||
[_onKeyChange, api, value]
|
||||
);
|
||||
|
||||
return (
|
||||
<LinkedWrapper
|
||||
className={className}
|
||||
label={label}
|
||||
withLabel={withLabel}
|
||||
>
|
||||
<SelectSection
|
||||
className='small'
|
||||
onChange={_onSectionChange}
|
||||
options={optionsSection}
|
||||
value={value}
|
||||
/>
|
||||
<SelectKey
|
||||
className='large'
|
||||
key={value.creator.section}
|
||||
onChange={_onKeyChange}
|
||||
options={optionsMethod}
|
||||
value={value}
|
||||
/>
|
||||
</LinkedWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(InputStorage);
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright 2017-2025 @polkadot/react-components authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export { keyOptions } from './key.js';
|
||||
export { sectionOptions } from './section.js';
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright 2017-2025 @polkadot/react-components authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { ApiPromise } from '@polkadot/api';
|
||||
import type { StorageEntry } from '@polkadot/types/primitive/types';
|
||||
import type { DropdownOption, DropdownOptions } from '../../util/types.js';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { getSiName } from '@polkadot/types/metadata/util';
|
||||
import { unwrapStorageType } from '@polkadot/types/util';
|
||||
|
||||
export function keyOptions (api: ApiPromise, sectionName: string): DropdownOptions {
|
||||
const section = api.query[sectionName];
|
||||
|
||||
if (!section || Object.keys(section).length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Object
|
||||
.keys(section)
|
||||
.filter((s) => !s.startsWith('$'))
|
||||
.sort()
|
||||
.map((value): DropdownOption => {
|
||||
const { meta: { docs, modifier, name, type } } = section[value] as unknown as StorageEntry;
|
||||
const output = unwrapStorageType(api.registry, type, modifier.isOptional);
|
||||
let input = '';
|
||||
|
||||
if (type.isMap) {
|
||||
const { hashers, key } = type.asMap;
|
||||
|
||||
if (hashers.length === 1) {
|
||||
input = getSiName(api.registry.lookup, key);
|
||||
} else {
|
||||
const si = api.registry.lookup.getSiType(key).def;
|
||||
|
||||
if (si.isTuple) {
|
||||
input = si.asTuple
|
||||
.map((t) => getSiName(api.registry.lookup, t))
|
||||
.join(', ');
|
||||
} else {
|
||||
input = si.asHistoricMetaCompat.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
className: 'ui--DropdownLinked-Item',
|
||||
key: `${sectionName}_${value}`,
|
||||
text: [
|
||||
<div
|
||||
className='ui--DropdownLinked-Item-call'
|
||||
key={`${sectionName}_${value}:call`}
|
||||
>
|
||||
{value}({input}): {output}
|
||||
</div>,
|
||||
<div
|
||||
className='ui--DropdownLinked-Item-text'
|
||||
key={`${sectionName}_${value}:text`}
|
||||
>
|
||||
{(docs[0] || 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 { DropdownOption, DropdownOptions } from '../../util/types.js';
|
||||
|
||||
export function sectionOptions (api: ApiPromise): DropdownOptions {
|
||||
return Object
|
||||
.keys(api.query)
|
||||
.filter((s) => !s.startsWith('$'))
|
||||
.sort()
|
||||
.filter((n) => Object.keys(api.query[n]).length)
|
||||
.map((value): DropdownOption => ({
|
||||
text: value,
|
||||
value
|
||||
}));
|
||||
}
|
||||
Reference in New Issue
Block a user