<commit_before>package omnitool::tool::html_sender;
# package to prep/deliver the 'mini-skeleton' of the tool view; includes the primary layout divs
# and the search/display controls.  The tool controls are what needs the most work.
# We are going to opt to do much of the work within Perl for easy re-use, rather than
# bury logic in the template

# should be 1.0, but everything starts with six up in here ;)
$omnitool::tools::html_sender::VERSION = '6.0';

# time to grow up
use strict;

# start our method to prepare/process the tool's skeleton divs
sub send_html {
	my $self = shift;

	# this will be filled if they called the 'send_tool_controls' uri
	my ($template) = @_;
	# default use case is the whole tools area
	$template ||= 'tool_area_skeleton.tt'; 

	# allow for a hook prior to the tools_controls, namely to augment $self->{attributes}{description}
	if ($self->can('pre_tool_controls')) {
		$self->pre_tool_controls();
	}

	# use the method below to get ready for the tools_controls area
	$self->tool_controls();

	# we will rely on $OTHOME/code/omnitool/static_files/tool_area_skeleton.tt
	my $tool_html = $self->{belt}->template_process(
		'template_file' => $template,
		'template_vars' => $self,
	);

	# send back; dispatcher.pm will throw to mr_zebra(), who will send out as html
	return $tool_html;
}

# companion method to send only the tools_controls HTML, i.e. for an advanced search submit
sub send_tool_controls {
	my $self = shift;

	# don't repeat yourself ;->
	return $self->send_html('tool_controls.tt');
}

# subroutine to send the breadcrumbs information
sub send_breadcrumbs {
	my $self = shift;

	# use another method to find our breadcrumbs, which will be our path of
	# tools from here to the 'top' tool. builds $self->{breadcrumbs}[]
	# allow for a hook too:
	if ($self->can('special_breadcrumbs')) {
		$self->special_breadcrumbs($self->{display_options}{altcode});
		# that'll be in a specialized class, so won't need 'tool_datacode'
	# our normal way; a little involved; see notes below
	} else {
		$self->find_breadcrumbs($self->{tool_datacode},$self->{display_options}{altcode});
	}

	# the breadcrumbs template needs the uri_path_base for the bookmarks links
	# $self->{bc_store}{bookmark_link} = '/tools/'.$self->{attributes}{uri_path_base}.'/bookmarks';

	# include the 'tool_and_instance'
	$self->{bc_store}{tool_and_instance} = $self->{tool_and_instance};

	# and the app-wide search JS function / name and app-wide quick-start tool, if they are filled
	foreach my $key ('appwide_search_function','appwide_search_name','appwide_quickstart_tool_uri') {
		$self->{bc_store}{$key} = $self->{luggage}{session}->{app_instance_info}{$key};
	}

	# ship them out
	return $self->{bc_store};

}

# method to prepare for the 'tool_controls' portion of the our tool_area_skeleton.tt template
# we are not building this area via jemplate; that is for the tool_display_area
sub tool_controls {
	my $self = shift;

	my ($filter_menu, $menu_cnt, $mode_view, $tk);

	# determine the child-actions which are labeled 'quick actions'
	foreach $tk (@{ $self->{attributes}{child_tools_keys} }) {
		push(@{ $self->{quick_actions} },$tk) if $self->{luggage}{session}{tools}{$tk}{link_type} eq 'Quick Actions';
	}

	# prepare the mode/view options
	# start with the tool mode views
	foreach $mode_view ( @{ $self->{tool_configs_keys}{tool_mode_configs} }) {
		# just need to set the name properly, if it's custom
		if ($self->{tool_configs}{tool_mode_configs}{$mode_view}{custom_type_name}) {
			$self->{tool_configs}{tool_mode_configs}{$mode_view}{mode_type} = $self->{tool_configs}{tool_mode_configs}{$mode_view}{custom_type_name};
		}

		# the uri to load the view
		$self->{tool_configs}{tool_mode_configs}{$mode_view}{uri} = $self->{my_base_uri}.'/tool_mode'.$mode_view;
	}

	# now the quick-search menus; limit to two
	$menu_cnt = 0;
	foreach $filter_menu ( @{ $self->{tool_configs_keys}{tool_filter_menus} }) {

		# just the quick search menus, which must be single-selects
		# limit to four quick-search menus
		next if $self->{quick_search_menus}[3] || $self->{tool_configs}{tool_filter_menus}{$filter_menu}{display_area} ne 'Quick Search' ||
			$self->{tool_configs}{tool_filter_menus}{$filter_menu}{menu_type} !~ /Single-Select|Month Chooser/;

		# add this filter menu to our 1-2 item list for the template processor
		push(@{ $self->{quick_search_menus} },$filter_menu);

	}

	# use method below to fetch the search options
	$self->build_filter_menu_options($self->{quick_search_menus});

	# tell the template if there is just one search menu
	if ($self->{quick_search_menus}[0] && !$self->{quick_search_menus}[1]) {
		$self->{one_search_menu} = 1;
	}

	# if this is a searching tool, we shall provide a text-search box
	if ($self->{attributes}{tool_type} eq 'Search - Screen') {
		$self->{has_search_box} = 1;
	}

	# if there are additional search menus, we shall provide the advanced search option
	if (scalar( @{ $self->{tool_configs_keys}{tool_filter_menus} } ) > scalar( @{ $self->{quick_search_menus} } )) {
		$self->{has_advanced_search} = 1;
	}
}

