Skip to content

Attendance Calendar Fields En

Calendar Fields Configuration

In ERPNext, it’s important to effectively communicate project information to users in a visual manner, considering the time-sensitive nature of projects. Alongside the standard list and report views for projects and tasks, ERPNext offers additional views like Gantt, Kanban, and Calendar.

The Calendar view in ERPNext is a powerful tool for managing tasks and projects in a visual and intuitive manner. It offers a calendar-based representation of tasks, allowing users to easily track schedules, deadlines, and resource allocation. When accessing the Calendar view within ERPNext, you’ll see a familiar monthly calendar layout. Tasks and events are displayed as color-coded blocks within the calendar cells. This visual representation provides a quick overview of the distribution and timing of tasks across different dates.

How to configure calendar view using Frappe Framework

To configure the Calendar view using the Frappe framework, you can follow these steps (all the steps will be represented on the Attendance Calendar example):

  1. Access the Frappe framework codebase where your project is located.

  2. Locate the file that defines the Calendar view configuration. In our case it’s:

    frappe-bench/apps/hrms/hrms/hr/doctype/attendance/attendance_calendar.js

    This file is usually named *docname*_calendar.js and it’s placed in the doctype directory (If such file doesn’t exist you can create it by this name *docname*_calendar.js)

  3. Open the *docname*_calendar.js file in a text editor or integrated development environment (IDE).

    Within the file, you will find the configuration options for the Calendar view. These options allow you to customize the behavior and appearance of the Calendar view.

    frappe.views.calendar["Attendance"] = {
    options: {
    header: {
    left: "prev, title, next",
    right: "today, month, agendaWeek, agendaDay",
    },
    color_map: {
    danger: "red",
    },
    color: "greeb",
    displayEventTime: false,
    },
    field_map: {
    start: "attendance_date",
    end: "attendance_date",
    title: "employee_name",
    allDay: 1,
    }
    }
  4. Modify the configuration options based on your requirements. Some common configuration options include:

    • Date Range: You can define the default date range to be displayed initially when the Calendar view is loaded.
    • Colors and Color Mapping: You can specify custom colors for events based on certain criteria or categories. For example, you can assign a specific color to events labeled as “High Priority” or “Urgent”.
    • Event Titles and Fields: You can specify which fields to display as the event titles in the Calendar view. These fields could include the event name, assigned user, or any other relevant information.
    • Views and Navigation: You can configure the available views (e.g., monthly, weekly, daily) and navigation options (e.g., previous, next) for users to switch between different time periods.
    • Event Creation and Editing: You can define the behavior and options available when creating or editing events in the Calendar view, such as specifying required fields or enabling specific features like drag-and-drop functionality.

Save the changes to the calendar.js file.

How to add desired fields to the event table in the Calendar View

Let’s say you want to add few fields in the title of the Calendar View. You could not do it using default Frappe Framework instruments but you can create such functionality step by step.

There are two files that works with calendar view in the Frappe Framework. First file is the calendar.py that parses the *docname*_calendar.js file and returns all the fields to display in the event. Second file is the calendar.js file that collects the fields from the calendar.py file and converts them to the HTML format.

