Override Kanban board design - HTML, CSS

Hi,

I need some help regarding overriding default kanban view board and cards design. I have already tried copying the kanban folder from frappe/public/js but to my custom app public/js folder but to no avail. Any changes, I made in the overrided files just don’t work at all.

The changes I specifically need are removing the + button from each column and cards.

Any help would be highly appreciated.

Thanks!

Hi, you no need copy old style.

You need to add your new file into hooks.py, in your custom app:

app_include_css = [
    "/assets/my_app_name/css/kanban.css"
]

Then run:

bench build;
bench clear-cache;
bench restart;

Then check if your new file is loaded on frontend.

2 Likes

Thanks for the prompt response, @janecek.mato.

This will do for the CSS part. Can you also share, how can I change the layout design in HTML. For instance, if I want to update the card with new fields or remove add button from each column.

Hello, it is not easy change html layout. You can do this by overriding JS class “KanbanView”.

1 Like

Oh, okay. Understood. Let me give it a try.

Thank-you very much for your time and help! Stay Safe!

@janecek.mato @JatBan
could you give an easy example how overriding the js class would work?
or do you have linke where this is described? thx!

crate new js file, and add it in hooks.py:

//change title

frappe.views.KanbanView = class KanbanView extends frappe.views.KanbanView {
    before_render(){
       this.data.forEach(function (card_data) {
           card_data["title"] = "";
           card_data["title"] += "<div>"+ card_data["name"] +"</div>";
      
       });
     }
}
4 Likes

We tried to add our custom class with before and after render event but it is not working. Would you please help how we can add our custom CSS class and HTML in kanban view? Below is our code for your reference

frappe.views.KanbanView = class KanbanView extends frappe.views.KanbanView {
before_render() {
var indicators = [];
this.board.columns.forEach(function (column_data) {
indicators[column_data[“column_name”]] = column_data[“indicator”];
//console.log(column_data,indicators);
});
this.$result.find(‘.kanban-column[data-column-value]’)
.each(function() {
var col_name = $(this).data().columnValue;
$(this).addClass(indicators[col_name]);
});
//console.log(this);
}
after_render() {
var indicators = [];
this.board.columns.forEach(function (column_data) {
indicators[column_data[“column_name”]] = column_data[“indicator”];
//console.log(column_data,indicators);
});
//console.log(this.$result.find(‘.kanban-column[data-column-value]’));
this.$result.find(‘.kanban-column[data-column-value]’)
.each(function() {
var col_name = $(this).data().columnValue;
//console.log(col_name, indicators[col_name]);
$(this).addClass(indicators[col_name]);
});
//console.log(this);
}
}

For first, try to format your code here. Its hard to read. And try to explain better what you exactly need.

frappe.views.KanbanView = class KanbanView extends frappe.views.KanbanView {
        before_render() {
                var indicators = [];
                this.board.columns.forEach(function (column_data) {
                        indicators[column_data["column_name"]] = column_data["indicator"];
                        //console.log(column_data,indicators);
                });
                this.$result.find('.kanban-column[data-column-value]')
                                        .each(function() {
                                               var col_name = $(this).data().columnValue;
                                               $(this).addClass(indicators[col_name]);
                                        });
                //console.log(this);
        }
        after_render() {
                var indicators = [];
                this.board.columns.forEach(function (column_data) {
                        indicators[column_data["column_name"]] = column_data["indicator"];
                        //console.log(column_data,indicators);
                });
                //console.log(this.$result.find('.kanban-column[data-column-value]'));
                this.$result.find('.kanban-column[data-column-value]')
                                        .each(function() {
                                                var col_name = $(this).data().columnValue;
                                                //console.log(col_name, indicators[col_name]);
                                                $(this).addClass(indicators[col_name]);
                                        });
                //console.log(this);
        }
}

@janecek.mato I hope now my js code is readable.
We want to add our custom css class, once our class is added then we can write custom css for formatting kanban view.