# method to generate the json for the advanced sort form jemplate modal
# this allows the user to sort their results by multiple columns/directions
sub advanced_sort_form {
	my $self = shift;

	# start the web form
	$self->{json_results}{form} = {
		'target_url' => $self->{my_json_uri},
		'title' => 'Advanced Sort Form',
		'submit_button_text' => 'Submit Advanced Sort Options',
		'hidden_fields' => {
			'client_connection_id' => $self->{client_connection_id},
		},
	};

	# call method from center_stage.pm to prep the field keys / names
	$self->get_omniclass_object( 'dt' => $self->{target_datatype} );
	$self->get_mode_config();
	$self->prep_fields_to_include();

	my (@field_keys, $num, $field);

	# info on the fields
	$self->{json_results}{form}{included_records_fields} = $self->{included_records_fields};
	$self->{json_results}{form}{included_field_names} = $self->{included_field_names};

	# this form is going to a right bit different.  We just need to infom the 'advanced_sort_form'
	# jemplate of how many fields we have to sort, what the field names are, and what our presets might be

	for ($num = 1; $num < 5; $num++) {
		$self->{json_results}{form}{fields}{$num} = {
			'order_number' => $num,
			'preset' => $self->{display_options}{'advanced_sort_'.$num}
		};
		push (@{ $self->{json_results}{form}{field_keys} }, $num);
	}

	# send it out
	return $self->{json_results};
}

