<commit_before>frappe.provide('frappe.views');

frappe.views.BaseList = class BaseList {
	constructor(opts) {
		Object.assign(this, opts);
	}

	show() {
		frappe.run_serially([
			() => this.init(),
			() => this.before_refresh(),
			() => this.refresh()
		]);
	}

	init() {

		if (this.init_promise) return this.init_promise;

		let tasks = [
			this.setup_defaults,
			this.set_stats,
			this.setup_fields,
			// make view
			this.setup_page,
			this.setup_side_bar,
			this.setup_main_section,
			this.setup_view,
		].map(fn => fn.bind(this));

		this.init_promise = frappe.run_serially(tasks);
		return this.init_promise;
	}

	setup_defaults() {
		this.page_name = frappe.get_route_str();
		this.page_title = this.page_title || __(this.doctype);
		this.meta = frappe.get_meta(this.doctype);
		this.settings = frappe.listview_settings[this.doctype] || {};
		this.user_settings = frappe.get_user_settings(this.doctype);

		this.start = 0;
		this.page_length = 20;
		this.data = [];
		this.method = 'frappe.desk.reportview.get';

		this.can_create = frappe.model.can_create(this.doctype);
		this.can_write = frappe.model.can_write(this.doctype);

		this.fields = [];
		this.filters = [];
		this.sort_by = 'modified';
		this.sort_order = 'desc';

		// Setup buttons
		this.primary_action = null;
		this.secondary_action = {
			label: __('Refresh'),
			action: () => this.refresh()
		};

		this.menu_items = [{
			label: __('Refresh'),
			action: () => this.refresh(),
			class: 'visible-xs'
		}];
	}

	setup_fields() {
		this.set_fields();
		this.build_fields();
	}

	set_fields() {
		let fields = [].concat(
			frappe.model.std_fields_list,
			this.meta.title_field
		);

		fields.forEach(f => this._add_field(f));
	}

	get_fields_in_list_view() {
		return this.meta.fields.filter(df => {
			return frappe.model.is_value_type(df.fieldtype) && (
				df.in_list_view
				&& frappe.perm.has_perm(this.doctype, df.permlevel, 'read')
			) || (
				df.fieldtype === 'Currency'
				&& df.options
				&& !df.options.includes(':')
			) || (
				df.fieldname === 'status'
			);
		});
	}

	build_fields() {
		// fill in missing doctype
		this.fields = this.fields.map(f => {
			if (typeof f === 'string') {
				f = [f, this.doctype];
			}
			return f;
		});
		// remove null or undefined values
		this.fields = this.fields.filter(Boolean);
		//de-duplicate
		this.fields = this.fields.uniqBy(f => f[0] + f[1]);
	}

	_add_field(fieldname) {
		if (!fieldname) return;
		let doctype = this.doctype;

		if (typeof fieldname === 'object') {
			// df is passed
			const df = fieldname;
			fieldname = df.fieldname;
			doctype = df.parent;
		}

		const is_valid_field = frappe.model.std_fields_list.includes(fieldname)
			|| frappe.meta.has_field(doctype, fieldname)
			|| fieldname === '_seen';

		if (!is_valid_field) {
			return;
		}

		this.fields.push([fieldname, doctype]);
	}

	set_stats() {
		this.stats = ['_user_tags'];
		// add workflow field (as priority)
		this.workflow_state_fieldname = frappe.workflow.get_state_fieldname(this.doctype);
		if (this.workflow_state_fieldname) {
			if (!frappe.workflow.workflows[this.doctype]['override_status']) {
				this._add_field(this.workflow_state_fieldname);
			}
			this.stats.push(this.workflow_state_fieldname);
		}
	}

	setup_page() {
		this.page = this.parent.page;
		this.$page = $(this.parent);
		this.page.page_form.removeClass('row').addClass('flex');
		this.setup_page_head();
	}

	setup_page_head() {
		this.set_title();
		this.set_menu_items();
		this.set_breadcrumbs();
	}

	set_title() {
		this.page.set_title(this.page_title);
	}

	set_menu_items() {
		const $secondary_action = this.page.set_secondary_action(
			this.secondary_action.label,
			this.secondary_action.action,
			this.secondary_action.icon
		);
		if (!this.secondary_action.icon) {
			$secondary_action.addClass('hidden-xs');
		} else {
			$secondary_action.addClass('visible-xs');
		}

		this.menu_items.map(item => {
			if (item.condition && item.condition() === false) {
				return;
			}
			const $item = this.page.add_menu_item(item.label, item.action, item.standard, item.shortcut);
			if (item.class) {
				$item && $item.addClass(item.class);
			}
		});
	}

	set_breadcrumbs() {
		frappe.breadcrumbs.add(this.meta.module, this.doctype);
	}

	setup_side_bar() {
		this.list_sidebar = new frappe.views.ListSidebar({
			doctype: this.doctype,
			stats: this.stats,
			parent: this.$page.find('.layout-side-section'),
			// set_filter: this.set_filter.bind(this),
			page: this.page,
			list_view: this
		});
	}

	toggle_side_bar() {
		let show_sidebar = JSON.parse(localStorage.show_sidebar || 'true');
		show_sidebar = !show_sidebar;
		localStorage.show_sidebar = show_sidebar;
		this.show_or_hide_sidebar();
	}

	show_or_hide_sidebar() {
		let show_sidebar = JSON.parse(localStorage.show_sidebar || 'true');
		$(document.body).toggleClass('no-list-sidebar', !show_sidebar);
	}

	setup_main_section() {
		return frappe.run_serially([
			this.setup_list_wrapper,
			this.show_or_hide_sidebar,
			this.setup_filter_area,
			this.setup_sort_selector,
			this.setup_result_area,
			this.setup_no_result_area,
			this.setup_freeze_area,
			this.setup_paging_area
		].map(fn => fn.bind(this)));
	}

	setup_list_wrapper() {
		this.$frappe_list = $('<div class="frappe-list">').appendTo(this.page.main);
	}

	setup_filter_area() {
		this.filter_area = new FilterArea(this);

		if (this.filters.length > 0) {
			return this.filter_area.set(this.filters);
		}
	}

	setup_sort_selector() {
		this.sort_selector = new frappe.ui.SortSelector({
			parent: this.filter_area.$filter_list_wrapper,
			doctype: this.doctype,
			args: {
				sort_by: this.sort_by,
				sort_order: this.sort_order
			},
			onchange: this.on_sort_change.bind(this)
		});
	}

	on_sort_change() {
		this.refresh();
	}

	setup_result_area() {
		this.$result = $(`<div class="result">`);
		this.$frappe_list.append(this.$result);
	}

	setup_no_result_area() {
		this.$no_result = $(`
			<div class="no-result text-muted flex justify-center align-center">
				${this.get_no_result_message()}
			</div>
		`).hide();<commit_msg>fix(base_list): Verify that filters are not undefined/empty. #9468 (#9487)<commit_after>frappe.provide('frappe.views');

frappe.views.BaseList = class BaseList {
	constructor(opts) {
		Object.assign(this, opts);
	}

	show() {
		frappe.run_serially([
			() => this.init(),
			() => this.before_refresh(),
			() => this.refresh()
		]);
	}

	init() {

		if (this.init_promise) return this.init_promise;

		let tasks = [
			this.setup_defaults,
			this.set_stats,
			this.setup_fields,
			// make view
			this.setup_page,
			this.setup_side_bar,
			this.setup_main_section,
			this.setup_view,
		].map(fn => fn.bind(this));

		this.init_promise = frappe.run_serially(tasks);
		return this.init_promise;
	}

	setup_defaults() {
		this.page_name = frappe.get_route_str();
		this.page_title = this.page_title || __(this.doctype);
		this.meta = frappe.get_meta(this.doctype);
		this.settings = frappe.listview_settings[this.doctype] || {};
		this.user_settings = frappe.get_user_settings(this.doctype);

		this.start = 0;
		this.page_length = 20;
		this.data = [];
		this.method = 'frappe.desk.reportview.get';

		this.can_create = frappe.model.can_create(this.doctype);
		this.can_write = frappe.model.can_write(this.doctype);

		this.fields = [];
		this.filters = [];
		this.sort_by = 'modified';
		this.sort_order = 'desc';

		// Setup buttons
		this.primary_action = null;
		this.secondary_action = {
			label: __('Refresh'),
			action: () => this.refresh()
		};

		this.menu_items = [{
			label: __('Refresh'),
			action: () => this.refresh(),
			class: 'visible-xs'
		}];
	}

	setup_fields() {
		this.set_fields();
		this.build_fields();
	}

	set_fields() {
		let fields = [].concat(
			frappe.model.std_fields_list,
			this.meta.title_field
		);

		fields.forEach(f => this._add_field(f));
	}

	get_fields_in_list_view() {
		return this.meta.fields.filter(df => {
			return frappe.model.is_value_type(df.fieldtype) && (
				df.in_list_view
				&& frappe.perm.has_perm(this.doctype, df.permlevel, 'read')
			) || (
				df.fieldtype === 'Currency'
				&& df.options
				&& !df.options.includes(':')
			) || (
				df.fieldname === 'status'
			);
		});
	}

	build_fields() {
		// fill in missing doctype
		this.fields = this.fields.map(f => {
			if (typeof f === 'string') {
				f = [f, this.doctype];
			}
			return f;
		});
		// remove null or undefined values
		this.fields = this.fields.filter(Boolean);
		//de-duplicate
		this.fields = this.fields.uniqBy(f => f[0] + f[1]);
	}

	_add_field(fieldname) {
		if (!fieldname) return;
		let doctype = this.doctype;

		if (typeof fieldname === 'object') {
			// df is passed
			const df = fieldname;
			fieldname = df.fieldname;
			doctype = df.parent;
		}

		const is_valid_field = frappe.model.std_fields_list.includes(fieldname)
			|| frappe.meta.has_field(doctype, fieldname)
			|| fieldname === '_seen';

		if (!is_valid_field) {
			return;
		}

		this.fields.push([fieldname, doctype]);
	}

	set_stats() {
		this.stats = ['_user_tags'];
		// add workflow field (as priority)
		this.workflow_state_fieldname = frappe.workflow.get_state_fieldname(this.doctype);
		if (this.workflow_state_fieldname) {
			if (!frappe.workflow.workflows[this.doctype]['override_status']) {
				this._add_field(this.workflow_state_fieldname);
			}
			this.stats.push(this.workflow_state_fieldname);
		}
	}

	setup_page() {
		this.page = this.parent.page;
		this.$page = $(this.parent);
		this.page.page_form.removeClass('row').addClass('flex');
		this.setup_page_head();
	}

	setup_page_head() {
		this.set_title();
		this.set_menu_items();
		this.set_breadcrumbs();
	}

	set_title() {
		this.page.set_title(this.page_title);
	}

	set_menu_items() {
		const $secondary_action = this.page.set_secondary_action(
			this.secondary_action.label,
			this.secondary_action.action,
			this.secondary_action.icon
		);
		if (!this.secondary_action.icon) {
			$secondary_action.addClass('hidden-xs');
		} else {
			$secondary_action.addClass('visible-xs');
		}

		this.menu_items.map(item => {
			if (item.condition && item.condition() === false) {
				return;
			}
			const $item = this.page.add_menu_item(item.label, item.action, item.standard, item.shortcut);
			if (item.class) {
				$item && $item.addClass(item.class);
			}
		});
	}

	set_breadcrumbs() {
		frappe.breadcrumbs.add(this.meta.module, this.doctype);
	}

	setup_side_bar() {
		this.list_sidebar = new frappe.views.ListSidebar({
			doctype: this.doctype,
			stats: this.stats,
			parent: this.$page.find('.layout-side-section'),
			// set_filter: this.set_filter.bind(this),
			page: this.page,
			list_view: this
		});
	}

	toggle_side_bar() {
		let show_sidebar = JSON.parse(localStorage.show_sidebar || 'true');
		show_sidebar = !show_sidebar;
		localStorage.show_sidebar = show_sidebar;
		this.show_or_hide_sidebar();
	}

	show_or_hide_sidebar() {
		let show_sidebar = JSON.parse(localStorage.show_sidebar || 'true');
		$(document.body).toggleClass('no-list-sidebar', !show_sidebar);
	}

	setup_main_section() {
		return frappe.run_serially([
			this.setup_list_wrapper,
			this.show_or_hide_sidebar,
			this.setup_filter_area,
			this.setup_sort_selector,
			this.setup_result_area,
			this.setup_no_result_area,
			this.setup_freeze_area,
			this.setup_paging_area
		].map(fn => fn.bind(this)));
	}

	setup_list_wrapper() {
		this.$frappe_list = $('<div class="frappe-list">').appendTo(this.page.main);
	}

	setup_filter_area() {
		this.filter_area = new FilterArea(this);

		if (this.filters && this.filters.length > 0) {
			return this.filter_area.set(this.filters);
		}
	}

	setup_sort_selector() {
		this.sort_selector = new frappe.ui.SortSelector({
			parent: this.filter_area.$filter_list_wrapper,
			doctype: this.doctype,
			args: {
				sort_by: this.sort_by,
				sort_order: this.sort_order
			},
			onchange: this.on_sort_change.bind(this)
		});
	}

	on_sort_change() {
		this.refresh();
	}

	setup_result_area() {
		this.$result = $(`<div class="result">`);
		this.$frappe_list.append(this.$result);
	}

	setup_no_result_area() {
		this.$no_result = $(`
			<div class="no-result text-muted flex justify-center align-center">
				${this.get_no_result_message()}
			</div>
		`).hide();
{'fraction_non_alphanumeric': 0.1601171588967537, 'fraction_numerical': 0.0016272068993572533, 'mean_word_length': 3.7349768875192604, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4216795', 'n_tokens_mistral': 5201, 'n_tokens_neox': 4599, 'n_words': 644}