更新架构,进行依赖注入
This commit is contained in:
parent
e06f6abc50
commit
b718780cf5
@ -223,14 +223,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef BasicD3ManagmentItem
|
* @typedef BasicD3ManagmentItem 用于管理一个 实体/连接 的 d3 上下文数据结构
|
||||||
* @property {'cell' | 'connection' | 'instantiation' | 'port' | 'wire'} type
|
* @property {'cell' | 'connection' | 'instantiation' | 'port' | 'wire'} type
|
||||||
* @property {BasicD3DataItem} data
|
* @property {BasicD3DataItem} data 用于绑定 d3 渲染的数据,【初始化/特殊事件】会使得 d3 去主动根据
|
||||||
* @property {d3.Selection} selection
|
* @property {d3.Selection} selection 渲染成图形对应的 d3 选择集
|
||||||
|
* @property {DragContext} [dragContext] 与当前这个 实体 相关的拖拽上下文(目前不支持 wire 和 connection 的)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef DragContext
|
* @typedef DragContext
|
||||||
* @property {BasicD3DataItem} data
|
|
||||||
* @property {ElkGraph} elkGraph
|
* @property {ElkGraph} elkGraph
|
||||||
*/
|
*/
|
@ -21,7 +21,7 @@ export class CellRender {
|
|||||||
* @description id 到管理数据项的映射
|
* @description id 到管理数据项的映射
|
||||||
* @type {Map<string, BasicD3ManagmentItem[]>}
|
* @type {Map<string, BasicD3ManagmentItem[]>}
|
||||||
*/
|
*/
|
||||||
this.id2selections = rootRender.id2selections;
|
this.id2manager = rootRender.id2manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,7 +44,8 @@ export class CellRender {
|
|||||||
render() {
|
render() {
|
||||||
const data = this.data;
|
const data = this.data;
|
||||||
const rootRender = this.rootRender;
|
const rootRender = this.rootRender;
|
||||||
const id2selections = this.id2selections;
|
const id2manager = this.id2manager;
|
||||||
|
const _this = this;
|
||||||
|
|
||||||
let cellSelections = this.parentSelection.selectAll('svg')
|
let cellSelections = this.parentSelection.selectAll('svg')
|
||||||
.data(data)
|
.data(data)
|
||||||
@ -67,74 +68,83 @@ export class CellRender {
|
|||||||
.attr('class', 'grab')
|
.attr('class', 'grab')
|
||||||
.on('end', function (data) {
|
.on('end', function (data) {
|
||||||
const cellSelection = d3.select(this);
|
const cellSelection = d3.select(this);
|
||||||
registerDragEvent(cellSelection, data, rootRender);
|
const manager = _this.createDataManager(cellSelection, data);
|
||||||
|
registerDragEvent(manager, rootRender);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cellSelections = cellSelections
|
cellSelections = cellSelections
|
||||||
.attr('class', 'grab')
|
.attr('class', 'grab')
|
||||||
.each(function (data) {
|
.each(function (data) {
|
||||||
const cellSelection = d3.select(this);
|
const cellSelection = d3.select(this);
|
||||||
registerDragEvent(cellSelection, data, rootRender);
|
const manager = _this.createDataManager(cellSelection, data);
|
||||||
|
registerDragEvent(manager, rootRender);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
cellSelections.each(function (data) {
|
|
||||||
const selection = d3.select(this);
|
|
||||||
if (!id2selections.has(data.id)) {
|
|
||||||
id2selections.set(data.id, []);
|
|
||||||
}
|
|
||||||
id2selections.get(data.id).push({
|
|
||||||
data,
|
|
||||||
selection,
|
|
||||||
type: 'cell'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.selections = cellSelections;
|
this.selections = cellSelections;
|
||||||
return cellSelections;
|
return cellSelections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {d3.Selection} selection
|
||||||
|
* @param {BasicD3DataItem} data
|
||||||
|
* @returns {BasicD3ManagmentItem}
|
||||||
|
*/
|
||||||
|
createDataManager(selection, data) {
|
||||||
|
const id2manager = this.id2manager;
|
||||||
|
// 创建拖拽上下文
|
||||||
|
const dragContext = {
|
||||||
|
elkGraph: {
|
||||||
|
// elk 是无状态的,id 取什么名字都行
|
||||||
|
id: 'root',
|
||||||
|
children: [],
|
||||||
|
edges: [],
|
||||||
|
layoutOptions: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const managerItem = {
|
||||||
|
data,
|
||||||
|
selection,
|
||||||
|
type: 'cell',
|
||||||
|
dragContext
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!id2manager.has(data.id)) {
|
||||||
|
id2manager.set(data.id, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
id2manager.set(data.id, managerItem);
|
||||||
|
return managerItem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 注册关于 器件 的拖动事件
|
* @description 注册关于 器件 的拖动事件
|
||||||
*
|
*
|
||||||
* 需要提取最小拓扑子图,然后重新调整各个区域的尺寸
|
* 需要提取最小拓扑子图,然后重新调整各个区域的尺寸
|
||||||
* @param {d3.Selection} selection
|
* @param {BasicD3ManagmentItem} manager
|
||||||
* @param {any} data
|
|
||||||
* @param {NetlistRender} rootRender
|
* @param {NetlistRender} rootRender
|
||||||
*/
|
*/
|
||||||
export function registerDragEvent(selection, data, rootRender) {
|
export function registerDragEvent(manager, rootRender) {
|
||||||
// 创建拖拽行为
|
// 创建拖拽行为
|
||||||
const drag = d3.drag();
|
const drag = d3.drag();
|
||||||
|
|
||||||
const dragContext = {
|
drag.on('start', async event => dragStart(event, manager, rootRender));
|
||||||
data: data,
|
drag.on('drag', async event => dragged(event, manager, rootRender));
|
||||||
elkGraph: {
|
drag.on('end', async event => dragEnd(event, manager, rootRender))
|
||||||
id: 'root',
|
|
||||||
children: [],
|
|
||||||
edges: [],
|
|
||||||
layoutOptions: {
|
|
||||||
// 伟大,无需多言
|
|
||||||
'elk.algorithm': ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
drag.on('start', async event => dragStart(event, selection, dragContext, rootRender));
|
manager.selection.call(drag);
|
||||||
drag.on('drag', async event => dragged(event, selection, dragContext, rootRender));
|
|
||||||
drag.on('end', async event => dragEnd(event, selection, dragContext, rootRender))
|
|
||||||
|
|
||||||
selection.call(drag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {d3.D3DragEvent} event
|
* @param {d3.D3DragEvent} event
|
||||||
* @param {d3.Selection} selection
|
* @param {BasicD3ManagmentItem} manager
|
||||||
* @param {DragContext} dragContext
|
|
||||||
* @param {NetlistRender} rootRender
|
* @param {NetlistRender} rootRender
|
||||||
*/
|
*/
|
||||||
function dragStart(event, selection, dragContext, rootRender) {
|
function dragStart(event, manager, rootRender) {
|
||||||
|
const selection = manager.selection;
|
||||||
selection.attr('class', 'grabbing');
|
selection.attr('class', 'grabbing');
|
||||||
|
|
||||||
// 更新拓扑图中各个节点的节点坐标
|
// 更新拓扑图中各个节点的节点坐标
|
||||||
@ -145,32 +155,34 @@ function dragStart(event, selection, dragContext, rootRender) {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {d3.D3DragEvent} event
|
* @param {d3.D3DragEvent} event
|
||||||
* @param {d3.Selection} selection
|
* @param {BasicD3ManagmentItem} manager
|
||||||
* @param {DragContext} dragContext
|
|
||||||
* @param {NetlistRender} rootRender
|
* @param {NetlistRender} rootRender
|
||||||
*/
|
*/
|
||||||
function dragged(event, selection, dragContext, rootRender) {
|
function dragged(event, manager, rootRender) {
|
||||||
// 当拖动结束时,D3 会根据绑定的数据(data.x 和 data.y)重新渲染元素,导致元素回到初始位置。
|
// 当拖动结束时,D3 会根据绑定的数据(data.x 和 data.y)重新渲染元素,导致元素回到初始位置。
|
||||||
// 所以需要 手动更新 data.x 和 data.y
|
// 所以需要 手动更新 data.x 和 data.y
|
||||||
dragContext.data.x = event.x;
|
const selection = manager.selection;
|
||||||
dragContext.data.y = event.y;
|
const data = manager.data;
|
||||||
|
|
||||||
|
data.x = event.x;
|
||||||
|
data.y = event.y;
|
||||||
|
|
||||||
selection
|
selection
|
||||||
.attr('x', event.x)
|
.attr('x', event.x)
|
||||||
.attr('y', event.y);
|
.attr('y', event.y);
|
||||||
|
|
||||||
// 根据最小拓扑图,提取出关键点,重新计算布局
|
// 根据最小拓扑图,提取出关键点,重新计算布局
|
||||||
console.log(dragContext.data);
|
const context = manager.dragContext;
|
||||||
|
console.log(context.elkGraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {d3.D3DragEvent} event
|
* @param {d3.D3DragEvent} event
|
||||||
* @param {d3.Selection} selection
|
* @param {BasicD3ManagmentItem} manager
|
||||||
* @param {DragContext} dragContext
|
|
||||||
* @param {NetlistRender} rootRender
|
* @param {NetlistRender} rootRender
|
||||||
*/
|
*/
|
||||||
function dragEnd(event, selection, dragContext, rootRender) {
|
function dragEnd(event, manager, rootRender) {
|
||||||
|
const selection = manager.selection;
|
||||||
selection.attr('class', 'grab');
|
selection.attr('class', 'grab');
|
||||||
}
|
}
|
@ -20,7 +20,7 @@ export class ConnectionRender {
|
|||||||
* @description id 到管理数据项的映射
|
* @description id 到管理数据项的映射
|
||||||
* @type {Map<string, BasicD3ManagmentItem[]>}
|
* @type {Map<string, BasicD3ManagmentItem[]>}
|
||||||
*/
|
*/
|
||||||
this.id2selections = rootRender.id2selections;
|
this.id2manager = rootRender.id2manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,7 +43,8 @@ export class ConnectionRender {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const data = this.data;
|
const data = this.data;
|
||||||
const id2selections = this.id2selections;
|
const id2manager = this.id2manager;
|
||||||
|
const _this = this;
|
||||||
|
|
||||||
let connectionSelections = this.parentSelection.selectAll('circle')
|
let connectionSelections = this.parentSelection.selectAll('circle')
|
||||||
.data(data)
|
.data(data)
|
||||||
@ -65,17 +66,33 @@ export class ConnectionRender {
|
|||||||
.attr('r', d => d.r)
|
.attr('r', d => d.r)
|
||||||
.each(function (data) {
|
.each(function (data) {
|
||||||
const selection = d3.select(this);
|
const selection = d3.select(this);
|
||||||
if (!id2selections.has(data.id)) {
|
const manager = _this.createDataManager(selection, data);
|
||||||
id2selections.set(data.id, []);
|
|
||||||
}
|
|
||||||
id2selections.get(data.id).push({
|
|
||||||
data,
|
|
||||||
selection,
|
|
||||||
type: 'connection'
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.selections = connectionSelections;
|
this.selections = connectionSelections;
|
||||||
return connectionSelections;
|
return connectionSelections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {d3.Selection} selection
|
||||||
|
* @param {BasicD3DataItem} data
|
||||||
|
* @returns {BasicD3ManagmentItem}
|
||||||
|
*/
|
||||||
|
createDataManager(selection, data) {
|
||||||
|
const id2manager = this.id2manager;
|
||||||
|
// connection 不需要拖拽上下文
|
||||||
|
const managerItem = {
|
||||||
|
data,
|
||||||
|
selection,
|
||||||
|
type: 'connection'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!id2manager.has(data.id)) {
|
||||||
|
id2manager.set(data.id, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
id2manager.set(data.id, managerItem);
|
||||||
|
return managerItem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,9 +62,13 @@ export class NetlistRender {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @description id 到管理数据项的映射
|
* @description id 到管理数据项的映射
|
||||||
|
*
|
||||||
|
* - key: id, 和 layout.js 中的赋值 id 一致,全局唯一
|
||||||
|
* - value: 每一个 id 对应的管理者,这里存储着数据视图和渲染视图,查询与操作DOM一体。一个 ID 对应的真实渲染体可能不只一个
|
||||||
|
* (比如对于 wire,一个 id 对应的 wire 可以是连续的折现,但是这些折现对应的渲染体是复数个的)
|
||||||
* @type {Map<string, BasicD3ManagmentItem[]>}
|
* @type {Map<string, BasicD3ManagmentItem[]>}
|
||||||
*/
|
*/
|
||||||
this.id2selections = new Map();
|
this.id2manager = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,7 +20,7 @@ export class InstantiationRender {
|
|||||||
* @description id 到管理数据项的映射
|
* @description id 到管理数据项的映射
|
||||||
* @type {Map<string, BasicD3ManagmentItem[]>}
|
* @type {Map<string, BasicD3ManagmentItem[]>}
|
||||||
*/
|
*/
|
||||||
this.id2selections = rootRender.id2selections;
|
this.id2manager = rootRender.id2manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@ export class PortRender {
|
|||||||
* @description id 到管理数据项的映射
|
* @description id 到管理数据项的映射
|
||||||
* @type {Map<string, BasicD3ManagmentItem[]>}
|
* @type {Map<string, BasicD3ManagmentItem[]>}
|
||||||
*/
|
*/
|
||||||
this.id2selections = rootRender.id2selections;
|
this.id2manager = rootRender.id2manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,7 +45,9 @@ export class PortRender {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const data = this.data;
|
const data = this.data;
|
||||||
const id2selections = this.id2selections;
|
const id2manager = this.id2manager;
|
||||||
|
const rootRender = this.rootRender;
|
||||||
|
const _this = this;
|
||||||
|
|
||||||
let portSelections = this.parentSelection.selectAll('g.port')
|
let portSelections = this.parentSelection.selectAll('g.port')
|
||||||
.data(data)
|
.data(data)
|
||||||
@ -91,18 +93,46 @@ export class PortRender {
|
|||||||
.attr('class', 'grab')
|
.attr('class', 'grab')
|
||||||
.each(function (data) {
|
.each(function (data) {
|
||||||
const portSelection = d3.select(this);
|
const portSelection = d3.select(this);
|
||||||
// 注册拖拽
|
const manager = _this.createDataManager(portSelection, data);
|
||||||
registerDragEvent(portSelection, data);
|
registerDragEvent(manager, rootRender);
|
||||||
// 进行管理
|
|
||||||
if (!id2selections.has(data.id)) {
|
|
||||||
id2selections.set(data.id, []);
|
|
||||||
}
|
|
||||||
id2selections.get(data.id).push({ data, selection: portSelection });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.selections = portSelections;
|
this.selections = portSelections;
|
||||||
return portSelections;
|
return portSelections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {d3.Selection} selection
|
||||||
|
* @param {BasicD3DataItem} data
|
||||||
|
* @returns {BasicD3ManagmentItem}
|
||||||
|
*/
|
||||||
|
createDataManager(selection, data) {
|
||||||
|
const id2manager = this.id2manager;
|
||||||
|
// 创建拖拽上下文
|
||||||
|
const dragContext = {
|
||||||
|
elkGraph: {
|
||||||
|
// elk 是无状态的,id 取什么名字都行
|
||||||
|
id: 'root',
|
||||||
|
children: [],
|
||||||
|
edges: [],
|
||||||
|
layoutOptions: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const managerItem = {
|
||||||
|
data,
|
||||||
|
selection,
|
||||||
|
type: 'port',
|
||||||
|
dragContext
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!id2manager.has(data.id)) {
|
||||||
|
id2manager.set(data.id, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
id2manager.set(data.id, managerItem);
|
||||||
|
return managerItem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -112,45 +142,50 @@ export class PortRender {
|
|||||||
* @description 注册关于 器件 的拖动事件
|
* @description 注册关于 器件 的拖动事件
|
||||||
*
|
*
|
||||||
* 需要提取最小拓扑子图,然后重新调整各个区域的尺寸
|
* 需要提取最小拓扑子图,然后重新调整各个区域的尺寸
|
||||||
* @param {d3.Selection} selection
|
* @param {BasicD3ManagmentItem} manager
|
||||||
* @param {any} data
|
* @param {NetlistRender} rootRender
|
||||||
*/
|
*/
|
||||||
export function registerDragEvent(selection, data) {
|
export function registerDragEvent(manager, rootRender) {
|
||||||
// 创建拖拽行为
|
// 创建拖拽行为
|
||||||
const drag = d3.drag();
|
const drag = d3.drag();
|
||||||
|
|
||||||
drag.on("start", event => dragStart(event, selection, data));
|
drag.on("start", event => dragStart(event, manager, rootRender));
|
||||||
drag.on("drag", event => dragged(event, selection, data));
|
drag.on("drag", event => dragged(event, manager, rootRender));
|
||||||
drag.on("end", event => dragEnd(event, selection, data));
|
drag.on("end", event => dragEnd(event, manager, rootRender));
|
||||||
|
|
||||||
selection.call(drag);
|
manager.selection.call(drag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param {d3.D3DragEvent} event
|
* @param {d3.D3DragEvent} event
|
||||||
* @param {d3.Selection} selection
|
* @param {BasicD3ManagmentItem} manager
|
||||||
|
* @param {NetlistRender} rootRender
|
||||||
*/
|
*/
|
||||||
function dragStart(event, selection, data) {
|
function dragStart(event, manager, rootRender) {
|
||||||
|
const selection = manager.selection;
|
||||||
selection.attr('class', 'grabbing');
|
selection.attr('class', 'grabbing');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param {d3.D3DragEvent} event
|
* @param {d3.D3DragEvent} event
|
||||||
* @param {d3.Selection} selection
|
* @param {BasicD3ManagmentItem} manager
|
||||||
|
* @param {NetlistRender} rootRender
|
||||||
*/
|
*/
|
||||||
function dragged(event, selection, data) {
|
function dragged(event, manager, rootRender) {
|
||||||
|
const selection = manager.selection;
|
||||||
|
const data = manager.data;
|
||||||
|
|
||||||
data.x = event.x;
|
data.x = event.x;
|
||||||
data.y = event.y;
|
data.y = event.y;
|
||||||
selection.attr("transform", `translate(${event.x}, ${event.y})`);
|
selection.attr("transform", `translate(${event.x}, ${event.y})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param {d3.D3DragEvent} event
|
* @param {d3.D3DragEvent} event
|
||||||
* @param {d3.Selection} selection
|
* @param {BasicD3ManagmentItem} manager
|
||||||
|
* @param {NetlistRender} rootRender
|
||||||
*/
|
*/
|
||||||
function dragEnd(event, selection, data) {
|
function dragEnd(event, manager, rootRender) {
|
||||||
|
const selection = manager.selection;
|
||||||
selection.attr('class', 'grab');
|
selection.attr('class', 'grab');
|
||||||
}
|
}
|
@ -21,7 +21,7 @@ export class WireRender {
|
|||||||
* @description id 到管理数据项的映射
|
* @description id 到管理数据项的映射
|
||||||
* @type {Map<string, BasicD3ManagmentItem[]>}
|
* @type {Map<string, BasicD3ManagmentItem[]>}
|
||||||
*/
|
*/
|
||||||
this.id2selections = rootRender.id2selections;
|
this.id2manager = rootRender.id2manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,7 +45,8 @@ export class WireRender {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const data = this.data;
|
const data = this.data;
|
||||||
const id2selections = this.id2selections;
|
const id2manager = this.id2manager;
|
||||||
|
const _this = this;
|
||||||
|
|
||||||
let lineSelections = this.selection.selectAll('line')
|
let lineSelections = this.selection.selectAll('line')
|
||||||
.data(data)
|
.data(data)
|
||||||
@ -67,10 +68,30 @@ export class WireRender {
|
|||||||
.attr('stroke-width', data => data.strokeWidth)
|
.attr('stroke-width', data => data.strokeWidth)
|
||||||
.each(function (data) {
|
.each(function (data) {
|
||||||
const selection = d3.select(this);
|
const selection = d3.select(this);
|
||||||
if (!id2selections.has(data.id)) {
|
const manager = _this.createDataManager(selection, data);
|
||||||
id2selections.set(data.id, []);
|
|
||||||
}
|
|
||||||
id2selections.get(data.id).push({ data, selection });
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {d3.Selection} selection
|
||||||
|
* @param {BasicD3DataItem} data
|
||||||
|
* @returns {BasicD3ManagmentItem}
|
||||||
|
*/
|
||||||
|
createDataManager(selection, data) {
|
||||||
|
const id2manager = this.id2manager;
|
||||||
|
// wire 不需要拖拽上下文
|
||||||
|
const managerItem = {
|
||||||
|
data,
|
||||||
|
selection,
|
||||||
|
type: 'wire'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!id2manager.has(data.id)) {
|
||||||
|
id2manager.set(data.id, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
id2manager.set(data.id, managerItem);
|
||||||
|
return managerItem;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user