Skip to content

Commit

Permalink
Support add, remove, update , getMenuById, addRootMenu features for m…
Browse files Browse the repository at this point in the history
…enuBar (#133)

* feat: support add, remove, update for menuBar

* feat: explore getMenuById interface for menuBar

* refactor: optimize add, remove logic for menuBar

* test: add testCases for menuBarService

* fix: fix test cases

* fix: fix test cases

* fix: fix test cases

* ci: resolve ci problems

* fix: rename builtInMenuData
  • Loading branch information
mumiao authored Apr 21, 2021
1 parent 0a420fb commit fd4f009
Show file tree
Hide file tree
Showing 4 changed files with 265 additions and 19 deletions.
4 changes: 2 additions & 2 deletions src/model/workbench/menuBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const MENU_VIEW_SIDEBAR = 'workbench.action.showSideBar';
export const MENU_VIEW_ACTIVITYBAR = 'workbench.action.showActivityBar';
export const MENU_VIEW_STATUSBAR = 'workbench.action.showStatusBar';

const builtMenuData = [
export const builtInMenuData = [
{
id: 'File',
name: 'File',
Expand Down Expand Up @@ -147,7 +147,7 @@ export class MenuBarModel implements IMenuBar {
public data: IMenuBarItem[];
public hidden = false;

constructor(data: IMenuBarItem[] = builtMenuData, hidden = false) {
constructor(data: IMenuBarItem[] = builtInMenuData, hidden = false) {
this.data = data;
this.hidden = hidden;
}
Expand Down
147 changes: 147 additions & 0 deletions src/services/workbench/__tests__/menuBarService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import 'reflect-metadata';
import { container } from 'tsyringe';
import { IMenuBarService, MenuBarService } from '../menuBarService';

describe('Test menuBarService', () => {
const menuBarService = container.resolve<IMenuBarService>(MenuBarService);
const builtInMenuData = [
{
id: '1',
name: 'root',
data: [
{
id: '2',
name: 'a',
data: [{ id: '3', name: 'c' }],
},
{
id: '4',
name: 'b',
},
],
},
];

test('Test menuBarService Class instance', () => {
expect(menuBarService).not.toBeUndefined();
expect(menuBarService.getState().data).not.toBeUndefined();
});

test('Test menuBarService init menuBarData', () => {
menuBarService.initMenu(builtInMenuData);
const result = menuBarService.getState();
expect(result.data).toEqual(builtInMenuData);
});

test('Test menuBarService add for menuBar', () => {
menuBarService.add(
{
id: '5',
name: 'd',
icon: 'check',
},
'2'
);
const result = menuBarService.getState();
expect(result?.data).toEqual([
{
id: '1',
name: 'root',
data: [
{
id: '2',
name: 'a',
data: [
{ id: '3', name: 'c' },
{ id: '5', name: 'd', icon: 'check' },
],
},
{
id: '4',
name: 'b',
},
],
},
]);
});
test('Test menuBarService remove for menuBar', () => {
menuBarService.remove('5');
const result = menuBarService.getState();
expect(result?.data).toEqual([
{
id: '1',
name: 'root',
data: [
{
id: '2',
name: 'a',
data: [{ id: '3', name: 'c' }],
},
{
id: '4',
name: 'b',
},
],
},
]);
});
test('Test menuBarService update for menuBar', () => {
menuBarService.update('3', {
id: '3',
icon: 'check',
name: 'modifierc',
});
const result = menuBarService.getState();
expect(result?.data).toEqual([
{
id: '1',
name: 'root',
data: [
{
id: '2',
name: 'a',
data: [{ id: '3', name: 'modifierc', icon: 'check' }],
},
{
id: '4',
name: 'b',
},
],
},
]);
});
test('Test menuBarService getMenuById for menuBar', () => {
const currentMenu = menuBarService.getMenuById('3');
expect(currentMenu).toEqual({
id: '3',
name: 'modifierc',
icon: 'check',
});
});

test('Test menuBarService addRootMenu for menuBar', () => {
menuBarService.addRootMenu({ id: '10', name: 'root10' });
const result = menuBarService.getState();
expect(result.data).toEqual([
{
id: '1',
name: 'root',
data: [
{
id: '2',
name: 'a',
data: [{ id: '3', name: 'modifierc', icon: 'check' }],
},
{
id: '4',
name: 'b',
},
],
},
{
id: '10',
name: 'root10',
},
]);
});
});
99 changes: 83 additions & 16 deletions src/services/workbench/menuBarService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import { singleton, container } from 'tsyringe';

export interface IMenuBarService extends Component<IMenuBar> {
showHide(): void;
push(data: IMenuBarItem | IMenuBarItem[]): void;
remove(index: number): void;
initMenu(data: IMenuBarItem[]): void;
addRootMenu(menu: IMenuBarItem | IMenuBarItem[]): void;
add(menuItem: IMenuBarItem, parentId: string): void;
remove(menuId: string): void;
getState(): IMenuBar;
getMenuById(menuId: string): IMenuBarItem;
update(menuId: string, menuItem: IMenuBarItem): void;
}
@singleton()
Expand All @@ -33,40 +36,91 @@ export class MenuBarService
});
}

public push(item: IMenuBarItem | IMenuBarItem[]) {
let original = this.state.data || [];
if (Array.isArray(item)) {
original = original.concat(item);
public initMenu = (menuData: IMenuBarItem[]) => {
this.setState({
data: menuData,
});
};

public add(menuItem: IMenuBarItem, parentId: string) {
const { data } = this.state;
const parentMenu = this.getMenuById(parentId);
if (!parentMenu) return;
const deepData = cloneDeep(data);
for (const menu of deepData) {
this.addMenu(menu, menuItem, parentId!);
}
this.setState({ data: deepData });
}

public addMenu(
menu: IMenuBarItem,
menuItem: IMenuBarItem,
parentId: string
): void {
if (menu?.id === parentId) {
const parentMenu = menu.data || [];
parentMenu.push(menuItem);
} else {
original.push(item);
if (menu?.data?.length) {
for (const item of menu?.data) {
this.addMenu(item, menuItem, parentId);
}
}
}
}

public remove(index: number) {
this.state.data!.splice(index, 1);
public remove(menuId: string): void {
const { data } = this.state;
const currentMenuItem = this.getMenuById(menuId);
if (!currentMenuItem) return;
const deepData = cloneDeep(data);
for (const menu of deepData) {
this.removeMenu(deepData, menu, menuId);
}
this.setState({ data: deepData });
}

public removeMenu(
data: IMenuBarItem[],
menu: IMenuBarItem,
currentMenuId: string
): void {
if (menu?.id === currentMenuId) {
const menuItem = data.find((menu) => menu.id === currentMenuId);
const idx = data.indexOf(menuItem!);
idx >= 0 && data.splice(idx, 1);
} else {
if (menu?.data?.length) {
for (const item of menu?.data) {
this.removeMenu(menu?.data, item, currentMenuId);
}
}
}
}

public update(menuId: string, menuItem = {}) {
public update(menuId: string, menuItem: IMenuBarItem = {}): void {
const { data } = this.state;
const currentMenuItem = this.getMenuById(menuId, data);
const currentMenuItem = this.getMenuById(menuId);
const deepData = cloneDeep(data);
for (const menu of deepData) {
this.updateMenu(menu, currentMenuItem!, menuItem);
}
this.setState({ data: deepData });
}

public getMenuById(menuId: string, data) {
const queue = [...data];
public getMenuById(menuId: string): any {
const { data } = this.state;
const queue = cloneDeep(data);
while (queue.length) {
const menu = queue.shift();
if (menu.id === menuId) return menu;
queue.push(...(menu.data || []));
if (menu?.id === menuId) return menu;
queue.push(...(menu?.data || []));
}
}

public updateMenu(
menu,
menu: IMenuBarItem,
currentMenuItem: IMenuBarItem,
menuItem: IMenuBarItem
) {
Expand All @@ -85,4 +139,17 @@ export class MenuBarService
}
}
}

public addRootMenu(menu: IMenuBarItem | IMenuBarItem[]): void {
const { data } = this.state;
let next = cloneDeep(data);
if (Array.isArray(menu)) {
next = next?.concat(menu);
} else {
next?.push(menu);
}
this.setState({
data: next,
});
}
}
34 changes: 33 additions & 1 deletion stories/extensions/test/testPane.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import * as React from 'react';
import { activityBarService, colorThemeService, panelService } from 'mo';
import {
activityBarService,
colorThemeService,
menuBarService,
panelService,
} from 'mo';
import { editorService, notificationService } from 'mo';
import { Button } from 'mo/components/button';
import { Select, Option } from 'mo/components/select';
Expand Down Expand Up @@ -100,6 +105,27 @@ export type GenericClassDecorator<T> = (target: T) => void;`,
};

const openCommand = function () {};

const appendMenu = function () {
const id = Math.random() * 10 + 1;
menuBarService.add(
{
id: id + '',
name: 'menuBar' + id,
iconName: '',
},
'Edit'
);
};

const removeMenu = function () {
menuBarService.remove('SelectAll');
};

const updateMenu = function () {
menuBarService.update('SelectAll', { icon: 'check' });
};

return (
<div>
<div style={{ margin: '50px 20px' }}>
Expand All @@ -126,6 +152,12 @@ export type GenericClassDecorator<T> = (target: T) => void;`,
Remove A Notification
</Button>
</div>
<div style={{ margin: '50px 20px' }}>
<h2>MenuBar:</h2>
<Button onClick={appendMenu}>Add MenuBar</Button>
<Button onClick={removeMenu}>Remove MenuBar</Button>
<Button onClick={updateMenu}>Update MenuBar</Button>
</div>
</div>
);
}
Expand Down

0 comments on commit fd4f009

Please sign in to comment.