# method to generate the form json for the advanced search form jemplate modal.
# includes all filter menus
# FYI: The template for these forms is in system_modals.tt
sub advanced_search_form {
	my $self = shift;

	my ($num, $trigger_menu, $filter_menu, $value_key, $tool_filter_menu, $form_field_type, $keyword_key, $keyword_operator_key, $start_key, $end_key, $opt);

	# use method below to fetch the search options for ALL menus:
	$self->build_filter_menu_options( $self->{tool_configs_keys}{tool_filter_menus} );

	# start the web form
	$self->{json_results}{form} = {
		'target_url' => $self->{my_json_uri},
		'title' => 'Advanced Search Form',
		# 'instructions' => 'To clear keywords or date ranges, simply delete text fields.',
		'submit_button_text' => 'Submit Advanced Search Parameters',
		'hidden_fields' => {
			'client_connection_id' => $self->{client_connection_id},
		},
	};

	# first the quick-search keyword
	$num = 1;
	$self->{json_results}{form}{fields}{$num} = {
		'title' => 'Wide Keyword',
		'name' => 'quick_keyword',
		'both_columns' => 1,
		'preset' => $self->{display_options}{'quick_keyword'},
		'field_type' => 'short_text',
		'instructions' => 'Perl-style regular expressions OK',
	};
	push (@{ $self->{json_results}{form}{field_keys} }, $num);

	# now add the menus to the form hash
	$num = 2;
	foreach $filter_menu (@{ $self->{tool_configs_keys}{tool_filter_menus} }) {

		$value_key = 'menu_'.$filter_menu; # the value / display_options key for the menu

		# some sanity here to access this menu
		$tool_filter_menu = $self->{tool_configs}{tool_filter_menus}{$filter_menu};

		# figure out the default / current option
		$$tool_filter_menu{default_option_value} ||= 'Any'; # 'Any' is our default default option
		if (!$self->{display_options}{$value_key} && $$tool_filter_menu{default_option_value}) {
			$self->{display_options}{$value_key} = $$tool_filter_menu{default_option_value};
			# this will get saved by display_options_manager() when we are done
		}

		# field type is based off 'menu type' option
		# seems like the 'chosen' menus don't work too well, so let's go with plain for now
		if ($$tool_filter_menu{menu_type} eq 'Single-Select') {
			$form_field_type = 'single_select_plain';
		} elsif ($$tool_filter_menu{menu_type} eq 'Multi-Select') {
			$form_field_type = 'advanced_search_multi_select';

		} elsif ($$tool_filter_menu{menu_type} eq 'Date Range') {
			$form_field_type = 'date_range';

		# this will be a special field type for advanced searches<commit_msg>Chosen selects in advanced search<commit_after>package omnitool::tool::html_sender;
# package to prep/deliver the 'mini-skeleton' of the tool view; includes the primary layout divs
# and the search/display controls.  The tool controls are what needs the most work.
# We are going to opt to do much of the work within Perl for easy re-use, rather than
# bury logic in the template

# should be 1.0, but everything starts with six up in here ;)
$omnitool::tools::html_sender::VERSION = '6.0';

# time to grow up
use strict;

# start our method to prepare/process the tool's skeleton divs
sub send_html {
	my $self = shift;

	# this will be filled if they called the 'send_tool_controls' uri
	my ($template) = @_;
	# default use case is the whole tools area
	$template ||= 'tool_area_skeleton.tt'; 

	# allow for a hook prior to the tools_controls, namely to augment $self->{attributes}{description}
	if ($self->can('pre_tool_controls')) {
		$self->pre_tool_controls();
	}

	# use the method below to get ready for the tools_controls area
	$self->tool_controls();

	# we will rely on $OTHOME/code/omnitool/static_files/tool_area_skeleton.tt
	my $tool_html = $self->{belt}->template_process(
		'template_file' => $template,
		'template_vars' => $self,
	);

	# send back; dispatcher.pm will throw to mr_zebra(), who will send out as html
	return $tool_html;
}

# companion method to send only the tools_controls HTML, i.e. for an advanced search submit
sub send_tool_controls {
	my $self = shift;

	# don't repeat yourself ;->
	return $self->send_html('tool_controls.tt');
}

# subroutine to send the breadcrumbs information
sub send_breadcrumbs {
	my $self = shift;

	# use another method to find our breadcrumbs, which will be our path of
	# tools from here to the 'top' tool. builds $self->{breadcrumbs}[]
	# allow for a hook too:
	if ($self->can('special_breadcrumbs')) {
		$self->special_breadcrumbs($self->{display_options}{altcode});
		# that'll be in a specialized class, so won't need 'tool_datacode'
	# our normal way; a little involved; see notes below
	} else {
		$self->find_breadcrumbs($self->{tool_datacode},$self->{display_options}{altcode});
	}

	# the breadcrumbs template needs the uri_path_base for the bookmarks links
	# $self->{bc_store}{bookmark_link} = '/tools/'.$self->{attributes}{uri_path_base}.'/bookmarks';

	# include the 'tool_and_instance'
	$self->{bc_store}{tool_and_instance} = $self->{tool_and_instance};

	# and the app-wide search JS function / name and app-wide quick-start tool, if they are filled
	foreach my $key ('appwide_search_function','appwide_search_name','appwide_quickstart_tool_uri') {
		$self->{bc_store}{$key} = $self->{luggage}{session}->{app_instance_info}{$key};
	}

	# ship them out
	return $self->{bc_store};

}

# method to prepare for the 'tool_controls' portion of the our tool_area_skeleton.tt template
# we are not building this area via jemplate; that is for the tool_display_area
sub tool_controls {
	my $self = shift;

	my ($filter_menu, $menu_cnt, $mode_view, $tk);

	# determine the child-actions which are labeled 'quick actions'
	foreach $tk (@{ $self->{attributes}{child_tools_keys} }) {
		push(@{ $self->{quick_actions} },$tk) if $self->{luggage}{session}{tools}{$tk}{link_type} eq 'Quick Actions';
	}

	# prepare the mode/view options
	# start with the tool mode views
	foreach $mode_view ( @{ $self->{tool_configs_keys}{tool_mode_configs} }) {
		# just need to set the name properly, if it's custom
		if ($self->{tool_configs}{tool_mode_configs}{$mode_view}{custom_type_name}) {
			$self->{tool_configs}{tool_mode_configs}{$mode_view}{mode_type} = $self->{tool_configs}{tool_mode_configs}{$mode_view}{custom_type_name};
		}

		# the uri to load the view
		$self->{tool_configs}{tool_mode_configs}{$mode_view}{uri} = $self->{my_base_uri}.'/tool_mode'.$mode_view;
	}

	# now the quick-search menus; limit to two
	$menu_cnt = 0;
	foreach $filter_menu ( @{ $self->{tool_configs_keys}{tool_filter_menus} }) {

		# just the quick search menus, which must be single-selects
		# limit to four quick-search menus
		next if $self->{quick_search_menus}[3] || $self->{tool_configs}{tool_filter_menus}{$filter_menu}{display_area} ne 'Quick Search' ||
			$self->{tool_configs}{tool_filter_menus}{$filter_menu}{menu_type} !~ /Single-Select|Month Chooser/;

		# add this filter menu to our 1-2 item list for the template processor
		push(@{ $self->{quick_search_menus} },$filter_menu);

	}

	# use method below to fetch the search options
	$self->build_filter_menu_options($self->{quick_search_menus});

	# tell the template if there is just one search menu
	if ($self->{quick_search_menus}[0] && !$self->{quick_search_menus}[1]) {
		$self->{one_search_menu} = 1;
	}

	# if this is a searching tool, we shall provide a text-search box
	if ($self->{attributes}{tool_type} eq 'Search - Screen') {
		$self->{has_search_box} = 1;
	}

	# if there are additional search menus, we shall provide the advanced search option
	if (scalar( @{ $self->{tool_configs_keys}{tool_filter_menus} } ) > scalar( @{ $self->{quick_search_menus} } )) {
		$self->{has_advanced_search} = 1;
	}
}

# method to generate the json for the advanced sort form jemplate modal
# this allows the user to sort their results by multiple columns/directions
sub advanced_sort_form {
	my $self = shift;

	# start the web form
	$self->{json_results}{form} = {
		'target_url' => $self->{my_json_uri},
		'title' => 'Advanced Sort Form',
		'submit_button_text' => 'Submit Advanced Sort Options',
		'hidden_fields' => {
			'client_connection_id' => $self->{client_connection_id},
		},
	};

	# call method from center_stage.pm to prep the field keys / names
	$self->get_omniclass_object( 'dt' => $self->{target_datatype} );
	$self->get_mode_config();
	$self->prep_fields_to_include();

	my (@field_keys, $num, $field);

	# info on the fields
	$self->{json_results}{form}{included_records_fields} = $self->{included_records_fields};
	$self->{json_results}{form}{included_field_names} = $self->{included_field_names};

	# this form is going to a right bit different.  We just need to infom the 'advanced_sort_form'
	# jemplate of how many fields we have to sort, what the field names are, and what our presets might be

	for ($num = 1; $num < 5; $num++) {
		$self->{json_results}{form}{fields}{$num} = {
			'order_number' => $num,
			'preset' => $self->{display_options}{'advanced_sort_'.$num}
		};
		push (@{ $self->{json_results}{form}{field_keys} }, $num);
	}

	# send it out
	return $self->{json_results};
}

# method to generate the form json for the advanced search form jemplate modal.
# includes all filter menus
# FYI: The template for these forms is in system_modals.tt
sub advanced_search_form {
	my $self = shift;

	my ($num, $trigger_menu, $filter_menu, $value_key, $tool_filter_menu, $form_field_type, $keyword_key, $keyword_operator_key, $start_key, $end_key, $opt);

	# use method below to fetch the search options for ALL menus:
	$self->build_filter_menu_options( $self->{tool_configs_keys}{tool_filter_menus} );

	# start the web form
	$self->{json_results}{form} = {
		'target_url' => $self->{my_json_uri},
		'title' => 'Advanced Search Form',
		# 'instructions' => 'To clear keywords or date ranges, simply delete text fields.',
		'submit_button_text' => 'Submit Advanced Search Parameters',
		'hidden_fields' => {
			'client_connection_id' => $self->{client_connection_id},
		},
	};

	# first the quick-search keyword
	$num = 1;
	$self->{json_results}{form}{fields}{$num} = {
		'title' => 'Wide Keyword',
		'name' => 'quick_keyword',
		'both_columns' => 1,
		'preset' => $self->{display_options}{'quick_keyword'},
		'field_type' => 'short_text',
		'instructions' => 'Perl-style regular expressions OK',
	};
	push (@{ $self->{json_results}{form}{field_keys} }, $num);

	# now add the menus to the form hash
	$num = 2;
	foreach $filter_menu (@{ $self->{tool_configs_keys}{tool_filter_menus} }) {

		$value_key = 'menu_'.$filter_menu; # the value / display_options key for the menu

		# some sanity here to access this menu
		$tool_filter_menu = $self->{tool_configs}{tool_filter_menus}{$filter_menu};

		# figure out the default / current option
		$$tool_filter_menu{default_option_value} ||= 'Any'; # 'Any' is our default default option
		if (!$self->{display_options}{$value_key} && $$tool_filter_menu{default_option_value}) {
			$self->{display_options}{$value_key} = $$tool_filter_menu{default_option_value};
			# this will get saved by display_options_manager() when we are done
		}

		# field type is based off 'menu type' option
		if ($$tool_filter_menu{menu_type} eq 'Single-Select') {
			$form_field_type = 'single_select';
		} elsif ($$tool_filter_menu{menu_type} eq 'Multi-Select') {
			$form_field_type = 'advanced_search_multi_select';

		} elsif ($$tool_filter_menu{menu_type} eq 'Date Range') {
			$form_field_type = 'date_range';

		# this will be a special field type for advanced searches
{'fraction_non_alphanumeric': 0.13731176798661462, 'fraction_numerical': 0.002007808142777468, 'mean_word_length': 5.082428765264586, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 197, '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': '6859977', 'n_tokens_mistral': 6316, 'n_tokens_neox': 6030, 'n_words': 1683}