@janecek.mato How to do that bro
I want to override this file
site.assets.frappe.js.frappe.view.kanban.kanban_board.js

please help

Answer : YES we can But not in the hooks

we have a file in frappe frappe.client.get_js

get_js() is whitelist function you can override that function like this

Note: ss_custom_erpnext = custom_app

override_whitelisted_methods = {
“frappe.client.get_js”:“ss_custom_erpnext.ss_custom_erpnext.hr.doctype.kanban_board.kanban_board.get_js”,
}

create kanban_board.py (in custom app)

indent preformatted text by 4 spaces

   @frappe.whitelist()
    def get_js(items):

‘’'Load JS code files. Will also append translations
and extend frappe._messages

:param items: JSON list of paths of the js files to be loaded.‘’’

‘’’
This is the function trigger this file location : site.assets.frappe.js.frappe.view.kanban.kanban_board.js

correct:
contentpath = ‘./assets/frappe/js/frappe/views/kanban/kanban_board.js’

overrided path:
‘./assets/ss_custom_erpnext/js/kanban_board.js’

‘’’
indent preformatted text by 4 spaces.

       items = json.loads(items)
    out = []
    for src in items:
    src = src.strip("/").split("/")

	if ".." in src or src[0] != "assets":
		frappe.throw(_("Invalid file path: {0}").format("/".join(src)))

	contentpath = os.path.join(frappe.local.sites_path, *src)

	if not contentpath == './assets/frappe/js/frappe/views/kanban/kanban_board.js':
		with open(contentpath, "r") as srcfile:
			code = frappe.utils.cstr(srcfile.read())
	else:
		contentpath = './assets/ss_custom_erpnext/js/kanban_board.js'
		with open(contentpath, "r") as srcfile:
			code = frappe.utils.cstr(srcfile.read())

	if frappe.local.lang != "en":
		messages = frappe.get_lang_dict("jsfile", contentpath)
		messages = json.dumps(messages)
		code += "\n\n$.extend(frappe._messages, {})".format(messages)

	out.append(code)

Blockquote
this will work corectly

1 Like

You can also override kanban_board.js in this way:

add this to your hooks.py:

app_include_js = [
	"/assets/ss_custom_erpnext/js/kanban_view.js",
]

Then in kanban_views.js:

frappe.provide("frappe.views");

frappe.views.KanbanView = class KanbanView extends frappe.views.KanbanView {
	get required_libs() {
		return [
			'assets/frappe/js/lib/fluxify.min.js',
			'assets/ss_custom_erpnext/js/kanban_board.js'
		];
	}
};

and then in kanban_board.js copy content from original kanban_board.js file, and change what you need

1 Like

Here I create new file name kanban_board_view_test.js @janecek.mato

I did all modification there but not working is there im missing anything please help
please help

This things should be in two separated files:

Then in kanban_views.js:

frappe.provide("frappe.views");

frappe.views.KanbanView = class KanbanView extends frappe.views.KanbanView {
	get required_libs() {
		return [
			'assets/frappe/js/lib/fluxify.min.js',
			'assets/ss_custom_erpnext/js/kanban_board.js'
		];
	}
};

And kanban_board.js:

frappe.provide("frappe.views");

(function() {

	var method_prefix = 'frappe.desk.doctype.kanban_board.kanban_board.';

	var store = fluxify.createStore({
		id: 'store',
		initialState: {
			doctype: '',
			board: {},
			card_meta: {},
			cards: [],
			columns: [],
			filters_modified: false,
			cur_list: {},
			empty_state: true
		},
    .......
    .......
    .......

Make some console logs, to know that files are loaded.

1 Like

Thsnk you so much it’s working fine

Hi sir , can you please explain me in details that how we can change the kanban board by programatically . I am new to frappe. And I am get confused that from where I should be start. I try above but it does not work. Please explain me .

check this please Override Kanban board design - HTML, CSS - #15 by Antony_Praveenkumar

why do you want to override a kanban board?