Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

refactor: adjust and extend activityService method of remove data #436

Merged
merged 3 commits into from
Sep 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions src/model/workbench/activityBar.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { IMenuItemProps } from 'mo/components/menu';
import { IMenuItemProps } from 'mo/components';
import { localize } from 'mo/i18n/localize';
import {
ACTION_QUICK_ACCESS_SETTINGS,
Expand Down Expand Up @@ -30,14 +30,18 @@ export interface IActivityBarItem {
checked?: boolean;
disabled?: boolean;
type?: 'normal' | 'global';
contextMenu?: IMenuItemProps[];
contextMenu?: IActivityMenuItemProps[];
className?: string;
render?: () => React.ReactNode | JSX.Element;
}

export interface IActivityMenuItemProps extends IMenuItemProps {
id: string;
}

export interface IActivityBar {
data?: IActivityBarItem[];
contextMenu?: IMenuItemProps[];
contextMenu?: IActivityMenuItemProps[];
selected?: string;
}

Expand Down Expand Up @@ -81,7 +85,7 @@ export function builtInActivityBar(): IActivityBar {
},
];

const contextMenuData: IMenuItemProps[] = [
const contextMenuData: IActivityMenuItemProps[] = [
{
id: CONTEXT_MENU_MENU,
name: localize('menubar', 'Menu'),
Expand Down Expand Up @@ -111,11 +115,11 @@ export function builtInActivityBar(): IActivityBar {

export class ActivityBarModel implements IActivityBar {
public data: IActivityBarItem[];
public contextMenu: IMenuItemProps[];
public contextMenu: IActivityMenuItemProps[];
public selected: string;
constructor(
data: IActivityBarItem[] = [],
contextMenu: IMenuItemProps[] = [],
contextMenu: IActivityMenuItemProps[] = [],
selected: string = ''
) {
this.data = data;
Expand Down
83 changes: 55 additions & 28 deletions src/services/__tests__/activityBarService.test.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,52 @@
import 'reflect-metadata';
import { container } from 'tsyringe';
import { ActivityBarService } from '../workbench';
import { ActivityBarEvent, IActivityBarItem } from 'mo/model';
import type { IMenuItemProps } from 'mo/components';
import {
ActivityBarEvent,
IActivityBarItem,
IActivityMenuItemProps,
} from 'mo/model';
import { expectLoggerErrorToBeCalled } from '@test/utils';

const activityBarService = container.resolve(ActivityBarService);

const mockBarData: IActivityBarItem = {
id: '1',
name: 'test',
};

const mockMenuData: IMenuItemProps = {
id: '1',
};
const mockBarData: IActivityBarItem[] = [
{
id: '1',
name: 'test1',
},
{ id: '2', name: 'test2' },
];

const mockMenuData: IActivityMenuItemProps[] = [
{
id: '1',
},
{ id: '2' },
];

describe('The ActivityBar Services', () => {
afterEach(() => {
activityBarService.reset();
});

test('Should support to add a single bar data', () => {
activityBarService.add(mockBarData);
activityBarService.add(mockBarData[0]);

const { data } = activityBarService.getState();
expect(data).toHaveLength(1);
expect(data![0]).toEqual(mockBarData);
expect(data![0]).toEqual(mockBarData[0]);
});

test('Should support to add a single bar data meanwhile active it', () => {
activityBarService.add(mockBarData, true);
activityBarService.add(mockBarData[0], true);

const { selected } = activityBarService.getState();
expect(selected).toBe('1');
});

test('Should support to batch add bars', () => {
const batchData = [mockBarData, { id: '2', name: 'test' }];
const batchData = [mockBarData[0], { id: '2', name: 'test' }];
activityBarService.add(batchData);

const { data } = activityBarService.getState();
Expand All @@ -46,14 +55,24 @@ describe('The ActivityBar Services', () => {

test('Should support remove bar data', () => {
const state = activityBarService.getState();
activityBarService.add(mockBarData);
activityBarService.add(mockBarData[0]);

expect(state.data).toHaveLength(1);

activityBarService.remove('1');
expect(state.data).toHaveLength(0);
});

test('Should support remove bar array data', () => {
const state = activityBarService.getState();
activityBarService.add(mockBarData);

expect(state.data).toHaveLength(2);

activityBarService.remove(['1', '2']);
expect(state.data).toHaveLength(0);
});

test('Should log error when remove failed', () => {
expectLoggerErrorToBeCalled(() => {
activityBarService.remove('1');
Expand All @@ -62,7 +81,7 @@ describe('The ActivityBar Services', () => {

test('Should support to hidden acitivity bar', () => {
const state = activityBarService.getState();
activityBarService.add(mockBarData);
activityBarService.add(mockBarData[0]);
expect(state.data![0].hidden).toBeFalsy();

activityBarService.toggleBar('1');
Expand All @@ -77,7 +96,7 @@ describe('The ActivityBar Services', () => {

test('Should select the following one if current bar is selected', () => {
const state = activityBarService.getState();
activityBarService.add(mockBarData, true);
activityBarService.add(mockBarData[0], true);
activityBarService.add({ id: '2', name: 'test' });

expect(state.selected).toBe('1');
Expand All @@ -88,7 +107,7 @@ describe('The ActivityBar Services', () => {

test('Should select the first one if current bar is selected and is last one', () => {
const state = activityBarService.getState();
activityBarService.add(mockBarData);
activityBarService.add(mockBarData[0]);
activityBarService.add({ id: '2', name: 'test' }, true);

expect(state.selected).toBe('2');
Expand All @@ -99,26 +118,26 @@ describe('The ActivityBar Services', () => {

test('Should support to add a context menu', () => {
const state = activityBarService.getState();
activityBarService.addContextMenu(mockMenuData);
activityBarService.addContextMenu(mockMenuData[0]);

expect(state.contextMenu).toHaveLength(1);
expect(state.contextMenu![0]).toEqual(mockMenuData);
expect(state.contextMenu![0]).toEqual(mockMenuData[0]);
});

test('Should support to batch add context menus', () => {
const state = activityBarService.getState();
const menus = [mockMenuData, { id: '2' }];
const menus = [mockMenuData[0], { id: '2' }];
activityBarService.addContextMenu(menus);

expect(state.contextMenu).toHaveLength(menus.length);
expect(state.contextMenu![0]).toEqual(mockMenuData);
expect(state.contextMenu![0]).toEqual(mockMenuData[0]);
expect(state.contextMenu![1]).toEqual(menus[1]);
});

test('Should support to toggle the status of context menus', () => {
const state = activityBarService.getState();

activityBarService.addContextMenu(mockMenuData);
activityBarService.addContextMenu(mockMenuData[0]);
expect(state.contextMenu![0].icon).toBeFalsy();

activityBarService.toggleContextMenuChecked('1');
Expand All @@ -133,12 +152,20 @@ describe('The ActivityBar Services', () => {

test('Should support to remove context menus', () => {
const state = activityBarService.getState();
activityBarService.addContextMenu(mockMenuData);
activityBarService.addContextMenu(mockMenuData[0]);

activityBarService.removeContextMenu('1');
expect(state.contextMenu).toHaveLength(0);
});

test('Should support to remove context menus array', () => {
const state = activityBarService.getState();
activityBarService.addContextMenu(mockMenuData);

activityBarService.removeContextMenu(['1', '2']);
expect(state.contextMenu).toHaveLength(0);
});

test('Should log error when remove context menus failed', () => {
expectLoggerErrorToBeCalled(() => {
activityBarService.removeContextMenu('1');
Expand All @@ -151,13 +178,13 @@ describe('The ActivityBar Services', () => {

activityBarService.emit(
ActivityBarEvent.OnClick,
mockBarData.id,
mockBarData
mockBarData[0].id,
mockBarData[0]
);

expect(mockFn).toBeCalled();
expect(mockFn.mock.calls[0][0]).toBe(mockBarData.id);
expect(mockFn.mock.calls[0][1]).toBe(mockBarData);
expect(mockFn.mock.calls[0][0]).toBe(mockBarData[0].id);
expect(mockFn.mock.calls[0][1]).toBe(mockBarData[0]);
});

test('Should support to subscribe onChange', () => {
Expand Down
74 changes: 51 additions & 23 deletions src/services/workbench/activityBarService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
IActivityBarItem,
} from 'mo/model/workbench/activityBar';
import { searchById } from '../helper';
import { IMenuItemProps } from 'mo/components/menu';
import { IActivityMenuItemProps } from 'mo/model';
import logger from 'mo/common/logger';
import { ISidebarService, SidebarService } from './sidebarService';

Expand All @@ -32,7 +32,7 @@ export interface IActivityBarService extends Component<IActivityBar> {
* Remove the specific activity bar by id
* @param id
*/
remove(id: string): void;
remove(id: string | string[]): void;
/**
* Toggle the specific activity bar between show or hide
* @param id activity bar id
Expand All @@ -46,12 +46,14 @@ export interface IActivityBarService extends Component<IActivityBar> {
/**
* Add new contextMenus for the activityBar
*/
addContextMenu(data: IMenuItemProps | IMenuItemProps[]): void;
addContextMenu(
data: IActivityMenuItemProps | IActivityMenuItemProps[]
): void;
/**
* Remove the specific contextMenu item by id
* @param id contextmenu id
*/
removeContextMenu(id: string): void;
removeContextMenu(id: string | string[]): void;
/**
* Add click event listener
* @param callback
Expand All @@ -77,6 +79,7 @@ export class ActivityBarService
this.state = container.resolve(ActivityBarModel);
this.sidebarService = container.resolve(SidebarService);
}

public setActive(id?: string) {
this.setState({
selected: id,
Expand Down Expand Up @@ -106,19 +109,36 @@ export class ActivityBarService
});
}

public remove(id: string) {
private getRemoveList<T extends IActivityBarItem | IActivityMenuItemProps>(
id: string | string[],
data: T[]
) {
return data.reduce((total: number[], item: T, key: number) => {
const strItem = item.id.toString();
if ((Array.isArray(id) && id.includes(strItem)) || id === strItem) {
return total.concat(key);
}
return total;
}, []);
}

public remove(id: string | string[]) {
const { data } = this.state;
const next = [...data!];
const index = next.findIndex(searchById(id));
if (index > -1) {
next.splice(index, 1);
this.setState({
data: next,
});
} else {
let next = [...data!];
const indexs = this.getRemoveList<IActivityBarItem>(id, next);

if (!indexs.length) {
logger.error(
"Remove the bar data failed, because there is no data found in barData via this 'id'"
);
} else {
next = next.filter((_, key) => {
return !indexs.includes(key);
});

this.setState({
data: next,
});
}
}

Expand All @@ -127,6 +147,7 @@ export class ActivityBarService
const next = data.concat();
const index = next.findIndex(searchById(id));
const target = next[index];

if (target) {
target.hidden = !target.hidden;
if (id === selected) {
Expand All @@ -146,6 +167,7 @@ export class ActivityBarService
const { contextMenu = [] } = this.state;
const newActions = contextMenu.concat();
const target = newActions.find(searchById(id));

if (target) {
target.icon = target.icon === 'check' ? '' : 'check';
this.setState({
Expand All @@ -158,8 +180,11 @@ export class ActivityBarService
}
}

public addContextMenu(contextMenu: IMenuItemProps | IMenuItemProps[]) {
public addContextMenu(
contextMenu: IActivityMenuItemProps | IActivityMenuItemProps[]
) {
let next = [...this.state.contextMenu!];

if (Array.isArray(contextMenu)) {
next = next?.concat(contextMenu);
} else {
Expand All @@ -170,19 +195,22 @@ export class ActivityBarService
});
}

public removeContextMenu(id: string) {
public removeContextMenu(id: string | string[]) {
const { contextMenu } = this.state;
const next = [...contextMenu!];
const index = next.findIndex(searchById(id));
if (index > -1) {
next.splice(index, 1);
let next = [...contextMenu!];
const indexs = this.getRemoveList<IActivityMenuItemProps>(id, next);

if (!indexs.length) {
logger.error(
"Remove the bar data failed, because there is no data found in barData via this 'id'"
);
} else {
next = next.filter((_, key) => {
return !indexs.includes(key);
});
this.setState({
contextMenu: next,
});
} else {
logger.error(
"Remove the context menus data failed, because there is no data found in context menus via this 'id'"
);
}
}

Expand Down
Loading