We can create the other_field list that would contain the fields which we need to be displayed in the event.

  1. Go to the get_events function in the calendar.py located by this path:

    frappe-bench/apps/frappe/frappe/desk/calendar.py
  2. In the get_events parameters add the other_field parameter and assign it the None value

  3. Then you need to parse the attendance_calendar.js to get the values from it. Type the following code after where the field_map and fields variables were declared:

    other_fields = frappe.parse_json(other_fields)

    frappe.parse_json(other_fields) function parses the other_fields list of the *docname*_calendar.js file and returns the result to the other_fields variable

  4. Now we need the fields from the other_fields variable to get to the return list. So we need to add them to the fields variable that will be returned by the get_events function. Type the following code after the if not fields statement:

    if other_fields:
    [fields.append(item) for item in list(other_fields)]

    If the other_fields list is not empty than it’s values append to the fields list

    The get_events function should look like this:

    def get_events(doctype, start, end, field_map, filters=None, fields=None, other_fields=None):
    field_map = frappe._dict(json.loads(field_map))
    fields = frappe.parse_json(fields)
    other_fields = frappe.parse_json(other_fields)
    doc_meta = frappe.get_meta(doctype)
    for d in doc_meta.fields:
    if d.fieldtype == "Color":
    field_map.update({"color": d.fieldname})
    filters = json.loads(filters) if filters else []
    if not fields:
    fields = [field_map.start, field_map.end, field_map.title, "name"]
    if other_fields:
    [fields.append(item) for item in list(other_fields)]
    if field_map.color:
    fields.append(field_map.color)
    start_date = "ifnull(%s, '0001-01-01 00:00:00')" % field_map.start
    end_date = "ifnull(%s, '2199-12-31 00:00:00')" % field_map.end
    filters += [
    [doctype, start_date, "<=", end],
    [doctype, end_date, ">=", start],
    ]
    fields = list({field for field in fields if field})
    return frappe.get_list(doctype, fields=fields, filters=filters)
  5. Go to the get_events function in the calendar.py located by this path:

    frappe-bench/apps/frappe/frappe/public/js/frappe/views/calendar/calendar.js
  6. In the get_args method of the Calendar class add a new field called other_fields to the args dictionary so the method would look like this:

    get_args(start, end) {
    var args = {
    doctype: this.doctype,
    start: this.get_system_datetime(start),
    end: this.get_system_datetime(end),
    fields: this.fields,
    filters: this.list_view.filter_area.get(),
    field_map: this.field_map,
    other_fields: this.other_fields
    };
    return args;
  7. Now we need to add the following code to the end of the prepare_events method:

    if (this.other_fields) {
    this.other_fields.forEach((item) => {
    if (item in d) {
    if (item == "leave_type" && d[item] === null) {
    return;
    }
    d.title += frappe.utils.html2text(d[item] + "\n")
    }
    })
    }
    • values variable contains all the values of the d object
    • if the other_fields isn’t empty each value of it is written to the event title d.title

    The prepare_events method should look like this:

    prepare_events(events) {
    var me = this;
    return (events || []).map((d) => {
    d.id = d.name;
    d.editable = frappe.model.can_write(d.doctype || me.doctype);
    // do not allow submitted/cancelled events to be moved / extended
    if (d.docstatus && d.docstatus > 0) {
    d.editable = false;
    }
    $.each(me.field_map, function (target, source) {
    d[target] = d[source];
    });
    if (!me.field_map.allDay) d.allDay = 1;
    if (!me.field_map.convertToUserTz) d.convertToUserTz = 1;
    // convert to user tz
    if (d.convertToUserTz) {
    d.start = frappe.datetime.convert_to_user_tz(d.start);
    d.end = frappe.datetime.convert_to_user_tz(d.end);
    }
    // show event on single day if start or end date is invalid
    if (!frappe.datetime.validate(d.start) && d.end) {
    d.start = frappe.datetime.add_days(d.end, -1);
    }
    if (d.start && !frappe.datetime.validate(d.end)) {
    d.end = frappe.datetime.add_days(d.start, 1);
    }
    me.fix_end_date_for_event_render(d);
    me.prepare_colors(d);
    d.title= frappe.utils.html2text(d.title + "\n");
    if (this.other_fields) {
    this.other_fields.forEach((item) => {
    if (item in d) {
    if (item == "leave_type" && d[item] === null) {
    return;
    }
    d.title += frappe.utils.html2text(d[item] + "\n")
    }
    })
    }
    return d;
    });
  8. Now we can add the other_fields list to the attendance_calendar.js and indicate the fields we need to be displayed in the event:

    other_fields: [
    "status",
    "leave_type"
    ]

    attendance_calendar.js should look like this:

    frappe.views.calendar["Attendance"] = {
    options: {
    header: {
    left: "prev, title, next",
    right: "today, month, agendaWeek, agendaDay",
    },
    color_map: {
    danger: "red",
    },
    color: "greeb",
    displayEventTime: false,
    },
    field_map: {
    start: "attendance_date",
    end: "attendance_date",
    title: "employee_name",
    allDay: 1,
    },
    other_fields: [
    "status",
    "leave_type"
    ],
    }

Now we can see that events have a contents of the status and leave_type fields