Skip to content

Commit

Permalink
feat: categories for Icons added
Browse files Browse the repository at this point in the history
  • Loading branch information
kayman233 committed Jan 10, 2024
1 parent 351c8a3 commit 4613331
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 78 deletions.
5 changes: 3 additions & 2 deletions packages/icon-export-ui/src/app/api/githubFilesFetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const updateCommit = async (octokit: Octokit, owner: string, repo: string
});

export const createBranch = async (octokit: Octokit, owner: string, repo: string, branchName: string) => {
const { commitSha } = await getCurrentSha(octokit, owner, repo, 'master');
const { commitSha } = await getCurrentSha(octokit, owner, repo, 'dev');

await octokit.rest.git.createRef({
owner,
Expand All @@ -107,7 +107,7 @@ export const createPullRequest = async (
octokit.rest.pulls.create({
owner,
repo,
base: 'refs/heads/master',
base: 'refs/heads/dev',
head: `refs/heads/${branchName}`,
title,
});
Expand All @@ -131,6 +131,7 @@ export const getFilesSource = async (
owner,
repo,
path,
ref: 'dev',
});

return result.data;
Expand Down
13 changes: 12 additions & 1 deletion packages/icon-export-ui/src/app/components/form/Form.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ChangeEvent, FC, FormEvent, useCallback, useMemo, useState } from 'react';
import React, { ChangeEvent, FC, FormEvent, useCallback, useEffect, useMemo, useState } from 'react';
import { TextField, Select } from '@salutejs/plasma-web';

import type { FormPayload, IconPayload, SelectItem } from '../../../types';
Expand Down Expand Up @@ -29,6 +29,17 @@ interface FormProps {
export const Form: FC<FormProps> = ({ onSubmit = () => {}, iconsMetaData }) => {
const [state, setState] = useState<FormPayload>({ ...defaultState, iconsMetaData });

useEffect(() => {
if (!iconsMetaData.length) {
return;
}

setState((prevState) => ({
...prevState,
iconsMetaData,
}));
}, [iconsMetaData]);

const onSubmitForm = useCallback(
async (event: FormEvent) => {
event.preventDefault();
Expand Down
32 changes: 16 additions & 16 deletions packages/icon-export-ui/src/app/components/iconItem/IconItem.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
import React, { ChangeEvent, FC } from 'react';
import { Select, TextField } from '@salutejs/plasma-web';
import { TextField } from '@salutejs/plasma-web';

import { Input } from '../input/Input';
import type { IconPayload, SelectItem } from '../../../types';
import type { IconPayload } from '../../../types';
import { IconPreview } from '../iconPreview/IconPreview';

import { StyledFirstBlock, StyledIconItem, StyledSecondBlock } from './IconItem.style';

interface IconItemProps {
name: string;
item: IconPayload;
category: string;
categories: SelectItem[];
onChangeInput: (event: ChangeEvent<HTMLInputElement>) => void;
}

export const IconItem: FC<IconItemProps> = ({ name, item, category, categories, onChangeInput }) => (
<StyledIconItem>
<StyledFirstBlock>
<Input label="Svg" content={<IconPreview svg={item.svg} />} />
<Input label="Size" content={<TextField readOnly value={item.size} />} />
</StyledFirstBlock>
<StyledSecondBlock>
<Input label="Name" content={<TextField name={name} value={item.name} onChange={onChangeInput} />} />
<Input label="Category" content={<Select value={category} items={categories} />} />
</StyledSecondBlock>
</StyledIconItem>
);
export const IconItem: FC<IconItemProps> = ({ name, item, onChangeInput }) => {
return (
<StyledIconItem>
<StyledFirstBlock>
<Input label="Svg" content={<IconPreview svg={item.svg} />} />
<Input label="Size" content={<TextField readOnly value={item.size} />} />
</StyledFirstBlock>
<StyledSecondBlock>
<Input label="Name" content={<TextField name={name} value={item.name} onChange={onChangeInput} />} />
<Input label="Category" content={<TextField readOnly value={item.category} />} />
</StyledSecondBlock>
</StyledIconItem>
);
};
63 changes: 29 additions & 34 deletions packages/icon-export-ui/src/app/components/iconList/IconList.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,11 @@
import React, { ChangeEvent, FC, useCallback, useState } from 'react';
import React, { ChangeEvent, FC, useCallback, useEffect, useState } from 'react';
import { ParagraphText1 } from '@salutejs/plasma-web';

import type { SelectItem, IconPayload } from '../../../types';
import type { IconPayload } from '../../../types';
import { IconItem } from '../iconItem/IconItem';

import { StyledIconList, StyledIconListContainer } from './IconList.style';

const categories: SelectItem[] = [
{ value: '--no-category--', label: '--no-category--' },
{ value: 'navigation', label: 'Navigation' },
{ value: 'universal', label: 'Universal' },
{ value: 'action', label: 'Action' },
{ value: 'alert', label: 'Alert' },
{ value: 'av', label: 'Av' },
{ value: 'connection', label: 'Connection' },
{ value: 'hardware', label: 'Hardware' },
{ value: 'communication', label: 'Communication' },
{ value: 'files', label: 'Files' },
{ value: 'map', label: 'Map' },
{ value: 'other', label: 'Other' },
{ value: 'logo', label: 'Logo' },
];

interface IconListProps {
iconsMetaData: IconPayload[];
onChangeIconsName: (data: IconPayload[]) => void;
Expand All @@ -31,25 +15,25 @@ interface IconListProps {
* Список выбранных иконок.
*/
export const IconList: FC<IconListProps> = ({ onChangeIconsName, iconsMetaData }) => {
const [state, setState] = useState(
iconsMetaData.reduce((acc: Record<string, IconPayload>, item, i) => {
acc[`${item.name}${i}`] = item;
return acc;
}, {}),
);
const [state, setState] = useState<Record<string, IconPayload>>();

const onChangeInput = useCallback(
(event: ChangeEvent<HTMLInputElement>) => {
event.persist();

const iconKey = event.target.name;

if (!state) {
return;
}

const newState = {
...state,
[iconKey]: {
size: state[iconKey].size,
svg: state[iconKey].svg,
name: event.target.value,
category: state[iconKey].category,
},
};

Expand All @@ -60,20 +44,31 @@ export const IconList: FC<IconListProps> = ({ onChangeIconsName, iconsMetaData }
[state, onChangeIconsName],
);

useEffect(() => {
if (!iconsMetaData.length) {
return;
}

const fromData = iconsMetaData.reduce((acc: Record<string, IconPayload>, item, i) => {
acc[`${item.name}${i}`] = item;
return acc;
}, {});
setState(fromData);
}, [iconsMetaData]);

return (
<StyledIconList>
<ParagraphText1>Icon list: {iconsMetaData.length}</ParagraphText1>
<StyledIconListContainer>
{iconsMetaData.map(({ name }, i) => (
<IconItem
key={`${name}${i}`}
name={`${name}${i}`}
item={state[`${name}${i}`]}
category="--no-category--"
categories={categories}
onChangeInput={onChangeInput}
/>
))}
{state &&
iconsMetaData.map(({ name }, i) => (
<IconItem
key={`${name}${i}`}
name={`${name}${i}`}
item={state[`${name}${i}`]}
onChangeInput={onChangeInput}
/>
))}
</StyledIconListContainer>
</StyledIconList>
);
Expand Down
13 changes: 10 additions & 3 deletions packages/icon-export-ui/src/app/components/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import prettier from 'prettier/standalone';
import type { Options } from 'prettier';

import { FilesPayloadResponse, IconComponents, IconPayload } from '../../types';
import { getIconAsset, getIconComponent, getIconSource, getIndexSource } from '../../source';
import { getIconAsset, getIconComponent, getIconSource, getIndexSource, getIconCategories } from '../../source';
import { getFilesSource } from '../api/githubFilesFetcher';

const prettierSetting: Options = {
Expand All @@ -24,6 +24,7 @@ export const prettify = (source: string) => prettier.format(source, prettierSett

export const getFilesPath = (iconName?: string, iconSize?: number) => ({
iconSourceExport: 'packages/plasma-icons/src/scalable/index.ts',
iconSourceComponent: 'packages/plasma-icons/src/scalable/Icon.tsx',
iconSourceImport16: 'packages/plasma-icons/src/scalable/Icon.assets.16/index.ts',
iconSourceImport24: 'packages/plasma-icons/src/scalable/Icon.assets.24/index.ts',
iconSourceImport36: 'packages/plasma-icons/src/scalable/Icon.assets.36/index.ts',
Expand All @@ -32,9 +33,9 @@ export const getFilesPath = (iconName?: string, iconSize?: number) => ({
});

export const getFilesPayload = (iconsMetaData: IconPayload[], ...args: string[]): FilesPayloadResponse => {
let [iconSourceExport, iconSourceImport16, iconSourceImport24, iconSourceImport36] = args;
let [iconSourceExport, iconSourceComponent, iconSourceImport16, iconSourceImport24, iconSourceImport36] = args;

const iconsComponents = iconsMetaData.map(({ size, name = 'IconName', svg }) => {
const iconsComponents = iconsMetaData.map(({ size, name = 'IconName', category, svg }) => {
iconSourceExport = getIndexSource(iconSourceExport, name);

if (size === 16) {
Expand All @@ -47,6 +48,8 @@ export const getFilesPayload = (iconsMetaData: IconPayload[], ...args: string[])
iconSourceImport36 = getIconSource(iconSourceImport36, name);
}

iconSourceComponent = getIconCategories(iconSourceComponent, name, size, category);

return {
iconSize: size,
iconName: name,
Expand All @@ -58,6 +61,7 @@ export const getFilesPayload = (iconsMetaData: IconPayload[], ...args: string[])
return {
iconsComponents,
iconSourceExport,
iconSourceComponent,
iconSourceImport16,
iconSourceImport24,
iconSourceImport36,
Expand All @@ -70,6 +74,7 @@ export const getGitHubData = async (token?: string, owner = 'salute-developers',
repo,
[
getFilesPath().iconSourceExport,
getFilesPath().iconSourceComponent,
getFilesPath().iconSourceImport16,
getFilesPath().iconSourceImport24,
getFilesPath().iconSourceImport36,
Expand All @@ -87,6 +92,7 @@ export const getFlatIconFiles = (iconsComponents: IconComponents[]) =>

export const getFilesTree = ({
iconSourceExport,
iconSourceComponent,
iconSourceImport16,
iconSourceImport24,
iconSourceImport36,
Expand All @@ -96,6 +102,7 @@ export const getFilesTree = ({

return {
[getFilesPath().iconSourceExport]: iconSourceExport,
[getFilesPath().iconSourceComponent]: iconSourceComponent,
[getFilesPath().iconSourceImport16]: iconSourceImport16,
[getFilesPath().iconSourceImport24]: iconSourceImport24,
[getFilesPath().iconSourceImport36]: iconSourceImport36,
Expand Down
12 changes: 7 additions & 5 deletions packages/icon-export-ui/src/app/hooks/useRunGithubPRProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ interface CreatPR {
token?: string;
}

const saveMetaData = (octokit: Octokit, owner: string, repo: string) => <T>(fn: (...args: any[]) => Promise<T>) => (
...args: any[]
) => fn(octokit, owner, repo, ...args);
const saveMetaData =
(octokit: Octokit, owner: string, repo: string) =>
<T>(fn: (...args: any[]) => Promise<T>) =>
(...args: any[]) =>
fn(octokit, owner, repo, ...args);

/**
* Хук для запуска процесса создания пул реквеста в GitHub. Возвращает:
Expand All @@ -44,7 +46,7 @@ export const useRunGithubPRProcess = ({ owner, repo, branchName }: RunProcessGit

const withMetaData = saveMetaData(octokit, owner, repo);

if (branchName !== 'master') {
if (branchName !== 'master' && branchName !== 'dev') {
setStep(0);
await withMetaData(createBranch)(branchName);
}
Expand All @@ -66,7 +68,7 @@ export const useRunGithubPRProcess = ({ owner, repo, branchName }: RunProcessGit
await withMetaData(updateCommit)(branchName, newCommitSha);

let pullRequest;
if (branchName !== 'master') {
if (branchName !== 'master' && branchName !== 'dev') {
setStep(6);
pullRequest = await withMetaData(createPullRequest)(branchName, prTitle);
}
Expand Down
65 changes: 50 additions & 15 deletions packages/icon-export-ui/src/plugin/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,69 @@ const defaultSetting = {
width: 700,
};

/**
* Получить имя, размер и категорию из полного имени
* Example:
* 24 / Operation / 24_ShareScreenOutline - новый формат
* Player / ic_36_pause_outline - старый формат
*/
const getNormalizedName = (name: string) => {
const secondPart = camelize(name).split('/')[1] || camelize(name);
const withoutPrefix = secondPart
.trim()
.replace(/^(\s*)[a-zA-Z_]+(\d\d)/g, '')
.replace(/\s/g, '');
return upperFirstLetter(withoutPrefix);
const trimmedName = name.replace(/\s/g, '');
// в новом формате
const [size, category, nameWithSize] = trimmedName.split('/');

if (!size || !category || !nameWithSize) {
const last = camelize(trimmedName).split('/').slice(-1)[0];
const withoutPrefix = last
.trim()
.replace(/^(\s*)[a-zA-Z_]+(\d\d)/g, '') // убирает все символы и размер перед названием: ic36pauseOutline -> pauseOutline
.replace(/\s/g, '');
return upperFirstLetter(withoutPrefix);
}

return {
size,
category,
name: upperFirstLetter(nameWithSize.split('_').slice(-1)[0]), // убирает размер перед названием
};
};

const getNames = async (node: ComponentNode | InstanceNode) => {
const { width, name: nodeName } = node;

const normalizedName = getNormalizedName(nodeName);
const svg = await getExportSvg(node);

const isString = typeof normalizedName === 'string';

return {
size: isString ? Math.round(width) : Number(normalizedName.size),
category: isString ? 'Other' : normalizedName.category,
name: isString ? normalizedName : normalizedName.name,
svg,
};
};

const sendMetaDataInfo = async (selections: readonly SceneNode[]) => {
const iconsMetaData = await Promise.all(
selections.map(async (selection) => {
const { width, name } = selection;
const { type } = selection;

if (type !== 'FRAME') {
return [];
}

const normalizedName = getNormalizedName(name);
const svg = await getExportSvg(selection);
const nodes = (selection as FrameNode).findAllWithCriteria({
types: ['COMPONENT', 'INSTANCE'],
});

return {
size: Math.round(width),
name: normalizedName,
svg,
};
return await Promise.all(nodes.map(getNames));
}),
);

const payload: UIMessage<IconPayload[]> = {
type: 'update-icon-data',
payload: iconsMetaData,
payload: iconsMetaData.flat(),
};
figma.ui.postMessage(payload);
};
Expand Down
Loading

0 comments on commit 4613331

Please sign in to comment.