diff --git a/.phpunit.result.cache b/.phpunit.result.cache index 03884ce7..1345d716 100644 --- a/.phpunit.result.cache +++ b/.phpunit.result.cache @@ -1 +1 @@ -{"version":1,"defects":{"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_an_array_from_column":3,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_an_array_from_raw":3,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_width_property_from_column":3},"times":{"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_generate_an_array_of_columns_from_a_model":0.127,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #0":0.013,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #1":0.012,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #2":0.012,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #3":0.012,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #4":0.012,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #5":0.013,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #6":0.013,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #7":0.012,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_exclude_columns":0.014,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_include_columns":0.012,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_rename_columns":0.011,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_can_generate_a_column_from_a_table_column":0.011,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_can_generate_a_column_from_a_scope":0.012,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_can_generate_a_delete_column":0.011,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #0":0.011,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #1":0.011,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #2":0.011,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #3":0.011,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #4":0.012,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_an_array_from_column":0.014,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_an_array_from_raw":0.012,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_width_property_from_column":0.011,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_mount_using_the_class":0.054,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_set_a_default_sort":0.019,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_show_and_hide_a_column":0.039,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_order_results":0.014,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_text":0.026,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_boolean":0.026,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_strings_as_a_boolean":0.029,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_selects":0.025,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_numbers":0.059,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_base_columns":0.013,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_has_one_relation_columns":0.013,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_where_query_for_a_has_one_column":0.013,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_has_many_relation_columns":0.014,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_has_many_relation_column_with_specific_aggregate":0.014,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_where_query_for_has_many_relation_columns":0.013,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_belongs_to_relation_columns":0.018,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_where_query_for_belongs_to_relation_columns":0.014,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_belongs_to_many_relation_columns":0.016,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a__where_query_for_belongs_to_many_relation_columns":0.013,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_mount_from_the_default_template_with_a_model":0.017,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::the_header_can_be_hidden_with_a_property":0.016,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::the_pagination_bar_can_be_hidden_with_a_property":0.016,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_per_page_with_a_property":0.023,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_include_columns_from_a_property":0.016,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_exclude_columns_from_a_property":0.017,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_hide_columns_from_a_property":0.021,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_mark_columns_for_date_format_from_a_property":0.017,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_mark_columns_for_time_format_from_a_property":0.018,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_sort_from_a_property":0.018,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::component_is_created_by_make_command":0.017,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::dot_nested_component_is_created_by_make_command":0.019,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::forward_slash_nested_component_is_created_by_make_command":0.016,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::multiword_component_is_created_by_make_command":0.014,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::pascal_case_component_is_automatically_converted_by_make_command":0.014,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::snake_case_component_is_automatically_converted_by_make_command":0.017,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::snake_case_component_is_automatically_converted_by_make_command_on_nested_component":0.018,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::new_component_model_name_matches_option":0.014,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::a_component_is_not_created_with_a_reserved_class_name":0.013}} \ No newline at end of file +{"version":1,"defects":{"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_an_array_from_column":3,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_an_array_from_raw":3,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_width_property_from_column":3,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_generate_an_array_of_columns_from_a_model":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #0":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #1":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #2":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #3":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #4":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #5":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #6":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #7":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_exclude_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_include_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_rename_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_can_generate_a_column_from_a_table_column":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_can_generate_a_column_from_a_scope":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_can_generate_a_delete_column":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #0":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #1":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #2":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #3":4,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #4":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_mount_using_the_class":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_set_a_default_sort":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_show_and_hide_a_column":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_order_results_for_a_column":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_order_results_for_multiple_columns_using_column_index":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_order_results_for_multiple_columns_using_column_name":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_text":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_boolean":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_strings_as_a_boolean":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_selects":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_numbers":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_toggles_sort_status_on_each_sort_trigger":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_base_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_has_one_relation_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_has_many_relation_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_has_many_relation_column_with_specific_aggregate":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_belongs_to_relation_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_belongs_to_many_relation_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_base_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_has_one_relation_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_where_query_for_a_has_one_column":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_has_many_relation_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_has_many_relation_column_with_specific_aggregate":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_where_query_for_has_many_relation_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_belongs_to_relation_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_where_query_for_belongs_to_relation_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_belongs_to_many_relation_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_where_query_for_belongs_to_many_relation_columns":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_mount_from_the_default_template_with_a_model":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::the_header_can_be_hidden_with_a_property":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::the_pagination_bar_can_be_hidden_with_a_property":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_per_page_with_a_property":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_include_columns_from_a_property":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_exclude_columns_from_a_property":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_hide_columns_from_a_property":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_mark_columns_for_date_format_from_a_property":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_mark_columns_for_time_format_from_a_property":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_sort_from_property_using_column_name_and_direction":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_sort_from_property_using_column_index":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_sort_from_property_using_column_index_and_direction":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_multisort_from_property_using_array":4,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_forget_multisort_session_on_demand":4,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::component_is_created_by_make_command":4,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::dot_nested_component_is_created_by_make_command":4,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::forward_slash_nested_component_is_created_by_make_command":4,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::multiword_component_is_created_by_make_command":4,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::pascal_case_component_is_automatically_converted_by_make_command":4,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::snake_case_component_is_automatically_converted_by_make_command":4,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::snake_case_component_is_automatically_converted_by_make_command_on_nested_component":4,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::new_component_model_name_matches_option":4,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::a_component_is_not_created_with_a_reserved_class_name":4,"Mediconesystems\\LivewireDatatables\\Tests\\PutSortToSessionTest::it_saves_sort_to_session_when_not_in_multisort":4,"Mediconesystems\\LivewireDatatables\\Tests\\PutSortToSessionTest::it_saves_sort_to_session_when_in_multisort":4},"times":{"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_generate_an_array_of_columns_from_a_model":0.184,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #0":0.034,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #1":0.033,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #2":0.033,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #3":0.033,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #4":0.033,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #5":0.033,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #6":0.034,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_correctly_populate_the_columns_from_the_model with data set #7":0.033,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_exclude_columns":0.037,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_include_columns":0.033,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnSetTest::it_can_rename_columns":0.033,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_can_generate_a_column_from_a_table_column":0.033,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_can_generate_a_column_from_a_scope":0.032,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_can_generate_a_delete_column":0.032,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #0":0.032,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #1":0.032,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #2":0.032,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #3":0.032,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_sets_properties_and_parameters with data set #4":0.032,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_an_array_from_column":0.036,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_an_array_from_raw":0.034,"Mediconesystems\\LivewireDatatables\\Tests\\ColumnTest::it_returns_width_property_from_column":0.033,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_mount_using_the_class":0.097,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_set_a_default_sort":0.048,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_show_and_hide_a_column":0.098,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_order_results":0.014,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_text":0.065,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_boolean":0.069,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_strings_as_a_boolean":0.066,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_selects":0.066,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_filter_results_based_on_numbers":0.139,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_base_columns":0.036,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_has_one_relation_columns":0.039,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_where_query_for_a_has_one_column":0.037,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_has_many_relation_columns":0.038,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_has_many_relation_column_with_specific_aggregate":0.038,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_where_query_for_has_many_relation_columns":0.038,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_belongs_to_relation_columns":0.039,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_where_query_for_belongs_to_relation_columns":0.04,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_query_builder_for_belongs_to_many_relation_columns":0.039,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a__where_query_for_belongs_to_many_relation_columns":0.013,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_mount_from_the_default_template_with_a_model":0.05,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::the_header_can_be_hidden_with_a_property":0.048,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::the_pagination_bar_can_be_hidden_with_a_property":0.05,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_per_page_with_a_property":0.064,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_include_columns_from_a_property":0.046,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_exclude_columns_from_a_property":0.047,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_hide_columns_from_a_property":0.048,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_mark_columns_for_date_format_from_a_property":0.048,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_mark_columns_for_time_format_from_a_property":0.053,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_sort_from_a_property":0.018,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::component_is_created_by_make_command":0.039,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::dot_nested_component_is_created_by_make_command":0.036,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::forward_slash_nested_component_is_created_by_make_command":0.036,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::multiword_component_is_created_by_make_command":0.038,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::pascal_case_component_is_automatically_converted_by_make_command":0.036,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::snake_case_component_is_automatically_converted_by_make_command":0.035,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::snake_case_component_is_automatically_converted_by_make_command_on_nested_component":0.041,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::new_component_model_name_matches_option":0.036,"Mediconesystems\\LivewireDatatables\\Tests\\MakeDatatableCommandTest::a_component_is_not_created_with_a_reserved_class_name":0.035,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_order_results_for_a_column":0.039,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_order_results_for_multiple_columns_using_column_index":0.044,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableClassTest::it_can_order_results_for_multiple_columns_using_column_name":0.044,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_toggles_sort_status_on_each_sort_trigger":0.038,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_base_columns":0.038,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_has_one_relation_columns":0.043,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_has_many_relation_columns":0.04,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_has_many_relation_column_with_specific_aggregate":0.038,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_belongs_to_relation_columns":0.045,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableMultisortableQueryBuilderTest::it_creates_a_multisort_query_builder_for_belongs_to_many_relation_columns":0.043,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableQueryBuilderTest::it_creates_a_where_query_for_belongs_to_many_relation_columns":0.039,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_sort_from_property_using_column_name_and_direction":0.047,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_sort_from_property_using_column_index":0.047,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_sort_from_property_using_column_index_and_direction":0.047,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_set_multisort_from_property_using_array":0.048,"Mediconesystems\\LivewireDatatables\\Tests\\LivewireDatatableTemplateTest::it_can_forget_multisort_session_on_demand":0.077,"Mediconesystems\\LivewireDatatables\\Tests\\PutSortToSessionTest::it_saves_sort_to_session_when_not_in_multisort":0.113,"Mediconesystems\\LivewireDatatables\\Tests\\PutSortToSessionTest::it_saves_sort_to_session_when_in_multisort":0.095}} \ No newline at end of file diff --git a/README.md b/README.md index d6329bf9..0c9868d1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ### Features - Use a model or query builder to supply data - Mutate and format columns using preset or custom callbacks -- Sort data using column or computed column +- Sort data using one or more columns or computed columns - Filter using booleans, times, dates, selects or free text - Create complex combined filters using the [complex query builder](#complex-query-builder) - Show / hide columns @@ -89,7 +89,8 @@ other as in the example above. |**dates**|*String\| Array* of column definitions [ and optional format in \ | delimited string]|column values are formatted as per the default date format, or format can be included in string with \| separator | ```:dates="['dob\|lS F y', 'created_at']"```| |**times**|*String\| Array* of column definitions [optional format in \ | delimited string]|column values are formatted as per the default time format, or format can be included in string with \| separator | ```'bedtime\|g:i A'```| |**searchable**|*String\| Array* of column names | Defines columns to be included in global search | ```searchable="name, email"```| -|**sort**|*String* of column definition [and optional 'asc' or 'desc' (default: 'desc') in \| delimited string] |Specifies the column and direction for initial table sort. Default is column 0 descending | ```sort="name\|asc"```| +|**sort**|*String, int or array* of column(s) definition [and optional 'asc' or 'desc' (default: 'desc') Specifies the column and direction for initial table sort. Default is column 0 descending | ```sort="name\|asc"```| +|**multisort**|*Boolean default: false*|When set to true, sort is done using multiple columns. |**hide-header**|*Boolean* default: *false*| The top row of the table including the column titles is removed if this is ```true``` | | |**hide-pagination**|*Boolean* default: *false*| Pagination controls are removed if this is ```true``` | | |**per-page**|*Integer* default: 10| Number of rows per page | ```per-page="20"``` | @@ -100,6 +101,22 @@ other as in the example above. |**afterTableSlot**| _String_ | blade view to be included immediately after the table in the component, which can therefore access public properties | [demo](https://livewire-datatables.com/complex) | --- +## Sorting by multiple columns (multisort) +![Multisort Demo](http://g.recordit.co/V0FOLGGPjO.gif "Multisort Demo") +### Enable multisort +Multisort is disabled by default. To enable it set ```multisort = true``` on your ```livewire-datatable``` component. +```html +... + + + +... +``` +### How does it work? +There's 3 possible states a column can have when multisort is enabled. Clicking on a column will advance its state. +- 1st click: column added to the sort with direction `desc`. +- 2nd click: direction changes to `asc`. +- 3rd click: column removed from sort. ## Component Syntax diff --git a/composer.json b/composer.json index c09a9c3e..2fcff9ff 100644 --- a/composer.json +++ b/composer.json @@ -20,8 +20,8 @@ } ], "require": { - "php": "^8.0", - "illuminate/support": "^7.0|^8.0|^9.0", + "php": "^8.2", + "illuminate/support": "^9.0|^v10.0", "livewire/livewire": "^2.4.4", "maatwebsite/excel": "^3.1", "reedware/laravel-relation-joins": "^2.4|^3.0" diff --git a/resources/views/livewire/datatables/datatable.blade.php b/resources/views/livewire/datatables/datatable.blade.php index be0b94ea..f72b34e5 100644 --- a/resources/views/livewire/datatables/datatable.blade.php +++ b/resources/views/livewire/datatables/datatable.blade.php @@ -2,6 +2,14 @@ @includeIf($beforeTableSlot)
+ @if(isset($this->multisort) && $this->multisort === true && count($this->sort) > 1) + + @endif
@if($this->searchableColumns()->count())
@@ -61,6 +69,32 @@ class="flex items-center px-4 py-2 text-xs font-medium tracking-wider text-green
@endif + @if(count($this->massActionsOptions)) +
+ + + +
+ @endif + @if($exportable)
- @if($column['sortable']) - - @else -
- {{ str_replace('_', ' ', $column['label']) }} -
@endif
@endif diff --git a/src/Column.php b/src/Column.php index 0c2d51a7..eb95edd0 100644 --- a/src/Column.php +++ b/src/Column.php @@ -214,7 +214,7 @@ public function sortBy($column) return $this; } - public function defaultSort($direction = true) + public function defaultSort(?string $direction = 'desc') { $this->defaultSort = $direction; diff --git a/src/ColumnSet.php b/src/ColumnSet.php index da4efb0b..9c598b90 100644 --- a/src/ColumnSet.php +++ b/src/ColumnSet.php @@ -147,8 +147,16 @@ public function search($searchable) public function sort($sort) { - if ($sort && $column = $this->columns->first(function ($column) use ($sort) { - return Str::after($column->name, '.') === Str::before($sort, '|'); + if (is_array($sort)) { + foreach ($sort as $arg) { + $this->sort($arg); + } + + return $this; + } + + if ($sort && $column = $this->columns->first(function ($column, $key) use ($sort) { + return Str::after($column->name, '.') === ($sort = Str::before($sort, '|')) || $sort === $key; })) { $column->defaultSort(Str::of($sort)->contains('|') ? Str::after($sort, '|') : null); } diff --git a/src/Http/Livewire/LivewireDatatable.php b/src/Http/Livewire/LivewireDatatable.php index 14165a41..a0611e60 100644 --- a/src/Http/Livewire/LivewireDatatable.php +++ b/src/Http/Livewire/LivewireDatatable.php @@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\Query\Expression; use Illuminate\Support\Arr; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use Illuminate\View\View; @@ -25,11 +26,12 @@ class LivewireDatatable extends Component use WithPagination, WithCallbacks, WithPresetDateFilters, WithPresetTimeFilters; const SEPARATOR = '|**lwdt**|'; + const DEFAULT_DIRECTION = 'desc'; + const ORDER_BY_DIRECTION_STATES = [self::DEFAULT_DIRECTION, 'asc', null]; public $model; public $columns; public $search; public $sort; - public $direction; public $activeDateFilters = []; public $activeTimeFilters = []; public $activeSelectFilters = []; @@ -64,6 +66,7 @@ class LivewireDatatable extends Component public $persistSort = true; public $persistPerPage = true; public $persistFilters = true; + public $multisort; public $row = 1; public $tablePrefix = ''; @@ -228,6 +231,7 @@ public function mount( $times = [], $searchable = [], $sort = null, + $multisort = false, $hideHeader = null, $hidePagination = null, $perPage = null, @@ -247,7 +251,7 @@ public function mount( 'times', 'searchable', 'sort', - 'hideHeader', + 'multisort', 'hideHeader', 'hidePagination', 'exportable', 'hideable', @@ -478,8 +482,13 @@ public function getSessionStoredSort() return; } - $this->sort = session()->get($this->sessionStorageKey() . '_sort', $this->sort); - $this->direction = session()->get($this->sessionStorageKey() . '_direction', $this->direction); + if (! $this->multisort) { + $this->sort = session()->get($this->sessionStorageKey() . '_sort', $this->sort); + + return; + } + + $this->sort = session()->get($this->sessionStorageKey() . '_multisort', $this->sort) ?? []; } public function getSessionStoredPerPage() @@ -497,10 +506,13 @@ public function setSessionStoredSort() return; } - session()->put([ - $this->sessionStorageKey() . '_sort' => $this->sort, - $this->sessionStorageKey() . '_direction' => $this->direction, - ]); + if (! $this->multisort) { + session()->put([$this->sessionStorageKey() . $this->name . '_sort' => $this->sort]); + + return; + } + + session()->put([$this->sessionStorageKey() . $this->name . '_multisort' => implode(',', $this->sort)]); } public function setSessionStoredFilters() @@ -544,13 +556,28 @@ public function initialiseSearch() public function initialiseSort() { - $this->sort = $this->defaultSort() - ? $this->defaultSort()['key'] - : collect($this->freshColumns)->reject(function ($column) { - return in_array($column['type'], Column::UNSORTABLE_TYPES) || $column['hidden']; - })->keys()->first(); + $default = $this->defaultSort(); + $direction = self::DEFAULT_DIRECTION; + + if ($default->isNotEmpty()) { + $this->sort = $default->transform(function ($column) { + return $column['key'] . '|' . $column['direction']; + })->values()->toArray(); + $this->getSessionStoredSort(); + + return; + } + + if (is_int($this->sort) || is_string($this->sort)) { + $columnIndex = $this->getIndexFromValue($this->sort); + $direction = $this->getColumnDirection($this->sort); + } else { + $columnIndex = collect($this->freshColumns)->reject(function ($column) { + return in_array($column['type'], Column::UNSORTABLE_TYPES) || $column['hidden']; + })->keys()->first(); + } - $this->direction = $this->defaultSort() && $this->defaultSort()['direction'] === 'asc'; + $this->sort = [$columnIndex . '|' . $direction]; $this->getSessionStoredSort(); } @@ -609,52 +636,53 @@ public function initialiseFilters() public function defaultSort() { - $columnIndex = collect($this->freshColumns)->search(function ($column) { + $columns = collect($this->freshColumns)->filter(function ($column) { return is_string($column['defaultSort']); }); - return is_numeric($columnIndex) ? [ - 'key' => $columnIndex, - 'direction' => $this->freshColumns[$columnIndex]['defaultSort'], - ] : null; + return $columns->map(function ($column, $index) { + return is_numeric($index) ? [ + 'key' => $index, + 'direction' => $this->freshColumns[$index]['defaultSort'], + ] : null; + }); } - public function getSortString($dbtable) + public function getSortString(int $index, string $dbTable) { - $column = $this->freshColumns[$this->sort]; + $column = $this->freshColumns[$index]; switch (true) { case $column['sort']: return $column['sort']; - break; case $column['base']: return $column['base']; - break; case is_array($column['select']): return Str::before($column['select'][0], ' AS '); - break; case $column['select']: return Str::before($column['select'], ' AS '); - break; default: + return $dbTable == 'pgsql' || $dbTable == 'sqlsrv' + ? new Expression('"' . $column['name'] . '"') + : new Expression('`' . $column['name'] . '`'); + } + } - switch ($dbtable) { - case 'mysql': - return new Expression('`' . $column['name'] . '`'); - break; - case 'pgsql': - return new Expression('"' . $column['name'] . '"'); - break; - case 'sqlsrv': - return new Expression("'" . $column['name'] . "'"); - break; - default: - return new Expression("'" . $column['name'] . "'"); - } + /** + * Attempt so summarize each data cell of the given column. + * In case we have a string or any other value that is not summarizable, + * we return a empty string. + */ + public function summarize($column) + { + try { + return $this->results->sum($column); + } catch (\TypeError $e) { + return ''; } } @@ -672,20 +700,6 @@ public function hasSummaryRow() return false; } - /** - * Attempt so summarize each data cell of the given column. - * In case we have a string or any other value that is not summarizable, - * we return a empty string. - */ - public function summarize($column) - { - try { - return $this->results->sum($column); - } catch (\TypeError $e) { - return ''; - } - } - public function updatingPerPage() { $this->refreshLivewireDatatable(); @@ -696,6 +710,19 @@ public function refreshLivewireDatatable() $this->setPage(1); } + public function getColumnDirection(string $sortString): string + { + $direction = self::DEFAULT_DIRECTION; + if (Str::contains($sortString, '|')) { + $direction = Str::after($sortString, '|'); + if (! in_array($direction, self::ORDER_BY_DIRECTION_STATES)) { + throw new \Exception("Invalid direction $direction given in getColumnDirection() method. Allowed values: asc, desc."); + } + } + + return $direction; + } + /** * Order the table by a given column index starting from 0. * @@ -705,33 +732,62 @@ public function refreshLivewireDatatable() */ public function sort($index, $direction = null) { - if (! in_array($direction, [null, 'asc', 'desc'])) { + if (! in_array($direction, self::ORDER_BY_DIRECTION_STATES)) { throw new \Exception("Invalid direction $direction given in sort() method. Allowed values: asc, desc."); } + $key = Str::snake(Str::afterLast(get_called_class(), '\\')); - if ($this->sort === (int) $index) { - if ($direction === null) { // toggle direction - $this->direction = ! $this->direction; + if ($this->multisort) { + if (($columnsWithDirection = $this->getColumnsFromSort($this->sort, $index))->isEmpty()) { + if ($direction === null) { + $sort = $index . '|' . $this->getColumnDirection($index); + } else { + $sort = $index . '|' . $direction; + } + $this->sort[] = $sort; } else { - $this->direction = $direction === 'asc' ? true : false; + $sortIndex = $columnsWithDirection->keys()->first(); + if ($direction === null) { + $toggledDirection = $this->toggleMultisortDirection($this->getColumnDirection($this->sort[$sortIndex])); + unset($this->sort[$sortIndex]); + $this->sort = array_values($this->sort); + $sort = $index . '|' . $toggledDirection; + if ($toggledDirection === null) { + return; + } + $this->sort[] = $sort; + } else { + $this->sort[$sortIndex] = + $index . '|' . $direction; + } } - } else { - $this->sort = (int) $index; + + $this->page = 1; + session()->put([$key . $this->name . '_multisort' => $this->sort]); + + return; } - if ($direction !== null) { - $this->direction = $direction === 'asc' ? true : false; + + if (in_array($index . '|' . $this->getColumnDirection($index), $this->sort)) { + if ($direction === null) { + $sort = [$index . '|' . $this->toggleSortDirection($this->getColumnDirection($index))]; + } else { + $sort = [$index . '|' . $direction]; + } + } else { + $direction = $direction ?? self::DEFAULT_DIRECTION; + $sort = [$index . '|' . $direction]; } - $this->setPage(1); - session()->put([ - $this->sessionStorageKey() . '_sort' => $this->sort, - $this->sessionStorageKey() . '_direction' => $this->direction, - ]); + $this->sort = $sort; + $this->page = 1; + + session()->put([$key . $this->name . '_sort' => $this->sort, $key . $this->name . '_direction' => Str::after($this->sort[0], '|')]); } public function toggle($index) { - if ($this->sort == $index) { + if (in_array($index, $this->sort)) { $this->initialiseSort(); } @@ -1446,11 +1502,23 @@ public function addTimeRangeFilter() */ public function addSort() { - if (isset($this->sort) && isset($this->freshColumns[$this->sort]) && $this->freshColumns[$this->sort]['name']) { - if (isset($this->pinnedRecords) && $this->pinnedRecords) { - $this->query->orderBy(DB::raw('FIELD(id,' . implode(',', $this->pinnedRecords) . ')'), 'DESC'); + if (! empty($this->sort)) { + $dbTable = $this->query->getConnection()->getPDO()->getAttribute(\PDO::ATTR_DRIVER_NAME); + foreach ($this->sort as $sort) { + $index = Str::before($sort, '|'); + if (! is_numeric($index) + && ! is_null(($index = optional(collect($this->freshColumns)->where('name', $index))->keys()->first()))) { + $columnName = Str::after($this->getSortString($index, $dbTable), '.'); + } else { + $columnName = $this->getSortString($index, $dbTable); + } + + if (isset($this->pinnedRecords) && $this->pinnedRecords) { + $this->query->orderBy(DB::raw('FIELD(id,' . implode(',', $this->pinnedRecords) . ')'), 'DESC'); + } + + $this->query->orderByRaw($columnName . ' ' . ($direction = Str::after($sort, '|') == $index ? self::DEFAULT_DIRECTION : Str::after($sort, '|'))); } - $this->query->orderBy(DB::raw($this->getSortString($this->query->getConnection()->getPDO()->getAttribute(\PDO::ATTR_DRIVER_NAME))), $this->direction ? 'asc' : 'desc'); } return $this; @@ -1665,6 +1733,8 @@ public function rowClasses($row, $loop) return config('livewire-datatables.default_classes.row.odd', 'divide-x divide-gray-100 text-sm text-gray-900 bg-gray-50'); } } + + $this->setSessionStoredHidden(); } public function cellClasses($row, $column) @@ -1673,6 +1743,47 @@ public function cellClasses($row, $column) return config('livewire-datatables.default_classes.cell', 'text-sm text-gray-900'); } + public function toggleSortDirection(string $direction): string + { + if (! in_array($direction, self::ORDER_BY_DIRECTION_STATES)) { + throw new \Exception("Invalid direction $direction given in toggleSortDirection() method. Allowed values: asc, desc."); + } + + switch ($direction) { + case self::DEFAULT_DIRECTION: + return 'asc'; + default: + return self::DEFAULT_DIRECTION; + } + } + + public function toggleMultisortDirection(string $direction): ?string + { + $directionState = array_search($direction, ($directions = self::ORDER_BY_DIRECTION_STATES)); + if ($directionState === false) { + throw new Exception('Undefined direction index in togglemultisortDirection()'); + } + return $directions[$directionState + 1]; + } + + public function getColumnsFromSort(array $sort, $index): Collection + { + return collect($sort)->filter(function ($value) use ($index) { + return $this->getIndexFromValue($value) == $index; + }); + } + + public function getIndexFromValue($q): ?int + { + return (int) Str::before($q, '|'); + } + + public function forgetSortSession() + { + session()->forget($this->sessionStorageKey() . $this->name . '_multisort'); + $this->sort = []; + } + public function getMassActions() { return collect($this->massActions)->map(function ($action) { diff --git a/tests/LivewireDatatableClassTest.php b/tests/LivewireDatatableClassTest.php index 8b7182e8..18296403 100644 --- a/tests/LivewireDatatableClassTest.php +++ b/tests/LivewireDatatableClassTest.php @@ -40,8 +40,7 @@ public function it_can_set_a_default_sort() $this->assertIsArray($subject->columns); - $this->assertEquals(0, $subject->sort); - $this->assertFalse($subject->direction); + $this->assertEquals(['0|desc'], $subject->sort); } /** @test */ @@ -60,7 +59,7 @@ public function it_can_show_and_hide_a_column() } /** @test */ - public function it_can_order_results() + public function it_can_order_results_for_a_column() { factory(DummyModel::class)->create(['subject' => 'Beet growing for noobs']); factory(DummyModel::class)->create(['subject' => 'Advanced beet growing']); @@ -71,13 +70,79 @@ public function it_can_order_results() $this->assertEquals('Advanced beet growing', $subject->results->getCollection()[1]->subject); $subject->forgetComputed(); - $subject->sort = 1; - $subject->direction = true; + $subject->sort = ['1|asc']; $this->assertEquals('Advanced beet growing', $subject->results->getCollection()[0]->subject); $this->assertEquals('Beet growing for noobs', $subject->results->getCollection()[1]->subject); } + /** @test */ + public function it_can_order_results_for_multiple_columns_using_column_index() + { + factory(DummyModel::class)->create(['subject' => 'Beet growing for noobs', 'category' => 'A']); + factory(DummyModel::class)->create(['subject' => 'Advanced beet growing', 'category' => 'A']); + factory(DummyModel::class)->create(['subject' => 'Advanced beet growing', 'category' => 'B']); + factory(DummyModel::class)->create(['subject' => 'Beet growing for noobs', 'category' => 'B']); + + $subject = new DummyTable(1); + + $this->assertEquals(['Beet growing for noobs', 'A'], [$subject->results->getCollection()[0]->subject, $subject->results->getCollection()[0]->category]); + $this->assertEquals(['Advanced beet growing', 'A'], [$subject->results->getCollection()[1]->subject, $subject->results->getCollection()[1]->category]); + $this->assertEquals(['Advanced beet growing', 'B'], [$subject->results->getCollection()[2]->subject, $subject->results->getCollection()[2]->category]); + $this->assertEquals(['Beet growing for noobs', 'B'], [$subject->results->getCollection()[3]->subject, $subject->results->getCollection()[3]->category]); + + $subject->forgetComputed(); + $subject->multisort = true; + $subject->sort = ['1|asc', '2|desc']; + + $this->assertEquals(['Advanced beet growing', 'B'], [$subject->results->getCollection()[0]->subject, $subject->results->getCollection()[0]->category]); + $this->assertEquals(['Advanced beet growing', 'A'], [$subject->results->getCollection()[1]->subject, $subject->results->getCollection()[1]->category]); + $this->assertEquals(['Beet growing for noobs', 'B'], [$subject->results->getCollection()[2]->subject, $subject->results->getCollection()[2]->category]); + $this->assertEquals(['Beet growing for noobs', 'A'], [$subject->results->getCollection()[3]->subject, $subject->results->getCollection()[3]->category]); + + $subject->forgetComputed(); + $subject->sort = ['1|asc', '2|asc']; + + $this->assertEquals(['Advanced beet growing', 'A'], [$subject->results->getCollection()[0]->subject, $subject->results->getCollection()[0]->category]); + $this->assertEquals(['Advanced beet growing', 'B'], [$subject->results->getCollection()[1]->subject, $subject->results->getCollection()[1]->category]); + $this->assertEquals(['Beet growing for noobs', 'A'], [$subject->results->getCollection()[2]->subject, $subject->results->getCollection()[2]->category]); + $this->assertEquals(['Beet growing for noobs', 'B'], [$subject->results->getCollection()[3]->subject, $subject->results->getCollection()[3]->category]); + + } + + /** @test */ + public function it_can_order_results_for_multiple_columns_using_column_name() + { + factory(DummyModel::class)->create(['subject' => 'Beet growing for noobs', 'category' => 'A']); + factory(DummyModel::class)->create(['subject' => 'Advanced beet growing', 'category' => 'A']); + factory(DummyModel::class)->create(['subject' => 'Advanced beet growing', 'category' => 'B']); + factory(DummyModel::class)->create(['subject' => 'Beet growing for noobs', 'category' => 'B']); + + $subject = new DummyTable(1); + + $this->assertEquals(['Beet growing for noobs', 'A'], [$subject->results->getCollection()[0]->subject, $subject->results->getCollection()[0]->category]); + $this->assertEquals(['Advanced beet growing', 'A'], [$subject->results->getCollection()[1]->subject, $subject->results->getCollection()[1]->category]); + $this->assertEquals(['Advanced beet growing', 'B'], [$subject->results->getCollection()[2]->subject, $subject->results->getCollection()[2]->category]); + $this->assertEquals(['Beet growing for noobs', 'B'], [$subject->results->getCollection()[3]->subject, $subject->results->getCollection()[3]->category]); + + $subject->forgetComputed(); + $subject->multisort = true; + $subject->sort = ['subject|asc', 'category|desc']; + + $this->assertEquals(['Advanced beet growing', 'B'], [$subject->results->getCollection()[0]->subject, $subject->results->getCollection()[0]->category]); + $this->assertEquals(['Advanced beet growing', 'A'], [$subject->results->getCollection()[1]->subject, $subject->results->getCollection()[1]->category]); + $this->assertEquals(['Beet growing for noobs', 'B'], [$subject->results->getCollection()[2]->subject, $subject->results->getCollection()[2]->category]); + $this->assertEquals(['Beet growing for noobs', 'A'], [$subject->results->getCollection()[3]->subject, $subject->results->getCollection()[3]->category]); + + $subject->forgetComputed(); + $subject->sort = ['subject|asc', 'category|asc']; + + $this->assertEquals(['Advanced beet growing', 'A'], [$subject->results->getCollection()[0]->subject, $subject->results->getCollection()[0]->category]); + $this->assertEquals(['Advanced beet growing', 'B'], [$subject->results->getCollection()[1]->subject, $subject->results->getCollection()[1]->category]); + $this->assertEquals(['Beet growing for noobs', 'A'], [$subject->results->getCollection()[2]->subject, $subject->results->getCollection()[2]->category]); + $this->assertEquals(['Beet growing for noobs', 'B'], [$subject->results->getCollection()[3]->subject, $subject->results->getCollection()[3]->category]); + } + /** @test */ public function it_can_filter_results_based_on_text() { diff --git a/tests/LivewireDatatableMultisortableQueryBuilderTest.php b/tests/LivewireDatatableMultisortableQueryBuilderTest.php new file mode 100644 index 00000000..db157a29 --- /dev/null +++ b/tests/LivewireDatatableMultisortableQueryBuilderTest.php @@ -0,0 +1,187 @@ +create(); + + $subject = new LivewireDatatable(1); + $subject->multisort = true; + $subject->mount(DummyModel::class, ['id', 'subject', 'category']); + + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_models"."subject" as "subject", "dummy_models"."category" as "category" from "dummy_models" order by `id` desc', $subject->getQuery()->toSql()); + + $subject->sort(0); + + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_models"."subject" as "subject", "dummy_models"."category" as "category" from "dummy_models" order by `id` asc', $subject->getQuery()->toSql()); + + $subject->sort(0); + + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_models"."subject" as "subject", "dummy_models"."category" as "category" from "dummy_models"', $subject->getQuery()->toSql()); + + $subject->sort(0); + + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_models"."subject" as "subject", "dummy_models"."category" as "category" from "dummy_models" order by `id` desc', $subject->getQuery()->toSql()); + + } + + /** @test */ + public function it_creates_a_multisort_query_builder_for_base_columns() + { + factory(DummyModel::class)->create(); + $subject = new LivewireDatatable(1); + $subject->multisort = true; + $subject->mount(DummyModel::class, ['id', 'subject', 'category']); + + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_models"."subject" as "subject", "dummy_models"."category" as "category" from "dummy_models" order by `id` desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_models"."subject" as "subject", "dummy_models"."category" as "category" from "dummy_models" order by `id` desc, `subject` desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_models"."subject" as "subject", "dummy_models"."category" as "category" from "dummy_models" order by `id` desc, `subject` asc', $subject->getQuery()->toSql()); + + $subject->sort(1); + + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_models"."subject" as "subject", "dummy_models"."category" as "category" from "dummy_models" order by `id` desc', $subject->getQuery()->toSql()); + + $subject->sort(2); + + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_models"."subject" as "subject", "dummy_models"."category" as "category" from "dummy_models" order by `id` desc, `category` desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_models"."subject" as "subject", "dummy_models"."category" as "category" from "dummy_models" order by `id` desc, `category` desc, `subject` desc', $subject->getQuery()->toSql()); + } + + /** @test */ + public function it_creates_a_multisort_query_builder_for_has_one_relation_columns() + { + factory(DummyModel::class)->create()->dummy_has_one()->save(factory(DummyHasOneModel::class)->make()); + + $subject = new LivewireDatatable(1); + $subject->multisort = true; + $subject->mount(DummyModel::class, ['id', 'dummy_has_one.name', 'dummy_has_one.category']); + + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_has_one_models"."name" as "dummy_has_one.name", "dummy_has_one_models"."category" as "dummy_has_one.category" from "dummy_models" left join "dummy_has_one_models" on "dummy_has_one_models"."dummy_model_id" = "dummy_models"."id" order by `id` desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + $subject->forgetComputed(); + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_has_one_models"."name" as "dummy_has_one.name", "dummy_has_one_models"."category" as "dummy_has_one.category" from "dummy_models" left join "dummy_has_one_models" on "dummy_has_one_models"."dummy_model_id" = "dummy_models"."id" order by dummy_models.id desc, dummy_has_one_models.name desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + $subject->forgetComputed(); + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_has_one_models"."name" as "dummy_has_one.name", "dummy_has_one_models"."category" as "dummy_has_one.category" from "dummy_models" left join "dummy_has_one_models" on "dummy_has_one_models"."dummy_model_id" = "dummy_models"."id" order by dummy_models.id desc, dummy_has_one_models.name asc', $subject->getQuery()->toSql()); + + $subject->sort(2); + $subject->forgetComputed(); + $this->assertEquals('select "dummy_models"."id" as "id", "dummy_has_one_models"."name" as "dummy_has_one.name", "dummy_has_one_models"."category" as "dummy_has_one.category" from "dummy_models" left join "dummy_has_one_models" on "dummy_has_one_models"."dummy_model_id" = "dummy_models"."id" order by dummy_models.id desc, dummy_has_one_models.name asc, dummy_has_one_models.category desc', $subject->getQuery()->toSql()); + } + + /** @test */ + public function it_creates_a_multisort_query_builder_for_has_many_relation_columns() + { + factory(DummyModel::class)->create()->dummy_has_many()->saveMany(factory(DummyHasManyModel::class, 2)->make()); + + $subject = new LivewireDatatable(1); + $subject->multisort = true; + $subject->mount(DummyModel::class, ['id', 'dummy_has_many.name']); + + $this->assertEquals('select (select group_concat(REPLACE(DISTINCT(dummy_has_many_models.name), \'\', \'\') , \', \') from "dummy_has_many_models" where "dummy_models"."id" = "dummy_has_many_models"."dummy_model_id") as `dummy_has_many.name`, "dummy_models"."id" as "id" from "dummy_models" order by `id` desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + + $this->assertEquals('select (select group_concat(REPLACE(DISTINCT(dummy_has_many_models.name), \'\', \'\') , \', \') from "dummy_has_many_models" where "dummy_models"."id" = "dummy_has_many_models"."dummy_model_id") as `dummy_has_many.name`, "dummy_models"."id" as "id" from "dummy_models" order by `id` desc, `dummy_has_many.name` desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + + $this->assertEquals('select (select group_concat(REPLACE(DISTINCT(dummy_has_many_models.name), \'\', \'\') , \', \') from "dummy_has_many_models" where "dummy_models"."id" = "dummy_has_many_models"."dummy_model_id") as `dummy_has_many.name`, "dummy_models"."id" as "id" from "dummy_models" order by `id` desc, `dummy_has_many.name` asc', $subject->getQuery()->toSql()); + + $subject->sort(0); + + $this->assertEquals('select (select group_concat(REPLACE(DISTINCT(dummy_has_many_models.name), \'\', \'\') , \', \') from "dummy_has_many_models" where "dummy_models"."id" = "dummy_has_many_models"."dummy_model_id") as `dummy_has_many.name`, "dummy_models"."id" as "id" from "dummy_models" order by `dummy_has_many.name` asc, `id` asc', $subject->getQuery()->toSql()); + } + + /** @test */ + public function it_creates_a_multisort_query_builder_for_has_many_relation_column_with_specific_aggregate() + { + factory(DummyModel::class)->create()->dummy_has_many()->saveMany(factory(DummyHasManyModel::class, 2)->make()); + + $subject = new LivewireDatatable(1); + $subject->multisort = true; + $subject->mount(DummyModel::class, ['id', 'dummy_has_many.id:avg']); + + $this->assertEquals('select (select COALESCE(avg(dummy_has_many_models.id),0) from "dummy_has_many_models" where "dummy_models"."id" = "dummy_has_many_models"."dummy_model_id") as `dummy_has_many.id:avg`, "dummy_models"."id" as "id" from "dummy_models" order by `id` desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + + $this->assertEquals('select (select COALESCE(avg(dummy_has_many_models.id),0) from "dummy_has_many_models" where "dummy_models"."id" = "dummy_has_many_models"."dummy_model_id") as `dummy_has_many.id:avg`, "dummy_models"."id" as "id" from "dummy_models" order by `id` desc, `dummy_has_many.id:avg` desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + + $this->assertEquals('select (select COALESCE(avg(dummy_has_many_models.id),0) from "dummy_has_many_models" where "dummy_models"."id" = "dummy_has_many_models"."dummy_model_id") as `dummy_has_many.id:avg`, "dummy_models"."id" as "id" from "dummy_models" order by `id` desc, `dummy_has_many.id:avg` asc', $subject->getQuery()->toSql()); + } + + /** @test */ + public function it_creates_a_multisort_query_builder_for_belongs_to_relation_columns() + { + factory(DummyModel::class)->create()->dummy_has_many()->saveMany(factory(DummyHasManyModel::class, 2)->make()); + + $subject = new LivewireDatatable(1); + $subject->multisort = true; + $subject->mount(DummyHasManyModel::class, ['id', 'dummy_model.name']); + + $this->assertEquals('select "dummy_has_many_models"."id" as "id", "dummy_models"."name" as "dummy_model.name" from "dummy_has_many_models" left join "dummy_models" on "dummy_models"."id" = "dummy_has_many_models"."dummy_model_id" order by `id` desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + $subject->forgetComputed(); + + $this->assertEquals('select "dummy_has_many_models"."id" as "id", "dummy_models"."name" as "dummy_model.name" from "dummy_has_many_models" left join "dummy_models" on "dummy_models"."id" = "dummy_has_many_models"."dummy_model_id" order by dummy_has_many_models.id desc, dummy_models.name desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + $subject->forgetComputed(); + + $this->assertEquals('select "dummy_has_many_models"."id" as "id", "dummy_models"."name" as "dummy_model.name" from "dummy_has_many_models" left join "dummy_models" on "dummy_models"."id" = "dummy_has_many_models"."dummy_model_id" order by dummy_has_many_models.id desc, dummy_models.name asc', $subject->getQuery()->toSql()); + + $subject->sort(0); + $subject->forgetComputed(); + + $this->assertEquals('select "dummy_has_many_models"."id" as "id", "dummy_models"."name" as "dummy_model.name" from "dummy_has_many_models" left join "dummy_models" on "dummy_models"."id" = "dummy_has_many_models"."dummy_model_id" order by dummy_models.name asc, dummy_has_many_models.id asc', $subject->getQuery()->toSql()); + } + + /** @test */ + public function it_creates_a_multisort_query_builder_for_belongs_to_many_relation_columns() + { + factory(DummyModel::class)->create()->dummy_belongs_to_many()->attach(factory(DummyBelongsToManyModel::class)->create()); + + $subject = new LivewireDatatable(1); + $subject->multisort = true; + $subject->mount(DummyModel::class, ['id', 'dummy_belongs_to_many.name']); + + $this->assertEquals('select (select group_concat(REPLACE(DISTINCT(dummy_belongs_to_many_models.name), \'\', \'\') , \', \') from "dummy_belongs_to_many_models" inner join "dummy_belongs_to_many_model_dummy_model" on "dummy_belongs_to_many_models"."id" = "dummy_belongs_to_many_model_dummy_model"."dummy_belongs_to_many_model_id" where "dummy_models"."id" = "dummy_belongs_to_many_model_dummy_model"."dummy_model_id" and "dummy_belongs_to_many_models"."deleted_at" is null) as `dummy_belongs_to_many.name`, "dummy_models"."id" as "id" from "dummy_models" order by `id` desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + + $this->assertEquals('select (select group_concat(REPLACE(DISTINCT(dummy_belongs_to_many_models.name), \'\', \'\') , \', \') from "dummy_belongs_to_many_models" inner join "dummy_belongs_to_many_model_dummy_model" on "dummy_belongs_to_many_models"."id" = "dummy_belongs_to_many_model_dummy_model"."dummy_belongs_to_many_model_id" where "dummy_models"."id" = "dummy_belongs_to_many_model_dummy_model"."dummy_model_id" and "dummy_belongs_to_many_models"."deleted_at" is null) as `dummy_belongs_to_many.name`, "dummy_models"."id" as "id" from "dummy_models" order by `id` desc, `dummy_belongs_to_many.name` desc', $subject->getQuery()->toSql()); + + $subject->sort(1); + + $this->assertEquals('select (select group_concat(REPLACE(DISTINCT(dummy_belongs_to_many_models.name), \'\', \'\') , \', \') from "dummy_belongs_to_many_models" inner join "dummy_belongs_to_many_model_dummy_model" on "dummy_belongs_to_many_models"."id" = "dummy_belongs_to_many_model_dummy_model"."dummy_belongs_to_many_model_id" where "dummy_models"."id" = "dummy_belongs_to_many_model_dummy_model"."dummy_model_id" and "dummy_belongs_to_many_models"."deleted_at" is null) as `dummy_belongs_to_many.name`, "dummy_models"."id" as "id" from "dummy_models" order by `id` desc, `dummy_belongs_to_many.name` asc', $subject->getQuery()->toSql()); + + $subject->sort(0); + + $this->assertEquals('select (select group_concat(REPLACE(DISTINCT(dummy_belongs_to_many_models.name), \'\', \'\') , \', \') from "dummy_belongs_to_many_models" inner join "dummy_belongs_to_many_model_dummy_model" on "dummy_belongs_to_many_models"."id" = "dummy_belongs_to_many_model_dummy_model"."dummy_belongs_to_many_model_id" where "dummy_models"."id" = "dummy_belongs_to_many_model_dummy_model"."dummy_model_id" and "dummy_belongs_to_many_models"."deleted_at" is null) as `dummy_belongs_to_many.name`, "dummy_models"."id" as "id" from "dummy_models" order by `dummy_belongs_to_many.name` asc, `id` asc', $subject->getQuery()->toSql()); + } +} diff --git a/tests/LivewireDatatableQueryBuilderTest.php b/tests/LivewireDatatableQueryBuilderTest.php index 725b5c6f..11125c44 100644 --- a/tests/LivewireDatatableQueryBuilderTest.php +++ b/tests/LivewireDatatableQueryBuilderTest.php @@ -187,7 +187,7 @@ public function it_creates_a_query_builder_for_belongs_to_many_relation_columns( } /** @test */ - public function it_creates_a__where_query_for_belongs_to_many_relation_columns() + public function it_creates_a_where_query_for_belongs_to_many_relation_columns() { factory(DummyModel::class)->create()->dummy_belongs_to_many()->attach(factory(DummyBelongsToManyModel::class)->create()); diff --git a/tests/LivewireDatatableTemplateTest.php b/tests/LivewireDatatableTemplateTest.php index 3457b2a4..ef3748ba 100644 --- a/tests/LivewireDatatableTemplateTest.php +++ b/tests/LivewireDatatableTemplateTest.php @@ -2,6 +2,7 @@ namespace Mediconesystems\LivewireDatatables\Tests; +use Illuminate\Support\Str; use Livewire\Livewire; use Mediconesystems\LivewireDatatables\Http\Livewire\LivewireDatatable; use Mediconesystems\LivewireDatatables\Tests\Models\DummyModel; @@ -152,7 +153,7 @@ public function it_can_mark_columns_for_time_format_from_a_property() } /** @test */ - public function it_can_set_sort_from_a_property() + public function it_can_set_sort_from_property_using_column_name_and_direction() { factory(DummyModel::class)->create(); @@ -164,7 +165,82 @@ public function it_can_set_sort_from_a_property() $this->assertEquals('Mediconesystems\LivewireDatatables\Tests\Models\DummyModel', $subject->model); $this->assertIsArray($subject->columns); - $this->assertEquals(1, $subject->sort); - $this->assertTrue($subject->direction); + $this->assertEquals(['1|asc'], $subject->sort); + } + + /** @test */ + public function it_can_set_sort_from_property_using_column_index() + { + factory(DummyModel::class)->create(); + + $subject = Livewire::test(LivewireDatatable::class, [ + 'model' => DummyModel::class, + 'sort' => 1, + ]); + + $this->assertEquals('Mediconesystems\LivewireDatatables\Tests\Models\DummyModel', $subject->model); + $this->assertIsArray($subject->columns); + + $this->assertEquals(['1|desc'], $subject->sort); + } + + /** @test */ + public function it_can_set_sort_from_property_using_column_index_and_direction() + { + factory(DummyModel::class)->create(); + + $subject = Livewire::test(LivewireDatatable::class, [ + 'model' => DummyModel::class, + 'sort' => '1|asc', + ]); + + $this->assertEquals('Mediconesystems\LivewireDatatables\Tests\Models\DummyModel', $subject->model); + $this->assertIsArray($subject->columns); + + $this->assertEquals(['1|asc'], $subject->sort); + } + + /** @test */ + public function it_can_set_multisort_from_property_using_array() + { + factory(DummyModel::class)->create(); + + $subject = Livewire::test(LivewireDatatable::class, [ + 'model' => DummyModel::class, + 'multisort' => true, + 'sort' => [ + 'subject|asc', + 'category|desc', + ], + ]); + + $this->assertEquals('Mediconesystems\LivewireDatatables\Tests\Models\DummyModel', $subject->model); + $this->assertIsArray($subject->columns); + + $this->assertEquals(['1|asc', '2|desc'], $subject->sort); + $this->assertEquals($subject->freshColumns[1]['defaultSort'], 'asc'); + $this->assertEquals($subject->freshColumns[2]['defaultSort'], 'desc'); + $this->assertNull($subject->direction); + } + + /** @test */ + public function it_can_forget_multisort_session_on_demand() + { + factory(DummyModel::class)->create(); + + $subject = Livewire::test(LivewireDatatable::class, [ + 'model' => DummyModel::class, + 'multisort' => true, + ]); + + $this->assertEquals('Mediconesystems\LivewireDatatables\Tests\Models\DummyModel', $subject->model); + $this->assertIsArray($subject->columns); + + $subject->assertDontSee('Reset Columns Sort'); + $subject->call('sort', 1); + $subject->assertSee('Reset Columns Sort'); + $subject->assertSessionHas($multisortSessionKey = Str::snake(Str::afterLast(LivewireDatatable::class, '\\')) . '_multisort'); + $subject->call('forgetSortSession'); + $subject->assertSessionMissing($multisortSessionKey); } } diff --git a/tests/PutSortToSessionTest.php b/tests/PutSortToSessionTest.php new file mode 100644 index 00000000..5bedb958 --- /dev/null +++ b/tests/PutSortToSessionTest.php @@ -0,0 +1,60 @@ +create(); + + $subject = Livewire::test(LivewireDatatable::class, [ + 'model' => DummyModel::class, + ]); + + $subject->call('sort', 1); + $this->assertSession(1, ['1|desc'], $sortSessionKey = Str::snake(Str::afterLast(LivewireDatatable::class, '\\')) . '_sort'); + + $subject->call('sort', 1); + $this->assertSession(1, ['1|asc'], $sortSessionKey); + + $subject->call('sort', 0); + $this->assertSession(1, ['0|desc'], $sortSessionKey); + } + + /** @test */ + public function it_saves_sort_to_session_when_in_multisort() + { + factory(DummyModel::class)->create(); + + $subject = Livewire::test(LivewireDatatable::class, [ + 'model' => DummyModel::class, + 'multisort' => true, + ]); + + $subject->call('sort', 1); + $this->assertSession(2, ['0|desc', '1|desc'], $multisortSessionKey = Str::snake(Str::afterLast(LivewireDatatable::class, '\\')) . '_multisort'); + + $subject->call('sort', 1); + $this->assertSession(2, ['0|desc', '1|asc'], $multisortSessionKey); + + $subject->call('sort', 2); + $this->assertSession(3, ['0|desc', '1|asc', '2|desc'], $multisortSessionKey); + } + + private function assertSession(int $expectedCount, array $columnsIndexDirection, string $sessionKey) + { + $session = session()->get($sessionKey); + $this->assertCount($expectedCount, $session); + foreach ($columnsIndexDirection as $columnIndexDirection) { + $this->assertTrue(in_array($columnIndexDirection, $session)); + } + + } +}