mirror of
https://github.com/DigiLive/mushroom-strategy.git
synced 2025-06-25 01:21:52 +02:00
Release v2.3.0 (#195)
Adds: - Strategy: - SceneCard: Support for Stateful scenes. Closes #190. - ValveCard: A card to control an entity of the valve domain. Closes #192. - LockView: A view for entities of the lock domain. Closes #171. - Modules: - RegistryFilter: Advanced filtering and sorting of Home Assistant registries. - Auxiliaries: Generic utility functions. - Debug: Centralized logging and debug level management. - Tooling: - ESLint configuration for linting. - Prettier configuration for code formatting. Removes: - Redundant types and interface annotations. - Redundant legacy and unused modules. - Localization constant from the `Helper` module in favor of a new `localize` utility. Refactors: - References regarding change of repository owner. - Auxiliary functions are moved from the `Helper` module to `Auxiliaries` module. - `Helper` module is renamed to `Registry` for centralized state and registry management. - `ControllerCard` is renamed to `HeaderCard`. - Doc-blocks and comments are updated for clarity and consistency. - The file tree is restructured for improved clarity, modularity, and scalability. - Third party type definitions are updated and cleaned up. - Issue and Pull Request templates. Optimizations: - Parallelization of dynamic imports for views and cards. - Improved error handling and logging throughout the codebase. - Sanitization of HASS registries after import. - Enforced stricter and simplified types and interfaces. - Localization now available at global scope. Fixes: - Wrong type in configuration of `HeaderCard`. - Translation files: Resolved key inconsistencies. - Removed unnecessary namespaces from types. - Typos and Grammar. - Explicit use of `any` types. - Turn off all entities of a domain with a chip tap action. - Rendering too small HASS area cards. - Count of active vacuums. Bumps: - Mushroom Strategy - home-assistant-js-websocket - superstruct - ts-loader - ts-node - typescript - webpack - webpack-cli
This commit is contained in:
450
.editorconfig
450
.editorconfig
@ -1,13 +1,8 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
ij_continuation_indent_size = 2
|
||||
ij_formatter_off_tag = @formatter:off
|
||||
ij_formatter_on_tag = @formatter:on
|
||||
ij_formatter_tags_enabled = true
|
||||
ij_smart_tabs = false
|
||||
ij_visual_guides =
|
||||
ij_wrap_on_typing = false
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
@ -15,444 +10,5 @@ max_line_length = 120
|
||||
tab_width = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[.editorconfig]
|
||||
ij_editorconfig_align_group_field_declarations = false
|
||||
ij_editorconfig_space_after_colon = false
|
||||
ij_editorconfig_space_after_comma = true
|
||||
ij_editorconfig_space_before_colon = false
|
||||
ij_editorconfig_space_before_comma = false
|
||||
ij_editorconfig_spaces_around_assignment_operators = true
|
||||
|
||||
[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul,phpunit.xml.dist}]
|
||||
ij_xml_align_attributes = true
|
||||
ij_xml_align_text = false
|
||||
ij_xml_attribute_wrap = normal
|
||||
ij_xml_block_comment_add_space = false
|
||||
ij_xml_block_comment_at_first_column = true
|
||||
ij_xml_keep_blank_lines = 2
|
||||
ij_xml_keep_indents_on_empty_lines = false
|
||||
ij_xml_keep_line_breaks = true
|
||||
ij_xml_keep_line_breaks_in_text = true
|
||||
ij_xml_keep_whitespaces = false
|
||||
ij_xml_keep_whitespaces_around_cdata = preserve
|
||||
ij_xml_keep_whitespaces_inside_cdata = false
|
||||
ij_xml_line_comment_at_first_column = true
|
||||
ij_xml_space_after_tag_name = false
|
||||
ij_xml_space_around_equals_in_attribute = false
|
||||
ij_xml_space_inside_empty_tag = false
|
||||
ij_xml_text_wrap = normal
|
||||
|
||||
[{*.ats,*.cts,*.mts,*.ts}]
|
||||
ij_typescript_align_imports = false
|
||||
ij_typescript_align_multiline_array_initializer_expression = false
|
||||
ij_typescript_align_multiline_binary_operation = false
|
||||
ij_typescript_align_multiline_chained_methods = false
|
||||
ij_typescript_align_multiline_extends_list = false
|
||||
ij_typescript_align_multiline_for = true
|
||||
ij_typescript_align_multiline_parameters = true
|
||||
ij_typescript_align_multiline_parameters_in_calls = false
|
||||
ij_typescript_align_multiline_ternary_operation = false
|
||||
ij_typescript_align_object_properties = 0
|
||||
ij_typescript_align_union_types = false
|
||||
ij_typescript_align_var_statements = 1
|
||||
ij_typescript_array_initializer_new_line_after_left_brace = false
|
||||
ij_typescript_array_initializer_right_brace_on_new_line = false
|
||||
ij_typescript_array_initializer_wrap = off
|
||||
ij_typescript_assignment_wrap = off
|
||||
ij_typescript_binary_operation_sign_on_next_line = false
|
||||
ij_typescript_binary_operation_wrap = off
|
||||
ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
|
||||
ij_typescript_blank_lines_after_imports = 1
|
||||
ij_typescript_blank_lines_around_class = 0
|
||||
ij_typescript_blank_lines_around_field = 0
|
||||
ij_typescript_blank_lines_around_field_in_interface = 0
|
||||
ij_typescript_blank_lines_around_function = 1
|
||||
ij_typescript_blank_lines_around_method = 1
|
||||
ij_typescript_blank_lines_around_method_in_interface = 1
|
||||
ij_typescript_block_brace_style = end_of_line
|
||||
ij_typescript_block_comment_add_space = false
|
||||
ij_typescript_block_comment_at_first_column = true
|
||||
ij_typescript_call_parameters_new_line_after_left_paren = false
|
||||
ij_typescript_call_parameters_right_paren_on_new_line = false
|
||||
ij_typescript_call_parameters_wrap = off
|
||||
ij_typescript_catch_on_new_line = false
|
||||
ij_typescript_chained_call_dot_on_new_line = true
|
||||
ij_typescript_class_brace_style = end_of_line
|
||||
ij_typescript_comma_on_new_line = false
|
||||
ij_typescript_do_while_brace_force = never
|
||||
ij_typescript_else_on_new_line = false
|
||||
ij_typescript_enforce_trailing_comma = keep
|
||||
ij_typescript_enum_constants_wrap = on_every_item
|
||||
ij_typescript_extends_keyword_wrap = off
|
||||
ij_typescript_extends_list_wrap = off
|
||||
ij_typescript_field_prefix = _
|
||||
ij_typescript_file_name_style = relaxed
|
||||
ij_typescript_finally_on_new_line = false
|
||||
ij_typescript_for_brace_force = never
|
||||
ij_typescript_for_statement_new_line_after_left_paren = false
|
||||
ij_typescript_for_statement_right_paren_on_new_line = false
|
||||
ij_typescript_for_statement_wrap = off
|
||||
ij_typescript_force_quote_style = false
|
||||
ij_typescript_force_semicolon_style = false
|
||||
ij_typescript_function_expression_brace_style = end_of_line
|
||||
ij_typescript_if_brace_force = never
|
||||
ij_typescript_import_merge_members = global
|
||||
ij_typescript_import_prefer_absolute_path = global
|
||||
ij_typescript_import_sort_members = true
|
||||
ij_typescript_import_sort_module_name = false
|
||||
ij_typescript_import_use_node_resolution = true
|
||||
ij_typescript_imports_wrap = on_every_item
|
||||
ij_typescript_indent_case_from_switch = true
|
||||
ij_typescript_indent_chained_calls = true
|
||||
ij_typescript_indent_package_children = 0
|
||||
ij_typescript_jsdoc_include_types = false
|
||||
ij_typescript_jsx_attribute_value = braces
|
||||
ij_typescript_keep_blank_lines_in_code = 2
|
||||
ij_typescript_keep_first_column_comment = true
|
||||
ij_typescript_keep_indents_on_empty_lines = false
|
||||
ij_typescript_keep_line_breaks = true
|
||||
ij_typescript_keep_simple_blocks_in_one_line = true
|
||||
ij_typescript_keep_simple_methods_in_one_line = false
|
||||
ij_typescript_line_comment_add_space = true
|
||||
ij_typescript_line_comment_at_first_column = false
|
||||
ij_typescript_method_brace_style = end_of_line
|
||||
ij_typescript_method_call_chain_wrap = off
|
||||
ij_typescript_method_parameters_new_line_after_left_paren = false
|
||||
ij_typescript_method_parameters_right_paren_on_new_line = false
|
||||
ij_typescript_method_parameters_wrap = off
|
||||
ij_typescript_object_literal_wrap = on_every_item
|
||||
ij_typescript_object_types_wrap = on_every_item
|
||||
ij_typescript_parentheses_expression_new_line_after_left_paren = false
|
||||
ij_typescript_parentheses_expression_right_paren_on_new_line = false
|
||||
ij_typescript_place_assignment_sign_on_next_line = false
|
||||
ij_typescript_prefer_as_type_cast = false
|
||||
ij_typescript_prefer_explicit_types_function_expression_returns = false
|
||||
ij_typescript_prefer_explicit_types_function_returns = false
|
||||
ij_typescript_prefer_explicit_types_vars_fields = false
|
||||
ij_typescript_prefer_parameters_wrap = false
|
||||
ij_typescript_property_prefix =
|
||||
ij_typescript_reformat_c_style_comments = true
|
||||
ij_typescript_space_after_colon = true
|
||||
ij_typescript_space_after_comma = true
|
||||
ij_typescript_space_after_dots_in_rest_parameter = false
|
||||
ij_typescript_space_after_generator_mult = true
|
||||
ij_typescript_space_after_property_colon = true
|
||||
ij_typescript_space_after_quest = true
|
||||
ij_typescript_space_after_type_colon = true
|
||||
ij_typescript_space_after_unary_not = false
|
||||
ij_typescript_space_before_async_arrow_lparen = true
|
||||
ij_typescript_space_before_catch_keyword = true
|
||||
ij_typescript_space_before_catch_left_brace = true
|
||||
ij_typescript_space_before_catch_parentheses = true
|
||||
ij_typescript_space_before_class_lbrace = true
|
||||
ij_typescript_space_before_class_left_brace = true
|
||||
ij_typescript_space_before_colon = true
|
||||
ij_typescript_space_before_comma = false
|
||||
ij_typescript_space_before_do_left_brace = true
|
||||
ij_typescript_space_before_else_keyword = true
|
||||
ij_typescript_space_before_else_left_brace = true
|
||||
ij_typescript_space_before_finally_keyword = true
|
||||
ij_typescript_space_before_finally_left_brace = true
|
||||
ij_typescript_space_before_for_left_brace = true
|
||||
ij_typescript_space_before_for_parentheses = true
|
||||
ij_typescript_space_before_for_semicolon = false
|
||||
ij_typescript_space_before_function_left_parenth = true
|
||||
ij_typescript_space_before_generator_mult = false
|
||||
ij_typescript_space_before_if_left_brace = true
|
||||
ij_typescript_space_before_if_parentheses = true
|
||||
ij_typescript_space_before_method_call_parentheses = false
|
||||
ij_typescript_space_before_method_left_brace = true
|
||||
ij_typescript_space_before_method_parentheses = false
|
||||
ij_typescript_space_before_property_colon = false
|
||||
ij_typescript_space_before_quest = true
|
||||
ij_typescript_space_before_switch_left_brace = true
|
||||
ij_typescript_space_before_switch_parentheses = true
|
||||
ij_typescript_space_before_try_left_brace = true
|
||||
ij_typescript_space_before_type_colon = false
|
||||
ij_typescript_space_before_unary_not = false
|
||||
ij_typescript_space_before_while_keyword = true
|
||||
ij_typescript_space_before_while_left_brace = true
|
||||
ij_typescript_space_before_while_parentheses = true
|
||||
ij_typescript_spaces_around_additive_operators = true
|
||||
ij_typescript_spaces_around_arrow_function_operator = true
|
||||
ij_typescript_spaces_around_assignment_operators = true
|
||||
ij_typescript_spaces_around_bitwise_operators = true
|
||||
ij_typescript_spaces_around_equality_operators = true
|
||||
ij_typescript_spaces_around_logical_operators = true
|
||||
ij_typescript_spaces_around_multiplicative_operators = true
|
||||
ij_typescript_spaces_around_relational_operators = true
|
||||
ij_typescript_spaces_around_shift_operators = true
|
||||
ij_typescript_spaces_around_unary_operator = false
|
||||
ij_typescript_spaces_within_array_initializer_brackets = false
|
||||
ij_typescript_spaces_within_brackets = false
|
||||
ij_typescript_spaces_within_catch_parentheses = false
|
||||
ij_typescript_spaces_within_for_parentheses = false
|
||||
ij_typescript_spaces_within_if_parentheses = false
|
||||
ij_typescript_spaces_within_imports = false
|
||||
ij_typescript_spaces_within_interpolation_expressions = false
|
||||
ij_typescript_spaces_within_method_call_parentheses = false
|
||||
ij_typescript_spaces_within_method_parentheses = false
|
||||
ij_typescript_spaces_within_object_literal_braces = false
|
||||
ij_typescript_spaces_within_object_type_braces = true
|
||||
ij_typescript_spaces_within_parentheses = false
|
||||
ij_typescript_spaces_within_switch_parentheses = false
|
||||
ij_typescript_spaces_within_type_assertion = false
|
||||
ij_typescript_spaces_within_union_types = true
|
||||
ij_typescript_spaces_within_while_parentheses = false
|
||||
ij_typescript_special_else_if_treatment = true
|
||||
ij_typescript_ternary_operation_signs_on_next_line = false
|
||||
ij_typescript_ternary_operation_wrap = off
|
||||
ij_typescript_union_types_wrap = on_every_item
|
||||
ij_typescript_use_chained_calls_group_indents = false
|
||||
ij_typescript_use_double_quotes = true
|
||||
ij_typescript_use_explicit_js_extension = auto
|
||||
ij_typescript_use_import_type = auto
|
||||
ij_typescript_use_path_mapping = always
|
||||
ij_typescript_use_public_modifier = false
|
||||
ij_typescript_use_semicolon_after_statement = true
|
||||
ij_typescript_var_declaration_wrap = normal
|
||||
ij_typescript_while_brace_force = never
|
||||
ij_typescript_while_on_new_line = false
|
||||
ij_typescript_wrap_comments = false
|
||||
|
||||
[{*.cjs,*.js}]
|
||||
ij_javascript_align_imports = false
|
||||
ij_javascript_align_multiline_array_initializer_expression = false
|
||||
ij_javascript_align_multiline_binary_operation = false
|
||||
ij_javascript_align_multiline_chained_methods = false
|
||||
ij_javascript_align_multiline_extends_list = false
|
||||
ij_javascript_align_multiline_for = false
|
||||
ij_javascript_align_multiline_parameters = false
|
||||
ij_javascript_align_multiline_parameters_in_calls = false
|
||||
ij_javascript_align_multiline_ternary_operation = false
|
||||
ij_javascript_align_object_properties = 0
|
||||
ij_javascript_align_union_types = false
|
||||
ij_javascript_align_var_statements = 0
|
||||
ij_javascript_array_initializer_new_line_after_left_brace = false
|
||||
ij_javascript_array_initializer_right_brace_on_new_line = false
|
||||
ij_javascript_array_initializer_wrap = off
|
||||
ij_javascript_assignment_wrap = off
|
||||
ij_javascript_binary_operation_sign_on_next_line = false
|
||||
ij_javascript_binary_operation_wrap = off
|
||||
ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
|
||||
ij_javascript_blank_lines_after_imports = 1
|
||||
ij_javascript_blank_lines_around_class = 1
|
||||
ij_javascript_blank_lines_around_field = 0
|
||||
ij_javascript_blank_lines_around_function = 1
|
||||
ij_javascript_blank_lines_around_method = 1
|
||||
ij_javascript_block_brace_style = end_of_line
|
||||
ij_javascript_block_comment_add_space = false
|
||||
ij_javascript_block_comment_at_first_column = true
|
||||
ij_javascript_call_parameters_new_line_after_left_paren = false
|
||||
ij_javascript_call_parameters_right_paren_on_new_line = false
|
||||
ij_javascript_call_parameters_wrap = off
|
||||
ij_javascript_catch_on_new_line = false
|
||||
ij_javascript_chained_call_dot_on_new_line = true
|
||||
ij_javascript_class_brace_style = end_of_line
|
||||
ij_javascript_comma_on_new_line = false
|
||||
ij_javascript_do_while_brace_force = never
|
||||
ij_javascript_else_on_new_line = false
|
||||
ij_javascript_enforce_trailing_comma = keep
|
||||
ij_javascript_extends_keyword_wrap = off
|
||||
ij_javascript_extends_list_wrap = off
|
||||
ij_javascript_field_prefix = _
|
||||
ij_javascript_file_name_style = relaxed
|
||||
ij_javascript_finally_on_new_line = false
|
||||
ij_javascript_for_brace_force = never
|
||||
ij_javascript_for_statement_new_line_after_left_paren = false
|
||||
ij_javascript_for_statement_right_paren_on_new_line = false
|
||||
ij_javascript_for_statement_wrap = off
|
||||
ij_javascript_force_quote_style = true
|
||||
ij_javascript_force_semicolon_style = true
|
||||
ij_javascript_function_expression_brace_style = end_of_line
|
||||
ij_javascript_if_brace_force = never
|
||||
ij_javascript_import_merge_members = global
|
||||
ij_javascript_import_prefer_absolute_path = global
|
||||
ij_javascript_import_sort_members = true
|
||||
ij_javascript_import_sort_module_name = false
|
||||
ij_javascript_import_use_node_resolution = true
|
||||
ij_javascript_imports_wrap = on_every_item
|
||||
ij_javascript_indent_case_from_switch = true
|
||||
ij_javascript_indent_chained_calls = true
|
||||
ij_javascript_indent_package_children = 0
|
||||
ij_javascript_jsx_attribute_value = braces
|
||||
ij_javascript_keep_blank_lines_in_code = 1
|
||||
ij_javascript_keep_first_column_comment = true
|
||||
ij_javascript_keep_indents_on_empty_lines = false
|
||||
ij_javascript_keep_line_breaks = true
|
||||
ij_javascript_keep_simple_blocks_in_one_line = true
|
||||
ij_javascript_keep_simple_methods_in_one_line = true
|
||||
ij_javascript_line_comment_add_space = true
|
||||
ij_javascript_line_comment_at_first_column = false
|
||||
ij_javascript_method_brace_style = end_of_line
|
||||
ij_javascript_method_call_chain_wrap = off
|
||||
ij_javascript_method_parameters_new_line_after_left_paren = false
|
||||
ij_javascript_method_parameters_right_paren_on_new_line = false
|
||||
ij_javascript_method_parameters_wrap = off
|
||||
ij_javascript_object_literal_wrap = on_every_item
|
||||
ij_javascript_object_types_wrap = on_every_item
|
||||
ij_javascript_parentheses_expression_new_line_after_left_paren = false
|
||||
ij_javascript_parentheses_expression_right_paren_on_new_line = false
|
||||
ij_javascript_place_assignment_sign_on_next_line = false
|
||||
ij_javascript_prefer_as_type_cast = false
|
||||
ij_javascript_prefer_explicit_types_function_expression_returns = false
|
||||
ij_javascript_prefer_explicit_types_function_returns = false
|
||||
ij_javascript_prefer_explicit_types_vars_fields = false
|
||||
ij_javascript_prefer_parameters_wrap = false
|
||||
ij_javascript_property_prefix =
|
||||
ij_javascript_reformat_c_style_comments = false
|
||||
ij_javascript_space_after_colon = true
|
||||
ij_javascript_space_after_comma = true
|
||||
ij_javascript_space_after_dots_in_rest_parameter = false
|
||||
ij_javascript_space_after_generator_mult = true
|
||||
ij_javascript_space_after_property_colon = true
|
||||
ij_javascript_space_after_quest = true
|
||||
ij_javascript_space_after_type_colon = true
|
||||
ij_javascript_space_after_unary_not = false
|
||||
ij_javascript_space_before_async_arrow_lparen = true
|
||||
ij_javascript_space_before_catch_keyword = true
|
||||
ij_javascript_space_before_catch_left_brace = true
|
||||
ij_javascript_space_before_catch_parentheses = true
|
||||
ij_javascript_space_before_class_lbrace = true
|
||||
ij_javascript_space_before_class_left_brace = true
|
||||
ij_javascript_space_before_colon = true
|
||||
ij_javascript_space_before_comma = false
|
||||
ij_javascript_space_before_do_left_brace = true
|
||||
ij_javascript_space_before_else_keyword = true
|
||||
ij_javascript_space_before_else_left_brace = true
|
||||
ij_javascript_space_before_finally_keyword = true
|
||||
ij_javascript_space_before_finally_left_brace = true
|
||||
ij_javascript_space_before_for_left_brace = true
|
||||
ij_javascript_space_before_for_parentheses = true
|
||||
ij_javascript_space_before_for_semicolon = false
|
||||
ij_javascript_space_before_function_left_parenth = true
|
||||
ij_javascript_space_before_generator_mult = true
|
||||
ij_javascript_space_before_if_left_brace = true
|
||||
ij_javascript_space_before_if_parentheses = true
|
||||
ij_javascript_space_before_method_call_parentheses = false
|
||||
ij_javascript_space_before_method_left_brace = true
|
||||
ij_javascript_space_before_method_parentheses = false
|
||||
ij_javascript_space_before_property_colon = false
|
||||
ij_javascript_space_before_quest = true
|
||||
ij_javascript_space_before_switch_left_brace = true
|
||||
ij_javascript_space_before_switch_parentheses = true
|
||||
ij_javascript_space_before_try_left_brace = true
|
||||
ij_javascript_space_before_type_colon = false
|
||||
ij_javascript_space_before_unary_not = false
|
||||
ij_javascript_space_before_while_keyword = true
|
||||
ij_javascript_space_before_while_left_brace = true
|
||||
ij_javascript_space_before_while_parentheses = true
|
||||
ij_javascript_spaces_around_additive_operators = true
|
||||
ij_javascript_spaces_around_arrow_function_operator = true
|
||||
ij_javascript_spaces_around_assignment_operators = true
|
||||
ij_javascript_spaces_around_bitwise_operators = true
|
||||
ij_javascript_spaces_around_equality_operators = true
|
||||
ij_javascript_spaces_around_logical_operators = true
|
||||
ij_javascript_spaces_around_multiplicative_operators = true
|
||||
ij_javascript_spaces_around_relational_operators = true
|
||||
ij_javascript_spaces_around_shift_operators = true
|
||||
ij_javascript_spaces_around_unary_operator = false
|
||||
ij_javascript_spaces_within_array_initializer_brackets = false
|
||||
ij_javascript_spaces_within_brackets = false
|
||||
ij_javascript_spaces_within_catch_parentheses = false
|
||||
ij_javascript_spaces_within_for_parentheses = false
|
||||
ij_javascript_spaces_within_if_parentheses = false
|
||||
ij_javascript_spaces_within_imports = false
|
||||
ij_javascript_spaces_within_interpolation_expressions = false
|
||||
ij_javascript_spaces_within_method_call_parentheses = false
|
||||
ij_javascript_spaces_within_method_parentheses = false
|
||||
ij_javascript_spaces_within_object_literal_braces = true
|
||||
ij_javascript_spaces_within_object_type_braces = true
|
||||
ij_javascript_spaces_within_parentheses = false
|
||||
ij_javascript_spaces_within_switch_parentheses = false
|
||||
ij_javascript_spaces_within_type_assertion = false
|
||||
ij_javascript_spaces_within_union_types = true
|
||||
ij_javascript_spaces_within_while_parentheses = false
|
||||
ij_javascript_special_else_if_treatment = true
|
||||
ij_javascript_ternary_operation_signs_on_next_line = true
|
||||
ij_javascript_ternary_operation_wrap = off
|
||||
ij_javascript_union_types_wrap = on_every_item
|
||||
ij_javascript_use_chained_calls_group_indents = false
|
||||
ij_javascript_use_double_quotes = true
|
||||
ij_javascript_use_explicit_js_extension = auto
|
||||
ij_javascript_use_path_mapping = always
|
||||
ij_javascript_use_public_modifier = false
|
||||
ij_javascript_use_semicolon_after_statement = true
|
||||
ij_javascript_var_declaration_wrap = normal
|
||||
ij_javascript_while_brace_force = never
|
||||
ij_javascript_while_on_new_line = false
|
||||
ij_javascript_wrap_comments = false
|
||||
|
||||
[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.prettierrc,.remarkrc,.stylelintrc,bowerrc,composer.lock,jest.config}]
|
||||
ij_json_array_wrapping = split_into_lines
|
||||
ij_json_keep_blank_lines_in_code = 0
|
||||
ij_json_keep_indents_on_empty_lines = false
|
||||
ij_json_keep_line_breaks = true
|
||||
ij_json_keep_trailing_comma = false
|
||||
ij_json_object_wrapping = split_into_lines
|
||||
ij_json_property_alignment = do_not_align
|
||||
ij_json_space_after_colon = true
|
||||
ij_json_space_after_comma = true
|
||||
ij_json_space_before_colon = false
|
||||
ij_json_space_before_comma = false
|
||||
ij_json_spaces_within_braces = false
|
||||
ij_json_spaces_within_brackets = false
|
||||
ij_json_wrap_long_lines = false
|
||||
|
||||
[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}]
|
||||
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
|
||||
ij_html_align_attributes = true
|
||||
ij_html_align_text = false
|
||||
ij_html_attribute_wrap = normal
|
||||
ij_html_block_comment_add_space = false
|
||||
ij_html_block_comment_at_first_column = true
|
||||
ij_html_do_not_align_children_of_min_lines = 0
|
||||
ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p
|
||||
ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot
|
||||
ij_html_enforce_quotes = false
|
||||
ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var
|
||||
ij_html_keep_blank_lines = 2
|
||||
ij_html_keep_indents_on_empty_lines = false
|
||||
ij_html_keep_line_breaks = true
|
||||
ij_html_keep_line_breaks_in_text = true
|
||||
ij_html_keep_whitespaces = false
|
||||
ij_html_keep_whitespaces_inside = span,pre,textarea
|
||||
ij_html_line_comment_at_first_column = true
|
||||
ij_html_new_line_after_last_attribute = never
|
||||
ij_html_new_line_before_first_attribute = never
|
||||
ij_html_quote_style = double
|
||||
ij_html_remove_new_line_before_tags = br
|
||||
ij_html_space_after_tag_name = false
|
||||
ij_html_space_around_equality_in_attribute = false
|
||||
ij_html_space_inside_empty_tag = false
|
||||
ij_html_text_wrap = normal
|
||||
|
||||
[{*.markdown,*.md}]
|
||||
ij_markdown_force_one_space_after_blockquote_symbol = true
|
||||
ij_markdown_force_one_space_after_header_symbol = true
|
||||
ij_markdown_force_one_space_after_list_bullet = true
|
||||
ij_markdown_force_one_space_between_words = true
|
||||
ij_markdown_format_tables = true
|
||||
ij_markdown_insert_quote_arrows_on_wrap = true
|
||||
ij_markdown_keep_indents_on_empty_lines = false
|
||||
ij_markdown_keep_line_breaks_inside_text_blocks = true
|
||||
ij_markdown_max_lines_around_block_elements = 1
|
||||
ij_markdown_max_lines_around_header = 1
|
||||
ij_markdown_max_lines_between_paragraphs = 1
|
||||
ij_markdown_min_lines_around_block_elements = 1
|
||||
ij_markdown_min_lines_around_header = 1
|
||||
ij_markdown_min_lines_between_paragraphs = 1
|
||||
ij_markdown_wrap_text_if_long = true
|
||||
ij_markdown_wrap_text_inside_blockquotes = true
|
||||
|
||||
[{*.yaml,*.yml}]
|
||||
ij_yaml_align_values_properties = do_not_align
|
||||
ij_yaml_autoinsert_sequence_marker = true
|
||||
ij_yaml_block_mapping_on_new_line = false
|
||||
ij_yaml_indent_sequence_value = true
|
||||
ij_yaml_keep_indents_on_empty_lines = false
|
||||
ij_yaml_keep_line_breaks = true
|
||||
ij_yaml_sequence_on_new_line = false
|
||||
ij_yaml_space_before_colon = false
|
||||
ij_yaml_spaces_within_braces = true
|
||||
ij_yaml_spaces_within_brackets = true
|
||||
trim_trailing_whitespace = false
|
||||
|
72
.eslintrc
72
.eslintrc
@ -0,0 +1,72 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"es2020": true,
|
||||
"node": true
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020,
|
||||
"project": "./tsconfig.json",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"ignorePatterns": [
|
||||
"dist/",
|
||||
"node_modules/",
|
||||
"*.js",
|
||||
"src/types/homeassistant/",
|
||||
"src/types/lovelace-mushroom/"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"webpack.config.ts",
|
||||
"webpack.dev.config.ts"
|
||||
],
|
||||
"parserOptions": {
|
||||
"project": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-empty-function": "warn",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"warn",
|
||||
{
|
||||
"argsIgnorePattern": "^_"
|
||||
}
|
||||
],
|
||||
"comma-dangle": [
|
||||
"error",
|
||||
"always-multiline"
|
||||
],
|
||||
"max-len": [
|
||||
"warn",
|
||||
{
|
||||
"code": 120
|
||||
}
|
||||
],
|
||||
"no-console": "off",
|
||||
"no-empty-function": "off",
|
||||
"no-unused-vars": "off",
|
||||
"quotes": [
|
||||
"error",
|
||||
"single",
|
||||
{
|
||||
"avoidEscape": true
|
||||
}
|
||||
],
|
||||
"semi": [
|
||||
"error",
|
||||
"always"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,34 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Versions**
|
||||
* Mushroom-Strategy:
|
||||
* HACS:
|
||||
* Mushroom:
|
||||
* Home Assistant:
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '…'
|
||||
2. Click on '…'
|
||||
3. Scroll down to '…'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
103
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
103
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
name: Bug Report
|
||||
description: File a bug report to help us improve the project.
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to report a bug!
|
||||
Please fill out the requested information to help us understand and reproduce the issue.
|
||||
|
||||
- type: input
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Briefly describe the bug you encountered.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduce
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Please provide clear and concise steps to reproduce the issue. Be as detailed as possible.
|
||||
placeholder: |
|
||||
1. ...
|
||||
2. ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: versions
|
||||
attributes:
|
||||
label: Versions
|
||||
description: Please provide the versions you use of the items below
|
||||
placeholder: |
|
||||
- Mushroom Dashboard:
|
||||
- Lovelace Mushroom:
|
||||
- Home Assistant:
|
||||
value: |
|
||||
- Mushroom Dashboard:
|
||||
- Lovelace Mushroom:
|
||||
- Home Assistant:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: What environment were you using when you encountered the bug?
|
||||
options:
|
||||
- "Web Browser (specify name and version)"
|
||||
- "Mobile Application (specify OS and version)"
|
||||
- "Other (please specify, including version)"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: environment-version
|
||||
attributes:
|
||||
label: Environment and Version
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What did you expect to happen?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What actually happened?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: error-logs
|
||||
attributes:
|
||||
label: Error Logs (if applicable)
|
||||
description: If you encountered any error messages or logs, please include them here.
|
||||
render: plain text
|
||||
|
||||
- type: textarea
|
||||
id: additional-information
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: Please provide any other relevant information or attachments that might help in understanding the issue.
|
||||
placeholder: |
|
||||
Add additional information or drop files here.
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Guidelines
|
||||
description: By submitting this issue, you agree to abide by our [contribution guidelines](blob/main/CONTRIBUTING.md).
|
||||
options:
|
||||
- label: I have read and agree to the guidelines.
|
||||
required: true
|
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Wiki
|
||||
url: https://github.com/DigiLive/mushroom-strategy/wiki
|
||||
about: Please consult to Wiki for more information about the strategy and how to configure it.
|
||||
- name: Discussions
|
||||
url: https://github.com/DigiLive/mushroom-strategy/discussions
|
||||
about: Discuss any other topic about the strategy over here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
88
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
88
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
name: Feature Request
|
||||
description: Suggest a new feature or improvement for the project.
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to suggest a new feature!
|
||||
Please provide as much detail as possible so we can understand your idea and its potential impact.
|
||||
|
||||
- type: input
|
||||
id: feature-title
|
||||
attributes:
|
||||
label: Feature Title
|
||||
description: Briefly and clearly describe your proposed feature.
|
||||
placeholder: e.g., Add support for...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: what-is-it
|
||||
attributes:
|
||||
label: What is the feature?
|
||||
description: Describe the feature in detail. What would it do? How would it work?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: problem-it-solves
|
||||
attributes:
|
||||
label: What problem does this feature solve?
|
||||
description: Explain the user need or pain point that this feature addresses. Why is it important?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: proposed-solution
|
||||
attributes:
|
||||
label: Proposed Solution (Optional)
|
||||
description: |
|
||||
If you have specific ideas on how this feature could be implemented, please share them here.
|
||||
Include any technical details or UI/UX suggestions.
|
||||
|
||||
- type: dropdown
|
||||
id: affected-area
|
||||
attributes:
|
||||
label: Affected Area (Optional)
|
||||
description: If this feature primarily relates to a specific part of the project, please indicate it.
|
||||
options:
|
||||
- User Interface (UI)
|
||||
- User Experience (UX)
|
||||
- Performance
|
||||
- Security
|
||||
- Documentation
|
||||
- Other (please specify below)
|
||||
default: 0
|
||||
|
||||
- type: input
|
||||
id: affected-area-other
|
||||
attributes:
|
||||
label: Other Affected Area (if selected above)
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: alternatives-considered
|
||||
attributes:
|
||||
label: Alternatives Considered (Optional)
|
||||
description: |
|
||||
Have you considered any alternative solutions or workarounds?
|
||||
If so, please describe them and why you think this proposed feature is better.
|
||||
|
||||
- type: textarea
|
||||
id: mockups-designs
|
||||
attributes:
|
||||
label: Mockups or Designs (Optional)
|
||||
description: |
|
||||
If you have any mockups, wireframes, or design ideas to illustrate your feature,
|
||||
you can describe them here or attach them to the issue.
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Guidelines
|
||||
description: By submitting this issue, you agree to abide by our [contribution guidelines](blob/main/CONTRIBUTING.md).
|
||||
options:
|
||||
- label: I have read and agree to the guidelines.
|
||||
required: true
|
50
.github/PULL_REQUEST_TEMPLATE.md
vendored
50
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,43 +1,13 @@
|
||||
Please click the `Preview` tab and select the type of Pull Request you are submitting.
|
||||
|
||||
- [Bug Fix](?expand=1&template=bugfix.md)
|
||||
- [Feature](?expand=1&template=feature.md)
|
||||
|
||||
> [!NOTE]
|
||||
> Follow the instructions inside the brackets and remove them.
|
||||
> In the Title field above, Provide a succinct and descriptive title for the pull request, e.g., "Improve caching mechanism for API calls"
|
||||
> The above types do not apply to any translation itself.
|
||||
> To add or fix a translation, select a type below.
|
||||
>
|
||||
> Follow the commit guidelines as described at https://github.com/DigiLive/gitChangelog/wiki/1-Introduction
|
||||
> - [Translation Contribution](?expand=1&template=translation.md)
|
||||
|
||||
## Description
|
||||
|
||||
[Provide a detailed explanation of the changes you have made. Include the reasons behind these changes and any relevant context. Link any related issues.]
|
||||
|
||||
## Type of Change
|
||||
|
||||
_Put an `x` in all boxes that apply_
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] Hot fix (corrects a major software bug or fault and should released as quickly as possible.)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] Documentation update
|
||||
- [ ] Refactoring
|
||||
- [ ] Security patch
|
||||
- [ ] UI/UX improvement
|
||||
|
||||
## Testing
|
||||
|
||||
[Detail the testing you have performed to ensure that these changes function as intended. Include information about any added tests.]
|
||||
|
||||
## Impact
|
||||
|
||||
[Discuss the impact of your changes on the project. This might include effects on performance, new dependencies, or changes in behaviour.]
|
||||
|
||||
## Additional Information
|
||||
|
||||
[Any additional information that reviewers should be aware of.]<br>
|
||||
[E.g.: Add (before/after) images when visual changes are applied.]
|
||||
|
||||
## Checklist
|
||||
|
||||
_Put an `x` in all boxes that apply_
|
||||
- [ ] My code adheres to the [coding and style guidelines](https://github.com/AalianKhan/mushroom-strategy/blob/main/CONTRIBUTING.md) of the project.
|
||||
- [ ] I have performed a self-review of my own code.
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas.
|
||||
- [ ] I have made corresponding changes to the documentation.
|
||||
- [ ] My changes generate no new warnings.
|
||||
> [!CAUTION]
|
||||
> Any Pull Request that does not follow the above types will be rejected.
|
||||
|
67
.github/PULL_REQUEST_TEMPLATE/bugfix.md
vendored
Normal file
67
.github/PULL_REQUEST_TEMPLATE/bugfix.md
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
# Bug Fix Pull Request
|
||||
|
||||
Thank you for contributing to the project by fixing this bug!
|
||||
Please fill out the following information to help us review your pull request.
|
||||
|
||||
---
|
||||
|
||||
### Bug Summary
|
||||
|
||||
Explain why this fix is needed and what problem it solves.
|
||||
If it relates to an existing issue, please link it.
|
||||
See [Linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue).
|
||||
|
||||
[Briefly describe the bug you are fixing]
|
||||
|
||||
---
|
||||
|
||||
### Motivation and Context
|
||||
|
||||
Explain why this bug needs to be fixed and the impact it has on the project or users.
|
||||
|
||||
[Your explanation here]
|
||||
|
||||
---
|
||||
|
||||
### List of Changes
|
||||
|
||||
[Provide a concise list of the main changes introduced by this pull request to fix the bug.]
|
||||
|
||||
- ...
|
||||
|
||||
### Steps to Reproduce (if not covered in the linked issue)
|
||||
|
||||
If the steps to reproduce the bug are not clearly outlined in the linked issue, please provide them here:
|
||||
|
||||
1. ...
|
||||
2. ...
|
||||
|
||||
### Expected Behavior (if not covered in the linked issue)
|
||||
|
||||
Describe what the expected behavior should have been before the bug occurred.
|
||||
|
||||
[Your description of the expected behavior]
|
||||
|
||||
### Actual Behavior (if not covered in the linked issue)
|
||||
|
||||
Describe the actual behavior that occurred due to the bug.
|
||||
|
||||
[Your description of the actual behavior]
|
||||
|
||||
---
|
||||
|
||||
### Wiki Updates
|
||||
|
||||
[If this bug fix requires any updates to the Wiki, please provide details here.]
|
||||
|
||||
---
|
||||
|
||||
### Agreements
|
||||
|
||||
Please confirm the following by inserting an `x` between the brackets:
|
||||
|
||||
- [ ] My code adheres to the [contribution guidelines](blob/main/CONTRIBUTING.md) of the project.
|
||||
- [ ] My changes generate no new warnings.
|
||||
- [ ] I have performed a self-review of my own code.
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas.
|
||||
- [ ] I have made corresponding changes to the documentation.
|
44
.github/PULL_REQUEST_TEMPLATE/feature.md
vendored
Normal file
44
.github/PULL_REQUEST_TEMPLATE/feature.md
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
# Feature Pull Request
|
||||
|
||||
Thank you for contributing to the project!
|
||||
Please fill out the following information to help us review your pull request.
|
||||
|
||||
---
|
||||
|
||||
### Feature Summary
|
||||
|
||||
[Briefly describe the feature you are proposing]
|
||||
|
||||
---
|
||||
|
||||
### Motivation and Context
|
||||
|
||||
Explain why this feature is needed and what problem it solves.
|
||||
If it relates to an existing issue, please link it.
|
||||
See [Linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue).
|
||||
|
||||
[Your explanation here]
|
||||
|
||||
---
|
||||
|
||||
### List of Changes
|
||||
|
||||
[Provide a concise list of the main changes introduced by this pull request.]
|
||||
|
||||
- ...
|
||||
|
||||
### Wiki Updates
|
||||
|
||||
[If this bug feature requires any updates to the Wiki, please provide details here.]
|
||||
|
||||
---
|
||||
|
||||
### Agreements
|
||||
|
||||
Please confirm the following by inserting an `x` between the brackets:
|
||||
|
||||
- [ ] My code adheres to the [contribution guidelines](blob/main/CONTRIBUTING.md) of the project.
|
||||
- [ ] My changes generate no new warnings.
|
||||
- [ ] I have performed a self-review of my own code.
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas.
|
||||
- [ ] I have made corresponding changes to the documentation.
|
71
.github/PULL_REQUEST_TEMPLATE/translation.md
vendored
Normal file
71
.github/PULL_REQUEST_TEMPLATE/translation.md
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
# Translation Contribution Pull Request
|
||||
|
||||
Thank you for contributing to the project's internationalization efforts!
|
||||
Please fill out the following information to help us review your translation changes.
|
||||
|
||||
---
|
||||
|
||||
### Type of Translation Contribution
|
||||
|
||||
Please select the type of contribution:
|
||||
|
||||
- [ ] Adding a new language translation
|
||||
- [ ] Fixing errors or improving an existing translation
|
||||
- [ ] Updating an existing translation with new strings
|
||||
|
||||
---
|
||||
|
||||
### Target Language
|
||||
|
||||
Please specify the language you are adding or modifying:
|
||||
|
||||
[List the target language here]
|
||||
|
||||
---
|
||||
|
||||
### Motivation and Context
|
||||
|
||||
Explain why this translation (addition, fix, or update) is needed.
|
||||
- For fixes, please describe the original error.
|
||||
- For updates, briefly explain the context of the new strings.
|
||||
|
||||
[Your explanation here]
|
||||
|
||||
---
|
||||
|
||||
### Scope of Changes
|
||||
|
||||
Please describe the scope of your translation changes.
|
||||
Which parts of the project are affected by these translations?
|
||||
|
||||
[Describe the affected areas]
|
||||
|
||||
---
|
||||
|
||||
### List of Changes
|
||||
|
||||
Provide a concise list of the main changes you've made in this pull request.
|
||||
If it's a large update, you can highlight key areas.
|
||||
|
||||
- ...
|
||||
|
||||
---
|
||||
|
||||
### Considerations for Reviewers
|
||||
|
||||
Are there any specific areas you would like reviewers to pay extra attention to?
|
||||
For example, specific terminology, cultural nuances, or consistency with existing translations.
|
||||
|
||||
[Any specific instructions for reviewers]
|
||||
|
||||
---
|
||||
|
||||
### Agreements
|
||||
|
||||
Please confirm the following:
|
||||
|
||||
- [ ] My code adheres to the [contribution guidelines](blob/main/CONTRIBUTING.md) of the project.
|
||||
- [ ] I have reviewed the existing translations for consistency.
|
||||
- [ ] I have used appropriate terminology and followed any project-specific translation guidelines.
|
||||
- [ ] I have tested the translations to the best of my ability.
|
||||
- [ ] My changes generate no new warnings or errors related to internationalization.
|
6
.github/workflows/validate.yml
vendored
6
.github/workflows/validate.yml
vendored
@ -1,8 +1,8 @@
|
||||
name: HACS validation
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
hacs:
|
||||
name: HACS Action
|
||||
|
58
.github/workflows/webpack.yml
vendored
58
.github/workflows/webpack.yml
vendored
@ -18,40 +18,40 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x]
|
||||
node-version: [ 18.x ]
|
||||
|
||||
# Checkout Repository
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.WORKFLOW_GIT_ACCESS_TOKEN }}
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.WORKFLOW_GIT_ACCESS_TOKEN }}
|
||||
|
||||
# Build steps
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
# Build steps
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Node Install
|
||||
run: npm ci
|
||||
- name: Node Install
|
||||
run: npm ci
|
||||
|
||||
- name: Build Distribution
|
||||
run: |
|
||||
npm run build
|
||||
- name: Build Distribution
|
||||
run: |
|
||||
npm run build
|
||||
|
||||
- name: Check for file changes
|
||||
id: checkDiff
|
||||
run: |
|
||||
git diff --quiet . || echo "changed=true" >> $GITHUB_OUTPUT
|
||||
- name: Check for file changes
|
||||
id: checkDiff
|
||||
run: |
|
||||
git diff --quiet . || echo "changed=true" >> $GITHUB_OUTPUT
|
||||
|
||||
# Commit and push all changed files.
|
||||
# Must only affect files that are listed in "paths-ignore".
|
||||
- name: GIT Commit Distribution Build
|
||||
# Only run on main branch push (e.g., pull request merge).
|
||||
if: github.event_name == 'push' && steps.checkDiff.outputs.changed == 'true'
|
||||
run: |
|
||||
git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}"
|
||||
git config --global user.email "ci_activity@noreply.github.com"
|
||||
git add dist
|
||||
git commit -m "${{ env.CI_COMMIT_MESSAGE }}"
|
||||
git push
|
||||
# Commit and push all changed files.
|
||||
# Must only affect files that are listed in "paths-ignore".
|
||||
- name: GIT Commit Distribution Build
|
||||
# Only run on a main branch push (e.g., pull request merge).
|
||||
if: github.event_name == 'push' && steps.checkDiff.outputs.changed == 'true'
|
||||
run: |
|
||||
git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}"
|
||||
git config --global user.email "ci_activity@noreply.github.com"
|
||||
git add dist
|
||||
git commit -m "${{ env.CI_COMMIT_MESSAGE }}"
|
||||
git push
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
/node_modules/
|
||||
/dist/
|
14
.prettierrc
Normal file
14
.prettierrc
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"arrowParens": "always",
|
||||
"bracketSpacing": true,
|
||||
"endOfLine": "lf",
|
||||
"jsxSingleQuote": true,
|
||||
"printWidth": 120,
|
||||
"proseWrap": "preserve",
|
||||
"quoteProps": "as-needed",
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "all",
|
||||
"useTabs": false
|
||||
}
|
@ -38,7 +38,7 @@ decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing
|
||||
This Code of Conduct applies within all community spaces and also applies when an individual is officially representing
|
||||
the community in public spaces. Examples of representing our community include using an official e-mail address, posting
|
||||
via an official social media account, or acting as an appointed representative at an online or offline event.
|
||||
|
||||
|
@ -6,17 +6,18 @@ All types of contributions are encouraged and valued.
|
||||
See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles
|
||||
them.
|
||||
|
||||
Please make sure to read the relevant section before making your contribution.
|
||||
It will make it a lot easier for us maintainers and smooth out the experience for all involved.
|
||||
Please make sure to read the relevant section before making your contribution.
|
||||
It will make it a lot easier for us maintainers and smooth out the experience for all involved.
|
||||
The community looks forward to your contributions.
|
||||
|
||||
> And if you like the project but just don't have time to contribute, that's fine.
|
||||
> There are other easy ways to support the project and show your appreciation, which we would also be thrilled about:
|
||||
> - Star the project
|
||||
> - Tweet about it
|
||||
> - Refer this project at your project's readme
|
||||
> - Mention the project at local meetups and tell your friends/colleagues
|
||||
> - Sponsor the project at GitHub Sponsors
|
||||
>
|
||||
> - Star the project.
|
||||
> - Tweet about it.
|
||||
> - Refer to this project in the readme of your project.
|
||||
> - Mention the project at local meetups and tell your friends/colleagues.
|
||||
> - Sponsor the project at [GitHub Sponsors][sponsorUrl].
|
||||
|
||||
## Table of Contents
|
||||
|
||||
@ -43,9 +44,9 @@ By participating, you are expected to uphold this code. Please report unacceptab
|
||||
|
||||
> [!TIP]
|
||||
> Before you ask a question, we assume that you have read the [README](README.md) file or the
|
||||
> available [Documentation](../../wiki).
|
||||
> available resources at the [Wiki][wikiUrl] or [Discussions][discussionsUrl].
|
||||
|
||||
Before you ask a question, it is best to search for existing [discussions](../../discussions) or [Issues](../../issues)
|
||||
Before you ask a question, it is best to search for existing [discussions][discussionsUrl] or [Issues][issuesUrl]
|
||||
that might
|
||||
help you.
|
||||
In case you have found a suitable topic and still need clarification, you can address your question in that topic.
|
||||
@ -53,7 +54,7 @@ It is also advisable to search the internet for answers first.
|
||||
|
||||
If you then still feel the need to ask a question and need clarification, we recommend the following:
|
||||
|
||||
- Open a new [discussion](../../discussions/new/choose) or [issue](../../issues/new/choose).
|
||||
- Open a new discussion or issue.
|
||||
- Provide as much context as you can about what you're running into.
|
||||
- Provide project and platform versions (nodejs, npm, etc), depending on what seems relevant.
|
||||
|
||||
@ -78,11 +79,11 @@ Please complete the following steps in advance to help us fix any potential bug
|
||||
|
||||
- Make sure that you are using the latest version.
|
||||
- Determine if your bug is really a bug and not an error on your side, e.g., using incompatible environment
|
||||
components/versions (Make sure that you have read the [documentation](../../wiki).
|
||||
components/versions (Make sure that you have read the [Wiki][wikiUrl].
|
||||
If you are looking for support, you might want to check [this section](#i-have-a-question)).
|
||||
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there
|
||||
is not already a bug report existing for your bug or error in the [bug tracker](../../issues?q=label%3Abug).
|
||||
- Also make sure to search the internet (including Stack Overflow) to see if users outside the GitHub community have
|
||||
is not already a report existing for your issue in the [issue tracker][issuesUrl].
|
||||
- Also, make sure to search the internet (including Stack Overflow) to see if users outside the GitHub community have
|
||||
discussed the issue.
|
||||
- Collect information about the bug:
|
||||
- Stack trace (Traceback).
|
||||
@ -91,16 +92,16 @@ Please complete the following steps in advance to help us fix any potential bug
|
||||
- Possibly your input and the output.
|
||||
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?
|
||||
|
||||
#### How Do I Submit a Good Bug Report?
|
||||
#### How Do I Submit a Good Report?
|
||||
|
||||
> [!CAUTION]
|
||||
> You must never report security related issues, vulnerabilities, or bugs including sensitive information to the issue
|
||||
> You must never report security-related issues, vulnerabilities, or bugs including sensitive information to the issue
|
||||
> tracker, or elsewhere in public.
|
||||
> Instead, sensitive bugs must be sent by email to a project leader.
|
||||
|
||||
We use GitHub issues to track bugs and errors. If you run into an issue with the project:
|
||||
|
||||
- Open an [issue](../../issues/new/choose).
|
||||
- Open an [issue][issuesUrl].
|
||||
- Explain the behavior you would expect and the actual behavior.
|
||||
- Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to
|
||||
recreate the issue on their own. This usually includes your code.
|
||||
@ -127,19 +128,19 @@ suggestions.
|
||||
#### Before Submitting an Enhancement
|
||||
|
||||
- Make sure that you are using the latest version.
|
||||
- Read the [documentation](../../wiki) carefully and find out if the functionality is already covered, maybe by an
|
||||
individual
|
||||
configuration.
|
||||
- Search the [issue tracker](../../issues) to see if the enhancement has already been suggested.
|
||||
- Read the [Wiki][wikiUrl] carefully and find out if the functionality is already covered, maybe by an
|
||||
individual configuration.
|
||||
- Search the [issue tracker][issuesUrl] or [Pull Requests][pullRequestUrl] to see if the enhancement has already been
|
||||
suggested.
|
||||
If it has, add a comment to the existing issue instead of opening a new one.
|
||||
- Find out whether your idea fits with the scope and aims of the project.
|
||||
It's up to you convince the developers of this feature's merits with a well-reasoned proposal.
|
||||
It's up to you to convince the developers of this feature's merits with a well-reasoned proposal.
|
||||
Keep in mind that we want features that will be useful to the majority of our users and not just a small subset.
|
||||
If you're just targeting a minority of users, consider writing an add-on/plugin library.
|
||||
|
||||
#### How Do I Submit a Good Enhancement Suggestion?
|
||||
|
||||
Enhancement suggestions are tracked as [GitHub issues](../../issues).
|
||||
Enhancement suggestions are tracked as [GitHub issues][issuesUrl].
|
||||
|
||||
- Use a **clear and descriptive title** for the issue to identify the suggestion.
|
||||
- Provide a **step-by-step description of the suggested enhancement** in as many details as possible.
|
||||
@ -209,3 +210,13 @@ Commit messages must follow [these](https://github.com/DigiLive/gitChangelog/wik
|
||||
## Attribution
|
||||
|
||||
This guide is based on the **contributing-gen**. [Make your own](https://github.com/bttger/contributing-gen)!
|
||||
|
||||
[issuesUrl]: https://github.com/DigiLive/mushroom-strategy/issues
|
||||
|
||||
[pullRequestUrl]: https://github.com/DigiLive/mushroom-strategy/pulls
|
||||
|
||||
[discussionsUrl]: https://github.com/DigiLive/mushroom-strategy/discussions
|
||||
|
||||
[wikiUrl]: https://github.com/DigiLive/mushroom-strategy/wiki
|
||||
|
||||
[sponsorUrl]: https://github.com/sponsors/DigiLive
|
||||
|
@ -63,13 +63,13 @@ Visit the [issues][issuesUrl] page.
|
||||
|
||||
[sponsorBadge]: https://img.shields.io/badge/Sponsor_him-%E2%9D%A4-%23db61a2.svg?&logo=github&color=%23fe8e86
|
||||
|
||||
[releaseBadge]: https://img.shields.io/badge/Release-v2.3.0-alpha.1-blue
|
||||
[releaseBadge]: https://img.shields.io/github/v/tag/digilive/mushroom-strategy?filter=v2.3.0&label=Release
|
||||
|
||||
<!-- Repository References -->
|
||||
|
||||
[repositoryUrl]: https://github.com/DigiLive/mushroom-strategy
|
||||
|
||||
[releaseUrl]: https://github.com/DigiLive/mushroom-strategy/releases/tag/v2.3.0-alpha.1
|
||||
[releaseUrl]: https://github.com/DigiLive/mushroom-strategy/releases/tag/v2.3.0
|
||||
|
||||
[issuesUrl]: https://github.com/DigiLive/mushroom-strategy/issues
|
||||
|
||||
|
1
dist/mushroom-strategy.js
vendored
1
dist/mushroom-strategy.js
vendored
File diff suppressed because one or more lines are too long
@ -1,5 +1,6 @@
|
||||
{
|
||||
"name": "Auto generating Mushroom dashboard strategy",
|
||||
"render_readme": true,
|
||||
"filename": "mushroom-strategy.js"
|
||||
"name": "Mushroom Dashboard Strategy ",
|
||||
"render_readme": true,
|
||||
"filename": "mushroom-strategy.js",
|
||||
"homeassistant": "2024.7.0"
|
||||
}
|
||||
|
1580
package-lock.json
generated
1580
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
39
package.json
39
package.json
@ -1,38 +1,49 @@
|
||||
{
|
||||
"name": "mushroom-strategy",
|
||||
"version": "2.2.0",
|
||||
"description": "Automatically create a dashboard using Mushroom cards",
|
||||
"version": "2.3.0",
|
||||
"description": "Automatically generate a dashboard of Mushroom cards.",
|
||||
"keywords": [
|
||||
"dashboard",
|
||||
"strategy",
|
||||
"mushroom"
|
||||
],
|
||||
"homepage": "https://github.com/AalianKhan/mushroom-strategy",
|
||||
"bugs": "https://github.com/AalianKhan/mushroom-strategy/issues",
|
||||
"homepage": "https://github.com/DigiLive/mushroom-strategy",
|
||||
"bugs": "https://github.com/DigiLive/mushroom-strategy/issues",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "Aalian Khan"
|
||||
"name": "Ferry Cools"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Ferry Cools"
|
||||
"name": "Aalian Khan"
|
||||
}
|
||||
],
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/DigiLive"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/AalianKhan/mushroom-strategy"
|
||||
"url": "https://github.com/DigiLive/mushroom-strategy"
|
||||
},
|
||||
"dependencies": {
|
||||
"deepmerge": "^4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"home-assistant-js-websocket": "^9",
|
||||
"superstruct": "^1",
|
||||
"ts-loader": "^9.5.0",
|
||||
"ts-node": "^10",
|
||||
"typescript": "^5",
|
||||
"@typescript-eslint/eslint-plugin": "^8.31.0",
|
||||
"@typescript-eslint/parser": "^8.31.0",
|
||||
"eslint": "^9.25.1",
|
||||
"eslint-config-prettier": "^10.1.2",
|
||||
"eslint-plugin-prettier": "^5.2.6",
|
||||
"home-assistant-js-websocket": "^9.5.0",
|
||||
"prettier": "^3.5.3",
|
||||
"superstruct": "^2.0.2",
|
||||
"ts-loader": "^9.5.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.8.3",
|
||||
"version-bump-prompt": "^6",
|
||||
"webpack": "^5.96.1",
|
||||
"webpack-cli": "^5.1.4"
|
||||
"webpack": "^5.99.7",
|
||||
"webpack-cli": "^6.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build-dev": "webpack --config webpack.dev.config.ts",
|
||||
|
498
src/Helper.ts
498
src/Helper.ts
@ -1,498 +0,0 @@
|
||||
import {getConfigurationDefaults} from "./configurationDefaults";
|
||||
import {HassEntities, HassEntity} from "home-assistant-js-websocket";
|
||||
import deepmerge from "deepmerge";
|
||||
import {EntityRegistryEntry} from "./types/homeassistant/data/entity_registry";
|
||||
import {DeviceRegistryEntry} from "./types/homeassistant/data/device_registry";
|
||||
import {AreaRegistryEntry} from "./types/homeassistant/data/area_registry";
|
||||
import {generic} from "./types/strategy/generic";
|
||||
import setupCustomLocalize from "./localize";
|
||||
import {applyEntityCategoryFilters} from "./utillties/filters";
|
||||
import StrategyArea = generic.StrategyArea;
|
||||
|
||||
/**
|
||||
* Helper Class
|
||||
*
|
||||
* Contains the objects of Home Assistant's registries and helper methods.
|
||||
*/
|
||||
class Helper {
|
||||
/**
|
||||
* An array of entities from Home Assistant's entity registry.
|
||||
*
|
||||
* @type {EntityRegistryEntry[]}
|
||||
* @private
|
||||
*/
|
||||
static #entities: EntityRegistryEntry[];
|
||||
|
||||
/**
|
||||
* An array of entities from Home Assistant's device registry.
|
||||
*
|
||||
* @type {DeviceRegistryEntry[]}
|
||||
* @private
|
||||
*/
|
||||
static #devices: DeviceRegistryEntry[];
|
||||
|
||||
/**
|
||||
* An array of entities from Home Assistant's area registry.
|
||||
*
|
||||
* @type {StrategyArea[]}
|
||||
* @private
|
||||
*/
|
||||
static #areas: StrategyArea[] = [];
|
||||
|
||||
/**
|
||||
* An array of state entities from Home Assistant's Hass object.
|
||||
*
|
||||
* @type {HassEntities}
|
||||
* @private
|
||||
*/
|
||||
static #hassStates: HassEntities;
|
||||
|
||||
/**
|
||||
* Indicates whether this module is initialized.
|
||||
*
|
||||
* @type {boolean} True if initialized.
|
||||
* @private
|
||||
*/
|
||||
static #initialized: boolean = false;
|
||||
|
||||
/**
|
||||
* The Custom strategy configuration.
|
||||
*
|
||||
* @type {generic.StrategyConfig}
|
||||
* @private
|
||||
*/
|
||||
static #strategyOptions: generic.StrategyConfig;
|
||||
|
||||
/**
|
||||
* Set to true for more verbose information in the console.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
static #debug: boolean;
|
||||
static customLocalize: Function;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* This class shouldn't be instantiated directly.
|
||||
* Instead, it should be initialized with method initialize().
|
||||
*
|
||||
* @throws {Error} If trying to instantiate this class.
|
||||
*/
|
||||
constructor() {
|
||||
throw new Error("This class should be invoked with method initialize() instead of using the keyword new!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom strategy configuration.
|
||||
*
|
||||
* @returns {generic.StrategyConfig}
|
||||
* @static
|
||||
*/
|
||||
static get strategyOptions(): generic.StrategyConfig {
|
||||
return this.#strategyOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entities from Home Assistant's area registry.
|
||||
*
|
||||
* @returns {StrategyArea[]}
|
||||
* @static
|
||||
*/
|
||||
static get areas(): StrategyArea[] {
|
||||
return this.#areas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the devices from Home Assistant's device registry.
|
||||
*
|
||||
* @returns {DeviceRegistryEntry[]}
|
||||
* @static
|
||||
*/
|
||||
static get devices(): DeviceRegistryEntry[] {
|
||||
return this.#devices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entities from Home Assistant's entity registry.
|
||||
*
|
||||
* @returns {EntityRegistryEntry[]}
|
||||
* @static
|
||||
*/
|
||||
static get entities(): EntityRegistryEntry[] {
|
||||
return this.#entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current debug mode of the mushroom strategy.
|
||||
*
|
||||
* @returns {boolean}
|
||||
* @static
|
||||
*/
|
||||
static get debug(): boolean {
|
||||
return this.#debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this module.
|
||||
*
|
||||
* @param {generic.DashBoardInfo} info Strategy information object.
|
||||
* @returns {Promise<void>}
|
||||
* @static
|
||||
*/
|
||||
static async initialize(info: generic.DashBoardInfo): Promise<void> {
|
||||
// Initialize properties.
|
||||
this.customLocalize = setupCustomLocalize(info.hass);
|
||||
|
||||
const configurationDefaults = getConfigurationDefaults(this.customLocalize)
|
||||
this.#strategyOptions = deepmerge(configurationDefaults, info.config?.strategy?.options ?? {});
|
||||
|
||||
this.#hassStates = info.hass.states;
|
||||
this.#debug = this.#strategyOptions.debug;
|
||||
|
||||
try {
|
||||
// Query the registries of Home Assistant.
|
||||
|
||||
// noinspection ES6MissingAwait False positive? https://youtrack.jetbrains.com/issue/WEB-63746
|
||||
[Helper.#entities, Helper.#devices, Helper.#areas] = await Promise.all([
|
||||
info.hass.callWS({type: "config/entity_registry/list"}) as Promise<EntityRegistryEntry[]>,
|
||||
info.hass.callWS({type: "config/device_registry/list"}) as Promise<DeviceRegistryEntry[]>,
|
||||
info.hass.callWS({type: "config/area_registry/list"}) as Promise<AreaRegistryEntry[]>,
|
||||
]);
|
||||
} catch (e) {
|
||||
Helper.logError("An error occurred while querying Home assistant's registries!", e);
|
||||
throw 'Check the console for details';
|
||||
}
|
||||
|
||||
// Create and add the undisclosed area if not hidden in the strategy options.
|
||||
if (!this.#strategyOptions.areas.undisclosed?.hidden) {
|
||||
this.#strategyOptions.areas.undisclosed = {
|
||||
...configurationDefaults.areas.undisclosed,
|
||||
...this.#strategyOptions.areas.undisclosed,
|
||||
};
|
||||
|
||||
// Make sure the custom configuration of the undisclosed area doesn't overwrite the area_id.
|
||||
this.#strategyOptions.areas.undisclosed.area_id = "undisclosed";
|
||||
|
||||
this.#areas.push(this.#strategyOptions.areas.undisclosed);
|
||||
}
|
||||
|
||||
// Merge custom areas of the strategy options into strategy areas.
|
||||
this.#areas = Helper.areas.map(area => {
|
||||
return {...area, ...this.#strategyOptions.areas?.[area.area_id]};
|
||||
});
|
||||
|
||||
// Sort strategy areas by order first and then by name.
|
||||
this.#areas.sort((a, b) => {
|
||||
return (a.order ?? Infinity) - (b.order ?? Infinity) || a.name.localeCompare(b.name);
|
||||
});
|
||||
|
||||
// Sort custom and default views of the strategy options by order first and then by title.
|
||||
this.#strategyOptions.views = Object.fromEntries(
|
||||
Object.entries(this.#strategyOptions.views).sort(([, a], [, b]) => {
|
||||
return (a.order ?? Infinity) - (b.order ?? Infinity) || (a.title ?? "undefined").localeCompare(b.title ?? "undefined");
|
||||
}),
|
||||
);
|
||||
|
||||
// Sort custom and default domains of the strategy options by order first and then by title.
|
||||
this.#strategyOptions.domains = Object.fromEntries(
|
||||
Object.entries(this.#strategyOptions.domains).sort(([, a], [, b]) => {
|
||||
return (a.order ?? Infinity) - (b.order ?? Infinity) || (a.title ?? "undefined").localeCompare(b.title ?? "undefined");
|
||||
}),
|
||||
);
|
||||
|
||||
this.#initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the initialization status of the Helper class.
|
||||
*
|
||||
* @returns {boolean} True if this module is initialized.
|
||||
* @static
|
||||
*/
|
||||
static isInitialized(): boolean {
|
||||
return this.#initialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a template string to define the number of a given domain's entities with a certain state.
|
||||
*
|
||||
* States are compared against a given value by a given operator.
|
||||
* States `unavailable` and `unknown` are always excluded.
|
||||
*
|
||||
* @param {string} domain The domain of the entities.
|
||||
* @param {string} operator The comparison operator between state and value.
|
||||
* @param {string} value The value to which the state is compared against.
|
||||
*
|
||||
* @return {string} The template string.
|
||||
* @static
|
||||
*/
|
||||
static getCountTemplate(domain: string, operator: string, value: string): string {
|
||||
/**
|
||||
* Array of entity state-entries, filtered by domain.
|
||||
*
|
||||
* Each element contains a template-string which is used to access home assistant's state machine (state object) in
|
||||
* a template.
|
||||
* E.g. "states['light.kitchen']"
|
||||
*
|
||||
* The array excludes hidden and disabled entities.
|
||||
*
|
||||
* @type {string[]}
|
||||
*/
|
||||
const states: string[] = [];
|
||||
|
||||
if (!this.isInitialized()) {
|
||||
console.warn("Helper class should be initialized before calling this method!");
|
||||
}
|
||||
|
||||
// Get the state of entities which are linked to the given area.
|
||||
for (const area of this.#areas) {
|
||||
let entities = this.getDeviceEntities(area, domain);
|
||||
|
||||
// Exclude hidden Config and Diagnostic entities.
|
||||
entities = applyEntityCategoryFilters(entities, domain);
|
||||
|
||||
const newStates = entities.map((entity) => `states['${entity.entity_id}']`);
|
||||
|
||||
states.push(...newStates);
|
||||
}
|
||||
|
||||
return (
|
||||
`{% set entities = [${states}] %}
|
||||
{{ entities
|
||||
| selectattr('state','${operator}','${value}')
|
||||
| selectattr('state','ne','unavailable')
|
||||
| selectattr('state','ne','unknown')
|
||||
| list
|
||||
| count
|
||||
}}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get device entities from the entity registry, filtered by area and domain.
|
||||
*
|
||||
* The entity registry is a registry where Home-Assistant keeps track of all entities.
|
||||
* A device is represented in Home Assistant via one or more entities.
|
||||
*
|
||||
* The result excludes hidden and disabled entities.
|
||||
*
|
||||
* @param {AreaRegistryEntry} area Area entity.
|
||||
* @param {string} [domain] The domain of the entity-id.
|
||||
*
|
||||
* @return {EntityRegistryEntry[]} Array of device entities.
|
||||
* @static
|
||||
*/
|
||||
static getDeviceEntities(area: AreaRegistryEntry, domain?: string): EntityRegistryEntry[] {
|
||||
if (!this.isInitialized()) {
|
||||
console.warn("Helper class should be initialized before calling this method!");
|
||||
}
|
||||
|
||||
// Get the ID of the devices which are linked to the given area.
|
||||
const areaDeviceIds = this.#devices.filter((device) => {
|
||||
return (device.area_id ?? "undisclosed") === area.area_id;
|
||||
}).map((device: DeviceRegistryEntry) => {
|
||||
|
||||
return device.id;
|
||||
});
|
||||
|
||||
// Return the entities of which all conditions of the callback function are met. @see areaFilterCallback.
|
||||
return this.#entities.filter(
|
||||
this.#areaFilterCallback, {
|
||||
area: area,
|
||||
domain: domain,
|
||||
areaDeviceIds: areaDeviceIds,
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return (a.original_name ?? "undefined").localeCompare(b.original_name ?? "undefined");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get state entities, filtered by area and domain.
|
||||
*
|
||||
* The result excludes hidden and disabled entities.
|
||||
*
|
||||
* @param {AreaRegistryEntry} area Area entity.
|
||||
* @param {string} domain Domain of the entity-id.
|
||||
*
|
||||
* @return {HassEntity[]} Array of state entities.
|
||||
*/
|
||||
static getStateEntities(area: AreaRegistryEntry, domain: string): HassEntity[] {
|
||||
if (!this.isInitialized()) {
|
||||
console.warn("Helper class should be initialized before calling this method!");
|
||||
}
|
||||
|
||||
const states: HassEntity[] = [];
|
||||
|
||||
// Create a map for the hassEntities and devices {id: object} to improve lookup speed.
|
||||
const entityMap: {
|
||||
[s: string]: EntityRegistryEntry;
|
||||
} = Object.fromEntries(this.#entities.map((entity) => [entity.entity_id, entity]));
|
||||
const deviceMap: {
|
||||
[s: string]: DeviceRegistryEntry;
|
||||
} = Object.fromEntries(this.#devices.map((device) => [device.id, device]));
|
||||
|
||||
// Get states whose entity-id starts with the given string.
|
||||
const stateEntities = Object.values(this.#hassStates).filter(
|
||||
(state) => state.entity_id.startsWith(`${domain}.`),
|
||||
);
|
||||
|
||||
for (const state of stateEntities) {
|
||||
const hassEntity = entityMap[state.entity_id];
|
||||
const device = deviceMap[hassEntity?.device_id ?? ""];
|
||||
|
||||
// Collect states of which any (whichever comes first) of the conditions below are met:
|
||||
// 1. The linked entity is linked to the given area.
|
||||
// 2. The entity is linked to a device, and the linked device is linked to the given area.
|
||||
if (
|
||||
(hassEntity?.area_id === area.area_id)
|
||||
|| (device && device.area_id === area.area_id)
|
||||
) {
|
||||
states.push(state);
|
||||
}
|
||||
}
|
||||
|
||||
return states;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the state object of a HASS entity.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The entity for which to get the state.
|
||||
* @returns {HassEntity | undefined} The state object of the entity, or undefined if not found.
|
||||
* @static
|
||||
*/
|
||||
static getEntityState(entity: EntityRegistryEntry): HassEntity | undefined {
|
||||
return this.#hassStates[entity.entity_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize a classname.
|
||||
*
|
||||
* The name is sanitized by capitalizing the first character of the name or after an underscore.
|
||||
* Underscores are removed.
|
||||
*
|
||||
* @param {string} className Name of the class to sanitize.
|
||||
* @returns {string} The sanitized classname.
|
||||
*/
|
||||
static sanitizeClassName(className: string): string {
|
||||
className = className.charAt(0).toUpperCase() + className.slice(1);
|
||||
|
||||
return className.replace(/([-_][a-z])/g, (group) => group
|
||||
.toUpperCase()
|
||||
.replace("-", "")
|
||||
.replace("_", ""),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ids of the views which aren't set to hidden in the strategy options.
|
||||
*
|
||||
* @return {string[]} An array of view ids.
|
||||
*/
|
||||
static getExposedViewIds(): string[] {
|
||||
if (!this.isInitialized()) {
|
||||
console.warn("Helper class should be initialized before calling this method!");
|
||||
}
|
||||
|
||||
return this.#getObjectKeysByPropertyValue(this.#strategyOptions.views, "hidden", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ids of the domain ids which aren't set to hidden in the strategy options.
|
||||
*
|
||||
* @return {string[]} An array of domain ids.
|
||||
*/
|
||||
static getExposedDomainIds(): string[] {
|
||||
if (!this.isInitialized()) {
|
||||
console.warn("Helper class should be initialized before calling this method!");
|
||||
}
|
||||
|
||||
return this.#getObjectKeysByPropertyValue(this.#strategyOptions.domains, "hidden", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for filtering entities.
|
||||
*
|
||||
* Entities of which all the conditions below are met are kept:
|
||||
* 1. The entity is not hidden and the entity's device is not hidden by the strategy options.
|
||||
* 2. The entity is not hidden and is not disabled by Hass.
|
||||
* 3. The entity's domain matches the given domain.
|
||||
* 4. The entity itself or else the entity's device is linked to the given area.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The current Hass entity to evaluate.
|
||||
* @this {AreaFilterContext}
|
||||
*
|
||||
* @return {boolean} True to keep the entity.
|
||||
* @static
|
||||
*/
|
||||
static #areaFilterCallback(
|
||||
this: {
|
||||
area: AreaRegistryEntry,
|
||||
areaDeviceIds: string[],
|
||||
domain: string,
|
||||
},
|
||||
entity: EntityRegistryEntry): boolean {
|
||||
const cardOptions = Helper.strategyOptions.card_options?.[entity.entity_id];
|
||||
const deviceOptions = Helper.strategyOptions.card_options?.[entity.device_id ?? "null"];
|
||||
|
||||
const entityUnhidden =
|
||||
!cardOptions?.hidden && !deviceOptions?.hidden // Condition 1.
|
||||
&& entity.hidden_by === null && entity.disabled_by === null; // Condition 2.
|
||||
const domainMatches = this.domain === undefined || entity.entity_id.startsWith(`${this.domain}.`); // Condition 3.
|
||||
// Condition 4.
|
||||
const entityLinked = this.area.area_id === "undisclosed"
|
||||
// Undisclosed area.
|
||||
? !entity.area_id && (this.areaDeviceIds.includes(entity.device_id ?? "") || !entity.device_id)
|
||||
// Area is a hass entity. Note: entity.area_id is set to null when using device's area.
|
||||
: entity.area_id === this.area.area_id || (!entity.area_id && this.areaDeviceIds.includes(entity.device_id ?? ""));
|
||||
|
||||
return (entityUnhidden && domainMatches && entityLinked);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the keys of nested objects by its property value.
|
||||
*
|
||||
* @param {Object<string, any>} object An object of objects.
|
||||
* @param {string|number} property The name of the property to evaluate.
|
||||
* @param {*} value The value which the property should match.
|
||||
*
|
||||
* @return {string[]} An array with keys.
|
||||
*/
|
||||
static #getObjectKeysByPropertyValue(
|
||||
object: { [k: string]: any },
|
||||
property: string, value: any
|
||||
): string[] {
|
||||
const keys: string[] = [];
|
||||
|
||||
for (const key of Object.keys(object)) {
|
||||
if (object[key][property] === value) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an error message to the console.
|
||||
*
|
||||
* @param {string} userMessage - The error message to display.
|
||||
* @param {unknown} [e] - (Optional) The error object or additional information.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
static logError(userMessage: string, e?: unknown): void {
|
||||
if (Helper.debug) {
|
||||
console.error(userMessage, e);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(userMessage);
|
||||
}
|
||||
}
|
||||
|
||||
export {Helper};
|
298
src/Registry.ts
Normal file
298
src/Registry.ts
Normal file
@ -0,0 +1,298 @@
|
||||
import deepmerge from 'deepmerge';
|
||||
import { HassEntities } from 'home-assistant-js-websocket';
|
||||
import { AreaRegistryEntry } from './types/homeassistant/data/area_registry';
|
||||
import { DeviceRegistryEntry } from './types/homeassistant/data/device_registry';
|
||||
import { EntityRegistryEntry } from './types/homeassistant/data/entity_registry';
|
||||
import {
|
||||
AllDomainsConfig,
|
||||
DashboardInfo,
|
||||
isSortable,
|
||||
SingleDomainConfig,
|
||||
StrategyArea,
|
||||
StrategyConfig,
|
||||
StrategyViewConfig,
|
||||
SupportedDomains,
|
||||
SupportedViews,
|
||||
} from './types/strategy/strategy-generics';
|
||||
import { logMessage, lvlFatal, lvlOff, lvlWarn, setDebugLevel } from './utilities/debug';
|
||||
import setupCustomLocalize from './utilities/localize';
|
||||
import RegistryFilter from './utilities/RegistryFilter';
|
||||
|
||||
/**
|
||||
* Registry Class
|
||||
*
|
||||
* Contains the entries of Home Assistant's registries and Strategy configuration.
|
||||
*/
|
||||
class Registry {
|
||||
/** Entries of Home Assistant's entity registry. */
|
||||
private static _entities: EntityRegistryEntry[];
|
||||
/** Entries of Home Assistant's device registry. */
|
||||
private static _devices: DeviceRegistryEntry[];
|
||||
/** Entries of Home Assistant's area registry. */
|
||||
private static _areas: StrategyArea[] = [];
|
||||
/** Entries of Home Assistant's state registry */
|
||||
private static _hassStates: HassEntities;
|
||||
/** Indicates whether this module is initialized. */
|
||||
private static _initialized: boolean = false;
|
||||
/** The Custom strategy configuration. */
|
||||
private static _strategyOptions: StrategyConfig;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @remarks
|
||||
* This class shouldn't be instantiated directly.
|
||||
* Instead, method {@link Registry.initialize} must be invoked.
|
||||
*/
|
||||
// noinspection JSUnusedLocalSymbols
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
private constructor() {}
|
||||
|
||||
/** The configuration of the strategy. */
|
||||
static get strategyOptions(): StrategyConfig {
|
||||
return Registry._strategyOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Home Assistant's Area registry.
|
||||
*
|
||||
* @remarks
|
||||
* This module makes changes to the registry at {@link Registry.initialize}.
|
||||
*/
|
||||
static get areas(): StrategyArea[] {
|
||||
return Registry._areas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Home Assistant's Device registry.
|
||||
*
|
||||
* @remarks
|
||||
* This module makes changes to the registry at {@link Registry.initialize}.
|
||||
*/
|
||||
static get devices(): DeviceRegistryEntry[] {
|
||||
return Registry._devices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Home Assistant's Entity registry.
|
||||
*
|
||||
* @remarks
|
||||
* This module makes changes to the registry at {@link Registry.initialize}.
|
||||
*/
|
||||
static get entities(): EntityRegistryEntry[] {
|
||||
return Registry._entities;
|
||||
}
|
||||
|
||||
/** Home Assistant's State registry. */
|
||||
static get hassStates(): HassEntities {
|
||||
return Registry._hassStates;
|
||||
}
|
||||
|
||||
/** Get the initialization status of the Registry class. */
|
||||
static get initialized(): boolean {
|
||||
return Registry._initialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this module.
|
||||
*
|
||||
* Imports the registries of Home Assistant and the strategy options.
|
||||
*
|
||||
* After importing, the registries are sanitized according to the provided strategy options.
|
||||
* This method must be called before using any other Registry functionality that depends on the imported data.
|
||||
*
|
||||
* @param {DashboardInfo} info Strategy information object.
|
||||
*/
|
||||
static async initialize(info: DashboardInfo): Promise<void> {
|
||||
setupCustomLocalize(info.hass);
|
||||
|
||||
// Import the Hass States and strategy options.
|
||||
Registry._hassStates = info.hass.states;
|
||||
const { ConfigurationDefaults } = await import('./configurationDefaults');
|
||||
|
||||
try {
|
||||
Registry._strategyOptions = deepmerge(ConfigurationDefaults, info.config?.strategy?.options ?? {});
|
||||
} catch (e) {
|
||||
logMessage(lvlFatal, 'Error importing strategy options!', e);
|
||||
}
|
||||
|
||||
setDebugLevel(Registry.strategyOptions.debug ? lvlFatal : lvlOff);
|
||||
|
||||
// Import the registries of Home Assistant.
|
||||
try {
|
||||
// noinspection ES6MissingAwait False positive? https://youtrack.jetbrains.com/issue/WEB-63746
|
||||
[Registry._entities, Registry._devices, Registry._areas] = await Promise.all([
|
||||
info.hass.callWS({ type: 'config/entity_registry/list' }) as Promise<EntityRegistryEntry[]>,
|
||||
info.hass.callWS({ type: 'config/device_registry/list' }) as Promise<DeviceRegistryEntry[]>,
|
||||
info.hass.callWS({ type: 'config/area_registry/list' }) as Promise<AreaRegistryEntry[]>,
|
||||
]);
|
||||
} catch (e) {
|
||||
logMessage(lvlFatal, 'Error importing Home Assistant registries!', e);
|
||||
}
|
||||
|
||||
// Process the entries of the Strategy Options.
|
||||
Registry._strategyOptions.extra_views.map((view) => ({
|
||||
...view,
|
||||
subview: false,
|
||||
}));
|
||||
|
||||
// Process entries of the HASS entity registry.
|
||||
Registry._entities = new RegistryFilter(Registry.entities)
|
||||
.not()
|
||||
.whereEntityCategory('config')
|
||||
.not()
|
||||
.whereEntityCategory('diagnostic')
|
||||
.isNotHidden()
|
||||
.whereDisabledBy(null)
|
||||
.orderBy(['name', 'original_name'], 'asc')
|
||||
.toList();
|
||||
|
||||
Registry._entities = Registry.entities.map((entity) => ({
|
||||
...entity,
|
||||
area_id: entity.area_id ?? 'undisclosed',
|
||||
}));
|
||||
|
||||
// Process entries of the HASS device registry.
|
||||
Registry._devices = new RegistryFilter(Registry.devices)
|
||||
.isNotHidden()
|
||||
.whereDisabledBy(null)
|
||||
.orderBy(['name_by_user', 'name'], 'asc')
|
||||
.toList();
|
||||
|
||||
Registry._devices = Registry.devices.map((device) => ({
|
||||
...device,
|
||||
area_id: device.area_id ?? 'undisclosed',
|
||||
}));
|
||||
|
||||
// Process entries of the HASS area registry.
|
||||
if (Registry.strategyOptions.areas._?.hidden) {
|
||||
Registry._areas = [];
|
||||
} else {
|
||||
// Create and add the undisclosed area if not hidden in the strategy options.
|
||||
if (!Registry.strategyOptions.areas.undisclosed?.hidden) {
|
||||
Registry.areas.push(ConfigurationDefaults.areas.undisclosed);
|
||||
}
|
||||
|
||||
// Merge area configurations of the Strategy options into the entries of the area registry.
|
||||
// TODO: Check for to do the same for devices.
|
||||
Registry._areas = Registry.areas.map((area) => {
|
||||
return { ...area, ...Registry.strategyOptions.areas['_'], ...Registry.strategyOptions.areas?.[area.area_id] };
|
||||
});
|
||||
|
||||
// Ensure the custom configuration of the undisclosed area doesn't overwrite the area_id.
|
||||
Registry.strategyOptions.areas.undisclosed.area_id = 'undisclosed';
|
||||
|
||||
// Remove hidden areas if configured as so and sort them by name.
|
||||
|
||||
Registry._areas = new RegistryFilter(Registry.areas).isNotHidden().orderBy(['order', 'name'], 'asc').toList();
|
||||
}
|
||||
|
||||
// Sort views by order first and then by title.
|
||||
const sortViews = () => {
|
||||
const entries = Object.entries(Registry.strategyOptions.views);
|
||||
|
||||
Registry.strategyOptions.views = Object.fromEntries(
|
||||
entries.sort(([_, a], [__, b]) => {
|
||||
return (a.order ?? Infinity) - (b.order ?? Infinity) || (a.title ?? '').localeCompare(b.title ?? '');
|
||||
}),
|
||||
) as Record<SupportedViews, StrategyViewConfig>;
|
||||
};
|
||||
|
||||
sortViews();
|
||||
|
||||
// Sort domains by order first and then by title.
|
||||
const sortDomains = () => {
|
||||
const entries = Object.entries(Registry.strategyOptions.domains);
|
||||
Registry.strategyOptions.domains = Object.fromEntries(
|
||||
entries.sort(([, a], [, b]) => {
|
||||
if (isSortable(a) && isSortable(b)) {
|
||||
return (a.order ?? Infinity) - (b.order ?? Infinity) || (a.title ?? '').localeCompare(b.title ?? '');
|
||||
}
|
||||
|
||||
return 0; // Maintain the original order when none or only one item is sortable.
|
||||
}),
|
||||
) as { [K in SupportedDomains]: K extends '_' ? AllDomainsConfig : SingleDomainConfig };
|
||||
};
|
||||
|
||||
sortDomains();
|
||||
|
||||
// Sort extra views by order first and then by title.
|
||||
// TODO: Add sorting to the wiki.
|
||||
const sortExtraViews = () => {
|
||||
Registry.strategyOptions.extra_views.sort((a, b) => {
|
||||
return (a.order ?? Infinity) - (b.order ?? Infinity) || (a.title ?? '').localeCompare(b.title ?? '');
|
||||
});
|
||||
};
|
||||
|
||||
sortExtraViews();
|
||||
|
||||
Registry._initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a template string to define the number of a given domain's entities with a certain state.
|
||||
*
|
||||
* States are compared against a given value by a given operator.
|
||||
* States `unavailable` and `unknown` are always excluded.
|
||||
*
|
||||
* @param {string} domain The domain of the entities.
|
||||
* @param {string} operator The comparison operator between state and value.
|
||||
* @param {string} value The value to which the state is compared against.
|
||||
*/
|
||||
static getCountTemplate(domain: SupportedDomains, operator: string, value: string): string {
|
||||
// noinspection JSMismatchedCollectionQueryUpdate
|
||||
/**
|
||||
* Array of entity state-entries, filtered by domain.
|
||||
*
|
||||
* Each element contains a template-string which is used to access home assistant's state machine (state object) in
|
||||
* a template; E.g. `states['light.kitchen']`.
|
||||
*/
|
||||
const states: string[] = [];
|
||||
|
||||
if (!Registry.initialized) {
|
||||
logMessage(lvlWarn, 'Registry not initialized!');
|
||||
|
||||
return '?';
|
||||
}
|
||||
|
||||
states.push(
|
||||
...new RegistryFilter(Registry.entities)
|
||||
.whereDomain(domain)
|
||||
.where((entity) => !entity.entity_id.endsWith('_stateful_scene'))
|
||||
.toList()
|
||||
.map((entity) => `states['${entity.entity_id}']`),
|
||||
);
|
||||
|
||||
return `{% set entities = [${states}] %}
|
||||
{{ entities
|
||||
| selectattr('state','${operator}','${value}')
|
||||
| selectattr('state','ne','unavailable')
|
||||
| selectattr('state','ne','unknown')
|
||||
| list
|
||||
| count
|
||||
}}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the names of the specified type which aren't set to hidden in the strategy options.
|
||||
*
|
||||
* @param {string} type The type of options to filter ("domain", "view", "chip").
|
||||
*
|
||||
* @returns {string[]} For domains and views: names of items that aren't hidden.
|
||||
* For chips: names of items that are explicitly set to true.
|
||||
*/
|
||||
static getExposedNames(type: 'domain' | 'view' | 'chip'): string[] {
|
||||
// TODO: Align chip with other types.
|
||||
if (type === 'chip') {
|
||||
return Object.entries(Registry.strategyOptions.chips)
|
||||
.filter(([_, value]) => value === true)
|
||||
.map(([key]) => key.split('_')[0]);
|
||||
}
|
||||
|
||||
const group = Registry.strategyOptions[`${type}s`] as Record<string, { hidden?: boolean }>;
|
||||
|
||||
return Object.keys(group).filter((key) => key !== '_' && key !== 'default' && !group[key].hidden);
|
||||
}
|
||||
}
|
||||
|
||||
export { Registry };
|
@ -1,59 +1,59 @@
|
||||
import {Helper} from "../Helper";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {generic} from "../types/strategy/generic";
|
||||
import {EntityCardConfig} from "../types/lovelace-mushroom/cards/entity-card-config";
|
||||
import { Registry } from '../Registry';
|
||||
import { LovelaceCardConfig } from '../types/homeassistant/data/lovelace/config/card';
|
||||
import { AbstractCardConfig } from '../types/strategy/strategy-cards';
|
||||
import { RegistryEntry } from '../types/strategy/strategy-generics';
|
||||
import { logMessage, lvlFatal } from '../utilities/debug';
|
||||
|
||||
/**
|
||||
* Abstract Card Class
|
||||
*
|
||||
* To create a new card, extend the new class with this one.
|
||||
* To create a card configuration, this class should be extended by a child class.
|
||||
* Child classes should override the default configuration so the card correctly reflects the entity.
|
||||
*
|
||||
* @class
|
||||
* @abstract
|
||||
* @remarks
|
||||
* Before using this class, the Registry module must be initialized by calling {@link Registry.initialize}.
|
||||
*/
|
||||
abstract class AbstractCard {
|
||||
/**
|
||||
* Entity to create the card for.
|
||||
*
|
||||
* @type {generic.RegistryEntry}
|
||||
*/
|
||||
entity: generic.RegistryEntry;
|
||||
/** The registry entry this card represents. */
|
||||
readonly entity: RegistryEntry;
|
||||
|
||||
/**
|
||||
* Configuration of the card.
|
||||
* The card configuration for this entity.
|
||||
*
|
||||
* @type {EntityCardConfig}
|
||||
* Child classes should override this property to reflect their own card type and options.
|
||||
*/
|
||||
config: EntityCardConfig = {
|
||||
type: "custom:mushroom-entity-card",
|
||||
icon: "mdi:help-circle",
|
||||
protected configuration: LovelaceCardConfig = {
|
||||
type: 'custom:mushroom-entity-card',
|
||||
icon: 'mdi:help-circle',
|
||||
};
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {generic.RegistryEntry} entity The hass entity to create a card for.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {RegistryEntry} entity The registry entry to create a card configuration for.
|
||||
*
|
||||
* @remarks
|
||||
* Before this class can be used, the Registry module must be initialized by calling {@link Registry.initialize}.
|
||||
*/
|
||||
protected constructor(entity: generic.RegistryEntry) {
|
||||
if (!Helper.isInitialized()) {
|
||||
throw new Error("The Helper module must be initialized before using this one.");
|
||||
protected constructor(entity: RegistryEntry) {
|
||||
if (!Registry.initialized) {
|
||||
logMessage(lvlFatal, 'Registry not initialized!');
|
||||
}
|
||||
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a card.
|
||||
* Get a card configuration.
|
||||
*
|
||||
* @return {cards.AbstractCardConfig} A card object.
|
||||
* The configuration should be set by any of the child classes so the card correctly reflects an entity.
|
||||
*/
|
||||
getCard(): cards.AbstractCardConfig {
|
||||
getCard(): AbstractCardConfig {
|
||||
return {
|
||||
...this.config,
|
||||
entity: "entity_id" in this.entity ? this.entity.entity_id : undefined,
|
||||
...this.configuration,
|
||||
entity: 'entity_id' in this.entity ? this.entity.entity_id : undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {AbstractCard};
|
||||
export default AbstractCard;
|
||||
|
@ -1,68 +1,52 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {AreaRegistryEntry} from "../types/homeassistant/data/area_registry";
|
||||
import {TemplateCardConfig} from "../types/lovelace-mushroom/cards/template-card-config";
|
||||
import { AreaRegistryEntry } from '../types/homeassistant/data/area_registry';
|
||||
import { TemplateCardConfig } from '../types/lovelace-mushroom/cards/template-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
/**
|
||||
* Area Card Class
|
||||
*
|
||||
* Used to create a card for an entity of the area domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create card configuration for an entry of the HASS area registry.
|
||||
*/
|
||||
class AreaCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {TemplateCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: TemplateCardConfig = {
|
||||
type: "custom:mushroom-template-card",
|
||||
primary: undefined,
|
||||
icon: "mdi:floor-plan",
|
||||
icon_color: "blue",
|
||||
tap_action: {
|
||||
action: "navigate",
|
||||
navigation_path: "",
|
||||
},
|
||||
hold_action: {
|
||||
action: "none",
|
||||
},
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): TemplateCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-template-card',
|
||||
primary: undefined,
|
||||
icon: 'mdi:floor-plan',
|
||||
icon_color: 'blue',
|
||||
tap_action: { action: 'navigate', navigation_path: '' },
|
||||
hold_action: { action: 'none' },
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {AreaRegistryEntry} area The area entity to create a card for.
|
||||
* @param {cards.TemplateCardOptions} [options={}] Options for the card.
|
||||
*
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {AreaRegistryEntry} area The HASS area to create a card configuration for.
|
||||
* @param {TemplateCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(area: AreaRegistryEntry, options: cards.TemplateCardOptions = {}) {
|
||||
constructor(area: AreaRegistryEntry, customConfiguration?: TemplateCardConfig) {
|
||||
super(area);
|
||||
|
||||
const configuration = AreaCard.getDefaultConfig();
|
||||
|
||||
let customConfig = customConfiguration;
|
||||
|
||||
configuration.primary = area.name;
|
||||
configuration.icon = area.icon || configuration.icon;
|
||||
|
||||
if (configuration.tap_action && 'navigation_path' in configuration.tap_action) {
|
||||
configuration.tap_action.navigation_path = area.area_id;
|
||||
}
|
||||
|
||||
// Don't override the default card type if default is set in the strategy options.
|
||||
if (options.type === "default") {
|
||||
delete options.type;
|
||||
if (customConfig && customConfig.type === 'default') {
|
||||
customConfig = { ...customConfig, type: configuration.type };
|
||||
}
|
||||
|
||||
// Initialize the default configuration.
|
||||
this.#defaultConfig.primary = area.name;
|
||||
|
||||
if (this.#defaultConfig.tap_action && ("navigation_path" in this.#defaultConfig.tap_action)) {
|
||||
this.#defaultConfig.tap_action.navigation_path = area.area_id;
|
||||
}
|
||||
|
||||
// Overwrite the default icon to the user-defined icon in hass.
|
||||
if (area.icon) {
|
||||
this.#defaultConfig.icon = area.icon;
|
||||
}
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...configuration, ...customConfig };
|
||||
}
|
||||
}
|
||||
|
||||
export {AreaCard};
|
||||
export default AreaCard;
|
||||
|
@ -1,42 +1,35 @@
|
||||
import {SensorCard} from "./SensorCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {EntityCardConfig} from "../types/lovelace-mushroom/cards/entity-card-config";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config';
|
||||
import SensorCard from './SensorCard';
|
||||
|
||||
/**
|
||||
* Sensor Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the binary_sensor domain.
|
||||
*
|
||||
* @class
|
||||
* @extends SensorCard
|
||||
* Used to create a card configuration to control an entity of the binary_sensor domain.
|
||||
*/
|
||||
class BinarySensorCard extends SensorCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {EntityCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: EntityCardConfig = {
|
||||
type: "custom:mushroom-entity-card",
|
||||
icon: "mdi:power-cycle",
|
||||
icon_color: "green",
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): EntityCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-entity-card',
|
||||
icon: 'mdi:power-cycle',
|
||||
icon_color: 'green',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.EntityCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {EntityCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.EntityCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...BinarySensorCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {BinarySensorCard};
|
||||
export default BinarySensorCard;
|
||||
|
@ -1,44 +1,37 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {PictureEntityCardConfig} from "../types/homeassistant/panels/lovelave/cards/types";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { PictureEntityCardConfig } from '../types/homeassistant/panels/lovelace/cards/types';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Camera Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the camera domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the camera domain.
|
||||
*/
|
||||
class CameraCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {PictureEntityCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: PictureEntityCardConfig = {
|
||||
entity: "",
|
||||
type: "picture-entity",
|
||||
show_name: false,
|
||||
show_state: false,
|
||||
camera_view: "live",
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): PictureEntityCardConfig {
|
||||
return {
|
||||
entity: '',
|
||||
type: 'picture-entity',
|
||||
show_name: false,
|
||||
show_state: false,
|
||||
camera_view: 'live',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.PictureEntityCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {PictureEntityCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.PictureEntityCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: PictureEntityCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...CameraCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {CameraCard};
|
||||
export default CameraCard;
|
||||
|
@ -1,48 +1,36 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {ClimateCardConfig} from "../types/lovelace-mushroom/cards/climate-card-config";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { ClimateCardConfig } from '../types/lovelace-mushroom/cards/climate-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Climate Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the climate domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the climate domain.
|
||||
*/
|
||||
class ClimateCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {ClimateCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: ClimateCardConfig = {
|
||||
type: "custom:mushroom-climate-card",
|
||||
icon: undefined,
|
||||
hvac_modes: [
|
||||
"off",
|
||||
"cool",
|
||||
"heat",
|
||||
"fan_only",
|
||||
],
|
||||
show_temperature_control: true,
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): ClimateCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-climate-card',
|
||||
icon: undefined,
|
||||
hvac_modes: ['off', 'cool', 'heat', 'fan_only'],
|
||||
show_temperature_control: true,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.ClimateCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {ClimateCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.ClimateCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: ClimateCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...ClimateCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {ClimateCard};
|
||||
export default ClimateCard;
|
||||
|
@ -1,102 +0,0 @@
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {StackCardConfig} from "../types/homeassistant/lovelace/cards/types";
|
||||
import {LovelaceCardConfig} from "../types/homeassistant/data/lovelace";
|
||||
import {HassServiceTarget} from "home-assistant-js-websocket";
|
||||
|
||||
/**
|
||||
* Controller Card class.
|
||||
*
|
||||
* Used for creating a Title Card with controls.
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
class ControllerCard {
|
||||
/**
|
||||
* @type {HassServiceTarget} The target to control the entities of.
|
||||
* @private
|
||||
*/
|
||||
readonly #target: HassServiceTarget;
|
||||
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {cards.ControllerCardConfig}
|
||||
* @private
|
||||
*/
|
||||
readonly #defaultConfig: cards.ControllerCardConfig = {
|
||||
type: "mushroom-title-card",
|
||||
showControls: true,
|
||||
iconOn: "mdi:power-on",
|
||||
iconOff: "mdi:power-off",
|
||||
onService: "none",
|
||||
offService: "none",
|
||||
};
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {HassServiceTarget} target The target to control the entities of.
|
||||
* @param {cards.ControllerCardOptions} options Controller Card options.
|
||||
*/
|
||||
constructor(target: HassServiceTarget, options: cards.ControllerCardOptions = {}) {
|
||||
this.#target = target;
|
||||
this.#defaultConfig = {
|
||||
...this.#defaultConfig,
|
||||
...options,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Controller card.
|
||||
*
|
||||
* @return {StackCardConfig} A Controller card.
|
||||
*/
|
||||
createCard(): StackCardConfig {
|
||||
const cards: LovelaceCardConfig[] = [
|
||||
{
|
||||
type: "custom:mushroom-title-card",
|
||||
title: this.#defaultConfig.title,
|
||||
subtitle: this.#defaultConfig.subtitle,
|
||||
},
|
||||
];
|
||||
|
||||
if (this.#defaultConfig.showControls) {
|
||||
cards.push({
|
||||
type: "horizontal-stack",
|
||||
cards: [
|
||||
{
|
||||
type: "custom:mushroom-template-card",
|
||||
icon: this.#defaultConfig.iconOff,
|
||||
layout: "vertical",
|
||||
icon_color: "red",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service: this.#defaultConfig.offService,
|
||||
target: this.#target,
|
||||
data: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "custom:mushroom-template-card",
|
||||
icon: this.#defaultConfig.iconOn,
|
||||
layout: "vertical",
|
||||
icon_color: "amber",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service: this.#defaultConfig.onService,
|
||||
target: this.#target,
|
||||
data: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: "horizontal-stack",
|
||||
cards: cards,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {ControllerCard};
|
@ -1,44 +1,37 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {CoverCardConfig} from "../types/lovelace-mushroom/cards/cover-card-config";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { CoverCardConfig } from '../types/lovelace-mushroom/cards/cover-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Cover Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the cover domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the cover domain.
|
||||
*/
|
||||
class CoverCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {CoverCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: CoverCardConfig = {
|
||||
type: "custom:mushroom-cover-card",
|
||||
icon: undefined,
|
||||
show_buttons_control: true,
|
||||
show_position_control: true,
|
||||
show_tilt_position_control: true,
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): CoverCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-cover-card',
|
||||
icon: undefined,
|
||||
show_buttons_control: true,
|
||||
show_position_control: true,
|
||||
show_tilt_position_control: true,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.CoverCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {CoverCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.CoverCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: CoverCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...CoverCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {CoverCard};
|
||||
export default CoverCard;
|
||||
|
@ -1,44 +1,37 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {FanCardConfig} from "../types/lovelace-mushroom/cards/fan-card-config";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { FanCardConfig } from '../types/lovelace-mushroom/cards/fan-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Fan Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the fan domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the fan domain.
|
||||
*/
|
||||
class FanCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {FanCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: FanCardConfig = {
|
||||
type: "custom:mushroom-fan-card",
|
||||
icon: undefined,
|
||||
show_percentage_control: true,
|
||||
show_oscillate_control: true,
|
||||
icon_animation: true,
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): FanCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-fan-card',
|
||||
icon: undefined,
|
||||
show_percentage_control: true,
|
||||
show_oscillate_control: true,
|
||||
icon_animation: true,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.FanCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {FanCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.FanCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: FanCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...FanCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {FanCard};
|
||||
export default FanCard;
|
||||
|
@ -1,49 +1,45 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {AreaRegistryEntry} from "../types/homeassistant/data/area_registry";
|
||||
import {AreaCardConfig} from "../types/homeassistant/lovelace/cards/types";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { AreaRegistryEntry } from '../types/homeassistant/data/area_registry';
|
||||
import { AreaCardConfig } from '../types/homeassistant/panels/lovelace/cards/types';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* HA Area Card Class
|
||||
*
|
||||
* Used to create a card for an entity of the area domain using the built-in type 'area'.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create card configuration for an entry of the HASS area registry.
|
||||
*/
|
||||
class AreaCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {AreaCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: AreaCardConfig = {
|
||||
type: "area",
|
||||
area: "",
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): AreaCardConfig {
|
||||
return {
|
||||
type: 'area',
|
||||
area: '',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {AreaRegistryEntry} area The area entity to create a card for.
|
||||
* @param {cards.AreaCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {AreaRegistryEntry} area The HASS entity to create a card configuration for.
|
||||
* @param {AreaCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
|
||||
constructor(area: AreaRegistryEntry, options: cards.AreaCardOptions = {}) {
|
||||
constructor(area: AreaRegistryEntry, customConfiguration?: AreaCardConfig) {
|
||||
super(area);
|
||||
|
||||
// Initialize the default configuration.
|
||||
this.#defaultConfig.area = area.area_id;
|
||||
this.#defaultConfig.navigation_path = this.#defaultConfig.area;
|
||||
const configuration = AreaCard.getDefaultConfig();
|
||||
|
||||
// Enforce the card type.
|
||||
delete options.type;
|
||||
configuration.area = area.area_id;
|
||||
configuration.navigation_path = configuration.area;
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = {
|
||||
...this.configuration,
|
||||
...configuration,
|
||||
...customConfiguration,
|
||||
type: configuration.type, // Enforce the card type.
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {AreaCard};
|
||||
export default AreaCard;
|
||||
|
101
src/cards/HeaderCard.ts
Normal file
101
src/cards/HeaderCard.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import { HassServiceTarget } from 'home-assistant-js-websocket';
|
||||
import { LovelaceCardConfig } from '../types/homeassistant/data/lovelace/config/card';
|
||||
import { StackCardConfig } from '../types/homeassistant/panels/lovelace/cards/types';
|
||||
import { CustomHeaderCardConfig, StrategyHeaderCardConfig } from '../types/strategy/strategy-cards';
|
||||
|
||||
/**
|
||||
* Header Card class.
|
||||
*
|
||||
* Used to create a card configuration for a Header Card.
|
||||
* The card can be used to describe a group of cards and optionally to control multiple entities.
|
||||
*/
|
||||
class HeaderCard {
|
||||
/** The target to control the entities of. */
|
||||
private readonly target: HassServiceTarget;
|
||||
/** The current configuration of the card after instantiating this class. */
|
||||
private readonly configuration: StrategyHeaderCardConfig;
|
||||
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): StrategyHeaderCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-title-card',
|
||||
showControls: true,
|
||||
iconOn: 'mdi:power-on',
|
||||
iconOff: 'mdi:power-off',
|
||||
onService: 'none',
|
||||
offService: 'none',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {HassServiceTarget} target The target which is optionally controlled by the card.
|
||||
* @param {CustomHeaderCardConfig} [customConfiguration] Custom card configuration.
|
||||
*
|
||||
* @remarks
|
||||
* The target object can contain one or multiple ids of different entry types.
|
||||
*/
|
||||
constructor(target: HassServiceTarget, customConfiguration?: CustomHeaderCardConfig) {
|
||||
this.target = target;
|
||||
this.configuration = { ...HeaderCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Header card configuration.
|
||||
*
|
||||
* @remarks
|
||||
* The card is represented by a horizontal stack of cards.
|
||||
* One title card and optionally two template cards to control entities.
|
||||
*/
|
||||
createCard(): StackCardConfig {
|
||||
// Create a title card.
|
||||
const cards: LovelaceCardConfig[] = [
|
||||
{
|
||||
type: 'custom:mushroom-title-card',
|
||||
title: this.configuration.title,
|
||||
subtitle: this.configuration.subtitle,
|
||||
},
|
||||
];
|
||||
|
||||
// Add controls to the card.
|
||||
if (this.configuration.showControls) {
|
||||
cards.push({
|
||||
type: 'horizontal-stack',
|
||||
cards: [
|
||||
{
|
||||
type: 'custom:mushroom-template-card',
|
||||
icon: this.configuration.iconOff,
|
||||
layout: 'vertical',
|
||||
icon_color: 'red',
|
||||
tap_action: {
|
||||
action: 'call-service',
|
||||
service: this.configuration.offService,
|
||||
target: this.target,
|
||||
data: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'custom:mushroom-template-card',
|
||||
icon: this.configuration.iconOn,
|
||||
layout: 'vertical',
|
||||
icon_color: 'amber',
|
||||
tap_action: {
|
||||
action: 'call-service',
|
||||
service: this.configuration.onService,
|
||||
target: this.target,
|
||||
data: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'horizontal-stack',
|
||||
cards: cards,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default HeaderCard;
|
@ -1,41 +1,34 @@
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {SelectCardConfig} from "../types/lovelace-mushroom/cards/select-card-config";
|
||||
import {SelectCard} from './SelectCard';
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { SelectCardConfig } from '../types/lovelace-mushroom/cards/select-card-config';
|
||||
import SelectCard from './SelectCard';
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported
|
||||
/**
|
||||
* InputSelect Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the input_select domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the input_select domain.
|
||||
*/
|
||||
class InputSelectCard extends SelectCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {SelectCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: SelectCardConfig = {
|
||||
type: "custom:mushroom-select-card",
|
||||
icon: undefined,
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): SelectCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-select-card',
|
||||
icon: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.InputSelectCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {SelectCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.InputSelectCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: SelectCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...InputSelectCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {InputSelectCard};
|
||||
export default InputSelectCard;
|
||||
|
@ -1,67 +1,55 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {LightCardConfig} from "../types/lovelace-mushroom/cards/light-card-config";
|
||||
import {generic} from "../types/strategy/generic";
|
||||
import isCallServiceActionConfig = generic.isCallServiceActionConfig;
|
||||
import isCallServiceActionTarget = generic.isCallServiceActionTarget;
|
||||
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { LightCardConfig } from '../types/lovelace-mushroom/cards/light-card-config';
|
||||
import { isCallServiceActionConfig } from '../types/strategy/strategy-generics';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Light Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the light domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the light domain.
|
||||
*/
|
||||
class LightCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {LightCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: LightCardConfig = {
|
||||
type: "custom:mushroom-light-card",
|
||||
icon: undefined,
|
||||
show_brightness_control: true,
|
||||
show_color_control: true,
|
||||
show_color_temp_control: true,
|
||||
use_light_color: true,
|
||||
double_tap_action: {
|
||||
action: "call-service",
|
||||
service: "light.turn_on",
|
||||
target: {
|
||||
entity_id: undefined,
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): LightCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-light-card',
|
||||
icon: undefined,
|
||||
show_brightness_control: true,
|
||||
show_color_control: true,
|
||||
show_color_temp_control: true,
|
||||
use_light_color: true,
|
||||
double_tap_action: {
|
||||
action: 'call-service',
|
||||
perform_action: 'light.turn_on',
|
||||
target: {
|
||||
entity_id: undefined,
|
||||
},
|
||||
data: {
|
||||
rgb_color: [255, 255, 255],
|
||||
},
|
||||
},
|
||||
data: {
|
||||
rgb_color: [255, 255, 255],
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.LightCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {LightCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.LightCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: LightCardConfig) {
|
||||
super(entity);
|
||||
|
||||
// Set the target for double-tap action.
|
||||
if (
|
||||
isCallServiceActionConfig(this.#defaultConfig.double_tap_action)
|
||||
&& isCallServiceActionTarget(this.#defaultConfig.double_tap_action.target)
|
||||
) {
|
||||
this.#defaultConfig.double_tap_action.target.entity_id = entity.entity_id;
|
||||
const configuration = LightCard.getDefaultConfig();
|
||||
|
||||
if (isCallServiceActionConfig(configuration.double_tap_action)) {
|
||||
configuration.double_tap_action.target = { entity_id: entity.entity_id };
|
||||
}
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...configuration, ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {LightCard};
|
||||
export default LightCard;
|
||||
|
@ -1,41 +1,34 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {LockCardConfig} from "../types/lovelace-mushroom/cards/lock-card-config";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { LockCardConfig } from '../types/lovelace-mushroom/cards/lock-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Lock Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the lock domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the lock domain.
|
||||
*/
|
||||
class LockCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {LockCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: LockCardConfig = {
|
||||
type: "custom:mushroom-lock-card",
|
||||
icon: undefined,
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): LockCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-lock-card',
|
||||
icon: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.LockCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {LockCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.LockCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: LockCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...LockCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {LockCard};
|
||||
export default LockCard;
|
||||
|
@ -1,51 +1,37 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {MediaPlayerCardConfig} from "../types/lovelace-mushroom/cards/media-player-card-config";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { MediaPlayerCardConfig } from '../types/lovelace-mushroom/cards/media-player-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Mediaplayer Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the media_player domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the media_player domain.
|
||||
*/
|
||||
class MediaPlayerCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {MediaPlayerCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: MediaPlayerCardConfig = {
|
||||
type: "custom:mushroom-media-player-card",
|
||||
use_media_info: true,
|
||||
media_controls: [
|
||||
"on_off",
|
||||
"play_pause_stop",
|
||||
],
|
||||
show_volume_level: true,
|
||||
volume_controls: [
|
||||
"volume_mute",
|
||||
"volume_set",
|
||||
"volume_buttons",
|
||||
],
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): MediaPlayerCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-media-player-card',
|
||||
use_media_info: true,
|
||||
media_controls: ['on_off', 'play_pause_stop'],
|
||||
show_volume_level: true,
|
||||
volume_controls: ['volume_mute', 'volume_set', 'volume_buttons'],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.MediaPlayerCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {MediaPlayerCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.MediaPlayerCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: MediaPlayerCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...MediaPlayerCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {MediaPlayerCard};
|
||||
export default MediaPlayerCard;
|
||||
|
@ -1,40 +1,32 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {EntityCardConfig} from "../types/lovelace-mushroom/cards/entity-card-config";
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Miscellaneous Card Class
|
||||
*
|
||||
* Used to create a card an entity of any domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of any domain.
|
||||
*/
|
||||
class MiscellaneousCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {EntityCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: EntityCardConfig = {
|
||||
type: "custom:mushroom-entity-card",
|
||||
icon_color: "blue-grey",
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): EntityCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-entity-card',
|
||||
icon_color: 'blue-grey',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.EntityCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {EntityCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.EntityCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...MiscellaneousCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {MiscellaneousCard};
|
||||
export default MiscellaneousCard;
|
||||
|
@ -1,41 +1,34 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {NumberCardConfig} from "../types/lovelace-mushroom/cards/number-card-config";
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { NumberCardConfig } from '../types/lovelace-mushroom/cards/number-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported
|
||||
/**
|
||||
* Number Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the number domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the number domain.
|
||||
*/
|
||||
class NumberCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {NumberCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: NumberCardConfig = {
|
||||
type: "custom:mushroom-number-card",
|
||||
icon: undefined,
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): NumberCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-number-card',
|
||||
icon: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.NumberCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {NumberCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.NumberCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: NumberCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...NumberCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {NumberCard};
|
||||
export default NumberCard;
|
||||
|
@ -1,43 +1,35 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {PersonCardConfig} from "../types/lovelace-mushroom/cards/person-card-config";
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { PersonCardConfig } from '../types/lovelace-mushroom/cards/person-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Person Card Class
|
||||
*
|
||||
* Used to create a card for an entity of the Person domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the person domain.
|
||||
*/
|
||||
class PersonCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {PersonCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: PersonCardConfig = {
|
||||
type: "custom:mushroom-person-card",
|
||||
layout: "vertical",
|
||||
primary_info: "none",
|
||||
secondary_info: "none",
|
||||
icon_type: "entity-picture",
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): PersonCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-person-card',
|
||||
layout: 'vertical',
|
||||
primary_info: 'none',
|
||||
secondary_info: 'none',
|
||||
icon_type: 'entity-picture',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.PersonCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {PersonCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.PersonCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: PersonCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...PersonCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {PersonCard};
|
||||
export default PersonCard;
|
||||
|
@ -1,63 +1,63 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {generic} from "../types/strategy/generic";
|
||||
import {EntityCardConfig} from "../types/lovelace-mushroom/cards/entity-card-config";
|
||||
import {Helper} from "../Helper";
|
||||
import isCallServiceActionConfig = generic.isCallServiceActionConfig;
|
||||
import isCallServiceActionTarget = generic.isCallServiceActionTarget;
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { Registry } from '../Registry';
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
import SwitchCard from './SwitchCard';
|
||||
import { isCallServiceActionConfig } from '../types/strategy/strategy-generics';
|
||||
|
||||
/**
|
||||
* Scene Card Class
|
||||
*
|
||||
* Used to create a card for an entity of the scene domain.
|
||||
* Used to create a card configuration to control an entity of the scene domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Supports Stateful scenes from https://github.com/hugobloem/stateful_scenes.
|
||||
* If the stateful scene entity is available, it will be used instead of the original scene entity.
|
||||
*/
|
||||
class SceneCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {EntityCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: EntityCardConfig = {
|
||||
type: "custom:mushroom-entity-card",
|
||||
icon: "mdi:palette",
|
||||
icon_color: "blue",
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service: "scene.turn_on",
|
||||
target: {
|
||||
entity_id: undefined,
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): EntityCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-entity-card',
|
||||
tap_action: {
|
||||
action: 'perform-action',
|
||||
perform_action: 'scene.turn_on',
|
||||
target: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.EntityCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {EntityCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.EntityCardOptions = {}) {
|
||||
super(entity);
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) {
|
||||
const sceneName = entity.entity_id.split('.').pop();
|
||||
const statefulScene = Registry.entities.find((entity) => entity.entity_id === `switch.${sceneName}_stateful_scene`);
|
||||
|
||||
// Set the target for tap action.
|
||||
if (
|
||||
isCallServiceActionConfig(this.#defaultConfig.tap_action)
|
||||
&& isCallServiceActionTarget(this.#defaultConfig.tap_action.target)
|
||||
) {
|
||||
this.#defaultConfig.tap_action.target.entity_id = entity.entity_id;
|
||||
super(statefulScene ?? entity);
|
||||
|
||||
// Stateful scene support.
|
||||
if (statefulScene) {
|
||||
this.configuration = new SwitchCard(statefulScene).getCard();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.#defaultConfig.icon = Helper.getEntityState(entity)?.attributes.icon ?? this.#defaultConfig.icon;
|
||||
// Initialize the default configuration.
|
||||
const configuration = SceneCard.getDefaultConfig();
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
if (isCallServiceActionConfig(configuration.tap_action)) {
|
||||
configuration.tap_action.target = { entity_id: entity.entity_id };
|
||||
}
|
||||
|
||||
configuration.icon = Registry.hassStates[entity.entity_id]?.attributes.icon ?? configuration.icon;
|
||||
|
||||
this.configuration = { ...this.configuration, ...configuration, ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {SceneCard};
|
||||
export default SceneCard;
|
||||
|
@ -1,41 +1,34 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {SelectCardConfig} from "../types/lovelace-mushroom/cards/select-card-config";
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { SelectCardConfig } from '../types/lovelace-mushroom/cards/select-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported
|
||||
/**
|
||||
* Select Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the select domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the select domain.
|
||||
*/
|
||||
class SelectCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {SelectCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: SelectCardConfig = {
|
||||
type: "custom:mushroom-select-card",
|
||||
icon: undefined,
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): SelectCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-select-card',
|
||||
icon: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.SelectCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {SelectCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.SelectCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: SelectCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...SelectCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {SelectCard};
|
||||
export default SelectCard;
|
||||
|
@ -1,42 +1,34 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {EntityCardConfig} from "../types/lovelace-mushroom/cards/entity-card-config";
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Sensor Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the sensor domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
*/
|
||||
class SensorCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {EntityCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: EntityCardConfig = {
|
||||
type: "custom:mushroom-entity-card",
|
||||
icon: "mdi:information",
|
||||
animate: true,
|
||||
line_color: "green",
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): EntityCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-entity-card',
|
||||
icon: 'mdi:information',
|
||||
animate: true,
|
||||
line_color: 'green',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.EntityCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {EntityCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.EntityCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...SensorCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {SensorCard};
|
||||
export default SensorCard;
|
||||
|
@ -1,44 +1,37 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {EntityCardConfig} from "../types/lovelace-mushroom/cards/entity-card-config";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Switch Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the switch domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the switch domain.
|
||||
*/
|
||||
class SwitchCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {EntityCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: EntityCardConfig = {
|
||||
type: "custom:mushroom-entity-card",
|
||||
icon: undefined,
|
||||
tap_action: {
|
||||
action: "toggle",
|
||||
},
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): EntityCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-entity-card',
|
||||
icon: undefined,
|
||||
tap_action: {
|
||||
action: 'toggle',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.EntityCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {EntityCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.EntityCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...SwitchCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {SwitchCard};
|
||||
export default SwitchCard;
|
||||
|
@ -1,46 +1,39 @@
|
||||
import {AbstractCard} from "./AbstractCard";
|
||||
import {cards} from "../types/strategy/cards";
|
||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
||||
import {VACUUM_COMMANDS, VacuumCardConfig} from "../types/lovelace-mushroom/cards/vacuum-card-config";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { VACUUM_COMMANDS, VacuumCardConfig } from '../types/lovelace-mushroom/cards/vacuum-card-config';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Vacuum Card Class
|
||||
*
|
||||
* Used to create a card for controlling an entity of the vacuum domain.
|
||||
*
|
||||
* @class
|
||||
* @extends AbstractCard
|
||||
* Used to create a card configuration to control an entity of the vacuum domain.
|
||||
*/
|
||||
class VacuumCard extends AbstractCard {
|
||||
/**
|
||||
* Default configuration of the card.
|
||||
*
|
||||
* @type {VacuumCardConfig}
|
||||
* @private
|
||||
*/
|
||||
#defaultConfig: VacuumCardConfig = {
|
||||
type: "custom:mushroom-vacuum-card",
|
||||
icon: undefined,
|
||||
icon_animation: true,
|
||||
commands: [...VACUUM_COMMANDS],
|
||||
tap_action: {
|
||||
action: "more-info",
|
||||
}
|
||||
};
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): VacuumCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-vacuum-card',
|
||||
icon: undefined,
|
||||
icon_animation: true,
|
||||
commands: [...VACUUM_COMMANDS],
|
||||
tap_action: {
|
||||
action: 'more-info',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
||||
* @param {cards.VacuumCardOptions} [options={}] Options for the card.
|
||||
* @throws {Error} If the Helper module isn't initialized.
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {VacuumCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, options: cards.VacuumCardOptions = {}) {
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: VacuumCardConfig) {
|
||||
super(entity);
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...VacuumCard.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {VacuumCard};
|
||||
export default VacuumCard;
|
||||
|
57
src/cards/ValveCard.ts
Normal file
57
src/cards/ValveCard.ts
Normal file
@ -0,0 +1,57 @@
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||
import { TemplateCardConfig } from '../types/lovelace-mushroom/cards/template-card-config';
|
||||
import { localize } from '../utilities/localize';
|
||||
import AbstractCard from './AbstractCard';
|
||||
|
||||
/**
|
||||
* Valve Card Class
|
||||
*
|
||||
* Used to create a card configuration to control an entity of the valve domain.
|
||||
*/
|
||||
class ValveCard extends AbstractCard {
|
||||
/** Returns the default configuration object for the card. */
|
||||
static getDefaultConfig(): TemplateCardConfig {
|
||||
return {
|
||||
type: 'custom:mushroom-template-card',
|
||||
icon: 'mdi:valve',
|
||||
icon_color: 'blue',
|
||||
double_tap_action: {
|
||||
action: 'toggle',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||
* @param {VacuumCardConfig} [customConfiguration] Custom card configuration.
|
||||
*/
|
||||
constructor(entity: EntityRegistryEntry, customConfiguration?: TemplateCardConfig) {
|
||||
super(entity);
|
||||
|
||||
// Initialize the default configuration.
|
||||
const configuration = ValveCard.getDefaultConfig();
|
||||
|
||||
configuration.entity = entity.entity_id;
|
||||
configuration.icon = entity.icon ?? configuration.icon;
|
||||
configuration.primary = entity.name ?? entity.original_name ?? '?';
|
||||
configuration.secondary = `{%
|
||||
set mapping = {
|
||||
'open': '${localize('valve.open')}',
|
||||
'opening': '${localize('valve.opening')}',
|
||||
'closed': '${localize('valve.closed')}',
|
||||
'closing': '${localize('valve.closing')}',
|
||||
'stopped': '${localize('valve.stopped')}',
|
||||
'unavailable': '${localize('generic.unavailable')}'
|
||||
}
|
||||
%}
|
||||
{{ mapping.get(states('${entity.entity_id}'), '${localize('generic.unknown')}') }}`;
|
||||
|
||||
this.configuration = { ...this.configuration, ...configuration, ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export default ValveCard;
|
@ -1,64 +1,48 @@
|
||||
import {HassServiceTarget} from "home-assistant-js-websocket";
|
||||
import {LovelaceChipConfig} from "../types/lovelace-mushroom/utils/lovelace/chip/types";
|
||||
import {Helper} from "../Helper";
|
||||
import {generic} from "../types/strategy/generic";
|
||||
import isCallServiceActionConfig = generic.isCallServiceActionConfig;
|
||||
import { Registry } from '../Registry';
|
||||
import { LovelaceChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types';
|
||||
import { logMessage, lvlFatal } from '../utilities/debug';
|
||||
|
||||
/**
|
||||
* Abstract Chip class.
|
||||
*
|
||||
* To create a new chip, extend this one.
|
||||
*
|
||||
* @class
|
||||
* @abstract
|
||||
*/
|
||||
abstract class AbstractChip {
|
||||
/**
|
||||
* Abstract Chip class.
|
||||
*
|
||||
* To create a chip configuration, this class should be extended by a child class.
|
||||
* Child classes should override the default configuration so the chip correctly reflects the entity.
|
||||
*
|
||||
* @remarks
|
||||
* Before using this class, the Registry module must be initialized by calling {@link Registry.initialize}.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Configuration of the chip.
|
||||
*
|
||||
* @type {LovelaceChipConfig}
|
||||
* Child classes should override this property to reflect their own card type and options.
|
||||
*/
|
||||
config: LovelaceChipConfig = {
|
||||
type: "template"
|
||||
protected configuration: LovelaceChipConfig = {
|
||||
// TODO: Check if this is correct vs custom:mushroom-template-badge. Also in child classes.
|
||||
type: 'template',
|
||||
};
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
*
|
||||
* @remarks
|
||||
* Before using this class, the Registry module must be initialized by calling {@link Registry.initialize}.
|
||||
*/
|
||||
protected constructor() {
|
||||
if (!Helper.isInitialized()) {
|
||||
throw new Error("The Helper module must be initialized before using this one.");
|
||||
if (!Registry.initialized) {
|
||||
logMessage(lvlFatal, 'Registry not initialized!');
|
||||
}
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Method is called on dymanically imported classes.
|
||||
/**
|
||||
* Get the chip.
|
||||
* Get a chip configuration.
|
||||
*
|
||||
* @returns {LovelaceChipConfig} A chip.
|
||||
* The configuration should be set by any of the child classes so the chip correctly reflects an entity.
|
||||
*/
|
||||
getChip(): LovelaceChipConfig {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the target to switch.
|
||||
*
|
||||
* @param {HassServiceTarget} target Target to switch.
|
||||
*/
|
||||
setTapActionTarget(target: HassServiceTarget) {
|
||||
if ("tap_action" in this.config && isCallServiceActionConfig(this.config.tap_action)) {
|
||||
this.config.tap_action.target = target;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Helper.debug) {
|
||||
console.warn(
|
||||
this.constructor.name
|
||||
+ " - Target not set: Invalid target or tap action.");
|
||||
}
|
||||
getChipConfiguration(): LovelaceChipConfig {
|
||||
return this.configuration;
|
||||
}
|
||||
}
|
||||
|
||||
export {AbstractChip};
|
||||
export default AbstractChip;
|
||||
|
@ -1,47 +1,42 @@
|
||||
import {Helper} from "../Helper";
|
||||
import {AbstractChip} from "./AbstractChip";
|
||||
import {chips} from "../types/strategy/chips";
|
||||
import {TemplateChipConfig} from "../types/lovelace-mushroom/utils/lovelace/chip/types";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { Registry } from '../Registry';
|
||||
import { TemplateChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types';
|
||||
import AbstractChip from './AbstractChip';
|
||||
|
||||
/**
|
||||
* Climate Chip class.
|
||||
*
|
||||
* Used to create a chip to indicate how many climates are operating.
|
||||
* Used to create a chip configuration to indicate how many climates are operating.
|
||||
*/
|
||||
class ClimateChip extends AbstractChip {
|
||||
/**
|
||||
* Default configuration of the chip.
|
||||
*
|
||||
* @type {TemplateChipConfig}
|
||||
*
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
readonly #defaultConfig: TemplateChipConfig = {
|
||||
type: "template",
|
||||
icon: "mdi:thermostat",
|
||||
icon_color: "orange",
|
||||
content: Helper.getCountTemplate("climate", "ne", "off"),
|
||||
tap_action: {
|
||||
action: "none",
|
||||
},
|
||||
hold_action: {
|
||||
action: "navigate",
|
||||
navigation_path: "climates",
|
||||
},
|
||||
};
|
||||
/** Returns the default configuration object for the chip. */
|
||||
static getDefaultConfig(): TemplateChipConfig {
|
||||
return {
|
||||
type: 'template',
|
||||
icon: 'mdi:thermostat',
|
||||
icon_color: 'orange',
|
||||
content: Registry.getCountTemplate('climate', 'ne', 'off'),
|
||||
tap_action: {
|
||||
action: 'none',
|
||||
},
|
||||
hold_action: {
|
||||
action: 'navigate',
|
||||
navigation_path: 'climates',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
*
|
||||
* @param {chips.TemplateChipOptions} options The chip options.
|
||||
* @param {TemplateChipConfig} [customConfiguration] Custom chip configuration.
|
||||
*/
|
||||
constructor(options: chips.TemplateChipOptions = {}) {
|
||||
constructor(customConfiguration?: TemplateChipConfig) {
|
||||
super();
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...ClimateChip.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {ClimateChip};
|
||||
export default ClimateChip;
|
||||
|
@ -1,47 +1,42 @@
|
||||
import {Helper} from "../Helper";
|
||||
import {chips} from "../types/strategy/chips";
|
||||
import {AbstractChip} from "./AbstractChip";
|
||||
import {TemplateChipConfig} from "../types/lovelace-mushroom/utils/lovelace/chip/types";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { Registry } from '../Registry';
|
||||
import { TemplateChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types';
|
||||
import AbstractChip from './AbstractChip';
|
||||
|
||||
/**
|
||||
* Cover Chip class.
|
||||
*
|
||||
* Used to create a chip to indicate how many covers aren't closed.
|
||||
* Used to create a chip configuration to indicate how many covers aren't closed.
|
||||
*/
|
||||
class CoverChip extends AbstractChip {
|
||||
/**
|
||||
* Default configuration of the chip.
|
||||
*
|
||||
* @type {TemplateChipConfig}
|
||||
*
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
readonly #defaultConfig: TemplateChipConfig = {
|
||||
type: "template",
|
||||
icon: "mdi:window-open",
|
||||
icon_color: "cyan",
|
||||
content: Helper.getCountTemplate("cover", "search", "(open|opening|closing)"),
|
||||
tap_action: {
|
||||
action: "none",
|
||||
},
|
||||
hold_action: {
|
||||
action: "navigate",
|
||||
navigation_path: "covers",
|
||||
},
|
||||
};
|
||||
/** Returns the default configuration object for the chip. */
|
||||
static getDefaultConfig(): TemplateChipConfig {
|
||||
return {
|
||||
type: 'template',
|
||||
icon: 'mdi:window-open',
|
||||
icon_color: 'cyan',
|
||||
content: Registry.getCountTemplate('cover', 'search', '(open|opening|closing)'),
|
||||
tap_action: {
|
||||
action: 'none',
|
||||
},
|
||||
hold_action: {
|
||||
action: 'navigate',
|
||||
navigation_path: 'covers',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
*
|
||||
* @param {chips.TemplateChipOptions} options The chip options.
|
||||
* @param {TemplateChipConfig} [customConfiguration] Custom chip configuration.
|
||||
*/
|
||||
constructor(options: chips.TemplateChipOptions = {}) {
|
||||
constructor(customConfiguration?: TemplateChipConfig) {
|
||||
super();
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...CoverChip.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {CoverChip};
|
||||
export default CoverChip;
|
||||
|
@ -1,48 +1,49 @@
|
||||
import {Helper} from "../Helper";
|
||||
import {chips} from "../types/strategy/chips";
|
||||
import {AbstractChip} from "./AbstractChip";
|
||||
import {TemplateChipConfig} from "../types/lovelace-mushroom/utils/lovelace/chip/types";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { Registry } from '../Registry';
|
||||
import { TemplateChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types';
|
||||
import AbstractChip from './AbstractChip';
|
||||
import RegistryFilter from '../utilities/RegistryFilter';
|
||||
|
||||
/**
|
||||
* Fan Chip class.
|
||||
*
|
||||
* Used to create a chip to indicate how many fans are on and to turn all off.
|
||||
* Used to create a chip to indicate how many fans are on and to switch them all off.
|
||||
*/
|
||||
class FanChip extends AbstractChip {
|
||||
/**
|
||||
* Default configuration of the chip.
|
||||
*
|
||||
* @type {TemplateChipConfig}
|
||||
*
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
readonly #defaultConfig: TemplateChipConfig = {
|
||||
type: "template",
|
||||
icon: "mdi:fan",
|
||||
icon_color: "green",
|
||||
content: Helper.getCountTemplate("fan", "eq", "on"),
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service: "fan.turn_off",
|
||||
},
|
||||
hold_action: {
|
||||
action: "navigate",
|
||||
navigation_path: "fans",
|
||||
},
|
||||
};
|
||||
/** Returns the default configuration object for the chip. */
|
||||
static getDefaultConfig(): TemplateChipConfig {
|
||||
return {
|
||||
type: 'template',
|
||||
icon: 'mdi:fan',
|
||||
icon_color: 'green',
|
||||
content: Registry.getCountTemplate('fan', 'eq', 'on'),
|
||||
tap_action: {
|
||||
action: 'perform-action',
|
||||
perform_action: 'fan.turn_off',
|
||||
target: {
|
||||
entity_id: new RegistryFilter(Registry.entities)
|
||||
.whereDomain('fan')
|
||||
.getValuesByProperty('entity_id') as string[],
|
||||
},
|
||||
},
|
||||
hold_action: {
|
||||
action: 'navigate',
|
||||
navigation_path: 'fans',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
*
|
||||
* @param {chips.TemplateChipOptions} options The chip options.
|
||||
* @param {TemplateChipConfig} [customConfiguration] Custom chip configuration.
|
||||
*/
|
||||
constructor(options: chips.TemplateChipOptions = {}) {
|
||||
constructor(customConfiguration?: TemplateChipConfig) {
|
||||
super();
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...FanChip.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {FanChip};
|
||||
export default FanChip;
|
||||
|
@ -1,48 +1,49 @@
|
||||
import {Helper} from "../Helper";
|
||||
import {chips} from "../types/strategy/chips";
|
||||
import {AbstractChip} from "./AbstractChip";
|
||||
import {TemplateChipConfig} from "../types/lovelace-mushroom/utils/lovelace/chip/types";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { Registry } from '../Registry';
|
||||
import { TemplateChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types';
|
||||
import AbstractChip from './AbstractChip';
|
||||
import RegistryFilter from '../utilities/RegistryFilter';
|
||||
|
||||
/**
|
||||
* Light Chip class.
|
||||
*
|
||||
* Used to create a chip to indicate how many lights are on and to turn all off.
|
||||
* Used to create a chip configuration to indicate how many lights are on and to switch them all off.
|
||||
*/
|
||||
class LightChip extends AbstractChip {
|
||||
/**
|
||||
* Default configuration of the chip.
|
||||
*
|
||||
* @type {TemplateChipConfig}
|
||||
*
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
readonly #defaultConfig: TemplateChipConfig = {
|
||||
type: "template",
|
||||
icon: "mdi:lightbulb-group",
|
||||
icon_color: "amber",
|
||||
content: Helper.getCountTemplate("light", "eq", "on"),
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service: "light.turn_off",
|
||||
},
|
||||
hold_action: {
|
||||
action: "navigate",
|
||||
navigation_path: "lights",
|
||||
},
|
||||
};
|
||||
/** Returns the default configuration object for the chip. */
|
||||
static getDefaultConfig(): TemplateChipConfig {
|
||||
return {
|
||||
type: 'template',
|
||||
icon: 'mdi:lightbulb-group',
|
||||
icon_color: 'amber',
|
||||
content: Registry.getCountTemplate('light', 'eq', 'on'),
|
||||
tap_action: {
|
||||
action: 'perform-action',
|
||||
perform_action: 'light.turn_off',
|
||||
target: {
|
||||
entity_id: new RegistryFilter(Registry.entities)
|
||||
.whereDomain('light')
|
||||
.getValuesByProperty('entity_id') as string[],
|
||||
},
|
||||
},
|
||||
hold_action: {
|
||||
action: 'navigate',
|
||||
navigation_path: 'lights',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
*
|
||||
* @param {chips.TemplateChipOptions} options The chip options.
|
||||
* @param {TemplateChipConfig} [customConfiguration] Custom chip configuration.
|
||||
*/
|
||||
constructor(options: chips.TemplateChipOptions = {}) {
|
||||
constructor(customConfiguration?: TemplateChipConfig) {
|
||||
super();
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...LightChip.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {LightChip};
|
||||
export default LightChip;
|
||||
|
@ -1,48 +1,49 @@
|
||||
import {Helper} from "../Helper";
|
||||
import {chips} from "../types/strategy/chips";
|
||||
import {AbstractChip} from "./AbstractChip";
|
||||
import {TemplateChipConfig} from "../types/lovelace-mushroom/utils/lovelace/chip/types";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||
|
||||
import { Registry } from '../Registry';
|
||||
import { TemplateChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types';
|
||||
import AbstractChip from './AbstractChip';
|
||||
import RegistryFilter from '../utilities/RegistryFilter';
|
||||
|
||||
/**
|
||||
* Switch Chip class.
|
||||
*
|
||||
* Used to create a chip to indicate how many switches are on and to turn all off.
|
||||
* Used to create a chip configuration to indicate how many switches are on and to switch them all off.
|
||||
*/
|
||||
class SwitchChip extends AbstractChip {
|
||||
/**
|
||||
* Default configuration of the chip.
|
||||
*
|
||||
* @type {TemplateChipConfig}
|
||||
*
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
readonly #defaultConfig: TemplateChipConfig = {
|
||||
type: "template",
|
||||
icon: "mdi:dip-switch",
|
||||
icon_color: "blue",
|
||||
content: Helper.getCountTemplate("switch", "eq", "on"),
|
||||
tap_action: {
|
||||
action: "call-service",
|
||||
service: "switch.turn_off",
|
||||
},
|
||||
hold_action: {
|
||||
action: "navigate",
|
||||
navigation_path: "switches",
|
||||
},
|
||||
};
|
||||
/** Returns the default configuration object for the chip. */
|
||||
static getDefaultConfig(): TemplateChipConfig {
|
||||
return {
|
||||
type: 'template',
|
||||
icon: 'mdi:dip-switch',
|
||||
icon_color: 'blue',
|
||||
content: Registry.getCountTemplate('switch', 'eq', 'on'),
|
||||
tap_action: {
|
||||
action: 'perform-action',
|
||||
perform_action: 'switch.turn_off',
|
||||
target: {
|
||||
entity_id: new RegistryFilter(Registry.entities)
|
||||
.whereDomain('switch')
|
||||
.getValuesByProperty('entity_id') as string[],
|
||||
},
|
||||
},
|
||||
hold_action: {
|
||||
action: 'navigate',
|
||||
navigation_path: 'switches',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
*
|
||||
* @param {chips.TemplateChipOptions} options The chip options.
|
||||
* @param {TemplateChipConfig} [customConfiguration] Custom chip configuration.
|
||||
*/
|
||||
constructor(options: chips.TemplateChipOptions = {}) {
|
||||
constructor(customConfiguration?: TemplateChipConfig) {
|
||||
super();
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...SwitchChip.getDefaultConfig(), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {SwitchChip};
|
||||
export default SwitchChip;
|
||||
|
@ -1,42 +1,35 @@
|
||||
import {chips} from "../types/strategy/chips";
|
||||
import {WeatherChipConfig} from "../types/lovelace-mushroom/utils/lovelace/chip/types";
|
||||
import {AbstractChip} from "./AbstractChip";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols False positive.
|
||||
|
||||
import { WeatherChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types';
|
||||
import AbstractChip from './AbstractChip';
|
||||
|
||||
/**
|
||||
* Weather Chip class.
|
||||
*
|
||||
* Used to create a chip for showing the weather.
|
||||
* Used to create a chip configuration to indicate the current weather.
|
||||
*/
|
||||
class WeatherChip extends AbstractChip {
|
||||
/**
|
||||
* Default configuration of the chip.
|
||||
*
|
||||
* @private
|
||||
* @readonly
|
||||
*/
|
||||
readonly #defaultConfig: WeatherChipConfig = {
|
||||
type: "weather",
|
||||
show_temperature: true,
|
||||
show_conditions: true,
|
||||
};
|
||||
/** Returns the default configuration object for the chip. */
|
||||
static getDefaultConfig(entityId: string): WeatherChipConfig {
|
||||
return {
|
||||
type: 'weather',
|
||||
entity: entityId,
|
||||
show_temperature: true,
|
||||
show_conditions: true,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
*
|
||||
* @param {string} entityId Id of a weather entity.
|
||||
* @param {chips.WeatherChipOptions} options Weather Chip options.
|
||||
* @param {WeatherChipConfig} [customConfiguration] Custom chip configuration.
|
||||
*/
|
||||
constructor(entityId: string, options: chips.WeatherChipOptions = {}) {
|
||||
constructor(entityId: string, customConfiguration?: WeatherChipConfig) {
|
||||
super();
|
||||
this.#defaultConfig = {
|
||||
...this.#defaultConfig,
|
||||
...{entity: entityId},
|
||||
...options,
|
||||
};
|
||||
|
||||
this.config = Object.assign(this.config, this.#defaultConfig, options);
|
||||
this.configuration = { ...this.configuration, ...WeatherChip.getDefaultConfig(entityId), ...customConfiguration };
|
||||
}
|
||||
}
|
||||
|
||||
export {WeatherChip};
|
||||
export default WeatherChip;
|
||||
|
@ -1,167 +1,188 @@
|
||||
import {generic} from "./types/strategy/generic";
|
||||
import StrategyDefaults = generic.StrategyDefaults;
|
||||
import { StrategyDefaults } from './types/strategy/strategy-generics';
|
||||
import { localize } from './utilities/localize';
|
||||
|
||||
/**
|
||||
* Default configuration for the mushroom strategy.
|
||||
*/
|
||||
export const getConfigurationDefaults = (localize: Function): StrategyDefaults => {
|
||||
return {
|
||||
areas: {
|
||||
undisclosed: {
|
||||
area_id: "undisclosed",
|
||||
floor_id: null,
|
||||
name: "Undisclosed",
|
||||
picture: null,
|
||||
icon: "mdi:floor-plan",
|
||||
labels: [],
|
||||
aliases: [],
|
||||
hidden: false,
|
||||
}
|
||||
export const ConfigurationDefaults: StrategyDefaults = {
|
||||
areas: {
|
||||
undisclosed: {
|
||||
// TODO: Refactor undisclosed to other.
|
||||
aliases: [],
|
||||
area_id: 'undisclosed',
|
||||
created_at: 0,
|
||||
floor_id: null,
|
||||
hidden: false,
|
||||
humidity_entity_id: null,
|
||||
icon: 'mdi:floor-plan',
|
||||
labels: [],
|
||||
modified_at: 0,
|
||||
name: localize('generic.undisclosed'),
|
||||
picture: null,
|
||||
temperature_entity_id: null,
|
||||
},
|
||||
debug: false,
|
||||
domains: {
|
||||
_: {
|
||||
hide_config_entities: true,
|
||||
hide_diagnostic_entities: true,
|
||||
},
|
||||
default: {
|
||||
title: localize("generic.miscellaneous"),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
light: {
|
||||
title: localize("light.lights"),
|
||||
showControls: true,
|
||||
iconOn: "mdi:lightbulb",
|
||||
iconOff: "mdi:lightbulb-off",
|
||||
onService: "light.turn_on",
|
||||
offService: "light.turn_off",
|
||||
hidden: false,
|
||||
},
|
||||
scene: {
|
||||
title: localize("scene.scenes"),
|
||||
showControls: false,
|
||||
onService: "scene.turn_on",
|
||||
hidden: false,
|
||||
},
|
||||
fan: {
|
||||
title: localize("fan.fans"),
|
||||
showControls: true,
|
||||
iconOn: "mdi:fan",
|
||||
iconOff: "mdi:fan-off",
|
||||
onService: "fan.turn_on",
|
||||
offService: "fan.turn_off",
|
||||
hidden: false,
|
||||
},
|
||||
cover: {
|
||||
title: localize("cover.covers"),
|
||||
showControls: true,
|
||||
iconOn: "mdi:arrow-up",
|
||||
iconOff: "mdi:arrow-down",
|
||||
onService: "cover.open_cover",
|
||||
offService: "cover.close_cover",
|
||||
hidden: false,
|
||||
},
|
||||
switch: {
|
||||
title: localize("switch.switches"),
|
||||
showControls: true,
|
||||
iconOn: "mdi:power-plug",
|
||||
iconOff: "mdi:power-plug-off",
|
||||
onService: "switch.turn_on",
|
||||
offService: "switch.turn_off",
|
||||
hidden: false,
|
||||
},
|
||||
camera: {
|
||||
title: localize("camera.cameras"),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
lock: {
|
||||
title: localize("lock.locks"),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
climate: {
|
||||
title: localize("climate.climates"),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
media_player: {
|
||||
title: localize("media_player.media_players"),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
sensor: {
|
||||
title: localize("sensor.sensors"),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
binary_sensor: {
|
||||
title: `${localize("sensor.binary")} ` + localize("sensor.sensors"),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
number: {
|
||||
title: localize("generic.numbers"),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
vacuum: {
|
||||
title: localize("vacuum.vacuums"),
|
||||
showControls: true,
|
||||
hidden: false,
|
||||
},
|
||||
select: {
|
||||
title: localize("select.selects"),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
input_select: {
|
||||
title: localize("input_select.input_selects"),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
},
|
||||
card_options: {},
|
||||
chips: {
|
||||
// TODO: Make chips sortable.
|
||||
weather_entity: 'auto',
|
||||
light_count: true,
|
||||
fan_count: true,
|
||||
cover_count: true,
|
||||
switch_count: true,
|
||||
climate_count: true,
|
||||
extra_chips: [],
|
||||
},
|
||||
debug: false,
|
||||
domains: {
|
||||
_: {
|
||||
hide_config_entities: undefined,
|
||||
hide_diagnostic_entities: undefined,
|
||||
},
|
||||
home_view: {
|
||||
hidden: [],
|
||||
binary_sensor: {
|
||||
title: `${localize('sensor.binary')} ` + localize('sensor.sensors'),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
views: {
|
||||
home: {
|
||||
order: 1,
|
||||
hidden: false,
|
||||
},
|
||||
light: {
|
||||
order: 2,
|
||||
hidden: false,
|
||||
},
|
||||
fan: {
|
||||
order: 3,
|
||||
hidden: false,
|
||||
},
|
||||
cover: {
|
||||
order: 4,
|
||||
hidden: false,
|
||||
},
|
||||
switch: {
|
||||
order: 5,
|
||||
hidden: false,
|
||||
},
|
||||
climate: {
|
||||
order: 6,
|
||||
hidden: false,
|
||||
},
|
||||
camera: {
|
||||
order: 7,
|
||||
hidden: false,
|
||||
},
|
||||
vacuum: {
|
||||
order: 8,
|
||||
hidden: false,
|
||||
},
|
||||
scene: {
|
||||
order: 9,
|
||||
hidden: false,
|
||||
},
|
||||
}
|
||||
};
|
||||
camera: {
|
||||
title: localize('camera.cameras'),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
climate: {
|
||||
title: localize('climate.climates'),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
cover: {
|
||||
title: localize('cover.covers'),
|
||||
showControls: true,
|
||||
iconOn: 'mdi:arrow-up',
|
||||
iconOff: 'mdi:arrow-down',
|
||||
onService: 'cover.open_cover',
|
||||
offService: 'cover.close_cover',
|
||||
hidden: false,
|
||||
},
|
||||
default: {
|
||||
title: localize('generic.miscellaneous'),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
fan: {
|
||||
title: localize('fan.fans'),
|
||||
showControls: true,
|
||||
iconOn: 'mdi:fan',
|
||||
iconOff: 'mdi:fan-off',
|
||||
onService: 'fan.turn_on',
|
||||
offService: 'fan.turn_off',
|
||||
hidden: false,
|
||||
},
|
||||
input_select: {
|
||||
title: localize('input_select.input_selects'),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
light: {
|
||||
title: localize('light.lights'),
|
||||
showControls: true,
|
||||
iconOn: 'mdi:lightbulb',
|
||||
iconOff: 'mdi:lightbulb-off',
|
||||
onService: 'light.turn_on',
|
||||
offService: 'light.turn_off',
|
||||
hidden: false,
|
||||
},
|
||||
lock: {
|
||||
title: localize('lock.locks'),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
media_player: {
|
||||
title: localize('media_player.media_players'),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
number: {
|
||||
title: localize('generic.numbers'),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
scene: {
|
||||
title: localize('scene.scenes'),
|
||||
showControls: false,
|
||||
onService: 'scene.turn_on',
|
||||
hidden: false,
|
||||
},
|
||||
select: {
|
||||
title: localize('select.selects'),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
sensor: {
|
||||
title: localize('sensor.sensors'),
|
||||
showControls: false,
|
||||
hidden: false,
|
||||
},
|
||||
switch: {
|
||||
title: localize('switch.switches'),
|
||||
showControls: true,
|
||||
iconOn: 'mdi:power-plug',
|
||||
iconOff: 'mdi:power-plug-off',
|
||||
onService: 'switch.turn_on',
|
||||
offService: 'switch.turn_off',
|
||||
hidden: false,
|
||||
},
|
||||
vacuum: {
|
||||
title: localize('vacuum.vacuums'),
|
||||
showControls: true,
|
||||
hidden: false,
|
||||
},
|
||||
},
|
||||
extra_cards: [],
|
||||
extra_views: [],
|
||||
home_view: {
|
||||
hidden: [],
|
||||
},
|
||||
views: {
|
||||
camera: {
|
||||
order: 7,
|
||||
hidden: false,
|
||||
},
|
||||
climate: {
|
||||
order: 6,
|
||||
hidden: false,
|
||||
},
|
||||
cover: {
|
||||
order: 4,
|
||||
hidden: false,
|
||||
},
|
||||
fan: {
|
||||
order: 3,
|
||||
hidden: false,
|
||||
},
|
||||
home: {
|
||||
order: 1,
|
||||
hidden: false,
|
||||
},
|
||||
light: {
|
||||
order: 2,
|
||||
hidden: false,
|
||||
},
|
||||
lock: {
|
||||
order: 10,
|
||||
hidden: false,
|
||||
},
|
||||
scene: {
|
||||
order: 9,
|
||||
hidden: false,
|
||||
},
|
||||
switch: {
|
||||
order: 5,
|
||||
hidden: false,
|
||||
},
|
||||
vacuum: {
|
||||
order: 8,
|
||||
hidden: false,
|
||||
},
|
||||
},
|
||||
quick_access_cards: [],
|
||||
};
|
||||
|
@ -1,60 +0,0 @@
|
||||
import {HomeAssistant} from "./types/homeassistant/types";
|
||||
import * as en from "./translations/en.json";
|
||||
import * as es from "./translations/es.json";
|
||||
import * as nl from "./translations/nl.json";
|
||||
import * as de from "./translations/de.json";
|
||||
|
||||
/* Registry of currently supported languages */
|
||||
const languages: Record<string, unknown> = {
|
||||
en,
|
||||
es,
|
||||
nl,
|
||||
de,
|
||||
};
|
||||
|
||||
/* The fallback language if the user-defined language isn't defined */
|
||||
const DEFAULT_LANG = "en";
|
||||
|
||||
/**
|
||||
* Get a string by keyword and language.
|
||||
*
|
||||
* @param {string} key The keyword to look for in object notation (E.g. generic.home).
|
||||
* @param {string} lang The language to get the string from (E.g. en).
|
||||
*
|
||||
* @return {string | undefined} The requested string or undefined if the keyword doesn't exist/on error.
|
||||
*/
|
||||
function getTranslatedString(key: string, lang: string): string | undefined {
|
||||
try {
|
||||
return key
|
||||
.split(".")
|
||||
.reduce(
|
||||
(o, i) => (o as Record<string, unknown>)[i],
|
||||
languages[lang]
|
||||
) as string;
|
||||
} catch (_) {
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the localization.
|
||||
*
|
||||
* It reads the user-defined language with a fall-back to english and returns a function to get strings from
|
||||
* language-files by keyword.
|
||||
*
|
||||
* If the keyword is undefined, or on error, the keyword itself is returned.
|
||||
*
|
||||
* @param {HomeAssistant} hass The Home Assistant object.
|
||||
* @return {(key: string) => string} The function to call for translating strings.
|
||||
*/
|
||||
export default function setupCustomLocalize(hass?: HomeAssistant): (key: string) => string {
|
||||
return function (key: string) {
|
||||
const lang = hass?.locale.language ?? DEFAULT_LANG;
|
||||
|
||||
let translated = getTranslatedString(key, lang);
|
||||
if (!translated) translated = getTranslatedString(key, DEFAULT_LANG);
|
||||
|
||||
return translated ?? key;
|
||||
};
|
||||
}
|
@ -1,268 +1,208 @@
|
||||
import {Helper} from "./Helper";
|
||||
import {SensorCard} from "./cards/SensorCard";
|
||||
import {ControllerCard} from "./cards/ControllerCard";
|
||||
import {generic} from "./types/strategy/generic";
|
||||
import {LovelaceCardConfig, LovelaceConfig, LovelaceViewConfig} from "./types/homeassistant/data/lovelace";
|
||||
import {StackCardConfig} from "./types/homeassistant/lovelace/cards/types";
|
||||
import {EntityCardConfig} from "./types/lovelace-mushroom/cards/entity-card-config";
|
||||
import {HassServiceTarget} from "home-assistant-js-websocket";
|
||||
import {applyEntityCategoryFilters} from "./utillties/filters";
|
||||
import StrategyArea = generic.StrategyArea;
|
||||
import { HassServiceTarget } from 'home-assistant-js-websocket';
|
||||
import HeaderCard from './cards/HeaderCard';
|
||||
import SensorCard from './cards/SensorCard';
|
||||
import { Registry } from './Registry';
|
||||
import { LovelaceCardConfig } from './types/homeassistant/data/lovelace/config/card';
|
||||
import { LovelaceConfig } from './types/homeassistant/data/lovelace/config/types';
|
||||
import { LovelaceViewConfig, LovelaceViewRawConfig } from './types/homeassistant/data/lovelace/config/view';
|
||||
import {
|
||||
DashboardInfo,
|
||||
isSupportedDomain,
|
||||
isSupportedView,
|
||||
StrategyArea,
|
||||
ViewInfo,
|
||||
} from './types/strategy/strategy-generics';
|
||||
import { sanitizeClassName } from './utilities/auxiliaries';
|
||||
import { logMessage, lvlError } from './utilities/debug';
|
||||
import RegistryFilter from './utilities/RegistryFilter';
|
||||
import { stackHorizontal } from './utilities/cardStacking';
|
||||
|
||||
/**
|
||||
* Mushroom Dashboard Strategy.<br>
|
||||
* <br>
|
||||
* Mushroom dashboard strategy provides a strategy for Home-Assistant to create a dashboard automatically.<br>
|
||||
* The strategy makes use Mushroom and Mini Graph cards to represent your entities.<br>
|
||||
* <br>
|
||||
* Features:<br>
|
||||
* 🛠 Automatically create dashboard with three lines of yaml.<br>
|
||||
* 😍 Built-in Views for several standard domains.<br>
|
||||
* 🎨 Many options to customize to your needs.<br>
|
||||
* <br>
|
||||
* Check the [Repository]{@link https://github.com/AalianKhan/mushroom-strategy} for more information.
|
||||
* The strategy makes use Mushroom and Mini Graph cards to represent your entities.
|
||||
*
|
||||
* @see https://github.com/DigiLive/mushroom-strategy
|
||||
*/
|
||||
class MushroomStrategy extends HTMLTemplateElement {
|
||||
/**
|
||||
* Generate a dashboard.
|
||||
*
|
||||
* Called when opening a dashboard.
|
||||
* This method creates views for each exposed domain and area.
|
||||
* It also adds custom views if specified in the strategy options.
|
||||
*
|
||||
* @param {generic.DashBoardInfo} info Dashboard strategy information object.
|
||||
* @return {Promise<LovelaceConfig>}
|
||||
* @param {DashboardInfo} info Dashboard strategy information object.
|
||||
*
|
||||
* @remarks
|
||||
* Called when opening a dashboard.
|
||||
*/
|
||||
static async generateDashboard(info: generic.DashBoardInfo): Promise<LovelaceConfig> {
|
||||
await Helper.initialize(info);
|
||||
static async generateDashboard(info: DashboardInfo): Promise<LovelaceConfig> {
|
||||
await Registry.initialize(info);
|
||||
|
||||
// Create views.
|
||||
const views: LovelaceViewConfig[] = info.config?.views ?? [];
|
||||
const views: LovelaceViewRawConfig[] = [];
|
||||
|
||||
let viewModule;
|
||||
// Parallelize view imports and creation.
|
||||
const viewPromises = Registry.getExposedNames('view')
|
||||
.filter(isSupportedView)
|
||||
.map(async (viewName) => {
|
||||
try {
|
||||
const moduleName = sanitizeClassName(`${viewName}View`);
|
||||
const View = (await import(`./views/${moduleName}`)).default;
|
||||
const currentView = new View(Registry.strategyOptions.views[viewName]);
|
||||
const viewConfiguration = await currentView.getView();
|
||||
|
||||
// Create a view for each exposed domain.
|
||||
for (let viewId of Helper.getExposedViewIds()) {
|
||||
try {
|
||||
const viewType = Helper.sanitizeClassName(viewId + "View");
|
||||
viewModule = await import(`./views/${viewType}`);
|
||||
const view: LovelaceViewConfig = await new viewModule[viewType](Helper.strategyOptions.views[viewId]).getView();
|
||||
|
||||
if (view.cards?.length) {
|
||||
views.push(view);
|
||||
if (viewConfiguration.cards.length) {
|
||||
return viewConfiguration;
|
||||
}
|
||||
} catch (e) {
|
||||
logMessage(lvlError, `Error importing ${viewName} view!`, e);
|
||||
}
|
||||
} catch (e) {
|
||||
Helper.logError(`View '${viewId}' couldn't be loaded!`, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
const resolvedViews = (await Promise.all(viewPromises)).filter(Boolean) as LovelaceViewRawConfig[];
|
||||
|
||||
views.push(...resolvedViews);
|
||||
|
||||
// Subviews for areas
|
||||
views.push(
|
||||
...Registry.areas.map((area) => ({
|
||||
title: area.name,
|
||||
path: area.area_id,
|
||||
subview: true,
|
||||
strategy: {
|
||||
type: 'custom:mushroom-strategy',
|
||||
options: { area },
|
||||
},
|
||||
})),
|
||||
);
|
||||
|
||||
// Extra views
|
||||
if (Registry.strategyOptions.extra_views) {
|
||||
views.push(...Registry.strategyOptions.extra_views);
|
||||
}
|
||||
|
||||
// Create subviews for each area.
|
||||
for (let area of Helper.areas) {
|
||||
if (!area.hidden) {
|
||||
views.push({
|
||||
title: area.name,
|
||||
path: area.area_id ?? area.name,
|
||||
subview: true,
|
||||
strategy: {
|
||||
type: "custom:mushroom-strategy",
|
||||
options: {
|
||||
area,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add custom views.
|
||||
if (Helper.strategyOptions.extra_views) {
|
||||
views.push(...Helper.strategyOptions.extra_views);
|
||||
}
|
||||
|
||||
// Return the created views.
|
||||
return {
|
||||
views: views,
|
||||
};
|
||||
return { views };
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a view.
|
||||
*
|
||||
* Called when opening a subview.
|
||||
* The method creates cards for each domain (e.g., sensors, switches, etc.) in the current area, using a combination
|
||||
* of Header cards and entity-specific cards.
|
||||
* It also handles miscellaneous entities that don't fit into any supported domain.
|
||||
*
|
||||
* @param {generic.ViewInfo} info The view's strategy information object.
|
||||
* @return {Promise<LovelaceViewConfig>}
|
||||
* @param {ViewInfo} info The view's strategy information object.
|
||||
*
|
||||
* @remarks
|
||||
* Called upon opening a subview.
|
||||
*/
|
||||
static async generateView(info: generic.ViewInfo): Promise<LovelaceViewConfig> {
|
||||
const exposedDomainIds = Helper.getExposedDomainIds();
|
||||
const area = info.view.strategy?.options?.area ?? {} as StrategyArea;
|
||||
static async generateView(info: ViewInfo): Promise<LovelaceViewConfig> {
|
||||
const exposedDomainNames = Registry.getExposedNames('domain');
|
||||
const area = info.view.strategy?.options?.area ?? ({} as StrategyArea);
|
||||
const areaEntities = new RegistryFilter(Registry.entities).whereAreaId(area.area_id).toList();
|
||||
const viewCards: LovelaceCardConfig[] = [...(area.extra_cards ?? [])];
|
||||
|
||||
// Set the target for controller cards to the current area.
|
||||
let target: HassServiceTarget = {
|
||||
area_id: [area.area_id],
|
||||
};
|
||||
// Set the target for any Header card to the current area.
|
||||
const target: HassServiceTarget = { area_id: [area.area_id] };
|
||||
|
||||
// Create cards for each domain.
|
||||
for (const domain of exposedDomainIds) {
|
||||
if (domain === "default") {
|
||||
continue;
|
||||
// Prepare promises for all supported domains
|
||||
const domainCardPromises = exposedDomainNames.filter(isSupportedDomain).map(async (domain) => {
|
||||
const moduleName = sanitizeClassName(domain + 'Card');
|
||||
|
||||
const entities = new RegistryFilter(areaEntities)
|
||||
.whereDomain(domain)
|
||||
.where((entity) => !(domain === 'switch' && entity.entity_id.endsWith('_stateful_scene')))
|
||||
.toList();
|
||||
|
||||
if (!entities.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const className = Helper.sanitizeClassName(domain + "Card");
|
||||
|
||||
let domainCards: EntityCardConfig[] = [];
|
||||
const titleCard = new HeaderCard(
|
||||
{ entity_id: entities.map((entity) => entity.entity_id) },
|
||||
Registry.strategyOptions.domains[domain],
|
||||
).createCard();
|
||||
|
||||
try {
|
||||
domainCards = await import(`./cards/${className}`).then(cardModule => {
|
||||
let domainCards: EntityCardConfig[] = [];
|
||||
let entities = Helper.getDeviceEntities(area, domain);
|
||||
const DomainCard = (await import(`./cards/${moduleName}`)).default;
|
||||
|
||||
// Exclude hidden Config and Diagnostic entities.
|
||||
entities = applyEntityCategoryFilters(entities, domain);
|
||||
|
||||
// Set the target for controller cards to entities without an area.
|
||||
if (area.area_id === "undisclosed") {
|
||||
target = {
|
||||
entity_id: entities.map(entity => entity.entity_id),
|
||||
}
|
||||
}
|
||||
|
||||
if (entities.length) {
|
||||
// Create a Controller card for the current domain.
|
||||
const titleCard = new ControllerCard(
|
||||
target,
|
||||
Helper.strategyOptions.domains[domain],
|
||||
).createCard();
|
||||
|
||||
if (domain === "sensor") {
|
||||
// Create a card for each sensor-entity of the current area.
|
||||
const sensorStates = Helper.getStateEntities(area, "sensor");
|
||||
const sensorCards: EntityCardConfig[] = [];
|
||||
|
||||
for (const sensor of entities) {
|
||||
// Find the state of the current sensor.
|
||||
const sensorState = sensorStates.find(state => state.entity_id === sensor.entity_id);
|
||||
let cardOptions = Helper.strategyOptions.card_options?.[sensor.entity_id];
|
||||
|
||||
if (sensorState?.attributes.unit_of_measurement) {
|
||||
cardOptions = {
|
||||
...{
|
||||
type: "custom:mini-graph-card",
|
||||
entities: [sensor.entity_id],
|
||||
},
|
||||
...cardOptions,
|
||||
};
|
||||
|
||||
sensorCards.push(new SensorCard(sensor, cardOptions).getCard());
|
||||
}
|
||||
}
|
||||
|
||||
if (sensorCards.length) {
|
||||
domainCards.push({
|
||||
type: "vertical-stack",
|
||||
cards: sensorCards,
|
||||
});
|
||||
|
||||
domainCards.unshift(titleCard);
|
||||
}
|
||||
|
||||
return domainCards;
|
||||
}
|
||||
|
||||
// Create a card for each other domain-entity of the current area.
|
||||
for (const entity of entities) {
|
||||
let deviceOptions;
|
||||
let cardOptions = Helper.strategyOptions.card_options?.[entity.entity_id];
|
||||
|
||||
if (entity.device_id) {
|
||||
deviceOptions = Helper.strategyOptions.card_options?.[entity.device_id];
|
||||
}
|
||||
|
||||
domainCards.push(new cardModule[className](entity, cardOptions).getCard());
|
||||
}
|
||||
|
||||
if (domain === "binary_sensor") {
|
||||
// Horizontally group every two binary sensor cards.
|
||||
const horizontalCards: EntityCardConfig[] = [];
|
||||
|
||||
for (let i = 0; i < domainCards.length; i += 2) {
|
||||
horizontalCards.push({
|
||||
type: "horizontal-stack",
|
||||
cards: domainCards.slice(i, i + 2),
|
||||
});
|
||||
}
|
||||
|
||||
domainCards = horizontalCards;
|
||||
}
|
||||
|
||||
if (domainCards.length) {
|
||||
domainCards.unshift(titleCard);
|
||||
}
|
||||
}
|
||||
|
||||
return domainCards;
|
||||
});
|
||||
} catch (e) {
|
||||
Helper.logError("An error occurred while creating the domain cards!", e);
|
||||
}
|
||||
|
||||
if (domainCards.length) {
|
||||
viewCards.push({
|
||||
type: "vertical-stack",
|
||||
cards: domainCards,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!Helper.strategyOptions.domains.default.hidden) {
|
||||
// Create cards for any other domain.
|
||||
// Collect entities of the current area and unexposed domains.
|
||||
let miscellaneousEntities = Helper.getDeviceEntities(area).filter(
|
||||
entity => !exposedDomainIds.includes(entity.entity_id.split(".", 1)[0])
|
||||
);
|
||||
|
||||
// Exclude hidden Config and Diagnostic entities.
|
||||
miscellaneousEntities = applyEntityCategoryFilters(miscellaneousEntities, "default");
|
||||
|
||||
// Create a column of miscellaneous entity cards.
|
||||
if (miscellaneousEntities.length) {
|
||||
let miscellaneousCards: (StackCardConfig | EntityCardConfig)[] = [];
|
||||
|
||||
try {
|
||||
miscellaneousCards = await import("./cards/MiscellaneousCard").then(cardModule => {
|
||||
const miscellaneousCards: (StackCardConfig | EntityCardConfig)[] = [
|
||||
new ControllerCard(target, Helper.strategyOptions.domains.default).createCard(),
|
||||
];
|
||||
|
||||
for (const entity of miscellaneousEntities) {
|
||||
let cardOptions = Helper.strategyOptions.card_options?.[entity.entity_id];
|
||||
let deviceOptions = Helper.strategyOptions.card_options?.[entity.device_id ?? "null"];
|
||||
|
||||
miscellaneousCards.push(new cardModule.MiscellaneousCard(entity, cardOptions).getCard());
|
||||
}
|
||||
|
||||
return miscellaneousCards;
|
||||
});
|
||||
} catch (e) {
|
||||
Helper.logError("An error occurred while creating the domain cards!", e);
|
||||
if (domain === 'sensor') {
|
||||
const domainCards = entities
|
||||
.filter((entity) => Registry.hassStates[entity.entity_id]?.attributes.unit_of_measurement)
|
||||
.map((entity) => {
|
||||
const options = {
|
||||
...(entity.device_id && Registry.strategyOptions.card_options?.[entity.device_id]),
|
||||
...Registry.strategyOptions.card_options?.[entity.entity_id],
|
||||
type: 'custom:mini-graph-card',
|
||||
entities: [entity.entity_id],
|
||||
};
|
||||
return new SensorCard(entity, options).getCard();
|
||||
});
|
||||
return domainCards.length ? { type: 'vertical-stack', cards: [titleCard, ...domainCards] } : null;
|
||||
}
|
||||
|
||||
viewCards.push({
|
||||
type: "vertical-stack",
|
||||
cards: miscellaneousCards,
|
||||
let domainCards = entities.map((entity) => {
|
||||
const cardOptions = {
|
||||
...(entity.device_id && Registry.strategyOptions.card_options?.[entity.device_id]),
|
||||
...Registry.strategyOptions.card_options?.[entity.entity_id],
|
||||
};
|
||||
return new DomainCard(entity, cardOptions).getCard();
|
||||
});
|
||||
|
||||
if (domain === 'binary_sensor') {
|
||||
domainCards = stackHorizontal(domainCards);
|
||||
}
|
||||
|
||||
return domainCards.length ? { type: 'vertical-stack', cards: [titleCard, ...domainCards] } : null;
|
||||
} catch (e) {
|
||||
logMessage(lvlError, `Error creating card configurations for domain ${domain}`, e);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Await all domain card stacks
|
||||
const domainCardStacks = (await Promise.all(domainCardPromises)).filter(Boolean) as LovelaceCardConfig[];
|
||||
viewCards.push(...domainCardStacks);
|
||||
|
||||
// Miscellaneous domain
|
||||
if (!Registry.strategyOptions.domains.default.hidden) {
|
||||
const miscellaneousEntities = new RegistryFilter(areaEntities)
|
||||
.not()
|
||||
.where((entity) => isSupportedDomain(entity.entity_id.split('.', 1)[0]))
|
||||
.toList();
|
||||
|
||||
if (miscellaneousEntities.length) {
|
||||
try {
|
||||
const MiscellaneousCard = (await import('./cards/MiscellaneousCard')).default;
|
||||
const miscellaneousCards = [
|
||||
new HeaderCard(target, Registry.strategyOptions.domains.default).createCard(),
|
||||
...miscellaneousEntities.map((entity) =>
|
||||
new MiscellaneousCard(entity, Registry.strategyOptions.card_options?.[entity.entity_id]).getCard(),
|
||||
),
|
||||
];
|
||||
|
||||
viewCards.push({
|
||||
type: 'vertical-stack',
|
||||
cards: miscellaneousCards,
|
||||
});
|
||||
} catch (e) {
|
||||
logMessage(lvlError, 'Error creating card configurations for domain `miscellaneous`', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return cards.
|
||||
return {
|
||||
cards: viewCards,
|
||||
};
|
||||
return { cards: viewCards };
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("ll-strategy-mushroom-strategy", MushroomStrategy);
|
||||
customElements.define('ll-strategy-mushroom-strategy', MushroomStrategy);
|
||||
|
||||
const version = "v2.2.0";
|
||||
const version = 'v2.3.0';
|
||||
console.info(
|
||||
"%c Mushroom Strategy %c ".concat(version, " "),
|
||||
"color: white; background: coral; font-weight: 700;", "color: coral; background: white; font-weight: 700;"
|
||||
'%c Mushroom Strategy %c '.concat(version, ' '),
|
||||
'color: white; background: coral; font-weight: 700;',
|
||||
'color: coral; background: white; font-weight: 700;',
|
||||
);
|
||||
|
@ -29,7 +29,10 @@
|
||||
"off": "Aus",
|
||||
"on": "Ein",
|
||||
"open": "Offen",
|
||||
"unclosed": "Nicht Geschlossen"
|
||||
"unavailable": "Nicht verfügbar",
|
||||
"unclosed": "Nicht Geschlossen",
|
||||
"undisclosed": "Sonstiges",
|
||||
"unknown": "Unbekannt"
|
||||
},
|
||||
"input_select": {
|
||||
"input_selects": "Auswahl-Eingaben"
|
||||
@ -39,7 +42,10 @@
|
||||
"lights": "Leuchten"
|
||||
},
|
||||
"lock": {
|
||||
"locks": "Schlösser"
|
||||
"locked": "Gesperrt",
|
||||
"all_locks": "Alle Schlösser",
|
||||
"locks": "Schlösser",
|
||||
"unlocked": "Entsperrt"
|
||||
},
|
||||
"media_player": {
|
||||
"media_players": "Wiedergabegeräte"
|
||||
@ -61,5 +67,14 @@
|
||||
"vacuum": {
|
||||
"all_vacuums": "Alle Staubsauger",
|
||||
"vacuums": "Staubsauger"
|
||||
},
|
||||
"valve": {
|
||||
"all_valves": "Alle Ventile",
|
||||
"valves": "Ventile",
|
||||
"open": "Offen",
|
||||
"opening": "Öffnet",
|
||||
"closed": "Geschlossen",
|
||||
"closing": "Schließt",
|
||||
"stopped": "Gestoppt"
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,10 @@
|
||||
"off": "Off",
|
||||
"on": "On",
|
||||
"open": "Open",
|
||||
"unclosed": "Unclosed"
|
||||
"unavailable": "Unavailable",
|
||||
"unclosed": "Unclosed",
|
||||
"undisclosed": "Other",
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"input_select": {
|
||||
"input_selects": "Input Selects"
|
||||
@ -39,10 +42,13 @@
|
||||
"lights": "Lights"
|
||||
},
|
||||
"lock": {
|
||||
"locks": "Locks"
|
||||
"all_locks": "All Locks",
|
||||
"locked": "Locked",
|
||||
"locks": "Locks",
|
||||
"unlocked": "Unlocked"
|
||||
},
|
||||
"media_player": {
|
||||
"media_players": "Mediaplayers"
|
||||
"media_players": "Media Players"
|
||||
},
|
||||
"scene": {
|
||||
"scenes": "Scenes"
|
||||
@ -61,5 +67,14 @@
|
||||
"vacuum": {
|
||||
"all_vacuums": "All Vacuums",
|
||||
"vacuums": "Vacuums"
|
||||
},
|
||||
"valve": {
|
||||
"all_valves": "All Valves",
|
||||
"valves": "Valves",
|
||||
"open": "Open",
|
||||
"opening": "Opening",
|
||||
"closed": "Closed",
|
||||
"closing": "Closing",
|
||||
"stopped": "Stopped"
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,10 @@
|
||||
"off": "Apagado",
|
||||
"on": "Encendido",
|
||||
"open": "Abierto",
|
||||
"unclosed": "Sin Cerrar"
|
||||
"unavailable": "No Disponible",
|
||||
"unclosed": "Sin Cerrar",
|
||||
"undisclosed": "Varios",
|
||||
"unknown": "Desconocido"
|
||||
},
|
||||
"input_select": {
|
||||
"input_selects": "Selecciones de Entrada"
|
||||
@ -39,11 +42,17 @@
|
||||
"lights": "Luces"
|
||||
},
|
||||
"lock": {
|
||||
"locks": "Candados"
|
||||
"all_locks": "Todas las Candados",
|
||||
"locked": "Locked",
|
||||
"locks": "Candados",
|
||||
"unlocked": "Desbloqueado"
|
||||
},
|
||||
"media_player": {
|
||||
"media_players": "Reproductores Multimedia"
|
||||
},
|
||||
"scene": {
|
||||
"scenes": "Scenas"
|
||||
},
|
||||
"select": {
|
||||
"selects": "Seleccionar"
|
||||
},
|
||||
@ -58,5 +67,14 @@
|
||||
"vacuum": {
|
||||
"all_vacuums": "Todas las Aspiradoras",
|
||||
"vacuums": "Aspiradoras"
|
||||
},
|
||||
"valve": {
|
||||
"all_valves": "Todas las válvulas",
|
||||
"valves": "Válvulas",
|
||||
"open": "Abierta",
|
||||
"opening": "Abriendo",
|
||||
"closed": "Cerrada",
|
||||
"closing": "Cerrando",
|
||||
"stopped": "Detenida"
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,9 @@
|
||||
"all": "Alle",
|
||||
"areas": "Ruimtes",
|
||||
"busy": "Bezig",
|
||||
"good_afternoon": "Goede middag",
|
||||
"good_evening": "Goede avond",
|
||||
"good_morning": "Goede morgen",
|
||||
"good_afternoon": "Goedemiddag",
|
||||
"good_evening": "Goedeavond",
|
||||
"good_morning": "Goedemorgen",
|
||||
"hello": "Hallo",
|
||||
"home": "Start",
|
||||
"miscellaneous": "Overige",
|
||||
@ -29,7 +29,10 @@
|
||||
"off": "Uit",
|
||||
"on": "Aan",
|
||||
"open": "Open",
|
||||
"unclosed": "Ongesloten"
|
||||
"unavailable": "Onbeschikbaar",
|
||||
"unclosed": "Niet Gesloten",
|
||||
"undisclosed": "Overige",
|
||||
"unknown": "Onbekend"
|
||||
},
|
||||
"input_select": {
|
||||
"input_selects": "Lijsten"
|
||||
@ -39,7 +42,10 @@
|
||||
"lights": "Lampen"
|
||||
},
|
||||
"lock": {
|
||||
"locks": "Sloten"
|
||||
"all_locks": "Alle Sloten",
|
||||
"locked": "Vergrendeld",
|
||||
"locks": "Sloten",
|
||||
"unlocked": "Ontgrendeld"
|
||||
},
|
||||
"media_player": {
|
||||
"media_players": "Mediaspelers"
|
||||
@ -61,5 +67,14 @@
|
||||
"vacuum": {
|
||||
"all_vacuums": "Alle Afzuiging",
|
||||
"vacuums": "Afzuiging"
|
||||
},
|
||||
"valve": {
|
||||
"all_valves": "Alle kleppen",
|
||||
"valves": "Kleppen",
|
||||
"open": "Open",
|
||||
"opening": "Openen",
|
||||
"closed": "Gesloten",
|
||||
"closing": "Sluiten",
|
||||
"stopped": "Gestopt"
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ This means properties are added/removed from the originals and subtypes may have
|
||||
The [Apache 2.0 License](https://github.com/home-assistant/frontend/blob/dev/LICENSE.md) applies to all files in this
|
||||
directory.
|
||||
|
||||
Copyright 2023 Ferry Cools
|
||||
Copyright 2023 Ferry Cools
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
46
src/types/homeassistant/common/translations/localize.ts
Normal file
46
src/types/homeassistant/common/translations/localize.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import type { TranslationDict } from '../../types';
|
||||
|
||||
// Exclude some patterns from key type checking for now
|
||||
// These are intended to be removed as errors are fixed
|
||||
// Fixing component category will require tighter definition of types from backend and/or web socket
|
||||
export type LocalizeKeys =
|
||||
| FlattenObjectKeys<Omit<TranslationDict, 'supervisor'>>
|
||||
| `panel.${string}`
|
||||
| `ui.card.alarm_control_panel.${string}`
|
||||
| `ui.card.weather.attributes.${string}`
|
||||
| `ui.card.weather.cardinal_direction.${string}`
|
||||
| `ui.card.lawn_mower.actions.${string}`
|
||||
| `ui.components.calendar.event.rrule.${string}`
|
||||
| `ui.components.selectors.file.${string}`
|
||||
| `ui.components.logbook.messages.detected_device_classes.${string}`
|
||||
| `ui.components.logbook.messages.cleared_device_classes.${string}`
|
||||
| `ui.dialogs.entity_registry.editor.${string}`
|
||||
| `ui.dialogs.more_info_control.lawn_mower.${string}`
|
||||
| `ui.dialogs.more_info_control.vacuum.${string}`
|
||||
| `ui.dialogs.quick-bar.commands.${string}`
|
||||
| `ui.dialogs.unhealthy.reason.${string}`
|
||||
| `ui.dialogs.unsupported.reason.${string}`
|
||||
| `ui.panel.config.${string}.${'caption' | 'description'}`
|
||||
| `ui.panel.config.dashboard.${string}`
|
||||
| `ui.panel.config.zha.${string}`
|
||||
| `ui.panel.config.zwave_js.${string}`
|
||||
| `ui.panel.lovelace.card.${string}`
|
||||
| `ui.panel.lovelace.editor.${string}`
|
||||
| `ui.panel.page-authorize.form.${string}`
|
||||
| `component.${string}`;
|
||||
|
||||
// Tweaked from https://www.raygesualdo.com/posts/flattening-object-keys-with-typescript-types
|
||||
export type FlattenObjectKeys<T extends Record<string, any>, Key extends keyof T = keyof T> = Key extends string
|
||||
? T[Key] extends Record<string, unknown>
|
||||
? `${Key}.${FlattenObjectKeys<T[Key]>}`
|
||||
: `${Key}`
|
||||
: never;
|
||||
|
||||
// Later, don't return string when HTML is passed, and don't allow undefined
|
||||
export type LocalizeFunc<Keys extends string = LocalizeKeys> = (
|
||||
key: Keys,
|
||||
values?: Record<
|
||||
string,
|
||||
string | number | { _$litType$: 1; strings: TemplateStringsArray; values: Array<unknown> } | null | undefined
|
||||
>,
|
||||
) => string;
|
@ -1,20 +1,29 @@
|
||||
import { RegistryEntry } from './registry';
|
||||
|
||||
/**
|
||||
* Area Entity.
|
||||
* Represents an entry in the Area Registry in Home Assistant.
|
||||
*
|
||||
* @property {string} area_id The id of the area.
|
||||
* @property {string|null} floor_id The id of the area's floor.
|
||||
* @property {string} name Name of the area.
|
||||
* @property {string|null} picture URL to a picture that should be used instead of showing the domain icon.
|
||||
* @property {string|null} icon Icon to show.
|
||||
* @property {string[]} labels Labels allow grouping elements irrespective of their physical location or type.
|
||||
* @property {string[]} aliases Array of aliases of the area.
|
||||
* @property {string[]} aliases - An array of aliases for the area.
|
||||
* @property {string} area_id - The unique identifier for the area.
|
||||
* @property {string|null} floor_id - The identifier for the area's floor, or null if not applicable.
|
||||
* @property {string|null} humidity_entity_id - The identifier for the area's humidity sensor, or null if not
|
||||
* applicable.
|
||||
* @property {string|null} icon - The icon to display for the area, or null if not specified.
|
||||
* @property {string[]} labels - Labels for grouping elements irrespective of their physical location or type.
|
||||
* @property {string} name - The name of the area.
|
||||
* @property {string|null} picture - The URL to a picture that should be used instead of the domain icon, or null if
|
||||
* not specified.
|
||||
* @property {string|null} temperature_entity_id - The identifier for the area's temperature sensor, or null if not
|
||||
* applicable.
|
||||
*/
|
||||
export interface AreaRegistryEntry {
|
||||
export interface AreaRegistryEntry extends RegistryEntry {
|
||||
aliases: string[];
|
||||
area_id: string;
|
||||
floor_id: string | null;
|
||||
name: string;
|
||||
picture: string | null;
|
||||
humidity_entity_id: string | null;
|
||||
icon: string | null;
|
||||
labels: string[];
|
||||
aliases: string[];
|
||||
name: string;
|
||||
picture: string | null;
|
||||
temperature_entity_id: string | null;
|
||||
}
|
||||
|
@ -1,19 +1,5 @@
|
||||
export const HVAC_MODES = [
|
||||
"auto",
|
||||
"heat_cool",
|
||||
"heat",
|
||||
"cool",
|
||||
"dry",
|
||||
"fan_only",
|
||||
"off",
|
||||
] as const;
|
||||
/** Represents the available HVAC modes for climate control in Home Assistant. */
|
||||
export const HVAC_MODES = ['auto', 'heat_cool', 'heat', 'cool', 'dry', 'fan_only', 'off'] as const;
|
||||
|
||||
/** Represents a type for HVAC modes in Home Assistant. */
|
||||
export type HvacMode = (typeof HVAC_MODES)[number];
|
||||
|
||||
HVAC_MODES.reduce(
|
||||
(order, mode, index) => {
|
||||
order[mode] = index;
|
||||
return order;
|
||||
},
|
||||
{} as Record<HvacMode, number>
|
||||
);
|
||||
|
@ -1,38 +1,46 @@
|
||||
/**
|
||||
* Device Entity.
|
||||
* Represents a device entity in the of Home Assistant's device registry .
|
||||
*
|
||||
* @property {string} id Unique ID of a device (generated by Home Assistant).
|
||||
* @property {string[]} config_entries
|
||||
* @property {Array} connections
|
||||
* @property {Array} identifiers
|
||||
* @property {string | null} manufacturer
|
||||
* @property {string | null} model
|
||||
* @property {string | null} name
|
||||
* @property {string | null} sw_version
|
||||
* @property {string | null} hw_version
|
||||
* @property {string | null} serial_number
|
||||
* @property {string | null} via_device_id
|
||||
* @property {string} area_id The Area which the device is placed in.
|
||||
* @property {string | null} name_by_user
|
||||
* @property {string[] | null} entry_type
|
||||
* @property {string | null} disabled_by Indicates by what this entity is disabled.
|
||||
* @property {string | null} configuration_url
|
||||
* @property {string} id - Unique identifier of the device (generated by Home Assistant).
|
||||
* @property {string[]} config_entries - Config entries linked to this device.
|
||||
* @property {Record<string, (string | null)[]>} config_entries_subentries - Subentries for the config entries.
|
||||
* @property {[string, string][]} connections - Tuples of (connection_type, connection identifier).
|
||||
* @property {[string, string][]} identifiers - Set of (DOMAIN, identifier) tuples identifying the device.
|
||||
* @property {string | null} manufacturer - The manufacturer of the device.
|
||||
* @property {string | null} model - The model name of the device.
|
||||
* @property {string | null} model_id - The model identifier of the device.
|
||||
* @property {string | null} name - The name of the device.
|
||||
* @property {string[]} labels - Labels for the device.
|
||||
* @property {string | null} sw_version - The firmware version of the device.
|
||||
* @property {string | null} hw_version - The hardware version of the device.
|
||||
* @property {string | null} serial_number - The serial number of the device.
|
||||
* @property {string | null} via_device_id - Identifier of a device that routes messages to this device.
|
||||
* @property {string | null} area_id - The area which the device is placed in.
|
||||
* @property {string | null} name_by_user - User configured name of the device.
|
||||
* @property {string[] | null} entry_type - The type of entry (e.g., service).
|
||||
* @property {string | null} disabled_by - Indicates what disabled this entity.
|
||||
* @property {string | null} configuration_url - URL for configuring the device.
|
||||
* @property {string | null} primary_config_entry - Identifier of the primary config entry for the device.
|
||||
*/
|
||||
export interface DeviceRegistryEntry {
|
||||
id: string;
|
||||
config_entries: string[];
|
||||
connections: Array<[string, string]>;
|
||||
identifiers: Array<[string, string]>;
|
||||
config_entries_subentries: Record<string, (string | null)[]>;
|
||||
connections: [string, string][];
|
||||
identifiers: [string, string][];
|
||||
manufacturer: string | null;
|
||||
model: string | null;
|
||||
model_id: string | null;
|
||||
name: string | null;
|
||||
labels: string[];
|
||||
sw_version: string | null;
|
||||
hw_version: string | null;
|
||||
serial_number: string | null;
|
||||
via_device_id: string | null;
|
||||
area_id: string | null;
|
||||
name_by_user: string | null;
|
||||
entry_type: "service" | null;
|
||||
disabled_by: "user" | "integration" | "config_entry" | null;
|
||||
entry_type: 'service' | null;
|
||||
disabled_by: 'user' | 'integration' | 'config_entry' | null;
|
||||
configuration_url: string | null;
|
||||
primary_config_entry: string | null;
|
||||
}
|
||||
|
@ -1,76 +1,143 @@
|
||||
import {LightColor} from "./light";
|
||||
import { LightColor } from './light';
|
||||
|
||||
type EntityCategory = "config" | "diagnostic";
|
||||
export type EntityCategory = 'config' | 'diagnostic';
|
||||
|
||||
/**
|
||||
* Represents the display entry for an entity in the entity registry.
|
||||
*
|
||||
* @property {string} entity_id - The unique identifier for the entity.
|
||||
* @property {string} [name] - The name of the entity.
|
||||
* @property {string} [icon] - The icon associated with the entity.
|
||||
* @property {string} [device_id] - The ID of the device linked to this entity.
|
||||
* @property {string} [area_id] - The ID of the area linked to this entity.
|
||||
* @property {string[]} labels - Labels associated with the entity.
|
||||
* @property {boolean} [hidden] - Indicates if the entity is hidden.
|
||||
* @property {EntityCategory} [entity_category] - The category of the entity.
|
||||
* @property {string} [translation_key] - The translation key for the entity.
|
||||
* @property {string} [platform] - The platform of the entity.
|
||||
* @property {number} [display_precision] - The display precision for the entity.
|
||||
* @property {boolean} [has_entity_name] - Indicates if the entity has a name.
|
||||
*/
|
||||
export interface EntityRegistryDisplayEntry {
|
||||
entity_id: string;
|
||||
name?: string;
|
||||
icon?: string;
|
||||
device_id?: string;
|
||||
area_id?: string;
|
||||
labels: string[];
|
||||
hidden?: boolean;
|
||||
entity_category?: EntityCategory;
|
||||
translation_key?: string;
|
||||
platform?: string;
|
||||
display_precision?: number;
|
||||
has_entity_name?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Home assistant entity.
|
||||
* Represents an entity in the entity registry of Home Assistant.
|
||||
*
|
||||
* @property {string} id
|
||||
* @property {string} entity_id The id of this entity.
|
||||
* @property {string} name The name of this entity.
|
||||
* @property {string | null} icon
|
||||
* @property {string | null} platform
|
||||
* @property {string | null} config_entry_id
|
||||
* @property {string | null} device_id The id of the device to which this entity is linked.
|
||||
* @property {string | null} area_id The id of the area to which this entity is linked.
|
||||
* @property {string | null} disabled_by Indicates by what this entity is disabled.
|
||||
* @property {Object} hidden_by Indicates by what this entity is hidden.
|
||||
* @property {EntityCategory | null} entity_category
|
||||
* @property {boolean} has_entity_name
|
||||
* @property {string} [original_name]
|
||||
* @property {string} unique_id
|
||||
* @property {string} [translation_key]
|
||||
* @property {EntityRegistryOptions | null} options
|
||||
* @property {string} id - The unique identifier for the entity.
|
||||
* @property {string} entity_id - The ID of the entity.
|
||||
* @property {string | null} name - The name of the entity.
|
||||
* @property {string | null} icon - The icon associated with the entity.
|
||||
* @property {string | null} platform - The platform of the entity.
|
||||
* @property {string | null} config_entry_id - The ID of the config entry associated with the entity.
|
||||
* @property {string | null} config_subentry_id - The ID of the config subentry associated with the entity.
|
||||
* @property {string | null} device_id - The ID of the device linked to this entity.
|
||||
* @property {string | null} area_id - The ID of the area linked to this entity.
|
||||
* @property {string[]} labels - Labels associated with the entity.
|
||||
* @property {"user" | "device" | "integration" | "config_entry" | null} disabled_by - Indicates what disabled this
|
||||
* entity.
|
||||
* @property {Exclude<EntityRegistryEntry["disabled_by"], "config_entry">} hidden_by - Indicates what hidden this
|
||||
* entity.
|
||||
* @property {EntityCategory | null} entity_category - The category of the entity.
|
||||
* @property {boolean} has_entity_name - Indicates if the entity has a name.
|
||||
* @property {string} [original_name] - The original name of the entity.
|
||||
* @property {string} unique_id - The unique identifier for the entity.
|
||||
* @property {string} [translation_key] - The translation key for the entity.
|
||||
* @property {EntityRegistryOptions | null} options - Additional options for the entity.
|
||||
* @property {Record<string, string>} categories - Categories associated with the entity.
|
||||
*/
|
||||
export interface EntityRegistryEntry {
|
||||
id: string;
|
||||
entity_id: string;
|
||||
name: string | null;
|
||||
icon: string | null;
|
||||
platform: string;
|
||||
platform: string | null;
|
||||
config_entry_id: string | null;
|
||||
config_subentry_id: string | null;
|
||||
device_id: string | null;
|
||||
area_id: string | null;
|
||||
disabled_by: "user" | "device" | "integration" | "config_entry" | null;
|
||||
hidden_by: Exclude<EntityRegistryEntry["disabled_by"], "config_entry">;
|
||||
labels: string[];
|
||||
disabled_by: 'user' | 'device' | 'integration' | 'config_entry' | null;
|
||||
hidden_by: Exclude<EntityRegistryEntry['disabled_by'], 'config_entry'>;
|
||||
entity_category: EntityCategory | null;
|
||||
has_entity_name: boolean;
|
||||
original_name?: string;
|
||||
unique_id: string;
|
||||
translation_key?: string;
|
||||
options: EntityRegistryOptions | null;
|
||||
categories: Record<string, string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents options for a sensor entity in Home Assistant.
|
||||
*
|
||||
* @property {number | null} [display_precision] - The display precision for the sensor.
|
||||
* @property {number | null} [suggested_display_precision] - Suggested display precision for the sensor.
|
||||
* @property {string | null} [unit_of_measurement] - The unit of measurement for the sensor.
|
||||
*/
|
||||
export interface SensorEntityOptions {
|
||||
display_precision?: number | null;
|
||||
suggested_display_precision?: number | null;
|
||||
unit_of_measurement?: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents options for a light entity in Home Assistant.
|
||||
*
|
||||
* @property {LightColor[]} [favorite_colors] - An array of favorite colors for the light.
|
||||
*/
|
||||
export interface LightEntityOptions {
|
||||
favorite_colors?: LightColor[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents options for a number entity in Home Assistant.
|
||||
*
|
||||
* @property {string | null} [unit_of_measurement] - The unit of measurement for the number.
|
||||
*/
|
||||
export interface NumberEntityOptions {
|
||||
unit_of_measurement?: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents options for a lock entity in Home Assistant.
|
||||
*
|
||||
* @property {string | null} [default_code] - The default code for the lock.
|
||||
*/
|
||||
export interface LockEntityOptions {
|
||||
default_code?: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents options for an alarm control panel entity in Home Assistant.
|
||||
*
|
||||
* @property {string | null} [default_code] - The default code for the alarm control panel.
|
||||
*/
|
||||
export interface AlarmControlPanelEntityOptions {
|
||||
default_code?: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents options for a weather entity in Home Assistant.
|
||||
*
|
||||
* @property {string | null} [precipitation_unit] - The unit of measurement for precipitation.
|
||||
* @property {string | null} [pressure_unit] - The unit of measurement for pressure.
|
||||
* @property {string | null} [temperature_unit] - The unit of measurement for temperature.
|
||||
* @property {string | null} [visibility_unit] - The unit of measurement for visibility.
|
||||
* @property {string | null} [wind_speed_unit] - The unit of measurement for wind speed.
|
||||
*/
|
||||
export interface WeatherEntityOptions {
|
||||
precipitation_unit?: string | null;
|
||||
pressure_unit?: string | null;
|
||||
@ -79,19 +146,40 @@ export interface WeatherEntityOptions {
|
||||
wind_speed_unit?: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents options for a switch entity in Home Assistant.
|
||||
*
|
||||
* @property {string} entity_id - The ID of the entity.
|
||||
* @property {boolean} invert - Indicates if the switch should be inverted.
|
||||
*/
|
||||
export interface SwitchAsXEntityOptions {
|
||||
entity_id: string;
|
||||
invert: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents options for an entity in the entity registry of Home Assistant.
|
||||
*
|
||||
* @property {NumberEntityOptions} [number] - Options for number entities.
|
||||
* @property {SensorEntityOptions} [sensor] - Options for sensor entities.
|
||||
* @property {AlarmControlPanelEntityOptions} [alarm_control_panel] - Options for alarm control panel entities.
|
||||
* @property {LockEntityOptions} [lock] - Options for lock entities.
|
||||
* @property {WeatherEntityOptions} [weather] - Options for weather entities.
|
||||
* @property {LightEntityOptions} [light] - Options for light entities.
|
||||
* @property {SwitchAsXEntityOptions} [switch_as_x] - Options for switch entities.
|
||||
* @property {Record<string, unknown>} [conversation] - Options for conversation entities.
|
||||
* @property {Record<string, unknown>} ["cloud.alexa"] - Options for Alexa cloud integration.
|
||||
* @property {Record<string, unknown>} ["cloud.google_assistant"] - Options for Google Assistant cloud integration.
|
||||
*/
|
||||
export interface EntityRegistryOptions {
|
||||
number?: NumberEntityOptions;
|
||||
sensor?: SensorEntityOptions;
|
||||
alarm_control_panel?: AlarmControlPanelEntityOptions;
|
||||
lock?: LockEntityOptions;
|
||||
weather?: WeatherEntityOptions;
|
||||
light?: LightEntityOptions;
|
||||
switch_as_x?: SwitchAsXEntityOptions;
|
||||
conversation?: Record<string, unknown>;
|
||||
"cloud.alexa"?: Record<string, unknown>;
|
||||
"cloud.google_assistant"?: Record<string, unknown>;
|
||||
'cloud.alexa'?: Record<string, unknown>;
|
||||
'cloud.google_assistant'?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
|
18
src/types/homeassistant/data/floor_registry.ts
Normal file
18
src/types/homeassistant/data/floor_registry.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { RegistryEntry } from './registry';
|
||||
|
||||
/**
|
||||
* Represents a floor entry in the Floor Registry of Home Assistant.
|
||||
*
|
||||
* @property {string} floor_id - The unique identifier for the floor.
|
||||
* @property {string} name - The name of the floor.
|
||||
* @property {number | null} level - The level of the floor (optional).
|
||||
* @property {string | null} icon - The icon associated with the floor (optional).
|
||||
* @property {string[]} aliases - An array of aliases for the floor.
|
||||
*/
|
||||
export interface FloorRegistryEntry extends RegistryEntry {
|
||||
floor_id: string;
|
||||
name: string;
|
||||
level: number | null;
|
||||
icon: string | null;
|
||||
aliases: string[];
|
||||
}
|
8
src/types/homeassistant/data/frontend.ts
Normal file
8
src/types/homeassistant/data/frontend.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Represents user data for the frontend in Home Assistant.
|
||||
*
|
||||
* @property {boolean} [showAdvanced] - Indicates whether advanced options should be shown to the user.
|
||||
*/
|
||||
export interface CoreFrontendUserData {
|
||||
showAdvanced?: boolean;
|
||||
}
|
@ -1,6 +1,16 @@
|
||||
/**
|
||||
* Represents the color options for a light entity in Home Assistant.
|
||||
*
|
||||
* @property {number} [color_temp_kelvin] - The color temperature in Kelvin.
|
||||
* @property {[number, number]} [hs_color] - The hue and saturation values.
|
||||
* @property {[number, number, number]} [rgb_color] - The red, green, and blue color values.
|
||||
* @property {[number, number, number, number]} [rgbw_color] - The red, green, blue, and white color values.
|
||||
* @property {[number, number, number, number, number]} [rgbww_color] - The red, green, blue, white, and warm white
|
||||
* color values.
|
||||
*/
|
||||
export type LightColor =
|
||||
| { color_temp_kelvin: number; }
|
||||
| { hs_color: [number, number]; }
|
||||
| { rgb_color: [number, number, number]; }
|
||||
| { rgbw_color: [number, number, number, number]; }
|
||||
| { rgbww_color: [number, number, number, number, number]; };
|
||||
| { color_temp_kelvin: number }
|
||||
| { hs_color: [number, number] }
|
||||
| { rgb_color: [number, number, number] }
|
||||
| { rgbw_color: [number, number, number, number] }
|
||||
| { rgbww_color: [number, number, number, number, number] };
|
||||
|
@ -1,118 +0,0 @@
|
||||
import {HassServiceTarget} from "home-assistant-js-websocket";
|
||||
|
||||
export type LovelaceStrategyConfig = {
|
||||
type: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
export interface LovelaceConfig {
|
||||
title?: string;
|
||||
strategy?: LovelaceStrategyConfig;
|
||||
views: LovelaceViewConfig[];
|
||||
background?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* View Config.
|
||||
*
|
||||
* @see https://www.home-assistant.io/dashboards/views/
|
||||
*/
|
||||
export interface LovelaceViewConfig {
|
||||
index?: number;
|
||||
title?: string;
|
||||
type?: string;
|
||||
strategy?: LovelaceStrategyConfig;
|
||||
badges?: Array<string | LovelaceBadgeConfig>;
|
||||
cards?: LovelaceCardConfig[];
|
||||
path?: string;
|
||||
icon?: string;
|
||||
theme?: string;
|
||||
panel?: boolean;
|
||||
background?: string;
|
||||
visible?: boolean | ShowViewConfig[];
|
||||
subview?: boolean;
|
||||
back_path?: string;
|
||||
}
|
||||
|
||||
export interface ShowViewConfig {
|
||||
user?: string;
|
||||
}
|
||||
|
||||
export interface LovelaceBadgeConfig {
|
||||
type?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface LovelaceCardConfig {
|
||||
index?: number;
|
||||
view_index?: number;
|
||||
view_layout?: any;
|
||||
type: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface ToggleActionConfig extends BaseActionConfig {
|
||||
action: "toggle";
|
||||
}
|
||||
|
||||
export interface CallServiceActionConfig extends BaseActionConfig {
|
||||
action: "call-service";
|
||||
service: string;
|
||||
target?: HassServiceTarget;
|
||||
// Property "service_data" is kept for backwards compatibility. Replaced by "data".
|
||||
service_data?: Record<string, unknown>;
|
||||
data?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface NavigateActionConfig extends BaseActionConfig {
|
||||
action: "navigate";
|
||||
navigation_path: string;
|
||||
navigation_replace?: boolean;
|
||||
}
|
||||
|
||||
export interface UrlActionConfig extends BaseActionConfig {
|
||||
action: "url";
|
||||
url_path: string;
|
||||
}
|
||||
|
||||
export interface MoreInfoActionConfig extends BaseActionConfig {
|
||||
action: "more-info";
|
||||
}
|
||||
|
||||
export interface AssistActionConfig extends BaseActionConfig {
|
||||
action: "assist";
|
||||
pipeline_id?: string;
|
||||
start_listening?: boolean;
|
||||
}
|
||||
|
||||
export interface NoActionConfig extends BaseActionConfig {
|
||||
action: "none";
|
||||
}
|
||||
|
||||
export interface CustomActionConfig extends BaseActionConfig {
|
||||
action: "fire-dom-event";
|
||||
}
|
||||
|
||||
export interface BaseActionConfig {
|
||||
action: string;
|
||||
confirmation?: ConfirmationRestrictionConfig;
|
||||
}
|
||||
|
||||
export interface ConfirmationRestrictionConfig {
|
||||
text?: string;
|
||||
exemptions?: RestrictionConfig[];
|
||||
}
|
||||
|
||||
export interface RestrictionConfig {
|
||||
user: string;
|
||||
}
|
||||
|
||||
export type ActionConfig =
|
||||
| ToggleActionConfig
|
||||
| CallServiceActionConfig
|
||||
| NavigateActionConfig
|
||||
| UrlActionConfig
|
||||
| MoreInfoActionConfig
|
||||
| AssistActionConfig
|
||||
| NoActionConfig
|
||||
| CustomActionConfig;
|
145
src/types/homeassistant/data/lovelace/config/action.ts
Normal file
145
src/types/homeassistant/data/lovelace/config/action.ts
Normal file
@ -0,0 +1,145 @@
|
||||
import { HassServiceTarget } from 'home-assistant-js-websocket';
|
||||
|
||||
/**
|
||||
* Represents the configuration for a toggle action in Home Assistant.
|
||||
*
|
||||
* @property {'toggle'} action - The action type, which is "toggle".
|
||||
*/
|
||||
export interface ToggleActionConfig extends BaseActionConfig {
|
||||
action: 'toggle';
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the configuration for a call service action in Home Assistant.
|
||||
*
|
||||
* @property {'call-service' | 'perform-action'} action - The action type, which can be "call-service" or
|
||||
* "perform-action".
|
||||
* @property {string} [service] - Deprecated; service name for backward compatibility.
|
||||
* @property {string} perform_action - The action to perform.
|
||||
* @property {HassServiceTarget} [target] - The target for the service call.
|
||||
* @property {Record<string, unknown>} [service_data] - Deprecated; service data for backward compatibility.
|
||||
* @property {Record<string, unknown>} [data] - The data to send with the service call.
|
||||
*/
|
||||
export interface CallServiceActionConfig extends BaseActionConfig {
|
||||
action: 'call-service' | 'perform-action';
|
||||
/** @deprecated "service" is kept for backwards compatibility. Replaced by "perform_action". */
|
||||
service?: string;
|
||||
perform_action: string;
|
||||
target?: HassServiceTarget;
|
||||
/** @deprecated "service_data" is kept for backwards compatibility. Replaced by "data". */
|
||||
service_data?: Record<string, unknown>;
|
||||
data?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the configuration for a navigate action in Home Assistant.
|
||||
*
|
||||
* @property {'navigate'} action - The action type, which is "navigate".
|
||||
* @property {string} navigation_path - The path to navigate to.
|
||||
* @property {boolean} [navigation_replace] - Whether to replace the current history entry.
|
||||
*/
|
||||
export interface NavigateActionConfig extends BaseActionConfig {
|
||||
action: 'navigate';
|
||||
navigation_path: string;
|
||||
navigation_replace?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the configuration for a URL action in Home Assistant.
|
||||
*
|
||||
* @property {'url'} action - The action type, which is "url".
|
||||
* @property {string} url_path - The URL path to navigate to.
|
||||
*/
|
||||
export interface UrlActionConfig extends BaseActionConfig {
|
||||
action: 'url';
|
||||
url_path: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the configuration for a more info action in Home Assistant.
|
||||
*
|
||||
* @property {'more-info'} action - The action type, which is "more-info".
|
||||
* @property {string} [entity] - The entity to show more information about.
|
||||
*/
|
||||
export interface MoreInfoActionConfig extends BaseActionConfig {
|
||||
action: 'more-info';
|
||||
entity?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the configuration for an assist action in Home Assistant.
|
||||
*
|
||||
* @property {'assist'} action - The action type, which is "assist".
|
||||
* @property {string} [pipeline_id] - The ID of the pipeline to use for the assist action.
|
||||
* @property {boolean} [start_listening] - Whether to start listening for user input.
|
||||
*/
|
||||
export interface AssistActionConfig extends BaseActionConfig {
|
||||
action: 'assist';
|
||||
pipeline_id?: string;
|
||||
start_listening?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the configuration for a no action in Home Assistant.
|
||||
*
|
||||
* @property {'none'} action - The action type, which is "none".
|
||||
*/
|
||||
export interface NoActionConfig extends BaseActionConfig {
|
||||
action: 'none';
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the configuration for a custom action in Home Assistant.
|
||||
*
|
||||
* @property {'fire-dom-event'} action - The action type, which is "fire-dom-event".
|
||||
*/
|
||||
export interface CustomActionConfig extends BaseActionConfig {
|
||||
action: 'fire-dom-event';
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the base configuration for an action in Home Assistant.
|
||||
*
|
||||
* @property {string} action - The type of action to perform.
|
||||
* @property {ConfirmationRestrictionConfig} [confirmation] - Optional confirmation settings for the action.
|
||||
*/
|
||||
export interface BaseActionConfig {
|
||||
action: string;
|
||||
confirmation?: ConfirmationRestrictionConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the confirmation restriction configuration for an action in Home Assistant.
|
||||
*
|
||||
* @property {string} [text] - The confirmation text.
|
||||
* @property {RestrictionConfig[]} [exemptions] - List of exemptions for the confirmation.
|
||||
*/
|
||||
export interface ConfirmationRestrictionConfig {
|
||||
text?: string;
|
||||
exemptions?: RestrictionConfig[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a restriction configuration in Home Assistant.
|
||||
*
|
||||
* @property {string} user - The user associated with the restriction.
|
||||
*/
|
||||
export interface RestrictionConfig {
|
||||
user: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the overall action configuration in Home Assistant.
|
||||
*
|
||||
* A union type representing different action-configurations available in Home Assistant.
|
||||
* Each action type can have its own specific configuration.
|
||||
*/
|
||||
export type ActionConfig =
|
||||
| ToggleActionConfig
|
||||
| CallServiceActionConfig
|
||||
| NavigateActionConfig
|
||||
| UrlActionConfig
|
||||
| MoreInfoActionConfig
|
||||
| AssistActionConfig
|
||||
| NoActionConfig
|
||||
| CustomActionConfig;
|
15
src/types/homeassistant/data/lovelace/config/badge.ts
Normal file
15
src/types/homeassistant/data/lovelace/config/badge.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { Condition } from '../../../panels/common/validate-condition';
|
||||
|
||||
/**
|
||||
* Represents the configuration for a Lovelace badge in Home Assistant.
|
||||
*
|
||||
* @property {string} type - The type of the badge.
|
||||
* @property {Condition[]} [visibility] - An optional array of visibility conditions for the badge.
|
||||
* @property {any} [key] - Additional properties can be included in the configuration.
|
||||
*/
|
||||
export interface LovelaceBadgeConfig {
|
||||
type: string;
|
||||
visibility?: Condition[];
|
||||
|
||||
[key: string]: any;
|
||||
}
|
27
src/types/homeassistant/data/lovelace/config/card.ts
Normal file
27
src/types/homeassistant/data/lovelace/config/card.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { Condition } from '../../../panels/common/validate-condition';
|
||||
import { LovelaceGridOptions, LovelaceLayoutOptions } from '../../../panels/lovelace/types';
|
||||
|
||||
/**
|
||||
* Represents the configuration for a Lovelace card in Home Assistant.
|
||||
*
|
||||
* @property {number} [index] - The index of the card in the view.
|
||||
* @property {number} [view_index] - The index of the view the card belongs to.
|
||||
* @property {any} [view_layout] - The layout options for the card view.
|
||||
* @property {LovelaceLayoutOptions} [layout_options] - Deprecated layout options; use `grid_options` instead.
|
||||
* @property {LovelaceGridOptions} [grid_options] - The grid options for the card layout.
|
||||
* @property {string} type - The type of the card.
|
||||
* @property {Condition[]} [visibility] - An optional array of visibility conditions for the card.
|
||||
* @property {any} [key] - Additional properties can be included in the configuration.
|
||||
*/
|
||||
export interface LovelaceCardConfig {
|
||||
index?: number;
|
||||
view_index?: number;
|
||||
view_layout?: any;
|
||||
/** @deprecated Use `grid_options` instead */
|
||||
layout_options?: LovelaceLayoutOptions;
|
||||
grid_options?: LovelaceGridOptions;
|
||||
type: string;
|
||||
visibility?: Condition[];
|
||||
|
||||
[key: string]: any;
|
||||
}
|
42
src/types/homeassistant/data/lovelace/config/section.ts
Normal file
42
src/types/homeassistant/data/lovelace/config/section.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { Condition } from '../../../panels/common/validate-condition';
|
||||
import { LovelaceCardConfig } from './card';
|
||||
import { LovelaceStrategyConfig } from './strategy';
|
||||
|
||||
/**
|
||||
* Represents the base configuration for a Lovelace section in Home Assistant.
|
||||
*
|
||||
* @property {Condition[]} [visibility] - An optional array of visibility conditions for the section.
|
||||
* @property {number} [column_span] - The number of columns the section spans.
|
||||
* @property {number} [row_span] - The number of rows the section spans.
|
||||
* @property {string} [title] - The title of the section (deprecated; use heading card instead).
|
||||
*/
|
||||
export interface LovelaceBaseSectionConfig {
|
||||
visibility?: Condition[];
|
||||
column_span?: number;
|
||||
row_span?: number;
|
||||
/** @deprecated Use heading card instead. */
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export interface LovelaceSectionConfig /**
|
||||
* Represents the configuration for a Lovelace section in Home Assistant.
|
||||
*
|
||||
* @property {string} [type] - The type of the section.
|
||||
* @property {LovelaceCardConfig[]} [cards] - An optional array of cards contained within the section.
|
||||
*/
|
||||
extends LovelaceBaseSectionConfig {
|
||||
type?: string;
|
||||
cards?: LovelaceCardConfig[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the configuration for a Lovelace strategy section in Home Assistant.
|
||||
*
|
||||
* @property {LovelaceStrategyConfig} strategy - The strategy configuration for the section.
|
||||
*/
|
||||
export interface LovelaceStrategySectionConfig extends LovelaceBaseSectionConfig {
|
||||
strategy: LovelaceStrategyConfig;
|
||||
}
|
||||
|
||||
/** Represents the raw configuration for a Lovelace section in Home Assistant. */
|
||||
export type LovelaceSectionRawConfig = LovelaceSectionConfig | LovelaceStrategySectionConfig;
|
11
src/types/homeassistant/data/lovelace/config/strategy.ts
Normal file
11
src/types/homeassistant/data/lovelace/config/strategy.ts
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Represents the configuration for a Lovelace strategy in Home Assistant.
|
||||
*
|
||||
* @property {string} type - The type of the strategy.
|
||||
* @property {any} [key] - Additional properties can be included in the configuration.
|
||||
*/
|
||||
export interface LovelaceStrategyConfig {
|
||||
type: string;
|
||||
|
||||
[key: string]: any;
|
||||
}
|
15
src/types/homeassistant/data/lovelace/config/types.ts
Normal file
15
src/types/homeassistant/data/lovelace/config/types.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { LovelaceViewRawConfig } from './view';
|
||||
|
||||
/** Represents the base configuration for a Lovelace dashboard in Home Assistant. */
|
||||
export interface LovelaceDashboardBaseConfig {}
|
||||
|
||||
/**
|
||||
* Represents the configuration for a Lovelace dashboard in Home Assistant.
|
||||
*
|
||||
* @property {string} [background] - An optional background image or color for the dashboard.
|
||||
* @property {LovelaceViewRawConfig[]} views - An array of views contained within the dashboard.
|
||||
*/
|
||||
export interface LovelaceConfig extends LovelaceDashboardBaseConfig {
|
||||
background?: string;
|
||||
views: LovelaceViewRawConfig[];
|
||||
}
|
117
src/types/homeassistant/data/lovelace/config/view.ts
Normal file
117
src/types/homeassistant/data/lovelace/config/view.ts
Normal file
@ -0,0 +1,117 @@
|
||||
import { LovelaceBadgeConfig } from './badge';
|
||||
import { LovelaceCardConfig } from './card';
|
||||
import { LovelaceSectionRawConfig } from './section';
|
||||
import { LovelaceStrategyConfig } from './strategy';
|
||||
|
||||
/**
|
||||
* Represents the configuration for showing a view in Home Assistant.
|
||||
*
|
||||
* @property {string} [user] - The user associated with the view.
|
||||
*/
|
||||
export interface ShowViewConfig {
|
||||
user?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the background configuration for a Lovelace view in Home Assistant.
|
||||
*
|
||||
* @property {string} [image] - The background image URL.
|
||||
* @property {number} [opacity] - The opacity of the background.
|
||||
* @property {'auto' | 'cover' | 'contain'} [size] - The size of the background image.
|
||||
* @property {'top left' | 'top center' | 'top right' | 'center left' | 'center' | 'center right' | 'bottom left' |
|
||||
* 'bottom center' | 'bottom right'} [alignment] - The alignment of the background image.
|
||||
* @property {'repeat' | 'no-repeat'} [repeat] - The repeat behavior of the background image.
|
||||
* @property {'scroll' | 'fixed'} [attachment] - The attachment behavior of the background image.
|
||||
*/
|
||||
export interface LovelaceViewBackgroundConfig {
|
||||
image?: string;
|
||||
opacity?: number;
|
||||
size?: 'auto' | 'cover' | 'contain';
|
||||
alignment?:
|
||||
| 'top left'
|
||||
| 'top center'
|
||||
| 'top right'
|
||||
| 'center left'
|
||||
| 'center'
|
||||
| 'center right'
|
||||
| 'bottom left'
|
||||
| 'bottom center'
|
||||
| 'bottom right';
|
||||
repeat?: 'repeat' | 'no-repeat';
|
||||
attachment?: 'scroll' | 'fixed';
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the header configuration for a Lovelace view in Home Assistant.
|
||||
*
|
||||
* @property {LovelaceCardConfig} [card] - The card to be displayed in the header.
|
||||
* @property {'start' | 'center' | 'responsive'} [layout] - The layout of the header.
|
||||
* @property {'bottom' | 'top'} [badges_position] - The position of badges in the header.
|
||||
*/
|
||||
export interface LovelaceViewHeaderConfig {
|
||||
card?: LovelaceCardConfig;
|
||||
layout?: 'start' | 'center' | 'responsive';
|
||||
badges_position?: 'bottom' | 'top';
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the base configuration for a Lovelace view in Home Assistant.
|
||||
*
|
||||
* @property {number} [index] - The index of the view.
|
||||
* @property {string} [title] - The title of the view.
|
||||
* @property {string} [path] - The path to the view.
|
||||
* @property {string} [icon] - The icon for the view.
|
||||
* @property {string} [theme] - The theme for the view.
|
||||
* @property {boolean} [panel] - Whether the view is a panel view.
|
||||
* @property {string | LovelaceViewBackgroundConfig} [background] - The background configuration for the view.
|
||||
* @property {boolean | ShowViewConfig[]} [visible] - Visibility settings for the view.
|
||||
* @property {boolean} [subview] - Whether the view is a subview.
|
||||
* @property {string} [back_path] - The path to go back to the previous view.
|
||||
* @property {number} [max_columns] - The maximum number of columns in the view.
|
||||
* @property {boolean} [dense_section_placement] - Whether to place sections densely.
|
||||
* @property {boolean} [top_margin] - Whether to add top margin to the view.
|
||||
*/
|
||||
export interface LovelaceBaseViewConfig {
|
||||
index?: number;
|
||||
title?: string;
|
||||
path?: string;
|
||||
icon?: string;
|
||||
theme?: string;
|
||||
panel?: boolean;
|
||||
background?: string | LovelaceViewBackgroundConfig;
|
||||
visible?: boolean | ShowViewConfig[];
|
||||
subview?: boolean;
|
||||
back_path?: string;
|
||||
max_columns?: number;
|
||||
dense_section_placement?: boolean;
|
||||
top_margin?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the configuration for a Lovelace view in Home Assistant.
|
||||
*
|
||||
* @property {string} [type] - The type of the view.
|
||||
* @property {(string | Partial<LovelaceBadgeConfig>)[]} [badges] - An array of badges for the view.
|
||||
* @property {LovelaceCardConfig[]} [cards] - An array of cards in the view.
|
||||
* @property {LovelaceSectionRawConfig[]} [sections] - An array of sections in the view.
|
||||
* @property {LovelaceViewHeaderConfig} [header] - The header configuration for the view.
|
||||
*/
|
||||
export interface LovelaceViewConfig extends LovelaceBaseViewConfig {
|
||||
type?: string;
|
||||
badges?: (string | Partial<LovelaceBadgeConfig>)[];
|
||||
cards?: LovelaceCardConfig[];
|
||||
sections?: LovelaceSectionRawConfig[];
|
||||
header?: LovelaceViewHeaderConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the configuration for a Lovelace strategy view in Home Assistant.
|
||||
*
|
||||
* @property {LovelaceStrategyConfig} strategy - The strategy configuration for the view.
|
||||
*/
|
||||
export interface LovelaceStrategyViewConfig extends LovelaceBaseViewConfig {
|
||||
strategy: LovelaceStrategyConfig;
|
||||
}
|
||||
|
||||
/**Represents the raw configuration for a Lovelace view in Home Assistant. */
|
||||
export type LovelaceViewRawConfig = LovelaceViewConfig | LovelaceStrategyViewConfig;
|
10
src/types/homeassistant/data/registry.ts
Normal file
10
src/types/homeassistant/data/registry.ts
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Represents a registry entry in Home Assistant.
|
||||
*
|
||||
* @property {number} created_at - The timestamp when the entry was created.
|
||||
* @property {number} modified_at - The timestamp when the entry was last modified.
|
||||
*/
|
||||
export interface RegistryEntry {
|
||||
created_at: number;
|
||||
modified_at: number;
|
||||
}
|
116
src/types/homeassistant/data/translations.ts
Normal file
116
src/types/homeassistant/data/translations.ts
Normal file
@ -0,0 +1,116 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
import { HomeAssistant } from '../types';
|
||||
|
||||
/** Represents the different formats for numbers in Home Assistant. */
|
||||
export enum NumberFormat {
|
||||
language = 'language',
|
||||
system = 'system',
|
||||
comma_decimal = 'comma_decimal',
|
||||
decimal_comma = 'decimal_comma',
|
||||
space_comma = 'space_comma',
|
||||
none = 'none',
|
||||
}
|
||||
|
||||
/**Represents the different formats for time in Home Assistant. */
|
||||
export enum TimeFormat {
|
||||
language = 'language',
|
||||
system = 'system',
|
||||
am_pm = '12',
|
||||
twenty_four = '24',
|
||||
}
|
||||
|
||||
/** Represents the different time zones in Home Assistant. */
|
||||
export enum TimeZone {
|
||||
local = 'local',
|
||||
server = 'server',
|
||||
}
|
||||
|
||||
/** Represents the different formats for dates in Home Assistant. */
|
||||
export enum DateFormat {
|
||||
language = 'language',
|
||||
system = 'system',
|
||||
DMY = 'DMY',
|
||||
MDY = 'MDY',
|
||||
YMD = 'YMD',
|
||||
}
|
||||
|
||||
/**Represents the first weekday in Home Assistant. */
|
||||
export enum FirstWeekday {
|
||||
language = 'language',
|
||||
monday = 'monday',
|
||||
tuesday = 'tuesday',
|
||||
wednesday = 'wednesday',
|
||||
thursday = 'thursday',
|
||||
friday = 'friday',
|
||||
saturday = 'saturday',
|
||||
sunday = 'sunday',
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the locale data for the frontend in Home Assistant.
|
||||
*
|
||||
* @property {string} language - The language of the frontend.
|
||||
* @property {NumberFormat} number_format - The format for numbers.
|
||||
* @property {TimeFormat} time_format - The format for time.
|
||||
* @property {DateFormat} date_format - The format for dates.
|
||||
* @property {FirstWeekday} first_weekday - The first weekday.
|
||||
* @property {TimeZone} time_zone - The time zone.
|
||||
*/
|
||||
export interface FrontendLocaleData {
|
||||
language: string;
|
||||
number_format: NumberFormat;
|
||||
time_format: TimeFormat;
|
||||
date_format: DateFormat;
|
||||
first_weekday: FirstWeekday;
|
||||
time_zone: TimeZone;
|
||||
}
|
||||
|
||||
/** Represents a category for translations in Home Assistant. */
|
||||
export type TranslationCategory =
|
||||
| 'title'
|
||||
| 'state'
|
||||
| 'entity'
|
||||
| 'entity_component'
|
||||
| 'exceptions'
|
||||
| 'config'
|
||||
| 'config_subentries'
|
||||
| 'config_panel'
|
||||
| 'options'
|
||||
| 'device_automation'
|
||||
| 'mfa_setup'
|
||||
| 'system_health'
|
||||
| 'application_credentials'
|
||||
| 'issues'
|
||||
| 'selector'
|
||||
| 'services';
|
||||
|
||||
/**
|
||||
* Retrieves the translations for Home Assistant.
|
||||
*
|
||||
* @async
|
||||
*
|
||||
* @param {HomeAssistant} hass - The Home Assistant instance.
|
||||
* @param {string} language - The language for translations.
|
||||
* @param {TranslationCategory} category - The category of translations.
|
||||
* @param {string | string[]} [integration] - Optional integration name(s).
|
||||
* @param {boolean} [config_flow] - Optional flag for config flow.
|
||||
*
|
||||
* @returns {Promise<Record<string, unknown>>} A promise resolving to an object containing translation key-value pairs.
|
||||
*/
|
||||
export const getHassTranslations = async (
|
||||
hass: HomeAssistant,
|
||||
language: string,
|
||||
category: TranslationCategory,
|
||||
integration?: string | string[],
|
||||
config_flow?: boolean,
|
||||
): Promise<Record<string, unknown>> => {
|
||||
const result = await hass.callWS<{ resources: Record<string, unknown> }>({
|
||||
type: 'frontend/get_translations',
|
||||
language,
|
||||
category,
|
||||
integration,
|
||||
config_flow,
|
||||
});
|
||||
return result.resources;
|
||||
};
|
50
src/types/homeassistant/data/ws-themes.ts
Normal file
50
src/types/homeassistant/data/ws-themes.ts
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Represents the variables for a theme in Home Assistant.
|
||||
*
|
||||
* @property {string} primary-color - The primary color of the theme.
|
||||
* @property {string} text-primary-color - The primary text color of the theme.
|
||||
* @property {string} accent-color - The accent color of the theme.
|
||||
* @property {string} [key] - Additional theme variables as key-value pairs.
|
||||
*/
|
||||
export interface ThemeVars {
|
||||
// Incomplete
|
||||
'primary-color': string;
|
||||
'text-primary-color': string;
|
||||
'accent-color': string;
|
||||
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a theme configuration in Home Assistant.
|
||||
*
|
||||
* @property {ThemeVars} modes.light - The light mode variables.
|
||||
* @property {ThemeVars} modes.dark - The dark mode variables.
|
||||
*/
|
||||
export type Theme = ThemeVars & {
|
||||
modes?: {
|
||||
light?: ThemeVars;
|
||||
dark?: ThemeVars;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the overall themes configuration in Home Assistant.
|
||||
*
|
||||
* @property {string} default_theme - The default theme name.
|
||||
* @property {string | null} default_dark_theme - The default dark theme name or null.
|
||||
* @property {Record<string, Theme>} themes - A record of available themes.
|
||||
* @property {boolean} darkMode - Currently effective dark mode.
|
||||
* It Will never be undefined.
|
||||
* If the user selected "auto" in the theme picker, this property will still contain
|
||||
* either true or false based on what has been determined via system preferences and
|
||||
* support for the selected theme.
|
||||
* @property {string} theme - Currently globally active theme name
|
||||
*/
|
||||
export interface Themes {
|
||||
default_theme: string;
|
||||
default_dark_theme: string | null;
|
||||
themes: Record<string, Theme>;
|
||||
darkMode: boolean;
|
||||
theme: string;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
import {LovelaceCardConfig} from "../../data/lovelace";
|
||||
|
||||
/**
|
||||
* Home Assistant Stack Card Config.
|
||||
*
|
||||
* @property {string} type The stack type.
|
||||
* @property {Object[]} cards The content of the stack.
|
||||
*
|
||||
* @see https://www.home-assistant.io/dashboards/horizontal-stack/
|
||||
* @see https://www.home-assistant.io/dashboards/vertical-stack/
|
||||
*/
|
||||
export interface StackCardConfig extends LovelaceCardConfig {
|
||||
cards: LovelaceCardConfig[];
|
||||
title?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Home Assistant Area Card Config.
|
||||
*
|
||||
* @see https://www.home-assistant.io/dashboards/area/
|
||||
*/
|
||||
export interface AreaCardConfig extends LovelaceCardConfig {
|
||||
area: string;
|
||||
navigation_path?: string;
|
||||
show_camera?: boolean;
|
||||
}
|
91
src/types/homeassistant/panels/common/validate-condition.ts
Normal file
91
src/types/homeassistant/panels/common/validate-condition.ts
Normal file
@ -0,0 +1,91 @@
|
||||
/** Represents a condition in Home Assistant. */
|
||||
export type Condition =
|
||||
| NumericStateCondition
|
||||
| StateCondition
|
||||
| ScreenCondition
|
||||
| UserCondition
|
||||
| OrCondition
|
||||
| AndCondition;
|
||||
|
||||
/**
|
||||
* Base interface for all conditions in Home Assistant.
|
||||
*
|
||||
* @property {string} condition - The type of condition.
|
||||
*/
|
||||
interface BaseCondition {
|
||||
condition: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a numeric state condition in Home Assistant.
|
||||
*
|
||||
* @property {'numeric_state'} condition - The condition type.
|
||||
* @property {string} [entity] - The entity to evaluate.
|
||||
* @property {string | number} [below] - The threshold value below which the condition is true.
|
||||
* @property {string | number} [above] - The threshold value above which the condition is true.
|
||||
*/
|
||||
export interface NumericStateCondition extends BaseCondition {
|
||||
condition: 'numeric_state';
|
||||
entity?: string;
|
||||
below?: string | number;
|
||||
above?: string | number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a state condition in Home Assistant.
|
||||
*
|
||||
* @property {'state'} condition - The condition type.
|
||||
* @property {string} [entity] - The entity to evaluate.
|
||||
* @property {string | string[]} [state] - The expected state of the entity.
|
||||
* @property {string | string[]} [state_not] - The state that the entity should not be in.
|
||||
*/
|
||||
export interface StateCondition extends BaseCondition {
|
||||
condition: 'state';
|
||||
entity?: string;
|
||||
state?: string | string[];
|
||||
state_not?: string | string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a screen condition in Home Assistant.
|
||||
*
|
||||
* @property {'screen'} condition - The condition type.
|
||||
* @property {string} [media_query] - The media query for screen conditions.
|
||||
*/
|
||||
export interface ScreenCondition extends BaseCondition {
|
||||
condition: 'screen';
|
||||
media_query?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a user condition in Home Assistant.
|
||||
*
|
||||
* @property {'user'} condition - The condition type.
|
||||
* @property {string[]} [users] - The list of users for the condition.
|
||||
*/
|
||||
export interface UserCondition extends BaseCondition {
|
||||
condition: 'user';
|
||||
users?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an OR condition in Home Assistant.
|
||||
*
|
||||
* @property {'or'} condition - The condition type.
|
||||
* @property {Condition[]} [conditions] - The list of conditions to evaluate.
|
||||
*/
|
||||
export interface OrCondition extends BaseCondition {
|
||||
condition: 'or';
|
||||
conditions?: Condition[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an AND condition in Home Assistant.
|
||||
*
|
||||
* @property {'and'} condition - The condition type.
|
||||
* @property {Condition[]} [conditions] - The list of conditions to evaluate.
|
||||
*/
|
||||
export interface AndCondition extends BaseCondition {
|
||||
condition: 'and';
|
||||
conditions?: Condition[];
|
||||
}
|
70
src/types/homeassistant/panels/lovelace/cards/types.ts
Normal file
70
src/types/homeassistant/panels/lovelace/cards/types.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { ActionConfig } from '../../../data/lovelace/config/action';
|
||||
import { LovelaceCardConfig } from '../../../data/lovelace/config/card';
|
||||
|
||||
/**
|
||||
* Home Assistant Area Card Config.
|
||||
*
|
||||
* @property {string} area - The area associated with the card.
|
||||
* @property {string} [navigation_path] - Optional navigation path for the card.
|
||||
* @property {boolean} [show_camera] - Whether to show the camera view.
|
||||
* @property {"live" | "auto"} [camera_view] - The camera view mode.
|
||||
* @property {string} [aspect_ratio] - The aspect ratio of the card.
|
||||
* @see https://www.home-assistant.io/dashboards/area/
|
||||
*/
|
||||
export interface AreaCardConfig extends LovelaceCardConfig {
|
||||
area: string;
|
||||
navigation_path?: string;
|
||||
show_camera?: boolean;
|
||||
camera_view?: 'live' | 'auto';
|
||||
aspect_ratio?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Home Assistant Picture Entity Config.
|
||||
*
|
||||
* @property {string} entity - An entity_id used for the picture.
|
||||
* @property {string} [name] - Overwrite entity name.
|
||||
* @property {string} [image] - URL of an image.
|
||||
* @property {string} [camera_image] - Camera entity_id to use.
|
||||
* @property {"live" | "auto"} [camera_view] - The camera view mode.
|
||||
* @property {Record<string, unknown>} [state_image] - Map entity states to images.
|
||||
* @property {string[]} [state_filter] - State-based CSS filters.
|
||||
* @property {string} [aspect_ratio] - Forces the height of the image to be a ratio of the width.
|
||||
* @property {ActionConfig} [tap_action] - Action taken on card tap.
|
||||
* @property {ActionConfig} [hold_action] - Action taken on card tap and hold.
|
||||
* @property {ActionConfig} [double_tap_action] - Action taken on card double tap.
|
||||
* @property {boolean} [show_name=true] - Shows name in footer.
|
||||
* @property {string} [theme=true] - Override the used theme for this card.
|
||||
* @property {boolean} [show_state] - Shows state in footer.
|
||||
* @see https://www.home-assistant.io/dashboards/picture-entity/
|
||||
*/
|
||||
export interface PictureEntityCardConfig extends LovelaceCardConfig {
|
||||
entity: string;
|
||||
name?: string;
|
||||
image?: string;
|
||||
camera_image?: string;
|
||||
camera_view?: 'live' | 'auto';
|
||||
state_image?: Record<string, unknown>;
|
||||
state_filter?: string[];
|
||||
aspect_ratio?: string;
|
||||
tap_action?: ActionConfig;
|
||||
hold_action?: ActionConfig;
|
||||
double_tap_action?: ActionConfig;
|
||||
show_name?: boolean;
|
||||
show_state?: boolean;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Home Assistant Stack Card Config.
|
||||
*
|
||||
* @property {string} type - The stack type.
|
||||
* @property {Object[]} cards - The content of the stack.
|
||||
* @see https://www.home-assistant.io/dashboards/horizontal-stack/
|
||||
* @see https://www.home-assistant.io/dashboards/vertical-stack/
|
||||
*/
|
||||
export interface StackCardConfig extends LovelaceCardConfig {
|
||||
type: string;
|
||||
cards: LovelaceCardConfig[];
|
||||
title?: string;
|
||||
}
|
37
src/types/homeassistant/panels/lovelace/types.ts
Normal file
37
src/types/homeassistant/panels/lovelace/types.ts
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Represents the layout options for Lovelace in Home Assistant.
|
||||
*
|
||||
* @property {number | "full"} [grid_columns] - The number of grid columns or "full".
|
||||
* @property {number | "auto"} [grid_rows] - The number of grid rows or "auto".
|
||||
* @property {number} [grid_max_columns] - The maximum number of grid columns.
|
||||
* @property {number} [grid_min_columns] - The minimum number of grid columns.
|
||||
* @property {number} [grid_min_rows] - The minimum number of grid rows.
|
||||
* @property {number} [grid_max_rows] - The maximum number of grid rows.
|
||||
*/
|
||||
export interface LovelaceLayoutOptions {
|
||||
grid_columns?: number | 'full';
|
||||
grid_rows?: number | 'auto';
|
||||
grid_max_columns?: number;
|
||||
grid_min_columns?: number;
|
||||
grid_min_rows?: number;
|
||||
grid_max_rows?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the grid options for Lovelace in Home Assistant.
|
||||
*
|
||||
* @property {number | "full"} [columns] - The number of columns or "full".
|
||||
* @property {number | "auto"} [rows] - The number of rows or "auto".
|
||||
* @property {number} [max_columns] - The maximum number of columns.
|
||||
* @property {number} [min_columns] - The minimum number of columns.
|
||||
* @property {number} [min_rows] - The minimum number of rows.
|
||||
* @property {number} [max_rows] - The maximum number of rows.
|
||||
*/
|
||||
export interface LovelaceGridOptions {
|
||||
columns?: number | 'full';
|
||||
rows?: number | 'auto';
|
||||
max_columns?: number;
|
||||
min_columns?: number;
|
||||
min_rows?: number;
|
||||
max_rows?: number;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
import {ActionConfig, LovelaceCardConfig} from "../../../data/lovelace";
|
||||
|
||||
/**
|
||||
* Home Assistant Picture Entity Config.
|
||||
*
|
||||
* @property {string} entity An entity_id used for the picture.
|
||||
* @property {string} [name] Overwrite entity name.
|
||||
* @property {string} [image] URL of an image.
|
||||
* @property {string} [camera_image] Camera entity_id to use. (not required if entity is already a camera-entity).
|
||||
* @property {string} [camera_view=auto] “live” will show the live view if stream is enabled.
|
||||
* @property {Record<string, unknown>} [state_image] Map entity states to images (state: image URL).
|
||||
* @property {string[]} [state_filter] State-based CSS filters.
|
||||
* @property {string} [aspect_ratio] Forces the height of the image to be a ratio of the width.
|
||||
* Valid formats: Height percentage value (23%) or ratio expressed with colon or “x”
|
||||
* separator (16:9 or 16x9).
|
||||
* For a ratio, the second element can be omitted and will default to “1”
|
||||
* (1.78 equals 1.78:1).
|
||||
* @property {ActionConfig} [tap_action] Action taken on card tap.
|
||||
* @property {ActionConfig} [hold_action] Action taken on card tap and hold.
|
||||
* @property {ActionConfig} [double_tap_action] Action taken on card double tap.
|
||||
* @property {boolean} [show_name=true] Shows name in footer.
|
||||
* @property {string} [theme=true] Override the used theme for this card with any loaded theme.
|
||||
*
|
||||
* @see https://www.home-assistant.io/dashboards/picture-entity/
|
||||
*/
|
||||
export interface PictureEntityCardConfig extends LovelaceCardConfig {
|
||||
entity: string;
|
||||
name?: string;
|
||||
image?: string;
|
||||
camera_image?: string;
|
||||
camera_view?: "live" | "auto";
|
||||
state_image?: Record<string, unknown>;
|
||||
state_filter?: string[];
|
||||
aspect_ratio?: string;
|
||||
tap_action?: ActionConfig;
|
||||
hold_action?: ActionConfig;
|
||||
double_tap_action?: ActionConfig;
|
||||
show_name?: boolean;
|
||||
show_state?: boolean;
|
||||
theme?: string;
|
||||
}
|
@ -1,19 +1,56 @@
|
||||
import {Auth, Connection, HassConfig, HassEntities, HassServices, MessageBase,} from "home-assistant-js-websocket";
|
||||
import {AreaRegistryEntry} from "./data/area_registry";
|
||||
import {DeviceRegistryEntry} from "./data/device_registry";
|
||||
import {EntityRegistryDisplayEntry} from "./data/entity_registry";
|
||||
import {
|
||||
Auth,
|
||||
Connection,
|
||||
HassConfig,
|
||||
HassEntities,
|
||||
HassEntity,
|
||||
HassServices,
|
||||
HassServiceTarget,
|
||||
MessageBase,
|
||||
} from 'home-assistant-js-websocket';
|
||||
import { LocalizeFunc } from './common/translations/localize';
|
||||
import { AreaRegistryEntry } from './data/area_registry';
|
||||
import { DeviceRegistryEntry } from './data/device_registry';
|
||||
import { EntityRegistryDisplayEntry } from './data/entity_registry';
|
||||
import { FloorRegistryEntry } from './data/floor_registry';
|
||||
import { CoreFrontendUserData } from './data/frontend';
|
||||
import { FrontendLocaleData, getHassTranslations } from './data/translations';
|
||||
import { Themes } from './data/ws-themes';
|
||||
|
||||
/**
|
||||
* Represents the credentials for a user in Home Assistant.
|
||||
*
|
||||
* @property {string} auth_provider_type - The type of authentication provider.
|
||||
* @property {string} auth_provider_id - The ID of the authentication provider.
|
||||
*/
|
||||
export interface Credential {
|
||||
auth_provider_type: string;
|
||||
auth_provider_id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a multifactor authentication module in Home Assistant.
|
||||
*
|
||||
* @property {string} id - The unique identifier for the MFA module.
|
||||
* @property {string} name - The name of the MFA module.
|
||||
* @property {boolean} enabled - Whether the MFA module is enabled.
|
||||
*/
|
||||
export interface MFAModule {
|
||||
id: string;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the current user in Home Assistant.
|
||||
*
|
||||
* @property {string} id - The unique identifier for the user.
|
||||
* @property {boolean} is_owner - Indicates if the user is an owner.
|
||||
* @property {boolean} is_admin - Indicates if the user is an admin.
|
||||
* @property {string} name - The name of the user.
|
||||
* @property {Credential[]} credentials - The credentials associated with the user.
|
||||
* @property {MFAModule[]} mfa_modules - The MFA modules associated with the user.
|
||||
*/
|
||||
export interface CurrentUser {
|
||||
id: string;
|
||||
is_owner: boolean;
|
||||
@ -23,6 +60,18 @@ export interface CurrentUser {
|
||||
mfa_modules: MFAModule[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents information about a panel in Home Assistant.
|
||||
*
|
||||
* @template T The type of the configuration object for the panel.
|
||||
*
|
||||
* @property {string} component_name - The name of the component for the panel.
|
||||
* @property {T} config - The configuration for the panel.
|
||||
* @property {string | null} icon - The icon for the panel.
|
||||
* @property {string | null} title - The title of the panel.
|
||||
* @property {string} url_path - The URL path for the panel.
|
||||
* @property {string} [config_panel_domain] - The domain for the configuration panel.
|
||||
*/
|
||||
export interface PanelInfo<T = Record<string, any> | null> {
|
||||
component_name: string;
|
||||
config: T;
|
||||
@ -32,64 +81,305 @@ export interface PanelInfo<T = Record<string, any> | null> {
|
||||
config_panel_domain?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the panels in Home Assistant.
|
||||
*
|
||||
* @property {Record<string, PanelInfo>} panels - The panel configurations.
|
||||
*/
|
||||
export interface Panels {
|
||||
[name: string]: PanelInfo;
|
||||
panels: Record<string, PanelInfo>;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents a translation in Home Assistant.
|
||||
*
|
||||
* @property {string} nativeName - The native name of the language.
|
||||
* @property {boolean} isRTL - Indicates if the language is written right-to-left.
|
||||
* @property {string} hash - The hash for the translation.
|
||||
*/
|
||||
export interface Translation {
|
||||
nativeName: string;
|
||||
isRTL: boolean;
|
||||
hash: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents metadata for translations in Home Assistant.
|
||||
*
|
||||
* @property {string[]} fragments - The fragments of the translation.
|
||||
* @property {Record<string, Translation>} translations - The translations mapped by language.
|
||||
*/
|
||||
export interface TranslationMetadata {
|
||||
fragments: string[];
|
||||
translations: {
|
||||
[lang: string]: Translation;
|
||||
};
|
||||
translations: Record<string, Translation>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a dictionary of translations in Home Assistant.
|
||||
*
|
||||
* @property {Record<string, string>} translations - The translations mapped by a key.
|
||||
*/
|
||||
export interface TranslationDict {
|
||||
translations: Record<string, string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents resources in Home Assistant.
|
||||
*
|
||||
* @property {Record<string, Record<string, string>>} resources - The resources mapped by a key.
|
||||
*/
|
||||
export interface Resources {
|
||||
[language: string]: Record<string, string>;
|
||||
resources: Record<string, Record<string, string>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the settings for themes in Home Assistant.
|
||||
*
|
||||
* @property {string} theme - The name of the selected theme.
|
||||
* @property {boolean} [dark] - Indicates if the theme is dark.
|
||||
* @property {string} [primaryColor] - The primary color of the theme.
|
||||
* @property {string} [accentColor] - The accent color of the theme.
|
||||
*/
|
||||
export interface ThemeSettings {
|
||||
theme: string;
|
||||
dark?: boolean;
|
||||
primaryColor?: string;
|
||||
accentColor?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the main Home Assistant object.
|
||||
*
|
||||
* @interface HomeAssistant
|
||||
* @property {Auth} auth - The authentication object.
|
||||
* @property {Connection} connection - The connection object.
|
||||
* @property {boolean} connected - Indicates if the connection is active.
|
||||
* @property {HassEntities} states - The current states of entities.
|
||||
* @property {Record<string, EntityRegistryDisplayEntry>} entities - The entities in the registry.
|
||||
* @property {Record<string, DeviceRegistryEntry>} devices - The devices in the registry.
|
||||
* @property {Record<string, AreaRegistryEntry>} areas - The areas in the registry.
|
||||
* @property {Record<string, FloorRegistryEntry>} floors - The floors in the registry.
|
||||
* @property {HassServices} services - The services available in Home Assistant.
|
||||
* @property {HassConfig} config - The configuration for Home Assistant.
|
||||
* @property {Themes} themes - The available themes.
|
||||
* @property {ThemeSettings | null} selectedTheme - The currently selected theme.
|
||||
* @property {Panels} panels - The panel configurations.
|
||||
* @property {string} panelUrl - The URL for the panel.
|
||||
* @property {string} language - The current language.
|
||||
* @property {string | null} selectedLanguage - The selected language.
|
||||
* @property {FrontendLocaleData} locale - The locale data.
|
||||
* @property {Resources} resources - The resources available.
|
||||
* @property {LocalizeFunc} localize - The localization function.
|
||||
* @property {TranslationMetadata} translationMetadata - The translation metadata.
|
||||
* @property {boolean} suspendWhenHidden - Indicates if the frontend should suspend when hidden.
|
||||
* @property {boolean} enableShortcuts - Indicates if shortcuts are enabled.
|
||||
* @property {boolean} vibrate - Indicates if vibration feedback is enabled.
|
||||
* @property {boolean} debugConnection - Indicates if debug mode is enabled for the connection.
|
||||
* @property {'docked' | 'always_hidden' | 'auto'} dockedSidebar - The sidebar visibility setting.
|
||||
* @property {string} defaultPanel - The default panel to show.
|
||||
* @property {string | null} moreInfoEntityId - The entity ID for more info.
|
||||
* @property {CurrentUser} [user] - The current user object.
|
||||
* @property {CoreFrontendUserData | null} [userData] - The frontend user data.
|
||||
*/
|
||||
export interface HomeAssistant {
|
||||
auth: Auth & { external?: any };
|
||||
auth: Auth & { external?: { [key: string]: any } };
|
||||
connection: Connection;
|
||||
connected: boolean;
|
||||
states: HassEntities;
|
||||
entities: { [id: string]: EntityRegistryDisplayEntry };
|
||||
devices: { [id: string]: DeviceRegistryEntry };
|
||||
areas: { [id: string]: AreaRegistryEntry };
|
||||
entities: Record<string, EntityRegistryDisplayEntry>;
|
||||
devices: Record<string, DeviceRegistryEntry>;
|
||||
areas: Record<string, AreaRegistryEntry>;
|
||||
floors: Record<string, FloorRegistryEntry>;
|
||||
services: HassServices;
|
||||
config: HassConfig;
|
||||
themes: { [k: string]: any };
|
||||
selectedTheme: { [k: string]: any } | null;
|
||||
themes: Themes;
|
||||
selectedTheme: ThemeSettings | null;
|
||||
panels: Panels;
|
||||
panelUrl: string;
|
||||
// i18n
|
||||
// current effective language in that order:
|
||||
// - backend saved user selected language
|
||||
// - language in local app storage
|
||||
// - browser language
|
||||
// - english (en)
|
||||
language: string;
|
||||
// local stored language, keep that name for backward compatibility
|
||||
selectedLanguage: string | null;
|
||||
locale: { [k: string]: any };
|
||||
locale: FrontendLocaleData;
|
||||
resources: Resources;
|
||||
localize: Function;
|
||||
localize: LocalizeFunc;
|
||||
translationMetadata: TranslationMetadata;
|
||||
suspendWhenHidden: boolean;
|
||||
enableShortcuts: boolean;
|
||||
vibrate: boolean;
|
||||
debugConnection: boolean;
|
||||
dockedSidebar: "docked" | "always_hidden" | "auto";
|
||||
dockedSidebar: 'docked' | 'always_hidden' | 'auto';
|
||||
defaultPanel: string;
|
||||
moreInfoEntityId: string | null;
|
||||
user?: CurrentUser;
|
||||
userData?: { [k: string]: any } | null;
|
||||
userData?: CoreFrontendUserData | null;
|
||||
|
||||
/**
|
||||
* Returns the URL for the Home Assistant instance.
|
||||
*
|
||||
* @param {any} path - Optional path to append to the base URL.
|
||||
*/
|
||||
hassUrl(path?: any): string;
|
||||
|
||||
/**
|
||||
* Calls a service in Home Assistant.
|
||||
*
|
||||
* @param {ServiceCallRequest['domain']} domain - The domain of the service.
|
||||
* @param {ServiceCallRequest['service']} service - The name of the service to call.
|
||||
* @param {ServiceCallRequest['serviceData']} [serviceData] - Optional data to send with the service call.
|
||||
* @param {ServiceCallRequest['target']} [target] - Optional target for the service call.
|
||||
* @param {boolean} [notifyOnError] - Whether to notify on error.
|
||||
* @param {boolean} [returnResponse] - Whether to return the response.
|
||||
*/
|
||||
callService(
|
||||
domain: ServiceCallRequest['domain'],
|
||||
service: ServiceCallRequest['service'],
|
||||
serviceData?: ServiceCallRequest['serviceData'],
|
||||
target?: ServiceCallRequest['target'],
|
||||
notifyOnError?: boolean,
|
||||
returnResponse?: boolean,
|
||||
): Promise<ServiceCallResponse>;
|
||||
|
||||
/**
|
||||
* Calls the Home Assistant API.
|
||||
*
|
||||
* @template T The expected response type.
|
||||
*
|
||||
* @param {'GET' | 'POST' | 'PUT' | 'DELETE'} method - The HTTP method to use.
|
||||
* @param {string} path - The API endpoint path.
|
||||
* @param {Record<string, any>} [parameters] - Optional parameters to send with the request.
|
||||
* @param {Record<string, string>} [headers] - Optional headers to include in the request.
|
||||
*/
|
||||
callApi<T>(
|
||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE',
|
||||
path: string,
|
||||
parameters?: Record<string, any>,
|
||||
headers?: Record<string, string>,
|
||||
): Promise<T>;
|
||||
|
||||
/**
|
||||
* Calls the Home Assistant API with raw response.
|
||||
*
|
||||
* @param {'GET' | 'POST' | 'PUT' | 'DELETE'} method - The HTTP method to use.
|
||||
* @param {string} path - The API endpoint path.
|
||||
* @param {Record<string, any>} [parameters] - Optional parameters to send with the request.
|
||||
* @param {Record<string, string>} [headers] - Optional headers to include in the request.
|
||||
* @param {AbortSignal} [signal] - Optional signal to abort the request.
|
||||
*/
|
||||
callApiRaw(
|
||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE',
|
||||
path: string,
|
||||
parameters?: Record<string, any>,
|
||||
headers?: Record<string, string>,
|
||||
signal?: AbortSignal,
|
||||
): Promise<Response>;
|
||||
|
||||
/**
|
||||
* Fetches a resource with authentication.
|
||||
*
|
||||
* @param {string} path - The resource path to fetch.
|
||||
* @param {Record<string, any>} [init] - Optional fetch options.
|
||||
*/
|
||||
fetchWithAuth(path: string, init?: Record<string, any>): Promise<Response>;
|
||||
|
||||
/**
|
||||
* Sends a WebSocket message.
|
||||
*
|
||||
* @param {MessageBase} msg - The message to send.
|
||||
*/
|
||||
sendWS(msg: MessageBase): void;
|
||||
|
||||
/**
|
||||
* Calls a WebSocket service.
|
||||
*
|
||||
* @template T The expected response type.
|
||||
*
|
||||
* @param {MessageBase} msg - The message to send.
|
||||
*/
|
||||
callWS<T>(msg: MessageBase): Promise<T>;
|
||||
|
||||
/**
|
||||
* Load backend translation.
|
||||
*
|
||||
* @param {Parameters<typeof getHassTranslations>[2]} category - The category of translations.
|
||||
* @param {Parameters<typeof getHassTranslations>[3]} [integrations] - Optional integrations to include.
|
||||
* @param {Parameters<typeof getHassTranslations>[4]} [configFlow] - Optional config flow.
|
||||
*
|
||||
* @returns {Promise<LocalizeFunc>} The localization function.
|
||||
*/
|
||||
loadBackendTranslation(
|
||||
category: Parameters<typeof getHassTranslations>[2],
|
||||
integrations?: Parameters<typeof getHassTranslations>[3],
|
||||
configFlow?: Parameters<typeof getHassTranslations>[4],
|
||||
): Promise<LocalizeFunc>;
|
||||
|
||||
/**
|
||||
* Load fragment translation.
|
||||
*
|
||||
* @param {string} fragment - The fragment to load.
|
||||
* @returns {Promise<LocalizeFunc | undefined>} The localization function or undefined.
|
||||
*/
|
||||
loadFragmentTranslation(fragment: string): Promise<LocalizeFunc | undefined>;
|
||||
|
||||
/**
|
||||
* Formats the state of an entity.
|
||||
*
|
||||
* @param {HassEntity} stateObj - The state object of the entity.
|
||||
* @param {string} [state] - Optional state to format.
|
||||
*/
|
||||
formatEntityState(stateObj: HassEntity, state?: string): string;
|
||||
|
||||
/**
|
||||
* Formats the value of an entity attribute.
|
||||
*
|
||||
* @param {HassEntity} stateObj - The state object of the entity.
|
||||
* @param {string} attribute - The attribute to format.
|
||||
* @param {any} [value] - Optional value to format.
|
||||
*/
|
||||
formatEntityAttributeValue(stateObj: HassEntity, attribute: string, value?: any): string;
|
||||
|
||||
/**
|
||||
* Formats the name of an entity attribute.
|
||||
*
|
||||
* @param {HassEntity} stateObj - The state object of the entity.
|
||||
* @param {string} attribute - The attribute to format.
|
||||
*/
|
||||
formatEntityAttributeName(stateObj: HassEntity, attribute: string): string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the context of a service call.
|
||||
*
|
||||
* @property {string} id - The unique identifier for the context.
|
||||
* @property {string} [parent_id] - The optional parent ID of the context.
|
||||
* @property {string | null} [user_id] - The optional user ID associated with the context.
|
||||
*/
|
||||
export interface Context {
|
||||
id: string;
|
||||
parent_id?: string;
|
||||
user_id?: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a service call request in Home Assistant.
|
||||
*
|
||||
* @property {string} domain - The domain of the service to call.
|
||||
* @property {string} service - The name of the service to call.
|
||||
* @property {Record<string, any>} [serviceData] - Optional data to send with the service call.
|
||||
* @property {HassServiceTarget} [target] - Optional target for the service call.
|
||||
*/
|
||||
export interface ServiceCallRequest {
|
||||
domain: string;
|
||||
service: string;
|
||||
serviceData?: Record<string, any>;
|
||||
target?: HassServiceTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the response from a service call in Home Assistant.
|
||||
*
|
||||
* @property {Context} context - The context of the service call.
|
||||
* @property {any} [response] - The optional response data from the service call.
|
||||
*/
|
||||
export interface ServiceCallResponse {
|
||||
context: Context;
|
||||
response?: any;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {LovelaceChipConfig} from "../utils/lovelace/chip/types";
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { LovelaceChipConfig } from '../utils/lovelace/chip/types';
|
||||
|
||||
/**
|
||||
* Chips Card Configuration
|
||||
*
|
||||
* @param {LovelaceChipConfig[]} chips Chips Array
|
||||
* @param {string} [alignment=start] Chips alignment (end, center, justify), when empty default behavior is start.
|
||||
* @property {LovelaceChipConfig[]} chips - Array of chips to display.
|
||||
* @property {string} [alignment] - Chips alignment (start, end, center, justify). Defaults to 'start'.
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/chips.md
|
||||
*/
|
||||
|
@ -1,15 +1,16 @@
|
||||
import {HvacMode} from "../../homeassistant/data/climate";
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
||||
import { HvacMode } from '../../homeassistant/data/climate';
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||
import { EntitySharedConfig } from '../shared/config/entity-config';
|
||||
|
||||
/**
|
||||
* Climate Card Config.
|
||||
* Climate Card Configuration
|
||||
*
|
||||
* @property {boolean} [show_temperature_control=false] Show buttons to control target temperature.
|
||||
* @property {HvacMode[]} [hvac_modes] List of hvac modes to display (auto, heat_cool, heat, cool, dry, fan_only, off).
|
||||
* @property {boolean} [collapsible_controls] Collapse controls when off.
|
||||
* @property {boolean} [show_temperature_control] - Show buttons to control target temperature. Defaults to false.
|
||||
* @property {HvacMode[]} [hvac_modes] - List of HVAC modes to display.
|
||||
* (auto, heat_cool, heat, cool, dry, fan_only, off).
|
||||
* @property {boolean} [collapsible_controls] - Collapse controls when off.
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/climate.md
|
||||
*/
|
||||
@ -17,7 +18,7 @@ export type ClimateCardConfig = LovelaceCardConfig &
|
||||
EntitySharedConfig &
|
||||
AppearanceSharedConfig &
|
||||
ActionsSharedConfig & {
|
||||
show_temperature_control?: boolean;
|
||||
hvac_modes?: HvacMode[];
|
||||
collapsible_controls?: boolean;
|
||||
};
|
||||
show_temperature_control?: boolean;
|
||||
hvac_modes?: HvacMode[];
|
||||
collapsible_controls?: boolean;
|
||||
};
|
||||
|
@ -1,14 +1,15 @@
|
||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||
import { EntitySharedConfig } from '../shared/config/entity-config';
|
||||
|
||||
/**
|
||||
* Cover Card Config.
|
||||
* Cover Card Configuration
|
||||
*
|
||||
* @property {boolean} [show_buttons_control=false] Show buttons to open, close and stop cover.
|
||||
* @property {boolean} [show_position_control=false] Show a slider to control position of the cover.
|
||||
* @property {boolean} [show_tilt_position_control=false] Show a slider to control tilt position of the cover.
|
||||
* @property {boolean} [show_buttons_control] - Show buttons to open, close, and stop the cover. Defaults to false.
|
||||
* @property {boolean} [show_position_control] - Show a slider to control the position of the cover. Defaults to false.
|
||||
* @property {boolean} [show_tilt_position_control] - Show a slider to control the tilt position of the cover. Defaults
|
||||
* to false.
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/cover.md
|
||||
*/
|
||||
@ -16,7 +17,7 @@ export type CoverCardConfig = LovelaceCardConfig &
|
||||
EntitySharedConfig &
|
||||
AppearanceSharedConfig &
|
||||
ActionsSharedConfig & {
|
||||
show_buttons_control?: boolean;
|
||||
show_position_control?: boolean;
|
||||
show_tilt_position_control?: boolean;
|
||||
};
|
||||
show_buttons_control?: boolean;
|
||||
show_position_control?: boolean;
|
||||
show_tilt_position_control?: boolean;
|
||||
};
|
||||
|
@ -1,12 +1,12 @@
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||
import { EntitySharedConfig } from '../shared/config/entity-config';
|
||||
|
||||
/**
|
||||
* Entity Card Config.
|
||||
* Entity Card Configuration
|
||||
*
|
||||
* @property {string} [icon_color=blue] Custom color for icon when entity is state is active.
|
||||
* @property {string} [icon_color] - Custom color for the icon when the entity's state is active. Defaults to 'blue'.
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/entity.md
|
||||
*/
|
||||
@ -14,5 +14,5 @@ export type EntityCardConfig = LovelaceCardConfig &
|
||||
EntitySharedConfig &
|
||||
AppearanceSharedConfig &
|
||||
ActionsSharedConfig & {
|
||||
icon_color?: string;
|
||||
};
|
||||
icon_color?: string;
|
||||
};
|
||||
|
@ -1,15 +1,15 @@
|
||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||
import { EntitySharedConfig } from '../shared/config/entity-config';
|
||||
|
||||
/**
|
||||
* Fan Card Config.
|
||||
* Fan Card Configuration
|
||||
*
|
||||
* @property {boolean} [icon_animation=false] Animate the icon when fan is on.
|
||||
* @property {boolean} [show_percentage_control=false] Show a slider to control speed.
|
||||
* @property {boolean} [show_oscillate_control=false] Show a button to control oscillation.
|
||||
* @property {boolean} [icon_animation=false] Animate the icon when fan is on.
|
||||
* @property {boolean} [icon_animation] - Animate the icon when the fan is on. Defaults to false.
|
||||
* @property {boolean} [show_percentage_control] - Show a slider to control speed. Defaults to false.
|
||||
* @property {boolean} [show_oscillate_control] - Show a button to control oscillation. Defaults to false.
|
||||
* @property {boolean} [show_direction_control] - Show a button to control the direction. Defaults to false.
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/fan.md
|
||||
*/
|
||||
@ -17,8 +17,8 @@ export type FanCardConfig = LovelaceCardConfig &
|
||||
EntitySharedConfig &
|
||||
AppearanceSharedConfig &
|
||||
ActionsSharedConfig & {
|
||||
icon_animation?: boolean;
|
||||
show_percentage_control?: boolean;
|
||||
show_oscillate_control?: boolean;
|
||||
collapsible_controls?: boolean;
|
||||
};
|
||||
icon_animation?: boolean;
|
||||
show_percentage_control?: boolean;
|
||||
show_oscillate_control?: boolean;
|
||||
show_direction_control?: boolean;
|
||||
};
|
||||
|
@ -1,18 +1,19 @@
|
||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||
import { EntitySharedConfig } from '../shared/config/entity-config';
|
||||
|
||||
/**
|
||||
* Light Card Config.
|
||||
* Light Card Configuration
|
||||
*
|
||||
* @property {string} [icon_color=blue] Custom color for icon and brightness bar when the lights are on and
|
||||
* use_light_color is false.
|
||||
* @property {boolean} [show_brightness_control=false] Show a slider to control brightness.
|
||||
* @property {boolean} [show_color_temp_control=false] Show a slider to control temperature color.
|
||||
* @property {boolean} [show_color_control=false] Show a slider to control RGB color.
|
||||
* @property {boolean} [collapsible_controls=false] Collapse controls when off.
|
||||
* @property {boolean} [use_light_color=false] Colorize the icon and slider according light temperature or color.
|
||||
* @property {string} [icon_color] - Custom color for icon and brightness bar when the lights are on and
|
||||
* `use_light_color` is false; Defaults to 'blue'.
|
||||
* @property {boolean} [show_brightness_control] - Show a slider to control brightness. Defaults to false.
|
||||
* @property {boolean} [show_color_temp_control] - Show a slider to control temperature color; Defaults to false.
|
||||
* @property {boolean} [show_color_control] - Show a slider to control RGB color. Defaults to false.
|
||||
* @property {boolean} [collapsible_controls] - Collapse controls when off; Defaults to false.
|
||||
* @property {boolean} [use_light_color] - Colorize the icon and slider according to light temperature or color.
|
||||
* Defaults to false.
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/light.md
|
||||
*/
|
||||
@ -20,10 +21,10 @@ export type LightCardConfig = LovelaceCardConfig &
|
||||
EntitySharedConfig &
|
||||
AppearanceSharedConfig &
|
||||
ActionsSharedConfig & {
|
||||
icon_color?: string;
|
||||
show_brightness_control?: boolean;
|
||||
show_color_temp_control?: boolean;
|
||||
show_color_control?: boolean;
|
||||
collapsible_controls?: boolean;
|
||||
use_light_color?: boolean;
|
||||
};
|
||||
icon_color?: string;
|
||||
show_brightness_control?: boolean;
|
||||
show_color_temp_control?: boolean;
|
||||
show_color_control?: boolean;
|
||||
collapsible_controls?: boolean;
|
||||
use_light_color?: boolean;
|
||||
};
|
||||
|
@ -1,14 +1,11 @@
|
||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||
import { EntitySharedConfig } from '../shared/config/entity-config';
|
||||
|
||||
/**
|
||||
* Lock Card Config.
|
||||
* Lock Card Configuration
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/lock.md
|
||||
*/
|
||||
export type LockCardConfig = LovelaceCardConfig &
|
||||
EntitySharedConfig &
|
||||
AppearanceSharedConfig &
|
||||
ActionsSharedConfig;
|
||||
export type LockCardConfig = LovelaceCardConfig & EntitySharedConfig & AppearanceSharedConfig & ActionsSharedConfig;
|
||||
|
@ -1,35 +1,37 @@
|
||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||
import { EntitySharedConfig } from '../shared/config/entity-config';
|
||||
|
||||
/** List of available media controls. */
|
||||
export const MEDIA_LAYER_MEDIA_CONTROLS = [
|
||||
"on_off",
|
||||
"shuffle",
|
||||
"previous",
|
||||
"play_pause_stop",
|
||||
"next",
|
||||
"repeat",
|
||||
'on_off',
|
||||
'shuffle',
|
||||
'previous',
|
||||
'play_pause_stop',
|
||||
'next',
|
||||
'repeat',
|
||||
] as const;
|
||||
|
||||
/** Represents a single media control option. */
|
||||
export type MediaPlayerMediaControl = (typeof MEDIA_LAYER_MEDIA_CONTROLS)[number];
|
||||
|
||||
export const MEDIA_PLAYER_VOLUME_CONTROLS = [
|
||||
"volume_mute",
|
||||
"volume_set",
|
||||
"volume_buttons",
|
||||
] as const;
|
||||
|
||||
/** List of available volume controls. */
|
||||
export const MEDIA_PLAYER_VOLUME_CONTROLS = ['volume_mute', 'volume_set', 'volume_buttons'] as const;
|
||||
/** Represents a single volume control option. */
|
||||
export type MediaPlayerVolumeControl = (typeof MEDIA_PLAYER_VOLUME_CONTROLS)[number];
|
||||
|
||||
/**
|
||||
* Media Player Card Config.
|
||||
* Media Player Card Configuration.
|
||||
*
|
||||
* @property {boolean} [use_media_info=false] Use media info instead of name, state, and icon when media is playing.
|
||||
* @property {boolean} [show_volume_level=false] Show volume level next to media state when media is playing.
|
||||
* @property {MediaPlayerVolumeControl[]} [volume_controls] List of controls to display (volume_mute, volume_set, volume_buttons)
|
||||
* @property {MediaPlayerMediaControl[]} [media_controls] List of controls to display (on_off, shuffle, previous, play_pause_stop, next, repeat)
|
||||
* @property {boolean} [collapsible_controls=false] Collapse controls when off
|
||||
* @property {boolean} [use_media_info] - Use media info instead of name, state, and icon when media is playing.
|
||||
* Defaults to false.
|
||||
* @property {boolean} [show_volume_level] - Show volume level next to media state when media is playing.
|
||||
* Defaults to false.
|
||||
* @property {MediaPlayerVolumeControl[]} [volume_controls] - List of controls to display.
|
||||
* (volume_mute, volume_set, volume_buttons)
|
||||
* @property {MediaPlayerMediaControl[]} [media_controls] - List of controls to display
|
||||
* (on_off, shuffle, previous, play_pause_stop, next, repeat)
|
||||
* @property {boolean} [collapsible_controls] - Collapse controls when off; Defaults to false.
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/media-player.md
|
||||
*/
|
||||
@ -37,9 +39,9 @@ export type MediaPlayerCardConfig = LovelaceCardConfig &
|
||||
EntitySharedConfig &
|
||||
AppearanceSharedConfig &
|
||||
ActionsSharedConfig & {
|
||||
use_media_info?: boolean;
|
||||
show_volume_level?: boolean;
|
||||
volume_controls?: MediaPlayerVolumeControl[];
|
||||
media_controls?: MediaPlayerMediaControl[];
|
||||
collapsible_controls?: boolean;
|
||||
};
|
||||
use_media_info?: boolean;
|
||||
show_volume_level?: boolean;
|
||||
volume_controls?: MediaPlayerVolumeControl[];
|
||||
media_controls?: MediaPlayerMediaControl[];
|
||||
collapsible_controls?: boolean;
|
||||
};
|
||||
|
@ -1,17 +1,17 @@
|
||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||
import { EntitySharedConfig } from '../shared/config/entity-config';
|
||||
|
||||
export const DISPLAY_MODES = ["slider", "buttons"] as const;
|
||||
export const DISPLAY_MODES = ['slider', 'buttons'] as const;
|
||||
|
||||
type DisplayMode = (typeof DISPLAY_MODES)[number];
|
||||
|
||||
/**
|
||||
* Number Card Config.
|
||||
* Number Card Configuration
|
||||
*
|
||||
* @property {string} [icon_color=blue] Custom color for icon when entity state is active.
|
||||
* @property {DisplayMode} [display_mode=slider] Slider or Button controls.
|
||||
* @property {string} [icon_color] - Custom color for the icon when the entity state is active. Defaults to 'blue'.
|
||||
* @property {DisplayMode} [display_mode] - Slider or Button controls. Defaults to 'slider'.
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/number.md
|
||||
*/
|
||||
@ -19,6 +19,6 @@ export type NumberCardConfig = LovelaceCardConfig &
|
||||
EntitySharedConfig &
|
||||
AppearanceSharedConfig &
|
||||
ActionsSharedConfig & {
|
||||
icon_color?: string;
|
||||
display_mode?: DisplayMode;
|
||||
};
|
||||
icon_color?: string;
|
||||
display_mode?: DisplayMode;
|
||||
};
|
||||
|
@ -1,14 +1,11 @@
|
||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||
import { EntitySharedConfig } from '../shared/config/entity-config';
|
||||
|
||||
/**
|
||||
* Person Card Config.
|
||||
* Person Card Configuration
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/person.md
|
||||
*/
|
||||
export type PersonCardConfig = LovelaceCardConfig &
|
||||
EntitySharedConfig &
|
||||
AppearanceSharedConfig &
|
||||
ActionsSharedConfig;
|
||||
export type PersonCardConfig = LovelaceCardConfig & EntitySharedConfig & AppearanceSharedConfig & ActionsSharedConfig;
|
||||
|
@ -1,12 +1,10 @@
|
||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||
import { EntitySharedConfig } from '../shared/config/entity-config';
|
||||
|
||||
/**
|
||||
* Select Card Config.
|
||||
*
|
||||
* @property {string} [icon_color=blue] Custom color for icon when entity state is active.
|
||||
* Select Card Configuration
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/select.md
|
||||
*/
|
||||
@ -14,5 +12,5 @@ export type SelectCardConfig = LovelaceCardConfig &
|
||||
EntitySharedConfig &
|
||||
AppearanceSharedConfig &
|
||||
ActionsSharedConfig & {
|
||||
icon_color?: string;
|
||||
};
|
||||
icon_color?: string;
|
||||
};
|
||||
|
@ -1,36 +1,35 @@
|
||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
||||
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||
|
||||
/**
|
||||
* Template Card Config.
|
||||
* Template Card Configuration
|
||||
*
|
||||
* @property {string} [entity]
|
||||
* @property {string} [icon] Icon to render. May contain templates.
|
||||
* @property {string} [icon_color] Icon color to render. May contain templates.
|
||||
* @property {string} [primary] Primary info to render. May contain templates.
|
||||
* @property {string} [secondary] Secondary info to render. May contain templates.
|
||||
* @property {string} [badge_icon] Badge icon to render. May contain templates.
|
||||
* @property {string} [badge_color] Badge icon color to render. May contain templates.
|
||||
* @property {string} [picture] Picture to render. May contain templates.
|
||||
* @property {boolean} [multiline_secondary] Enables support for multiline text for the secondary info.
|
||||
* @property {string | string[]} [entity_id] Only reacts to the state changes of these entities.
|
||||
* This can be used if the automatic analysis fails to find all relevant
|
||||
* entities.
|
||||
* @property {string} [entity] - Entity associated with the card.
|
||||
* @property {string} [icon] - Icon to render. May contain templates.
|
||||
* @property {string} [icon_color] - Icon color to render. May contain templates.
|
||||
* @property {string} [primary] - Primary info to render. May contain templates.
|
||||
* @property {string} [secondary] - Secondary info to render. May contain templates.
|
||||
* @property {string} [badge_icon] - Badge icon to render. May contain templates.
|
||||
* @property {string} [badge_color] - Badge icon color to render. May contain templates.
|
||||
* @property {string} [picture] - The picture to render. May contain templates.
|
||||
* @property {boolean} [multiline_secondary] - Enables support for multiline text for the secondary info.
|
||||
* @property {string | string[]} [entity_id] - Only reacts to the state changes of these entities. This can be used if
|
||||
* the automatic analysis fails to find all relevant entities.
|
||||
*
|
||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/template.md
|
||||
*/
|
||||
export type TemplateCardConfig = LovelaceCardConfig &
|
||||
AppearanceSharedConfig &
|
||||
ActionsSharedConfig & {
|
||||
entity?: string;
|
||||
icon?: string;
|
||||
icon_color?: string;
|
||||
primary?: string;
|
||||
secondary?: string;
|
||||
badge_icon?: string;
|
||||
badge_color?: string;
|
||||
picture?: string;
|
||||
multiline_secondary?: boolean;
|
||||
entity_id?: string | string[];
|
||||
};
|
||||
entity?: string;
|
||||
icon?: string;
|
||||
icon_color?: string;
|
||||
primary?: string;
|
||||
secondary?: string;
|
||||
badge_icon?: string;
|
||||
badge_color?: string;
|
||||
picture?: string;
|
||||
multiline_secondary?: boolean;
|
||||
entity_id?: string | string[];
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user