Reagindo a eventos do gráfico
Com nossas tarefas definidas, precisamos mapear cada uma com o elemento pertinente renderizado no Viewer. Para fazer isso, precisamos recuperar as propriedades dos elementos logo após a entrada do arquivo csv.
Esse é o nosso primeiro passo! Através do método getbulkProperties. Para este exemplo, mapeamos tarefas e elementos com base no valor de uma propriedade definida, e essa propriedade será definida pelo arquivo config.js
. Vamos adicionar dois campos no arquivo de configuração: Um para armazenar os objetos e um para armazenar uma correlação entre tarefas e propriedades, assim como o trecho abaixo:
export const phasing_config = {
"propFilter": "Type Name",
"tasks": [],
"requiredProps": {
"id": "ID",
"taskName": "NAME",
"startDate": "START",
"endDate": "END",
"taskProgress": "PROGRESS",
"dependencies": "DEPENDENCIES"
},
========START OF THE ADDITIONAL CONTENT========
"objects": {},
"mapTaksNProps": {}
========END OF THE ADDITIONAL CONTENT========
}
Onde os objetos de objects
serão do tipo taskId: [dbid1, dbid2, ...]
e os objetos de mapTaksNProps
serão do tipo property value: task Id
.
Para esta demonstração, usaremos a propriedade Type Name
para mapeamento. Com isso, podemos definir o método para mapear tarefas e elementos. Adicione o conteúdo abaixo dentro da função update
da classe PhasingPanel
:
...
update(model, dbids) {
if (phasing_config.tasks.length === 0) {
this.inputCSV();
}
========START OF THE ADDITIONAL CONTENT========
model.getBulkProperties(dbids, { propFilter: phasing_config.propFilter }, (results) => {
results.map((result => {
this.updateObjects(result);
}))
}, (err) => {
console.error(err);
});
========END OF THE ADDITIONAL CONTENT========
if (phasing_config.tasks.length > 0) {
this.gantt = this.createGanttChart();
}
}
========START OF THE ADDITIONAL CONTENT========
updateObjects(result) {
let currentTaskId = phasing_config.mapTaksNProps[result.properties[0].displayValue];
if (!!currentTaskId) {
if (!phasing_config.objects[currentTaskId])
phasing_config.objects[currentTaskId] = [];
phasing_config.objects[currentTaskId].push(result.dbId);
}
}
========END OF THE ADDITIONAL CONTENT========
...
E isso cobre os elementos, agora precisamos implementar o campo mapTaksNProps
com os valores da nossa entrada. Para isso, vamos aproveitar a função addPropToMap
chamada toda vez que lemos o csv.
Adicione a função addPropToMap
dentro da classe PhasingPanel
:
...
updateObjects(result) {
let currentTaskId = phasing_config.mapTaksNProps[result.properties[0].displayValue];
if (!!currentTaskId) {
if (!phasing_config.objects[currentTaskId])
phasing_config.objects[currentTaskId] = [];
phasing_config.objects[currentTaskId].push(result.dbId);
}
}
========START OF THE ADDITIONAL CONTENT========
addPropToMap(filterValue, taskId) {
phasing_config.mapTaksNProps[filterValue] = taskId;
}
========END OF THE ADDITIONAL CONTENT========
E referenciá-lo dentro da função lineToObject
:
...
//This function converts a line from imported csv into an object to generate the GANTT chart
lineToObject(line, inputHeadersLine) {
let parameters = line.split(',');
let inputHeaders = inputHeadersLine.split(',');
let newObject = {};
Object.values(phasing_config.requiredProps).forEach(requiredProp => {
newObject.id = parameters[inputHeaders.findIndex(h => h === phasing_config.requiredProps.id)];
newObject.name = parameters[inputHeaders.findIndex(h => h === phasing_config.requiredProps.taskName)];
newObject.start = parameters[inputHeaders.findIndex(h => h === phasing_config.requiredProps.startDate)];
newObject.end = parameters[inputHeaders.findIndex(h => h === phasing_config.requiredProps.endDate)];
newObject.progress = parameters[inputHeaders.findIndex(h => h === phasing_config.requiredProps.taskProgress)];
newObject.dependencies = parameters[inputHeaders.findIndex(h => h === phasing_config.requiredProps.dependencies)];
newObject.dependencies.replaceAll('-', ',');
});
========START OF THE ADDITIONAL CONTENT========
this.addPropToMap(parameters[inputHeaders.findIndex(h => h === phasing_config.propFilter)], newObject.id);
========END OF THE ADDITIONAL CONTENT========
return newObject;
}
Agora que temos nossa agenda com tarefas e elementos de modelo devidamente mapeados, podemos aproveitar os eventos acionados pelo Frappe-Gantt. O primeiro que podemos usar é o on_click
de forma a isolar elementos apropriados quando uma tarefa é clicada.
Para conseguir isso, precisamos alterar PhasingPanel.js
adicionando o conteúdo abaixo.
Primeiro, adicionamos o evento on_click
na criação do gráfico de Gantt dentro da função createGanttChart
:
...
createGanttChart() {
document.getElementById('phasing-container').innerHTML = `<svg id="phasing-container"></svg>`;
let newGantt = new Gantt("#phasing-container", phasing_config.tasks,
========START OF THE ADDITIONAL CONTENT========
{
on_click: this.barCLickEvent.bind(this)
}
========END OF THE ADDITIONAL CONTENT========
);
return newGantt;
}
========START OF THE ADDITIONAL CONTENT========
barCLickEvent(task) {
this.extension.viewer.isolate(phasing_config.objects[task.id]);
}
========END OF THE ADDITIONAL CONTENT========
...
E agora podemos isolar elementos vinculados clicando duas vezes em uma tarefa, assim como no gif abaixo:
No próximo passo, implementaremos métodos para lidar com a coloração de elementos com base em seu progresso.