Hey all,
I am working on a GANTT chart application which shows tasks planned in on employees. My question is if it is possible to add week numbers to the value axis labels. I found the setLabelFunction() which allows me to add Javascript code in a string in order to create custom labels but I am not sure how I should get started with this in order to add week numbers to the axis.
Do any of you have experience with using this function or know another way of adding weeknumbers/custom date labels to a chart? Any help to get me started would be appreciated!
(Blue scribbled out area contains the employees, I am trying to add week numbers in the red marked area. XML and Java code used is displayed below as well, but I think it will not be of much use)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
caption="msg://browseCaption"
messagesPack="com.company.gantttest.web.employee" xmlns:chart="http://schemas.haulmont.com/charts/charts.xsd">
<data readOnly="true">
<collection id="employeesDc"
class="com.company.gantttest.entity.Employee"
view="employee-view">
<loader id="employeesDl">
<query><![CDATA[select e from gantttest_Employee e ORDER BY e.group.position, e.id]]></query>
</loader>
</collection>
</data>
<dialogMode height="600"
width="800"/>
<layout spacing="true">
<vbox id="vbox" spacing="true">
<buttonsPanel align="MIDDLE_CENTER">
<button id="refreshButton" align="MIDDLE_CENTER" caption="Refresh" invoke="onRefreshButtonClick"
stylename="primary"/>
<button id="resetButton" caption="Huidige week" invoke="onResetButtonClick" stylename="primary"
align="MIDDLE_CENTER"/>
<button id="newTaskButton" caption="Nieuwe taak" invoke="onNewTaskButtonClick" stylename="friendly"
align="MIDDLE_CENTER"/>
<button id="button_2" caption="Taak voor iedereen" invoke="onButton_2Click"/>
</buttonsPanel>
<buttonsPanel height="51px" id="buttonsPanel_1" align="MIDDLE_CENTER">
<button id="button_1" caption="Vorige week" invoke="onBackClick" stylename="danger"
align="MIDDLE_CENTER"/>
<dateField id="dateField" align="MIDDLE_CENTER" caption="Ga naar: " datatype="dateTime"/>
<button id="button" caption="Volgende week" invoke="onNextClick" stylename="friendly"
align="MIDDLE_CENTER"/>
</buttonsPanel>
<chart:ganttChart id="ganttChart1"
brightnessStep="1"
balloonDateFormat="JJ:NN"
creditsPosition="BOTTOM_RIGHT"
panEventsEnabled="true"
additionalSegmentFields="captionCreated, captionUpdated, captionStart, captionEnd, orderId, task, order, category.description"
colorField="category.color"
categoryField="name"
gridAboveGraphs="false"
columnWidth="1"
dataContainer="employeesDc"
endDateField="end"
marginRight="10"
period="WEEKS"
rotate="true"
segmentsField="tasks"
startDateField="start"
theme="LIGHT"
width="100%" height="AUTO"
synchronizeGrid="true"
>
<chart:graph balloonText="<strong>[[orderId]] [[task]] </strong> <br> [[category.description]] <br> <i>[[order]] </i> <br> <br> <strong>Start:</strong> [[captionStart]] <br> <strong>Eind:</strong> [[captionEnd]] <br>"
fontSize="11"
bullet="ROUND"
behindColumns="false"
fillAlphas="0.75"
labelText="[[task]]"
labelPosition="MIDDLE"
bulletSize="12"
bulletBorderAlpha="255"
bulletColor="BLACK"
bulletBorderThickness="6"
showBulletsAt="HIGH"
useLineColorForBulletBorder="true"
/>
<chart:valueAxis id="axis1"
maximum="4"
minimum="1"
type="DATE"
position="TOP"
includeAllValues="true"
labelsEnabled="true"
labelRotation="90"
boldLabels="true"
/>
<chart:chartCursor cursorAlpha="0.3"
cursorPosition="MIDDLE"
fullWidth="true"
valueLineAlpha="0.5"
valueBalloonsEnabled="false"
valueLineBalloonEnabled="true"
valueLineEnabled="true"
selectWithoutZooming="true"
valueZoomable="false"
/>
</chart:ganttChart>
</vbox>
</layout>
</window>
Java code:
@UiController("gantttest_Employee.browsePlanning")
@UiDescriptor("planning.xml")
@LookupComponent("employeesTable")
@LoadDataBeforeShow
public class Planning extends StandardLookup<Employee> {
@Inject
private GanttChart ganttChart1;
@Inject
private DateField<Date> dateField;
@Inject
private Screens screens;
@Inject
private DataManager dataManager;
@Inject
private Notifications notifications;
@Inject
private CollectionLoader<Employee> employeesDl;
@Inject
private CollectionContainer<Employee> employeesDc;
@Inject
private Dialogs dialogs;
//******INITIATIE VAN SCHERMEN******//
//Deze code wordt uitgevoerd bij initialisering van het scherm
@Subscribe
private void onInit(InitEvent event) {
//Listeners die bij wijzigingen van het dateField, de closest maandag berekenen en de grafiek aanpassen.
dateField.addValueChangeListener(dateValueChangeEvent -> ganttChart1.setStartDate(calculateStartDate(dateField.getValue())));
dateField.addValueChangeListener(dateValueChangeEvent -> ganttChart1.repaint());
//Listeners die luisteren naar klik acties in de grafiek. Een voor linkermuisknop (taak openen en aanpassen) en een voor rechtermuisknop (taak verwijderen)
ganttChart1.addGraphItemClickListener(graphItemClickEvent -> showScreen(graphItemClickEvent.getEntity()));
ganttChart1.addGraphItemRightClickListener(graphItemClickEvent -> deleteEntity(graphItemClickEvent.getEntity()));
}
//Voer deze code uit op het moment dat alle onderdelen van het scherm geladen zijn.
@Subscribe
private void onAfterShow(AfterShowEvent event) {
//Zet datum op datum van vandaag
Date date = new Date();
//Calculeer de dichtbijzijnste maandag
ganttChart1.setStartDate(calculateStartDate(date));
//Tel het aantal medewerkers en calculeer de hoogte van de GANTT op basis van dit
setGanttLength();
//Notificatie met instructies
notifications.create(Notifications.NotificationType.TRAY).withCaption("Klik met linkermuisknop op taken om deze te openen. Gebruik rechtermuisknop om taken te verwijderen!").show();
}
//******CALCULATIES******//
//Functie die de closest maandag opzoekt
private Date calculateStartDate(Date date) {
//Als er geen datum aangereikt wordt, gebruik de datum van vandaag
if (date == null) {
date = new Date();
}
//Zet de datum om naar een instant (lang getal) en haal er precies 1 dag aan seconden af (dit is omdat de grafiek altijd een week naar voren toe stond)
Instant instant = date.toInstant().minusSeconds(604800);
//Zet de instant weer om naar een datum
Date dateConverted = Date.from(instant);
//Haal de dag van de week op via de funcie dayOfWeek()
Integer day = dayOfWeek(date);
Calendar calendar = Calendar.getInstance();
calendar.setTime(dateConverted);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
Date datec = calendar.getTime();
//Zoek aan de hand van if/else statements op welke dag van de week de datum valt. En stel aan de hand van seconden bij zodat de begindatum van de GANTT chart altijd op maandag is.
if (day == Calendar.MONDAY) {
return dateConverted;
}
else if (day == Calendar.TUESDAY) {
Instant i = datec.toInstant().minusSeconds(86400);
return Date.from(i);
}
else if (day == Calendar.WEDNESDAY) {
Instant i = datec.toInstant().minusSeconds(172800);
return Date.from(i);
}
else if (day == Calendar.THURSDAY) {
Instant i = datec.toInstant().minusSeconds(259200);
return Date.from(i);
}
else if (day == Calendar.FRIDAY) {
Instant i = datec.toInstant().minusSeconds(345600);
return Date.from(i);
}
else if (day == Calendar.SATURDAY) {
Instant i = datec.toInstant().minusSeconds(432000);
return Date.from(i);
}
else if (day == Calendar.SUNDAY) {
Instant i = datec.toInstant().minusSeconds(518400);
return Date.from(i);
}
//Indien geen van de condities klopt, geef dan een foutmelding
throw new IllegalArgumentException("No day of the week!");
}
//Function die de dag van de week opzoekt.
private Integer dayOfWeek(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal.get (Calendar.DAY_OF_WEEK);
}
//Wanneer er met linkermuisknop op een scherm gedrukt wordt, dan wordt deze actie aangeroepen. Aan de hand van de entityID wordt het desbetreffende scherm van de taak opgezocht.
private void showScreen(Entity id) {
//Maak een nieuwe instance van het task-edit scherm
EditorScreen screen = screens.create(TaskEdit.class);
//Zet de waardes van de instance op de waardes die vanuit de klikactie komt
screen.setEntityToEdit(id);
//Voeg een evenement toe die ervoor zorgt dat de GANTT chart opnieuw geladen wordt op het moment dat het edit scherm gesloten wordt.
((TaskEdit) screen).addAfterCloseListener(afterCloseEvent -> reloadData());
//Laat het scherm zien
((TaskEdit) screen).show();
}
//Wanneer er met rechtermuisknop geklikt wordt, voer deze functie dan uit. Aan de hand van entityID wordt de task waar op gedrukt wordt, verwijderd.
private void deleteEntity(Entity id) {
//Maak een dialoog scherm en vraag om confirmatie van verwijderen
dialogs.createOptionDialog()
.withCaption("Verwijderen van taak!")
.withMessage("Weet je zeker dat je deze taak wil verwijderen?")
.withActions(
//Actie voor het verwijderen van het scherm
new DialogAction(DialogAction.Type.YES, Action.Status.PRIMARY).withHandler(e -> {
//Verwijder de task met overeenkomende id
dataManager.remove(id);
notifications.create().withCaption("Verwijderd!").withDescription("De taak is verwijderd.").show();
//Laad de datasource opnieuw zodat wijzigingen zichtbaar worden
employeesDl.load();
}),
//Actie voor het annuleren en niets doen
new DialogAction(DialogAction.Type.NO)
)
.show();
}
//Bereken en stel de hoogte van de GANTT in.
private void setGanttLength() {
//Variabeles om op te tellen
Integer c = 0;
Integer cn = 0;
//Loop door alle medewerkers in het systeem
for (Employee employee : employeesDc.getItems()) {
//Voor elke medewerker, tel 1 op
cn = c + 1;
c = cn;
}
//Doe het aantal medewerkers keer 25 (elke medewerker heeft 25 pixels nodig om weer te geven)
Integer height = c * 25;
String heightString = height.toString();
//Stel de hoogte van de GANTT in
ganttChart1.setHeight(heightString);
}
//Functie die alle data herlaad
private void reloadData() {
employeesDl.load();
ganttChart1.repaint();
}
//******BUTTONS******//
//Functie die aangeroepen wordt bij het indrukken van de volgende week button
public void onNextClick() {
Date start = ganttChart1.getStartDate();
Instant instant = start.toInstant().plusSeconds(604800);
Date added = Date.from(instant);
ganttChart1.setStartDate(added) ;
ganttChart1.repaint();
}
//Functie die aangeroepen wordt bij het indrukken van de vorige week button
public void onBackClick() {
Date start = ganttChart1.getStartDate();
Instant instant = start.toInstant().minusSeconds(604800);
Date added = Date.from(instant);
ganttChart1.setStartDate(added) ;
ganttChart1.repaint();
}
//Functie die aangeroepen wordt bij het indrukken van de refresh button
public void onRefreshButtonClick() {
reloadData();
}
//Functie die aangeroepen wordt bij het indrukken van de reset button
public void onResetButtonClick() {
dateField.clear();
ganttChart1.setStartDate(calculateStartDate(dateField.getValue()));
ganttChart1.repaint();
}
//Functie die aangeroepen wordt bij het indrukken van de nieuwe taak button
public void onNewTaskButtonClick() {
//Zet variabele als een task-edit scherm.
EditorScreen screen = screens.create(TaskEdit.class);
//Zet de data in het scherm op een nieuwe instance van de taak
screen.setEntityToEdit(new Task());
((TaskEdit) screen).addAfterCloseListener(afterCloseEvent -> reloadData());
//Laat het scherm zien
((TaskEdit) screen).show();
}
//Functie die aangeroepen wordt bij het indrukken van de taak voor iedereen button
public void onButton_2Click() {
//Zet variabele als een task-edit scherm.
EditorScreen screen = screens.create(TaskEditForAll.class);
//Zet de data in het scherm op een nieuwe instance van de taak
screen.setEntityToEdit(new Task());
((TaskEditForAll) screen).addAfterCloseListener(afterCloseEvent -> reloadData());
//Laat het scherm zien
((TaskEditForAll) screen).show();
}
}