forked from DigiLive/mushroom-strategy
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
|
charset = utf-8
|
||||||
end_of_line = lf
|
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_size = 2
|
||||||
indent_style = space
|
indent_style = space
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
@ -15,444 +10,5 @@ max_line_length = 120
|
|||||||
tab_width = 2
|
tab_width = 2
|
||||||
trim_trailing_whitespace = true
|
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}]
|
[{*.markdown,*.md}]
|
||||||
ij_markdown_force_one_space_after_blockquote_symbol = true
|
trim_trailing_whitespace = false
|
||||||
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
|
|
||||||
|
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]
|
> [!NOTE]
|
||||||
> Follow the instructions inside the brackets and remove them.
|
> The above types do not apply to any translation itself.
|
||||||
> In the Title field above, Provide a succinct and descriptive title for the pull request, e.g., "Improve caching mechanism for API calls"
|
> 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
|
> [!CAUTION]
|
||||||
|
> Any Pull Request that does not follow the above types will be rejected.
|
||||||
[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.
|
|
||||||
|
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
|
name: HACS validation
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
jobs:
|
jobs:
|
||||||
hacs:
|
hacs:
|
||||||
name: HACS Action
|
name: HACS Action
|
||||||
|
58
.github/workflows/webpack.yml
vendored
58
.github/workflows/webpack.yml
vendored
@ -18,40 +18,40 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [18.x]
|
node-version: [ 18.x ]
|
||||||
|
|
||||||
# Checkout Repository
|
# Checkout Repository
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.WORKFLOW_GIT_ACCESS_TOKEN }}
|
token: ${{ secrets.WORKFLOW_GIT_ACCESS_TOKEN }}
|
||||||
|
|
||||||
# Build steps
|
# Build steps
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
- name: Node Install
|
- name: Node Install
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: Build Distribution
|
- name: Build Distribution
|
||||||
run: |
|
run: |
|
||||||
npm run build
|
npm run build
|
||||||
|
|
||||||
- name: Check for file changes
|
- name: Check for file changes
|
||||||
id: checkDiff
|
id: checkDiff
|
||||||
run: |
|
run: |
|
||||||
git diff --quiet . || echo "changed=true" >> $GITHUB_OUTPUT
|
git diff --quiet . || echo "changed=true" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
# Commit and push all changed files.
|
# Commit and push all changed files.
|
||||||
# Must only affect files that are listed in "paths-ignore".
|
# Must only affect files that are listed in "paths-ignore".
|
||||||
- name: GIT Commit Distribution Build
|
- name: GIT Commit Distribution Build
|
||||||
# Only run on main branch push (e.g., pull request merge).
|
# Only run on a main branch push (e.g., pull request merge).
|
||||||
if: github.event_name == 'push' && steps.checkDiff.outputs.changed == 'true'
|
if: github.event_name == 'push' && steps.checkDiff.outputs.changed == 'true'
|
||||||
run: |
|
run: |
|
||||||
git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}"
|
git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}"
|
||||||
git config --global user.email "ci_activity@noreply.github.com"
|
git config --global user.email "ci_activity@noreply.github.com"
|
||||||
git add dist
|
git add dist
|
||||||
git commit -m "${{ env.CI_COMMIT_MESSAGE }}"
|
git commit -m "${{ env.CI_COMMIT_MESSAGE }}"
|
||||||
git push
|
git push
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
/node_modules/
|
/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
|
## 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
|
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.
|
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
|
See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles
|
||||||
them.
|
them.
|
||||||
|
|
||||||
Please make sure to read the relevant section before making your contribution.
|
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.
|
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.
|
The community looks forward to your contributions.
|
||||||
|
|
||||||
> And if you like the project but just don't have time to contribute, that's fine.
|
> 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:
|
> 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
|
> - Star the project.
|
||||||
> - Refer this project at your project's readme
|
> - Tweet about it.
|
||||||
> - Mention the project at local meetups and tell your friends/colleagues
|
> - Refer to this project in the readme of your project.
|
||||||
> - Sponsor the project at GitHub Sponsors
|
> - Mention the project at local meetups and tell your friends/colleagues.
|
||||||
|
> - Sponsor the project at [GitHub Sponsors][sponsorUrl].
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
@ -43,9 +44,9 @@ By participating, you are expected to uphold this code. Please report unacceptab
|
|||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Before you ask a question, we assume that you have read the [README](README.md) file or the
|
> 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
|
that might
|
||||||
help you.
|
help you.
|
||||||
In case you have found a suitable topic and still need clarification, you can address your question in that topic.
|
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:
|
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 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.
|
- 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.
|
- 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
|
- 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)).
|
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
|
- 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).
|
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
|
- Also, make sure to search the internet (including Stack Overflow) to see if users outside the GitHub community have
|
||||||
discussed the issue.
|
discussed the issue.
|
||||||
- Collect information about the bug:
|
- Collect information about the bug:
|
||||||
- Stack trace (Traceback).
|
- 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.
|
- Possibly your input and the output.
|
||||||
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?
|
- 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]
|
> [!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.
|
> tracker, or elsewhere in public.
|
||||||
> Instead, sensitive bugs must be sent by email to a project leader.
|
> 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:
|
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.
|
- 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
|
- 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.
|
recreate the issue on their own. This usually includes your code.
|
||||||
@ -127,19 +128,19 @@ suggestions.
|
|||||||
#### Before Submitting an Enhancement
|
#### Before Submitting an Enhancement
|
||||||
|
|
||||||
- Make sure that you are using the latest version.
|
- 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
|
- Read the [Wiki][wikiUrl] carefully and find out if the functionality is already covered, maybe by an
|
||||||
individual
|
individual configuration.
|
||||||
configuration.
|
- Search the [issue tracker][issuesUrl] or [Pull Requests][pullRequestUrl] to see if the enhancement has already been
|
||||||
- Search the [issue tracker](../../issues) to see if the enhancement has already been suggested.
|
suggested.
|
||||||
If it has, add a comment to the existing issue instead of opening a new one.
|
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.
|
- 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.
|
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.
|
If you're just targeting a minority of users, consider writing an add-on/plugin library.
|
||||||
|
|
||||||
#### How Do I Submit a Good Enhancement Suggestion?
|
#### 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.
|
- 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.
|
- 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
|
## Attribution
|
||||||
|
|
||||||
This guide is based on the **contributing-gen**. [Make your own](https://github.com/bttger/contributing-gen)!
|
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
|
[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 -->
|
<!-- Repository References -->
|
||||||
|
|
||||||
[repositoryUrl]: https://github.com/DigiLive/mushroom-strategy
|
[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
|
[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",
|
"name": "Mushroom Dashboard Strategy ",
|
||||||
"render_readme": true,
|
"render_readme": true,
|
||||||
"filename": "mushroom-strategy.js"
|
"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",
|
"name": "mushroom-strategy",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"description": "Automatically create a dashboard using Mushroom cards",
|
"description": "Automatically generate a dashboard of Mushroom cards.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
"dashboard",
|
||||||
"strategy",
|
"strategy",
|
||||||
"mushroom"
|
"mushroom"
|
||||||
],
|
],
|
||||||
"homepage": "https://github.com/AalianKhan/mushroom-strategy",
|
"homepage": "https://github.com/DigiLive/mushroom-strategy",
|
||||||
"bugs": "https://github.com/AalianKhan/mushroom-strategy/issues",
|
"bugs": "https://github.com/DigiLive/mushroom-strategy/issues",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Aalian Khan"
|
"name": "Ferry Cools"
|
||||||
},
|
},
|
||||||
"contributors": [
|
"contributors": [
|
||||||
{
|
{
|
||||||
"name": "Ferry Cools"
|
"name": "Aalian Khan"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/DigiLive"
|
||||||
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/AalianKhan/mushroom-strategy"
|
"url": "https://github.com/DigiLive/mushroom-strategy"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"deepmerge": "^4"
|
"deepmerge": "^4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"home-assistant-js-websocket": "^9",
|
"@typescript-eslint/eslint-plugin": "^8.31.0",
|
||||||
"superstruct": "^1",
|
"@typescript-eslint/parser": "^8.31.0",
|
||||||
"ts-loader": "^9.5.0",
|
"eslint": "^9.25.1",
|
||||||
"ts-node": "^10",
|
"eslint-config-prettier": "^10.1.2",
|
||||||
"typescript": "^5",
|
"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",
|
"version-bump-prompt": "^6",
|
||||||
"webpack": "^5.96.1",
|
"webpack": "^5.99.7",
|
||||||
"webpack-cli": "^5.1.4"
|
"webpack-cli": "^6.0.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build-dev": "webpack --config webpack.dev.config.ts",
|
"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 { Registry } from '../Registry';
|
||||||
import {cards} from "../types/strategy/cards";
|
import { LovelaceCardConfig } from '../types/homeassistant/data/lovelace/config/card';
|
||||||
import {generic} from "../types/strategy/generic";
|
import { AbstractCardConfig } from '../types/strategy/strategy-cards';
|
||||||
import {EntityCardConfig} from "../types/lovelace-mushroom/cards/entity-card-config";
|
import { RegistryEntry } from '../types/strategy/strategy-generics';
|
||||||
|
import { logMessage, lvlFatal } from '../utilities/debug';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract Card Class
|
* 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
|
* @remarks
|
||||||
* @abstract
|
* Before using this class, the Registry module must be initialized by calling {@link Registry.initialize}.
|
||||||
*/
|
*/
|
||||||
abstract class AbstractCard {
|
abstract class AbstractCard {
|
||||||
/**
|
/** The registry entry this card represents. */
|
||||||
* Entity to create the card for.
|
readonly entity: RegistryEntry;
|
||||||
*
|
|
||||||
* @type {generic.RegistryEntry}
|
|
||||||
*/
|
|
||||||
entity: generic.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 = {
|
protected configuration: LovelaceCardConfig = {
|
||||||
type: "custom:mushroom-entity-card",
|
type: 'custom:mushroom-entity-card',
|
||||||
icon: "mdi:help-circle",
|
icon: 'mdi:help-circle',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {generic.RegistryEntry} entity The hass entity to create a card for.
|
* @param {RegistryEntry} entity The registry entry to create a card configuration for.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
*
|
||||||
|
* @remarks
|
||||||
|
* Before this class can be used, the Registry module must be initialized by calling {@link Registry.initialize}.
|
||||||
*/
|
*/
|
||||||
protected constructor(entity: generic.RegistryEntry) {
|
protected constructor(entity: RegistryEntry) {
|
||||||
if (!Helper.isInitialized()) {
|
if (!Registry.initialized) {
|
||||||
throw new Error("The Helper module must be initialized before using this one.");
|
logMessage(lvlFatal, 'Registry not initialized!');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.entity = entity;
|
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 {
|
return {
|
||||||
...this.config,
|
...this.configuration,
|
||||||
entity: "entity_id" in this.entity ? this.entity.entity_id : undefined,
|
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 { AreaRegistryEntry } from '../types/homeassistant/data/area_registry';
|
||||||
import {cards} from "../types/strategy/cards";
|
import { TemplateCardConfig } from '../types/lovelace-mushroom/cards/template-card-config';
|
||||||
import {AreaRegistryEntry} from "../types/homeassistant/data/area_registry";
|
import AbstractCard from './AbstractCard';
|
||||||
import {TemplateCardConfig} from "../types/lovelace-mushroom/cards/template-card-config";
|
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
|
||||||
/**
|
/**
|
||||||
* Area Card Class
|
* Area Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for an entity of the area domain.
|
* Used to create card configuration for an entry of the HASS area registry.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class AreaCard extends AbstractCard {
|
class AreaCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): TemplateCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {TemplateCardConfig}
|
type: 'custom:mushroom-template-card',
|
||||||
* @private
|
primary: undefined,
|
||||||
*/
|
icon: 'mdi:floor-plan',
|
||||||
#defaultConfig: TemplateCardConfig = {
|
icon_color: 'blue',
|
||||||
type: "custom:mushroom-template-card",
|
tap_action: { action: 'navigate', navigation_path: '' },
|
||||||
primary: undefined,
|
hold_action: { action: 'none' },
|
||||||
icon: "mdi:floor-plan",
|
};
|
||||||
icon_color: "blue",
|
}
|
||||||
tap_action: {
|
|
||||||
action: "navigate",
|
|
||||||
navigation_path: "",
|
|
||||||
},
|
|
||||||
hold_action: {
|
|
||||||
action: "none",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {AreaRegistryEntry} area The area entity to create a card for.
|
* @param {AreaRegistryEntry} area The HASS area to create a card configuration for.
|
||||||
* @param {cards.TemplateCardOptions} [options={}] Options for the card.
|
* @param {TemplateCardConfig} [customConfiguration] Custom card configuration.
|
||||||
*
|
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(area: AreaRegistryEntry, options: cards.TemplateCardOptions = {}) {
|
constructor(area: AreaRegistryEntry, customConfiguration?: TemplateCardConfig) {
|
||||||
super(area);
|
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.
|
// Don't override the default card type if default is set in the strategy options.
|
||||||
if (options.type === "default") {
|
if (customConfig && customConfig.type === 'default') {
|
||||||
delete options.type;
|
customConfig = { ...customConfig, type: configuration.type };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the default configuration.
|
this.configuration = { ...this.configuration, ...configuration, ...customConfig };
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
// 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
|
* Sensor Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the binary_sensor domain.
|
* Used to create a card configuration to control an entity of the binary_sensor domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends SensorCard
|
|
||||||
*/
|
*/
|
||||||
class BinarySensorCard extends SensorCard {
|
class BinarySensorCard extends SensorCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): EntityCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {EntityCardConfig}
|
type: 'custom:mushroom-entity-card',
|
||||||
* @private
|
icon: 'mdi:power-cycle',
|
||||||
*/
|
icon_color: 'green',
|
||||||
#defaultConfig: EntityCardConfig = {
|
};
|
||||||
type: "custom:mushroom-entity-card",
|
}
|
||||||
icon: "mdi:power-cycle",
|
|
||||||
icon_color: "green",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.EntityCardOptions} [options={}] Options for the card.
|
* @param {EntityCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.EntityCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) {
|
||||||
super(entity);
|
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.
|
// 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
|
* Camera Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the camera domain.
|
* Used to create a card configuration to control an entity of the camera domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class CameraCard extends AbstractCard {
|
class CameraCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): PictureEntityCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {PictureEntityCardConfig}
|
entity: '',
|
||||||
* @private
|
type: 'picture-entity',
|
||||||
*/
|
show_name: false,
|
||||||
#defaultConfig: PictureEntityCardConfig = {
|
show_state: false,
|
||||||
entity: "",
|
camera_view: 'live',
|
||||||
type: "picture-entity",
|
};
|
||||||
show_name: false,
|
}
|
||||||
show_state: false,
|
|
||||||
camera_view: "live",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.PictureEntityCardOptions} [options={}] Options for the card.
|
* @param {PictureEntityCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.PictureEntityCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: PictureEntityCardConfig) {
|
||||||
super(entity);
|
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.
|
// 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
|
* Climate Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the climate domain.
|
* Used to create a card configuration to control an entity of the climate domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class ClimateCard extends AbstractCard {
|
class ClimateCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): ClimateCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {ClimateCardConfig}
|
type: 'custom:mushroom-climate-card',
|
||||||
* @private
|
icon: undefined,
|
||||||
*/
|
hvac_modes: ['off', 'cool', 'heat', 'fan_only'],
|
||||||
#defaultConfig: ClimateCardConfig = {
|
show_temperature_control: true,
|
||||||
type: "custom:mushroom-climate-card",
|
};
|
||||||
icon: undefined,
|
}
|
||||||
hvac_modes: [
|
|
||||||
"off",
|
|
||||||
"cool",
|
|
||||||
"heat",
|
|
||||||
"fan_only",
|
|
||||||
],
|
|
||||||
show_temperature_control: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.ClimateCardOptions} [options={}] Options for the card.
|
* @param {ClimateCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.ClimateCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: ClimateCardConfig) {
|
||||||
super(entity);
|
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.
|
// 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
|
* Cover Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the cover domain.
|
* Used to create a card configuration to control an entity of the cover domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class CoverCard extends AbstractCard {
|
class CoverCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): CoverCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {CoverCardConfig}
|
type: 'custom:mushroom-cover-card',
|
||||||
* @private
|
icon: undefined,
|
||||||
*/
|
show_buttons_control: true,
|
||||||
#defaultConfig: CoverCardConfig = {
|
show_position_control: true,
|
||||||
type: "custom:mushroom-cover-card",
|
show_tilt_position_control: true,
|
||||||
icon: undefined,
|
};
|
||||||
show_buttons_control: true,
|
}
|
||||||
show_position_control: true,
|
|
||||||
show_tilt_position_control: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.CoverCardOptions} [options={}] Options for the card.
|
* @param {CoverCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.CoverCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: CoverCardConfig) {
|
||||||
super(entity);
|
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.
|
// 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
|
* Fan Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the fan domain.
|
* Used to create a card configuration to control an entity of the fan domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class FanCard extends AbstractCard {
|
class FanCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): FanCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {FanCardConfig}
|
type: 'custom:mushroom-fan-card',
|
||||||
* @private
|
icon: undefined,
|
||||||
*/
|
show_percentage_control: true,
|
||||||
#defaultConfig: FanCardConfig = {
|
show_oscillate_control: true,
|
||||||
type: "custom:mushroom-fan-card",
|
icon_animation: true,
|
||||||
icon: undefined,
|
};
|
||||||
show_percentage_control: true,
|
}
|
||||||
show_oscillate_control: true,
|
|
||||||
icon_animation: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.FanCardOptions} [options={}] Options for the card.
|
* @param {FanCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.FanCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: FanCardConfig) {
|
||||||
super(entity);
|
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.
|
// 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
|
* HA Area Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for an entity of the area domain using the built-in type 'area'.
|
* Used to create card configuration for an entry of the HASS area registry.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class AreaCard extends AbstractCard {
|
class AreaCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): AreaCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {AreaCardConfig}
|
type: 'area',
|
||||||
* @private
|
area: '',
|
||||||
*/
|
};
|
||||||
#defaultConfig: AreaCardConfig = {
|
}
|
||||||
type: "area",
|
|
||||||
area: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {AreaRegistryEntry} area The area entity to create a card for.
|
* @param {AreaRegistryEntry} area The HASS entity to create a card configuration for.
|
||||||
* @param {cards.AreaCardOptions} [options={}] Options for the card.
|
* @param {AreaCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
|
constructor(area: AreaRegistryEntry, customConfiguration?: AreaCardConfig) {
|
||||||
constructor(area: AreaRegistryEntry, options: cards.AreaCardOptions = {}) {
|
|
||||||
super(area);
|
super(area);
|
||||||
|
|
||||||
// Initialize the default configuration.
|
// Initialize the default configuration.
|
||||||
this.#defaultConfig.area = area.area_id;
|
const configuration = AreaCard.getDefaultConfig();
|
||||||
this.#defaultConfig.navigation_path = this.#defaultConfig.area;
|
|
||||||
|
|
||||||
// Enforce the card type.
|
configuration.area = area.area_id;
|
||||||
delete options.type;
|
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";
|
// 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 { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||||
import {SelectCard} from './SelectCard';
|
import { SelectCardConfig } from '../types/lovelace-mushroom/cards/select-card-config';
|
||||||
|
import SelectCard from './SelectCard';
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported
|
|
||||||
/**
|
/**
|
||||||
* InputSelect Card Class
|
* InputSelect Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the input_select domain.
|
* Used to create a card configuration to control an entity of the input_select domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class InputSelectCard extends SelectCard {
|
class InputSelectCard extends SelectCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): SelectCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {SelectCardConfig}
|
type: 'custom:mushroom-select-card',
|
||||||
* @private
|
icon: undefined,
|
||||||
*/
|
};
|
||||||
#defaultConfig: SelectCardConfig = {
|
}
|
||||||
type: "custom:mushroom-select-card",
|
|
||||||
icon: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.InputSelectCardOptions} [options={}] Options for the card.
|
* @param {SelectCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.InputSelectCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: SelectCardConfig) {
|
||||||
super(entity);
|
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.
|
// 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
|
* Light Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the light domain.
|
* Used to create a card configuration to control an entity of the light domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class LightCard extends AbstractCard {
|
class LightCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): LightCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {LightCardConfig}
|
type: 'custom:mushroom-light-card',
|
||||||
* @private
|
icon: undefined,
|
||||||
*/
|
show_brightness_control: true,
|
||||||
#defaultConfig: LightCardConfig = {
|
show_color_control: true,
|
||||||
type: "custom:mushroom-light-card",
|
show_color_temp_control: true,
|
||||||
icon: undefined,
|
use_light_color: true,
|
||||||
show_brightness_control: true,
|
double_tap_action: {
|
||||||
show_color_control: true,
|
action: 'call-service',
|
||||||
show_color_temp_control: true,
|
perform_action: 'light.turn_on',
|
||||||
use_light_color: true,
|
target: {
|
||||||
double_tap_action: {
|
entity_id: undefined,
|
||||||
action: "call-service",
|
},
|
||||||
service: "light.turn_on",
|
data: {
|
||||||
target: {
|
rgb_color: [255, 255, 255],
|
||||||
entity_id: undefined,
|
},
|
||||||
},
|
},
|
||||||
data: {
|
};
|
||||||
rgb_color: [255, 255, 255],
|
}
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.LightCardOptions} [options={}] Options for the card.
|
* @param {LightCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.LightCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: LightCardConfig) {
|
||||||
super(entity);
|
super(entity);
|
||||||
|
|
||||||
// Set the target for double-tap action.
|
const configuration = LightCard.getDefaultConfig();
|
||||||
if (
|
|
||||||
isCallServiceActionConfig(this.#defaultConfig.double_tap_action)
|
if (isCallServiceActionConfig(configuration.double_tap_action)) {
|
||||||
&& isCallServiceActionTarget(this.#defaultConfig.double_tap_action.target)
|
configuration.double_tap_action.target = { entity_id: entity.entity_id };
|
||||||
) {
|
|
||||||
this.#defaultConfig.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.
|
// 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
|
* Lock Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the lock domain.
|
* Used to create a card configuration to control an entity of the lock domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class LockCard extends AbstractCard {
|
class LockCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): LockCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {LockCardConfig}
|
type: 'custom:mushroom-lock-card',
|
||||||
* @private
|
icon: undefined,
|
||||||
*/
|
};
|
||||||
#defaultConfig: LockCardConfig = {
|
}
|
||||||
type: "custom:mushroom-lock-card",
|
|
||||||
icon: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.LockCardOptions} [options={}] Options for the card.
|
* @param {LockCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.LockCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: LockCardConfig) {
|
||||||
super(entity);
|
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.
|
// 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
|
* Mediaplayer Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the media_player domain.
|
* Used to create a card configuration to control an entity of the media_player domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class MediaPlayerCard extends AbstractCard {
|
class MediaPlayerCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): MediaPlayerCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {MediaPlayerCardConfig}
|
type: 'custom:mushroom-media-player-card',
|
||||||
* @private
|
use_media_info: true,
|
||||||
*/
|
media_controls: ['on_off', 'play_pause_stop'],
|
||||||
#defaultConfig: MediaPlayerCardConfig = {
|
show_volume_level: true,
|
||||||
type: "custom:mushroom-media-player-card",
|
volume_controls: ['volume_mute', 'volume_set', 'volume_buttons'],
|
||||||
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.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.MediaPlayerCardOptions} [options={}] Options for the card.
|
* @param {MediaPlayerCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.MediaPlayerCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: MediaPlayerCardConfig) {
|
||||||
super(entity);
|
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 { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||||
import {cards} from "../types/strategy/cards";
|
import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config';
|
||||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
import AbstractCard from './AbstractCard';
|
||||||
import {EntityCardConfig} from "../types/lovelace-mushroom/cards/entity-card-config";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Miscellaneous Card Class
|
* Miscellaneous Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card an entity of any domain.
|
* Used to create a card configuration to control an entity of any domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class MiscellaneousCard extends AbstractCard {
|
class MiscellaneousCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): EntityCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {EntityCardConfig}
|
type: 'custom:mushroom-entity-card',
|
||||||
* @private
|
icon_color: 'blue-grey',
|
||||||
*/
|
};
|
||||||
#defaultConfig: EntityCardConfig = {
|
}
|
||||||
type: "custom:mushroom-entity-card",
|
|
||||||
icon_color: "blue-grey",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.EntityCardOptions} [options={}] Options for the card.
|
* @param {EntityCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.EntityCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) {
|
||||||
super(entity);
|
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";
|
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||||
import {cards} from "../types/strategy/cards";
|
|
||||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||||
import {NumberCardConfig} from "../types/lovelace-mushroom/cards/number-card-config";
|
import { NumberCardConfig } from '../types/lovelace-mushroom/cards/number-card-config';
|
||||||
|
import AbstractCard from './AbstractCard';
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported
|
|
||||||
/**
|
/**
|
||||||
* Number Card Class
|
* Number Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the number domain.
|
* Used to create a card configuration to control an entity of the number domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class NumberCard extends AbstractCard {
|
class NumberCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): NumberCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {NumberCardConfig}
|
type: 'custom:mushroom-number-card',
|
||||||
* @private
|
icon: undefined,
|
||||||
*/
|
};
|
||||||
#defaultConfig: NumberCardConfig = {
|
}
|
||||||
type: "custom:mushroom-number-card",
|
|
||||||
icon: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.NumberCardOptions} [options={}] Options for the card.
|
* @param {NumberCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.NumberCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: NumberCardConfig) {
|
||||||
super(entity);
|
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 { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||||
import {cards} from "../types/strategy/cards";
|
import { PersonCardConfig } from '../types/lovelace-mushroom/cards/person-card-config';
|
||||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
import AbstractCard from './AbstractCard';
|
||||||
import {PersonCardConfig} from "../types/lovelace-mushroom/cards/person-card-config";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Person Card Class
|
* Person Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for an entity of the Person domain.
|
* Used to create a card configuration to control an entity of the person domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class PersonCard extends AbstractCard {
|
class PersonCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): PersonCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {PersonCardConfig}
|
type: 'custom:mushroom-person-card',
|
||||||
* @private
|
layout: 'vertical',
|
||||||
*/
|
primary_info: 'none',
|
||||||
#defaultConfig: PersonCardConfig = {
|
secondary_info: 'none',
|
||||||
type: "custom:mushroom-person-card",
|
icon_type: 'entity-picture',
|
||||||
layout: "vertical",
|
};
|
||||||
primary_info: "none",
|
}
|
||||||
secondary_info: "none",
|
|
||||||
icon_type: "entity-picture",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.PersonCardOptions} [options={}] Options for the card.
|
* @param {PersonCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.PersonCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: PersonCardConfig) {
|
||||||
super(entity);
|
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.
|
// 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
|
* 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
|
* Supports Stateful scenes from https://github.com/hugobloem/stateful_scenes.
|
||||||
* @extends AbstractCard
|
* If the stateful scene entity is available, it will be used instead of the original scene entity.
|
||||||
*/
|
*/
|
||||||
class SceneCard extends AbstractCard {
|
class SceneCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): EntityCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {EntityCardConfig}
|
type: 'custom:mushroom-entity-card',
|
||||||
* @private
|
tap_action: {
|
||||||
*/
|
action: 'perform-action',
|
||||||
#defaultConfig: EntityCardConfig = {
|
perform_action: 'scene.turn_on',
|
||||||
type: "custom:mushroom-entity-card",
|
target: {},
|
||||||
icon: "mdi:palette",
|
|
||||||
icon_color: "blue",
|
|
||||||
tap_action: {
|
|
||||||
action: "call-service",
|
|
||||||
service: "scene.turn_on",
|
|
||||||
target: {
|
|
||||||
entity_id: undefined,
|
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.EntityCardOptions} [options={}] Options for the card.
|
* @param {EntityCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.EntityCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) {
|
||||||
super(entity);
|
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.
|
super(statefulScene ?? entity);
|
||||||
if (
|
|
||||||
isCallServiceActionConfig(this.#defaultConfig.tap_action)
|
// Stateful scene support.
|
||||||
&& isCallServiceActionTarget(this.#defaultConfig.tap_action.target)
|
if (statefulScene) {
|
||||||
) {
|
this.configuration = new SwitchCard(statefulScene).getCard();
|
||||||
this.#defaultConfig.tap_action.target.entity_id = entity.entity_id;
|
|
||||||
|
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";
|
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
|
||||||
import {cards} from "../types/strategy/cards";
|
|
||||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||||
import {SelectCardConfig} from "../types/lovelace-mushroom/cards/select-card-config";
|
import { SelectCardConfig } from '../types/lovelace-mushroom/cards/select-card-config';
|
||||||
|
import AbstractCard from './AbstractCard';
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols Class is dynamically imported
|
|
||||||
/**
|
/**
|
||||||
* Select Card Class
|
* Select Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the select domain.
|
* Used to create a card configuration to control an entity of the select domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class SelectCard extends AbstractCard {
|
class SelectCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): SelectCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {SelectCardConfig}
|
type: 'custom:mushroom-select-card',
|
||||||
* @private
|
icon: undefined,
|
||||||
*/
|
};
|
||||||
#defaultConfig: SelectCardConfig = {
|
}
|
||||||
type: "custom:mushroom-select-card",
|
|
||||||
icon: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.SelectCardOptions} [options={}] Options for the card.
|
* @param {SelectCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.SelectCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: SelectCardConfig) {
|
||||||
super(entity);
|
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 { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry';
|
||||||
import {cards} from "../types/strategy/cards";
|
import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config';
|
||||||
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
|
import AbstractCard from './AbstractCard';
|
||||||
import {EntityCardConfig} from "../types/lovelace-mushroom/cards/entity-card-config";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sensor Card Class
|
* Sensor Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the sensor domain.
|
* Used to create a card for controlling an entity of the sensor domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class SensorCard extends AbstractCard {
|
class SensorCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): EntityCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {EntityCardConfig}
|
type: 'custom:mushroom-entity-card',
|
||||||
* @private
|
icon: 'mdi:information',
|
||||||
*/
|
animate: true,
|
||||||
#defaultConfig: EntityCardConfig = {
|
line_color: 'green',
|
||||||
type: "custom:mushroom-entity-card",
|
};
|
||||||
icon: "mdi:information",
|
}
|
||||||
animate: true,
|
|
||||||
line_color: "green",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.EntityCardOptions} [options={}] Options for the card.
|
* @param {EntityCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.EntityCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) {
|
||||||
super(entity);
|
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.
|
// 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
|
* Switch Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the switch domain.
|
* Used to create a card configuration to control an entity of the switch domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class SwitchCard extends AbstractCard {
|
class SwitchCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): EntityCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {EntityCardConfig}
|
type: 'custom:mushroom-entity-card',
|
||||||
* @private
|
icon: undefined,
|
||||||
*/
|
tap_action: {
|
||||||
#defaultConfig: EntityCardConfig = {
|
action: 'toggle',
|
||||||
type: "custom:mushroom-entity-card",
|
},
|
||||||
icon: undefined,
|
};
|
||||||
tap_action: {
|
}
|
||||||
action: "toggle",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.EntityCardOptions} [options={}] Options for the card.
|
* @param {EntityCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.EntityCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) {
|
||||||
super(entity);
|
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.
|
// 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
|
* Vacuum Card Class
|
||||||
*
|
*
|
||||||
* Used to create a card for controlling an entity of the vacuum domain.
|
* Used to create a card configuration to control an entity of the vacuum domain.
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @extends AbstractCard
|
|
||||||
*/
|
*/
|
||||||
class VacuumCard extends AbstractCard {
|
class VacuumCard extends AbstractCard {
|
||||||
/**
|
/** Returns the default configuration object for the card. */
|
||||||
* Default configuration of the card.
|
static getDefaultConfig(): VacuumCardConfig {
|
||||||
*
|
return {
|
||||||
* @type {VacuumCardConfig}
|
type: 'custom:mushroom-vacuum-card',
|
||||||
* @private
|
icon: undefined,
|
||||||
*/
|
icon_animation: true,
|
||||||
#defaultConfig: VacuumCardConfig = {
|
commands: [...VACUUM_COMMANDS],
|
||||||
type: "custom:mushroom-vacuum-card",
|
tap_action: {
|
||||||
icon: undefined,
|
action: 'more-info',
|
||||||
icon_animation: true,
|
},
|
||||||
commands: [...VACUUM_COMMANDS],
|
};
|
||||||
tap_action: {
|
}
|
||||||
action: "more-info",
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
|
* @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for.
|
||||||
* @param {cards.VacuumCardOptions} [options={}] Options for the card.
|
* @param {VacuumCardConfig} [customConfiguration] Custom card configuration.
|
||||||
* @throws {Error} If the Helper module isn't initialized.
|
|
||||||
*/
|
*/
|
||||||
constructor(entity: EntityRegistryEntry, options: cards.VacuumCardOptions = {}) {
|
constructor(entity: EntityRegistryEntry, customConfiguration?: VacuumCardConfig) {
|
||||||
super(entity);
|
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 { Registry } from '../Registry';
|
||||||
import {LovelaceChipConfig} from "../types/lovelace-mushroom/utils/lovelace/chip/types";
|
import { LovelaceChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types';
|
||||||
import {Helper} from "../Helper";
|
import { logMessage, lvlFatal } from '../utilities/debug';
|
||||||
import {generic} from "../types/strategy/generic";
|
|
||||||
import isCallServiceActionConfig = generic.isCallServiceActionConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract Chip class.
|
|
||||||
*
|
|
||||||
* To create a new chip, extend this one.
|
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @abstract
|
|
||||||
*/
|
|
||||||
abstract class AbstractChip {
|
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.
|
* Configuration of the chip.
|
||||||
*
|
*
|
||||||
* @type {LovelaceChipConfig}
|
* Child classes should override this property to reflect their own card type and options.
|
||||||
*/
|
*/
|
||||||
config: LovelaceChipConfig = {
|
protected configuration: LovelaceChipConfig = {
|
||||||
type: "template"
|
// TODO: Check if this is correct vs custom:mushroom-template-badge. Also in child classes.
|
||||||
|
type: 'template',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Constructor.
|
* Class Constructor.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Before using this class, the Registry module must be initialized by calling {@link Registry.initialize}.
|
||||||
*/
|
*/
|
||||||
protected constructor() {
|
protected constructor() {
|
||||||
if (!Helper.isInitialized()) {
|
if (!Registry.initialized) {
|
||||||
throw new Error("The Helper module must be initialized before using this one.");
|
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 {
|
getChipConfiguration(): LovelaceChipConfig {
|
||||||
return this.config;
|
return this.configuration;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
// 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.
|
* 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 {
|
class ClimateChip extends AbstractChip {
|
||||||
/**
|
/** Returns the default configuration object for the chip. */
|
||||||
* Default configuration of the chip.
|
static getDefaultConfig(): TemplateChipConfig {
|
||||||
*
|
return {
|
||||||
* @type {TemplateChipConfig}
|
type: 'template',
|
||||||
*
|
icon: 'mdi:thermostat',
|
||||||
* @readonly
|
icon_color: 'orange',
|
||||||
* @private
|
content: Registry.getCountTemplate('climate', 'ne', 'off'),
|
||||||
*/
|
tap_action: {
|
||||||
readonly #defaultConfig: TemplateChipConfig = {
|
action: 'none',
|
||||||
type: "template",
|
},
|
||||||
icon: "mdi:thermostat",
|
hold_action: {
|
||||||
icon_color: "orange",
|
action: 'navigate',
|
||||||
content: Helper.getCountTemplate("climate", "ne", "off"),
|
navigation_path: 'climates',
|
||||||
tap_action: {
|
},
|
||||||
action: "none",
|
};
|
||||||
},
|
}
|
||||||
hold_action: {
|
|
||||||
action: "navigate",
|
|
||||||
navigation_path: "climates",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Constructor.
|
* Class Constructor.
|
||||||
*
|
*
|
||||||
* @param {chips.TemplateChipOptions} options The chip options.
|
* @param {TemplateChipConfig} [customConfiguration] Custom chip configuration.
|
||||||
*/
|
*/
|
||||||
constructor(options: chips.TemplateChipOptions = {}) {
|
constructor(customConfiguration?: TemplateChipConfig) {
|
||||||
super();
|
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.
|
// 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.
|
* 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 {
|
class CoverChip extends AbstractChip {
|
||||||
/**
|
/** Returns the default configuration object for the chip. */
|
||||||
* Default configuration of the chip.
|
static getDefaultConfig(): TemplateChipConfig {
|
||||||
*
|
return {
|
||||||
* @type {TemplateChipConfig}
|
type: 'template',
|
||||||
*
|
icon: 'mdi:window-open',
|
||||||
* @readonly
|
icon_color: 'cyan',
|
||||||
* @private
|
content: Registry.getCountTemplate('cover', 'search', '(open|opening|closing)'),
|
||||||
*/
|
tap_action: {
|
||||||
readonly #defaultConfig: TemplateChipConfig = {
|
action: 'none',
|
||||||
type: "template",
|
},
|
||||||
icon: "mdi:window-open",
|
hold_action: {
|
||||||
icon_color: "cyan",
|
action: 'navigate',
|
||||||
content: Helper.getCountTemplate("cover", "search", "(open|opening|closing)"),
|
navigation_path: 'covers',
|
||||||
tap_action: {
|
},
|
||||||
action: "none",
|
};
|
||||||
},
|
}
|
||||||
hold_action: {
|
|
||||||
action: "navigate",
|
|
||||||
navigation_path: "covers",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Constructor.
|
* Class Constructor.
|
||||||
*
|
*
|
||||||
* @param {chips.TemplateChipOptions} options The chip options.
|
* @param {TemplateChipConfig} [customConfiguration] Custom chip configuration.
|
||||||
*/
|
*/
|
||||||
constructor(options: chips.TemplateChipOptions = {}) {
|
constructor(customConfiguration?: TemplateChipConfig) {
|
||||||
super();
|
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.
|
// 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.
|
* 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 {
|
class FanChip extends AbstractChip {
|
||||||
/**
|
/** Returns the default configuration object for the chip. */
|
||||||
* Default configuration of the chip.
|
static getDefaultConfig(): TemplateChipConfig {
|
||||||
*
|
return {
|
||||||
* @type {TemplateChipConfig}
|
type: 'template',
|
||||||
*
|
icon: 'mdi:fan',
|
||||||
* @readonly
|
icon_color: 'green',
|
||||||
* @private
|
content: Registry.getCountTemplate('fan', 'eq', 'on'),
|
||||||
*/
|
tap_action: {
|
||||||
readonly #defaultConfig: TemplateChipConfig = {
|
action: 'perform-action',
|
||||||
type: "template",
|
perform_action: 'fan.turn_off',
|
||||||
icon: "mdi:fan",
|
target: {
|
||||||
icon_color: "green",
|
entity_id: new RegistryFilter(Registry.entities)
|
||||||
content: Helper.getCountTemplate("fan", "eq", "on"),
|
.whereDomain('fan')
|
||||||
tap_action: {
|
.getValuesByProperty('entity_id') as string[],
|
||||||
action: "call-service",
|
},
|
||||||
service: "fan.turn_off",
|
},
|
||||||
},
|
hold_action: {
|
||||||
hold_action: {
|
action: 'navigate',
|
||||||
action: "navigate",
|
navigation_path: 'fans',
|
||||||
navigation_path: "fans",
|
},
|
||||||
},
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Constructor.
|
* Class Constructor.
|
||||||
*
|
*
|
||||||
* @param {chips.TemplateChipOptions} options The chip options.
|
* @param {TemplateChipConfig} [customConfiguration] Custom chip configuration.
|
||||||
*/
|
*/
|
||||||
constructor(options: chips.TemplateChipOptions = {}) {
|
constructor(customConfiguration?: TemplateChipConfig) {
|
||||||
super();
|
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.
|
// 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.
|
* 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 {
|
class LightChip extends AbstractChip {
|
||||||
/**
|
/** Returns the default configuration object for the chip. */
|
||||||
* Default configuration of the chip.
|
static getDefaultConfig(): TemplateChipConfig {
|
||||||
*
|
return {
|
||||||
* @type {TemplateChipConfig}
|
type: 'template',
|
||||||
*
|
icon: 'mdi:lightbulb-group',
|
||||||
* @readonly
|
icon_color: 'amber',
|
||||||
* @private
|
content: Registry.getCountTemplate('light', 'eq', 'on'),
|
||||||
*/
|
tap_action: {
|
||||||
readonly #defaultConfig: TemplateChipConfig = {
|
action: 'perform-action',
|
||||||
type: "template",
|
perform_action: 'light.turn_off',
|
||||||
icon: "mdi:lightbulb-group",
|
target: {
|
||||||
icon_color: "amber",
|
entity_id: new RegistryFilter(Registry.entities)
|
||||||
content: Helper.getCountTemplate("light", "eq", "on"),
|
.whereDomain('light')
|
||||||
tap_action: {
|
.getValuesByProperty('entity_id') as string[],
|
||||||
action: "call-service",
|
},
|
||||||
service: "light.turn_off",
|
},
|
||||||
},
|
hold_action: {
|
||||||
hold_action: {
|
action: 'navigate',
|
||||||
action: "navigate",
|
navigation_path: 'lights',
|
||||||
navigation_path: "lights",
|
},
|
||||||
},
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Constructor.
|
* Class Constructor.
|
||||||
*
|
*
|
||||||
* @param {chips.TemplateChipOptions} options The chip options.
|
* @param {TemplateChipConfig} [customConfiguration] Custom chip configuration.
|
||||||
*/
|
*/
|
||||||
constructor(options: chips.TemplateChipOptions = {}) {
|
constructor(customConfiguration?: TemplateChipConfig) {
|
||||||
super();
|
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.
|
// 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.
|
* 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 {
|
class SwitchChip extends AbstractChip {
|
||||||
/**
|
/** Returns the default configuration object for the chip. */
|
||||||
* Default configuration of the chip.
|
static getDefaultConfig(): TemplateChipConfig {
|
||||||
*
|
return {
|
||||||
* @type {TemplateChipConfig}
|
type: 'template',
|
||||||
*
|
icon: 'mdi:dip-switch',
|
||||||
* @readonly
|
icon_color: 'blue',
|
||||||
* @private
|
content: Registry.getCountTemplate('switch', 'eq', 'on'),
|
||||||
*/
|
tap_action: {
|
||||||
readonly #defaultConfig: TemplateChipConfig = {
|
action: 'perform-action',
|
||||||
type: "template",
|
perform_action: 'switch.turn_off',
|
||||||
icon: "mdi:dip-switch",
|
target: {
|
||||||
icon_color: "blue",
|
entity_id: new RegistryFilter(Registry.entities)
|
||||||
content: Helper.getCountTemplate("switch", "eq", "on"),
|
.whereDomain('switch')
|
||||||
tap_action: {
|
.getValuesByProperty('entity_id') as string[],
|
||||||
action: "call-service",
|
},
|
||||||
service: "switch.turn_off",
|
},
|
||||||
},
|
hold_action: {
|
||||||
hold_action: {
|
action: 'navigate',
|
||||||
action: "navigate",
|
navigation_path: 'switches',
|
||||||
navigation_path: "switches",
|
},
|
||||||
},
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Constructor.
|
* Class Constructor.
|
||||||
*
|
*
|
||||||
* @param {chips.TemplateChipOptions} options The chip options.
|
* @param {TemplateChipConfig} [customConfiguration] Custom chip configuration.
|
||||||
*/
|
*/
|
||||||
constructor(options: chips.TemplateChipOptions = {}) {
|
constructor(customConfiguration?: TemplateChipConfig) {
|
||||||
super();
|
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.
|
// noinspection JSUnusedGlobalSymbols False positive.
|
||||||
|
|
||||||
|
import { WeatherChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types';
|
||||||
|
import AbstractChip from './AbstractChip';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Weather Chip class.
|
* 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 {
|
class WeatherChip extends AbstractChip {
|
||||||
/**
|
/** Returns the default configuration object for the chip. */
|
||||||
* Default configuration of the chip.
|
static getDefaultConfig(entityId: string): WeatherChipConfig {
|
||||||
*
|
return {
|
||||||
* @private
|
type: 'weather',
|
||||||
* @readonly
|
entity: entityId,
|
||||||
*/
|
show_temperature: true,
|
||||||
readonly #defaultConfig: WeatherChipConfig = {
|
show_conditions: true,
|
||||||
type: "weather",
|
};
|
||||||
show_temperature: true,
|
}
|
||||||
show_conditions: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Constructor.
|
* Class Constructor.
|
||||||
*
|
*
|
||||||
* @param {string} entityId Id of a weather entity.
|
* @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();
|
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 } from './types/strategy/strategy-generics';
|
||||||
import StrategyDefaults = generic.StrategyDefaults;
|
import { localize } from './utilities/localize';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default configuration for the mushroom strategy.
|
* Default configuration for the mushroom strategy.
|
||||||
*/
|
*/
|
||||||
export const getConfigurationDefaults = (localize: Function): StrategyDefaults => {
|
export const ConfigurationDefaults: StrategyDefaults = {
|
||||||
return {
|
areas: {
|
||||||
areas: {
|
undisclosed: {
|
||||||
undisclosed: {
|
// TODO: Refactor undisclosed to other.
|
||||||
area_id: "undisclosed",
|
aliases: [],
|
||||||
floor_id: null,
|
area_id: 'undisclosed',
|
||||||
name: "Undisclosed",
|
created_at: 0,
|
||||||
picture: null,
|
floor_id: null,
|
||||||
icon: "mdi:floor-plan",
|
hidden: false,
|
||||||
labels: [],
|
humidity_entity_id: null,
|
||||||
aliases: [],
|
icon: 'mdi:floor-plan',
|
||||||
hidden: false,
|
labels: [],
|
||||||
}
|
modified_at: 0,
|
||||||
|
name: localize('generic.undisclosed'),
|
||||||
|
picture: null,
|
||||||
|
temperature_entity_id: null,
|
||||||
},
|
},
|
||||||
debug: false,
|
},
|
||||||
domains: {
|
card_options: {},
|
||||||
_: {
|
chips: {
|
||||||
hide_config_entities: true,
|
// TODO: Make chips sortable.
|
||||||
hide_diagnostic_entities: true,
|
weather_entity: 'auto',
|
||||||
},
|
light_count: true,
|
||||||
default: {
|
fan_count: true,
|
||||||
title: localize("generic.miscellaneous"),
|
cover_count: true,
|
||||||
showControls: false,
|
switch_count: true,
|
||||||
hidden: false,
|
climate_count: true,
|
||||||
},
|
extra_chips: [],
|
||||||
light: {
|
},
|
||||||
title: localize("light.lights"),
|
debug: false,
|
||||||
showControls: true,
|
domains: {
|
||||||
iconOn: "mdi:lightbulb",
|
_: {
|
||||||
iconOff: "mdi:lightbulb-off",
|
hide_config_entities: undefined,
|
||||||
onService: "light.turn_on",
|
hide_diagnostic_entities: undefined,
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
home_view: {
|
binary_sensor: {
|
||||||
hidden: [],
|
title: `${localize('sensor.binary')} ` + localize('sensor.sensors'),
|
||||||
|
showControls: false,
|
||||||
|
hidden: false,
|
||||||
},
|
},
|
||||||
views: {
|
camera: {
|
||||||
home: {
|
title: localize('camera.cameras'),
|
||||||
order: 1,
|
showControls: false,
|
||||||
hidden: false,
|
hidden: false,
|
||||||
},
|
},
|
||||||
light: {
|
climate: {
|
||||||
order: 2,
|
title: localize('climate.climates'),
|
||||||
hidden: false,
|
showControls: false,
|
||||||
},
|
hidden: false,
|
||||||
fan: {
|
},
|
||||||
order: 3,
|
cover: {
|
||||||
hidden: false,
|
title: localize('cover.covers'),
|
||||||
},
|
showControls: true,
|
||||||
cover: {
|
iconOn: 'mdi:arrow-up',
|
||||||
order: 4,
|
iconOff: 'mdi:arrow-down',
|
||||||
hidden: false,
|
onService: 'cover.open_cover',
|
||||||
},
|
offService: 'cover.close_cover',
|
||||||
switch: {
|
hidden: false,
|
||||||
order: 5,
|
},
|
||||||
hidden: false,
|
default: {
|
||||||
},
|
title: localize('generic.miscellaneous'),
|
||||||
climate: {
|
showControls: false,
|
||||||
order: 6,
|
hidden: false,
|
||||||
hidden: false,
|
},
|
||||||
},
|
fan: {
|
||||||
camera: {
|
title: localize('fan.fans'),
|
||||||
order: 7,
|
showControls: true,
|
||||||
hidden: false,
|
iconOn: 'mdi:fan',
|
||||||
},
|
iconOff: 'mdi:fan-off',
|
||||||
vacuum: {
|
onService: 'fan.turn_on',
|
||||||
order: 8,
|
offService: 'fan.turn_off',
|
||||||
hidden: false,
|
hidden: false,
|
||||||
},
|
},
|
||||||
scene: {
|
input_select: {
|
||||||
order: 9,
|
title: localize('input_select.input_selects'),
|
||||||
hidden: false,
|
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 { HassServiceTarget } from 'home-assistant-js-websocket';
|
||||||
import {SensorCard} from "./cards/SensorCard";
|
import HeaderCard from './cards/HeaderCard';
|
||||||
import {ControllerCard} from "./cards/ControllerCard";
|
import SensorCard from './cards/SensorCard';
|
||||||
import {generic} from "./types/strategy/generic";
|
import { Registry } from './Registry';
|
||||||
import {LovelaceCardConfig, LovelaceConfig, LovelaceViewConfig} from "./types/homeassistant/data/lovelace";
|
import { LovelaceCardConfig } from './types/homeassistant/data/lovelace/config/card';
|
||||||
import {StackCardConfig} from "./types/homeassistant/lovelace/cards/types";
|
import { LovelaceConfig } from './types/homeassistant/data/lovelace/config/types';
|
||||||
import {EntityCardConfig} from "./types/lovelace-mushroom/cards/entity-card-config";
|
import { LovelaceViewConfig, LovelaceViewRawConfig } from './types/homeassistant/data/lovelace/config/view';
|
||||||
import {HassServiceTarget} from "home-assistant-js-websocket";
|
import {
|
||||||
import {applyEntityCategoryFilters} from "./utillties/filters";
|
DashboardInfo,
|
||||||
import StrategyArea = generic.StrategyArea;
|
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>
|
* Mushroom Dashboard Strategy.<br>
|
||||||
* <br>
|
* <br>
|
||||||
* Mushroom dashboard strategy provides a strategy for Home-Assistant to create a dashboard automatically.<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>
|
* The strategy makes use Mushroom and Mini Graph cards to represent your entities.
|
||||||
* <br>
|
*
|
||||||
* Features:<br>
|
* @see https://github.com/DigiLive/mushroom-strategy
|
||||||
* 🛠 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.
|
|
||||||
*/
|
*/
|
||||||
class MushroomStrategy extends HTMLTemplateElement {
|
class MushroomStrategy extends HTMLTemplateElement {
|
||||||
/**
|
/**
|
||||||
* Generate a dashboard.
|
* 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.
|
* @param {DashboardInfo} info Dashboard strategy information object.
|
||||||
* @return {Promise<LovelaceConfig>}
|
*
|
||||||
|
* @remarks
|
||||||
|
* Called when opening a dashboard.
|
||||||
*/
|
*/
|
||||||
static async generateDashboard(info: generic.DashBoardInfo): Promise<LovelaceConfig> {
|
static async generateDashboard(info: DashboardInfo): Promise<LovelaceConfig> {
|
||||||
await Helper.initialize(info);
|
await Registry.initialize(info);
|
||||||
|
|
||||||
// Create views.
|
const views: LovelaceViewRawConfig[] = [];
|
||||||
const views: LovelaceViewConfig[] = info.config?.views ?? [];
|
|
||||||
|
|
||||||
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.
|
if (viewConfiguration.cards.length) {
|
||||||
for (let viewId of Helper.getExposedViewIds()) {
|
return viewConfiguration;
|
||||||
try {
|
}
|
||||||
const viewType = Helper.sanitizeClassName(viewId + "View");
|
} catch (e) {
|
||||||
viewModule = await import(`./views/${viewType}`);
|
logMessage(lvlError, `Error importing ${viewName} view!`, e);
|
||||||
const view: LovelaceViewConfig = await new viewModule[viewType](Helper.strategyOptions.views[viewId]).getView();
|
|
||||||
|
|
||||||
if (view.cards?.length) {
|
|
||||||
views.push(view);
|
|
||||||
}
|
}
|
||||||
} 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.
|
return { views };
|
||||||
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,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a view.
|
* 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.
|
* @param {ViewInfo} info The view's strategy information object.
|
||||||
* @return {Promise<LovelaceViewConfig>}
|
*
|
||||||
|
* @remarks
|
||||||
|
* Called upon opening a subview.
|
||||||
*/
|
*/
|
||||||
static async generateView(info: generic.ViewInfo): Promise<LovelaceViewConfig> {
|
static async generateView(info: ViewInfo): Promise<LovelaceViewConfig> {
|
||||||
const exposedDomainIds = Helper.getExposedDomainIds();
|
const exposedDomainNames = Registry.getExposedNames('domain');
|
||||||
const area = info.view.strategy?.options?.area ?? {} as StrategyArea;
|
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 ?? [])];
|
const viewCards: LovelaceCardConfig[] = [...(area.extra_cards ?? [])];
|
||||||
|
|
||||||
// Set the target for controller cards to the current area.
|
// Set the target for any Header card to the current area.
|
||||||
let target: HassServiceTarget = {
|
const target: HassServiceTarget = { area_id: [area.area_id] };
|
||||||
area_id: [area.area_id],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create cards for each domain.
|
// Prepare promises for all supported domains
|
||||||
for (const domain of exposedDomainIds) {
|
const domainCardPromises = exposedDomainNames.filter(isSupportedDomain).map(async (domain) => {
|
||||||
if (domain === "default") {
|
const moduleName = sanitizeClassName(domain + 'Card');
|
||||||
continue;
|
|
||||||
|
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");
|
const titleCard = new HeaderCard(
|
||||||
|
{ entity_id: entities.map((entity) => entity.entity_id) },
|
||||||
let domainCards: EntityCardConfig[] = [];
|
Registry.strategyOptions.domains[domain],
|
||||||
|
).createCard();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
domainCards = await import(`./cards/${className}`).then(cardModule => {
|
const DomainCard = (await import(`./cards/${moduleName}`)).default;
|
||||||
let domainCards: EntityCardConfig[] = [];
|
|
||||||
let entities = Helper.getDeviceEntities(area, domain);
|
|
||||||
|
|
||||||
// Exclude hidden Config and Diagnostic entities.
|
if (domain === 'sensor') {
|
||||||
entities = applyEntityCategoryFilters(entities, domain);
|
const domainCards = entities
|
||||||
|
.filter((entity) => Registry.hassStates[entity.entity_id]?.attributes.unit_of_measurement)
|
||||||
// Set the target for controller cards to entities without an area.
|
.map((entity) => {
|
||||||
if (area.area_id === "undisclosed") {
|
const options = {
|
||||||
target = {
|
...(entity.device_id && Registry.strategyOptions.card_options?.[entity.device_id]),
|
||||||
entity_id: entities.map(entity => entity.entity_id),
|
...Registry.strategyOptions.card_options?.[entity.entity_id],
|
||||||
}
|
type: 'custom:mini-graph-card',
|
||||||
}
|
entities: [entity.entity_id],
|
||||||
|
};
|
||||||
if (entities.length) {
|
return new SensorCard(entity, options).getCard();
|
||||||
// Create a Controller card for the current domain.
|
});
|
||||||
const titleCard = new ControllerCard(
|
return domainCards.length ? { type: 'vertical-stack', cards: [titleCard, ...domainCards] } : null;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
viewCards.push({
|
let domainCards = entities.map((entity) => {
|
||||||
type: "vertical-stack",
|
const cardOptions = {
|
||||||
cards: miscellaneousCards,
|
...(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(
|
console.info(
|
||||||
"%c Mushroom Strategy %c ".concat(version, " "),
|
'%c Mushroom Strategy %c '.concat(version, ' '),
|
||||||
"color: white; background: coral; font-weight: 700;", "color: coral; background: white; font-weight: 700;"
|
'color: white; background: coral; font-weight: 700;',
|
||||||
|
'color: coral; background: white; font-weight: 700;',
|
||||||
);
|
);
|
||||||
|
@ -29,7 +29,10 @@
|
|||||||
"off": "Aus",
|
"off": "Aus",
|
||||||
"on": "Ein",
|
"on": "Ein",
|
||||||
"open": "Offen",
|
"open": "Offen",
|
||||||
"unclosed": "Nicht Geschlossen"
|
"unavailable": "Nicht verfügbar",
|
||||||
|
"unclosed": "Nicht Geschlossen",
|
||||||
|
"undisclosed": "Sonstiges",
|
||||||
|
"unknown": "Unbekannt"
|
||||||
},
|
},
|
||||||
"input_select": {
|
"input_select": {
|
||||||
"input_selects": "Auswahl-Eingaben"
|
"input_selects": "Auswahl-Eingaben"
|
||||||
@ -39,7 +42,10 @@
|
|||||||
"lights": "Leuchten"
|
"lights": "Leuchten"
|
||||||
},
|
},
|
||||||
"lock": {
|
"lock": {
|
||||||
"locks": "Schlösser"
|
"locked": "Gesperrt",
|
||||||
|
"all_locks": "Alle Schlösser",
|
||||||
|
"locks": "Schlösser",
|
||||||
|
"unlocked": "Entsperrt"
|
||||||
},
|
},
|
||||||
"media_player": {
|
"media_player": {
|
||||||
"media_players": "Wiedergabegeräte"
|
"media_players": "Wiedergabegeräte"
|
||||||
@ -61,5 +67,14 @@
|
|||||||
"vacuum": {
|
"vacuum": {
|
||||||
"all_vacuums": "Alle Staubsauger",
|
"all_vacuums": "Alle Staubsauger",
|
||||||
"vacuums": "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",
|
"off": "Off",
|
||||||
"on": "On",
|
"on": "On",
|
||||||
"open": "Open",
|
"open": "Open",
|
||||||
"unclosed": "Unclosed"
|
"unavailable": "Unavailable",
|
||||||
|
"unclosed": "Unclosed",
|
||||||
|
"undisclosed": "Other",
|
||||||
|
"unknown": "Unknown"
|
||||||
},
|
},
|
||||||
"input_select": {
|
"input_select": {
|
||||||
"input_selects": "Input Selects"
|
"input_selects": "Input Selects"
|
||||||
@ -39,10 +42,13 @@
|
|||||||
"lights": "Lights"
|
"lights": "Lights"
|
||||||
},
|
},
|
||||||
"lock": {
|
"lock": {
|
||||||
"locks": "Locks"
|
"all_locks": "All Locks",
|
||||||
|
"locked": "Locked",
|
||||||
|
"locks": "Locks",
|
||||||
|
"unlocked": "Unlocked"
|
||||||
},
|
},
|
||||||
"media_player": {
|
"media_player": {
|
||||||
"media_players": "Mediaplayers"
|
"media_players": "Media Players"
|
||||||
},
|
},
|
||||||
"scene": {
|
"scene": {
|
||||||
"scenes": "Scenes"
|
"scenes": "Scenes"
|
||||||
@ -61,5 +67,14 @@
|
|||||||
"vacuum": {
|
"vacuum": {
|
||||||
"all_vacuums": "All Vacuums",
|
"all_vacuums": "All Vacuums",
|
||||||
"vacuums": "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",
|
"off": "Apagado",
|
||||||
"on": "Encendido",
|
"on": "Encendido",
|
||||||
"open": "Abierto",
|
"open": "Abierto",
|
||||||
"unclosed": "Sin Cerrar"
|
"unavailable": "No Disponible",
|
||||||
|
"unclosed": "Sin Cerrar",
|
||||||
|
"undisclosed": "Varios",
|
||||||
|
"unknown": "Desconocido"
|
||||||
},
|
},
|
||||||
"input_select": {
|
"input_select": {
|
||||||
"input_selects": "Selecciones de Entrada"
|
"input_selects": "Selecciones de Entrada"
|
||||||
@ -39,11 +42,17 @@
|
|||||||
"lights": "Luces"
|
"lights": "Luces"
|
||||||
},
|
},
|
||||||
"lock": {
|
"lock": {
|
||||||
"locks": "Candados"
|
"all_locks": "Todas las Candados",
|
||||||
|
"locked": "Locked",
|
||||||
|
"locks": "Candados",
|
||||||
|
"unlocked": "Desbloqueado"
|
||||||
},
|
},
|
||||||
"media_player": {
|
"media_player": {
|
||||||
"media_players": "Reproductores Multimedia"
|
"media_players": "Reproductores Multimedia"
|
||||||
},
|
},
|
||||||
|
"scene": {
|
||||||
|
"scenes": "Scenas"
|
||||||
|
},
|
||||||
"select": {
|
"select": {
|
||||||
"selects": "Seleccionar"
|
"selects": "Seleccionar"
|
||||||
},
|
},
|
||||||
@ -58,5 +67,14 @@
|
|||||||
"vacuum": {
|
"vacuum": {
|
||||||
"all_vacuums": "Todas las Aspiradoras",
|
"all_vacuums": "Todas las Aspiradoras",
|
||||||
"vacuums": "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",
|
"all": "Alle",
|
||||||
"areas": "Ruimtes",
|
"areas": "Ruimtes",
|
||||||
"busy": "Bezig",
|
"busy": "Bezig",
|
||||||
"good_afternoon": "Goede middag",
|
"good_afternoon": "Goedemiddag",
|
||||||
"good_evening": "Goede avond",
|
"good_evening": "Goedeavond",
|
||||||
"good_morning": "Goede morgen",
|
"good_morning": "Goedemorgen",
|
||||||
"hello": "Hallo",
|
"hello": "Hallo",
|
||||||
"home": "Start",
|
"home": "Start",
|
||||||
"miscellaneous": "Overige",
|
"miscellaneous": "Overige",
|
||||||
@ -29,7 +29,10 @@
|
|||||||
"off": "Uit",
|
"off": "Uit",
|
||||||
"on": "Aan",
|
"on": "Aan",
|
||||||
"open": "Open",
|
"open": "Open",
|
||||||
"unclosed": "Ongesloten"
|
"unavailable": "Onbeschikbaar",
|
||||||
|
"unclosed": "Niet Gesloten",
|
||||||
|
"undisclosed": "Overige",
|
||||||
|
"unknown": "Onbekend"
|
||||||
},
|
},
|
||||||
"input_select": {
|
"input_select": {
|
||||||
"input_selects": "Lijsten"
|
"input_selects": "Lijsten"
|
||||||
@ -39,7 +42,10 @@
|
|||||||
"lights": "Lampen"
|
"lights": "Lampen"
|
||||||
},
|
},
|
||||||
"lock": {
|
"lock": {
|
||||||
"locks": "Sloten"
|
"all_locks": "Alle Sloten",
|
||||||
|
"locked": "Vergrendeld",
|
||||||
|
"locks": "Sloten",
|
||||||
|
"unlocked": "Ontgrendeld"
|
||||||
},
|
},
|
||||||
"media_player": {
|
"media_player": {
|
||||||
"media_players": "Mediaspelers"
|
"media_players": "Mediaspelers"
|
||||||
@ -61,5 +67,14 @@
|
|||||||
"vacuum": {
|
"vacuum": {
|
||||||
"all_vacuums": "Alle Afzuiging",
|
"all_vacuums": "Alle Afzuiging",
|
||||||
"vacuums": "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
|
The [Apache 2.0 License](https://github.com/home-assistant/frontend/blob/dev/LICENSE.md) applies to all files in this
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
Copyright 2023 Ferry Cools
|
Copyright 2023 Ferry Cools
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with 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[]} aliases - An array of aliases for the area.
|
||||||
* @property {string|null} floor_id The id of the area's floor.
|
* @property {string} area_id - The unique identifier for the area.
|
||||||
* @property {string} name Name of the area.
|
* @property {string|null} floor_id - The identifier for the area's floor, or null if not applicable.
|
||||||
* @property {string|null} picture URL to a picture that should be used instead of showing the domain icon.
|
* @property {string|null} humidity_entity_id - The identifier for the area's humidity sensor, or null if not
|
||||||
* @property {string|null} icon Icon to show.
|
* applicable.
|
||||||
* @property {string[]} labels Labels allow grouping elements irrespective of their physical location or type.
|
* @property {string|null} icon - The icon to display for the area, or null if not specified.
|
||||||
* @property {string[]} aliases Array of aliases of the area.
|
* @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;
|
area_id: string;
|
||||||
floor_id: string | null;
|
floor_id: string | null;
|
||||||
name: string;
|
humidity_entity_id: string | null;
|
||||||
picture: string | null;
|
|
||||||
icon: string | null;
|
icon: string | null;
|
||||||
labels: string[];
|
labels: string[];
|
||||||
aliases: string[];
|
name: string;
|
||||||
|
picture: string | null;
|
||||||
|
temperature_entity_id: string | null;
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,5 @@
|
|||||||
export const HVAC_MODES = [
|
/** Represents the available HVAC modes for climate control in Home Assistant. */
|
||||||
"auto",
|
export const HVAC_MODES = ['auto', 'heat_cool', 'heat', 'cool', 'dry', 'fan_only', 'off'] as const;
|
||||||
"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];
|
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} id - Unique identifier of the device (generated by Home Assistant).
|
||||||
* @property {string[]} config_entries
|
* @property {string[]} config_entries - Config entries linked to this device.
|
||||||
* @property {Array} connections
|
* @property {Record<string, (string | null)[]>} config_entries_subentries - Subentries for the config entries.
|
||||||
* @property {Array} identifiers
|
* @property {[string, string][]} connections - Tuples of (connection_type, connection identifier).
|
||||||
* @property {string | null} manufacturer
|
* @property {[string, string][]} identifiers - Set of (DOMAIN, identifier) tuples identifying the device.
|
||||||
* @property {string | null} model
|
* @property {string | null} manufacturer - The manufacturer of the device.
|
||||||
* @property {string | null} name
|
* @property {string | null} model - The model name of the device.
|
||||||
* @property {string | null} sw_version
|
* @property {string | null} model_id - The model identifier of the device.
|
||||||
* @property {string | null} hw_version
|
* @property {string | null} name - The name of the device.
|
||||||
* @property {string | null} serial_number
|
* @property {string[]} labels - Labels for the device.
|
||||||
* @property {string | null} via_device_id
|
* @property {string | null} sw_version - The firmware version of the device.
|
||||||
* @property {string} area_id The Area which the device is placed in.
|
* @property {string | null} hw_version - The hardware version of the device.
|
||||||
* @property {string | null} name_by_user
|
* @property {string | null} serial_number - The serial number of the device.
|
||||||
* @property {string[] | null} entry_type
|
* @property {string | null} via_device_id - Identifier of a device that routes messages to this device.
|
||||||
* @property {string | null} disabled_by Indicates by what this entity is disabled.
|
* @property {string | null} area_id - The area which the device is placed in.
|
||||||
* @property {string | null} configuration_url
|
* @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 {
|
export interface DeviceRegistryEntry {
|
||||||
id: string;
|
id: string;
|
||||||
config_entries: string[];
|
config_entries: string[];
|
||||||
connections: Array<[string, string]>;
|
config_entries_subentries: Record<string, (string | null)[]>;
|
||||||
identifiers: Array<[string, string]>;
|
connections: [string, string][];
|
||||||
|
identifiers: [string, string][];
|
||||||
manufacturer: string | null;
|
manufacturer: string | null;
|
||||||
model: string | null;
|
model: string | null;
|
||||||
|
model_id: string | null;
|
||||||
name: string | null;
|
name: string | null;
|
||||||
|
labels: string[];
|
||||||
sw_version: string | null;
|
sw_version: string | null;
|
||||||
hw_version: string | null;
|
hw_version: string | null;
|
||||||
serial_number: string | null;
|
serial_number: string | null;
|
||||||
via_device_id: string | null;
|
via_device_id: string | null;
|
||||||
area_id: string | null;
|
area_id: string | null;
|
||||||
name_by_user: string | null;
|
name_by_user: string | null;
|
||||||
entry_type: "service" | null;
|
entry_type: 'service' | null;
|
||||||
disabled_by: "user" | "integration" | "config_entry" | null;
|
disabled_by: 'user' | 'integration' | 'config_entry' | null;
|
||||||
configuration_url: string | 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 {
|
export interface EntityRegistryDisplayEntry {
|
||||||
entity_id: string;
|
entity_id: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
icon?: string;
|
||||||
device_id?: string;
|
device_id?: string;
|
||||||
area_id?: string;
|
area_id?: string;
|
||||||
|
labels: string[];
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
entity_category?: EntityCategory;
|
entity_category?: EntityCategory;
|
||||||
translation_key?: string;
|
translation_key?: string;
|
||||||
platform?: string;
|
platform?: string;
|
||||||
display_precision?: number;
|
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} id - The unique identifier for the entity.
|
||||||
* @property {string} entity_id The id of this entity.
|
* @property {string} entity_id - The ID of the entity.
|
||||||
* @property {string} name The name of this entity.
|
* @property {string | null} name - The name of the entity.
|
||||||
* @property {string | null} icon
|
* @property {string | null} icon - The icon associated with the entity.
|
||||||
* @property {string | null} platform
|
* @property {string | null} platform - The platform of the entity.
|
||||||
* @property {string | null} config_entry_id
|
* @property {string | null} config_entry_id - The ID of the config entry associated with the entity.
|
||||||
* @property {string | null} device_id The id of the device to which this entity is linked.
|
* @property {string | null} config_subentry_id - The ID of the config subentry associated with the entity.
|
||||||
* @property {string | null} area_id The id of the area to which this entity is linked.
|
* @property {string | null} device_id - The ID of the device linked to this entity.
|
||||||
* @property {string | null} disabled_by Indicates by what this entity is disabled.
|
* @property {string | null} area_id - The ID of the area linked to this entity.
|
||||||
* @property {Object} hidden_by Indicates by what this entity is hidden.
|
* @property {string[]} labels - Labels associated with the entity.
|
||||||
* @property {EntityCategory | null} entity_category
|
* @property {"user" | "device" | "integration" | "config_entry" | null} disabled_by - Indicates what disabled this
|
||||||
* @property {boolean} has_entity_name
|
* entity.
|
||||||
* @property {string} [original_name]
|
* @property {Exclude<EntityRegistryEntry["disabled_by"], "config_entry">} hidden_by - Indicates what hidden this
|
||||||
* @property {string} unique_id
|
* entity.
|
||||||
* @property {string} [translation_key]
|
* @property {EntityCategory | null} entity_category - The category of the entity.
|
||||||
* @property {EntityRegistryOptions | null} options
|
* @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 {
|
export interface EntityRegistryEntry {
|
||||||
id: string;
|
id: string;
|
||||||
entity_id: string;
|
entity_id: string;
|
||||||
name: string | null;
|
name: string | null;
|
||||||
icon: string | null;
|
icon: string | null;
|
||||||
platform: string;
|
platform: string | null;
|
||||||
config_entry_id: string | null;
|
config_entry_id: string | null;
|
||||||
|
config_subentry_id: string | null;
|
||||||
device_id: string | null;
|
device_id: string | null;
|
||||||
area_id: string | null;
|
area_id: string | null;
|
||||||
disabled_by: "user" | "device" | "integration" | "config_entry" | null;
|
labels: string[];
|
||||||
hidden_by: Exclude<EntityRegistryEntry["disabled_by"], "config_entry">;
|
disabled_by: 'user' | 'device' | 'integration' | 'config_entry' | null;
|
||||||
|
hidden_by: Exclude<EntityRegistryEntry['disabled_by'], 'config_entry'>;
|
||||||
entity_category: EntityCategory | null;
|
entity_category: EntityCategory | null;
|
||||||
has_entity_name: boolean;
|
has_entity_name: boolean;
|
||||||
original_name?: string;
|
original_name?: string;
|
||||||
unique_id: string;
|
unique_id: string;
|
||||||
translation_key?: string;
|
translation_key?: string;
|
||||||
options: EntityRegistryOptions | null;
|
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 {
|
export interface SensorEntityOptions {
|
||||||
display_precision?: number | null;
|
display_precision?: number | null;
|
||||||
suggested_display_precision?: number | null;
|
suggested_display_precision?: number | null;
|
||||||
unit_of_measurement?: string | 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 {
|
export interface LightEntityOptions {
|
||||||
favorite_colors?: LightColor[];
|
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 {
|
export interface NumberEntityOptions {
|
||||||
unit_of_measurement?: string | null;
|
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 {
|
export interface LockEntityOptions {
|
||||||
default_code?: string | null;
|
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 {
|
export interface WeatherEntityOptions {
|
||||||
precipitation_unit?: string | null;
|
precipitation_unit?: string | null;
|
||||||
pressure_unit?: string | null;
|
pressure_unit?: string | null;
|
||||||
@ -79,19 +146,40 @@ export interface WeatherEntityOptions {
|
|||||||
wind_speed_unit?: string | null;
|
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 {
|
export interface SwitchAsXEntityOptions {
|
||||||
entity_id: string;
|
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 {
|
export interface EntityRegistryOptions {
|
||||||
number?: NumberEntityOptions;
|
number?: NumberEntityOptions;
|
||||||
sensor?: SensorEntityOptions;
|
sensor?: SensorEntityOptions;
|
||||||
|
alarm_control_panel?: AlarmControlPanelEntityOptions;
|
||||||
lock?: LockEntityOptions;
|
lock?: LockEntityOptions;
|
||||||
weather?: WeatherEntityOptions;
|
weather?: WeatherEntityOptions;
|
||||||
light?: LightEntityOptions;
|
light?: LightEntityOptions;
|
||||||
switch_as_x?: SwitchAsXEntityOptions;
|
switch_as_x?: SwitchAsXEntityOptions;
|
||||||
conversation?: Record<string, unknown>;
|
conversation?: Record<string, unknown>;
|
||||||
"cloud.alexa"?: Record<string, unknown>;
|
'cloud.alexa'?: Record<string, unknown>;
|
||||||
"cloud.google_assistant"?: 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 =
|
export type LightColor =
|
||||||
| { color_temp_kelvin: number; }
|
| { color_temp_kelvin: number }
|
||||||
| { hs_color: [number, number]; }
|
| { hs_color: [number, number] }
|
||||||
| { rgb_color: [number, number, number]; }
|
| { rgb_color: [number, number, number] }
|
||||||
| { rgbw_color: [number, number, number, number]; }
|
| { rgbw_color: [number, number, number, number] }
|
||||||
| { rgbww_color: [number, 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 {
|
||||||
import {AreaRegistryEntry} from "./data/area_registry";
|
Auth,
|
||||||
import {DeviceRegistryEntry} from "./data/device_registry";
|
Connection,
|
||||||
import {EntityRegistryDisplayEntry} from "./data/entity_registry";
|
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 {
|
export interface Credential {
|
||||||
auth_provider_type: string;
|
auth_provider_type: string;
|
||||||
auth_provider_id: 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 {
|
export interface MFAModule {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
enabled: boolean;
|
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 {
|
export interface CurrentUser {
|
||||||
id: string;
|
id: string;
|
||||||
is_owner: boolean;
|
is_owner: boolean;
|
||||||
@ -23,6 +60,18 @@ export interface CurrentUser {
|
|||||||
mfa_modules: MFAModule[];
|
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> {
|
export interface PanelInfo<T = Record<string, any> | null> {
|
||||||
component_name: string;
|
component_name: string;
|
||||||
config: T;
|
config: T;
|
||||||
@ -32,64 +81,305 @@ export interface PanelInfo<T = Record<string, any> | null> {
|
|||||||
config_panel_domain?: string;
|
config_panel_domain?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the panels in Home Assistant.
|
||||||
|
*
|
||||||
|
* @property {Record<string, PanelInfo>} panels - The panel configurations.
|
||||||
|
*/
|
||||||
export interface Panels {
|
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 {
|
export interface Translation {
|
||||||
nativeName: string;
|
nativeName: string;
|
||||||
isRTL: boolean;
|
isRTL: boolean;
|
||||||
hash: string;
|
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 {
|
export interface TranslationMetadata {
|
||||||
fragments: string[];
|
fragments: string[];
|
||||||
translations: {
|
translations: Record<string, Translation>;
|
||||||
[lang: 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 {
|
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 {
|
export interface HomeAssistant {
|
||||||
auth: Auth & { external?: any };
|
auth: Auth & { external?: { [key: string]: any } };
|
||||||
connection: Connection;
|
connection: Connection;
|
||||||
connected: boolean;
|
connected: boolean;
|
||||||
states: HassEntities;
|
states: HassEntities;
|
||||||
entities: { [id: string]: EntityRegistryDisplayEntry };
|
entities: Record<string, EntityRegistryDisplayEntry>;
|
||||||
devices: { [id: string]: DeviceRegistryEntry };
|
devices: Record<string, DeviceRegistryEntry>;
|
||||||
areas: { [id: string]: AreaRegistryEntry };
|
areas: Record<string, AreaRegistryEntry>;
|
||||||
|
floors: Record<string, FloorRegistryEntry>;
|
||||||
services: HassServices;
|
services: HassServices;
|
||||||
config: HassConfig;
|
config: HassConfig;
|
||||||
themes: { [k: string]: any };
|
themes: Themes;
|
||||||
selectedTheme: { [k: string]: any } | null;
|
selectedTheme: ThemeSettings | null;
|
||||||
panels: Panels;
|
panels: Panels;
|
||||||
panelUrl: string;
|
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;
|
language: string;
|
||||||
// local stored language, keep that name for backward compatibility
|
|
||||||
selectedLanguage: string | null;
|
selectedLanguage: string | null;
|
||||||
locale: { [k: string]: any };
|
locale: FrontendLocaleData;
|
||||||
resources: Resources;
|
resources: Resources;
|
||||||
localize: Function;
|
localize: LocalizeFunc;
|
||||||
translationMetadata: TranslationMetadata;
|
translationMetadata: TranslationMetadata;
|
||||||
suspendWhenHidden: boolean;
|
suspendWhenHidden: boolean;
|
||||||
enableShortcuts: boolean;
|
enableShortcuts: boolean;
|
||||||
vibrate: boolean;
|
vibrate: boolean;
|
||||||
debugConnection: boolean;
|
debugConnection: boolean;
|
||||||
dockedSidebar: "docked" | "always_hidden" | "auto";
|
dockedSidebar: 'docked' | 'always_hidden' | 'auto';
|
||||||
defaultPanel: string;
|
defaultPanel: string;
|
||||||
moreInfoEntityId: string | null;
|
moreInfoEntityId: string | null;
|
||||||
user?: CurrentUser;
|
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>;
|
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 { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {LovelaceChipConfig} from "../utils/lovelace/chip/types";
|
import { LovelaceChipConfig } from '../utils/lovelace/chip/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chips Card Configuration
|
* Chips Card Configuration
|
||||||
*
|
*
|
||||||
* @param {LovelaceChipConfig[]} chips Chips Array
|
* @property {LovelaceChipConfig[]} chips - Array of chips to display.
|
||||||
* @param {string} [alignment=start] Chips alignment (end, center, justify), when empty default behavior is start.
|
* @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
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/chips.md
|
||||||
*/
|
*/
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import {HvacMode} from "../../homeassistant/data/climate";
|
import { HvacMode } from '../../homeassistant/data/climate';
|
||||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||||
import {ActionsSharedConfig} from "../shared/config/actions-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 {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 {HvacMode[]} [hvac_modes] - List of HVAC modes to display.
|
||||||
* @property {boolean} [collapsible_controls] Collapse controls when off.
|
* (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
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/climate.md
|
||||||
*/
|
*/
|
||||||
@ -17,7 +18,7 @@ export type ClimateCardConfig = LovelaceCardConfig &
|
|||||||
EntitySharedConfig &
|
EntitySharedConfig &
|
||||||
AppearanceSharedConfig &
|
AppearanceSharedConfig &
|
||||||
ActionsSharedConfig & {
|
ActionsSharedConfig & {
|
||||||
show_temperature_control?: boolean;
|
show_temperature_control?: boolean;
|
||||||
hvac_modes?: HvacMode[];
|
hvac_modes?: HvacMode[];
|
||||||
collapsible_controls?: boolean;
|
collapsible_controls?: boolean;
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
import { AppearanceSharedConfig } from '../shared/config/appearance-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_buttons_control] - Show buttons to open, close, and stop the cover. Defaults to false.
|
||||||
* @property {boolean} [show_position_control=false] Show a slider to control position of the cover.
|
* @property {boolean} [show_position_control] - Show a slider to control the position of the cover. Defaults to false.
|
||||||
* @property {boolean} [show_tilt_position_control=false] Show a slider to control tilt position of the cover.
|
* @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
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/cover.md
|
||||||
*/
|
*/
|
||||||
@ -16,7 +17,7 @@ export type CoverCardConfig = LovelaceCardConfig &
|
|||||||
EntitySharedConfig &
|
EntitySharedConfig &
|
||||||
AppearanceSharedConfig &
|
AppearanceSharedConfig &
|
||||||
ActionsSharedConfig & {
|
ActionsSharedConfig & {
|
||||||
show_buttons_control?: boolean;
|
show_buttons_control?: boolean;
|
||||||
show_position_control?: boolean;
|
show_position_control?: boolean;
|
||||||
show_tilt_position_control?: boolean;
|
show_tilt_position_control?: boolean;
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||||
import {ActionsSharedConfig} from "../shared/config/actions-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
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/entity.md
|
||||||
*/
|
*/
|
||||||
@ -14,5 +14,5 @@ export type EntityCardConfig = LovelaceCardConfig &
|
|||||||
EntitySharedConfig &
|
EntitySharedConfig &
|
||||||
AppearanceSharedConfig &
|
AppearanceSharedConfig &
|
||||||
ActionsSharedConfig & {
|
ActionsSharedConfig & {
|
||||||
icon_color?: string;
|
icon_color?: string;
|
||||||
};
|
};
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
import { AppearanceSharedConfig } from '../shared/config/appearance-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} [icon_animation] - Animate the icon when the fan is on. Defaults to false.
|
||||||
* @property {boolean} [show_percentage_control=false] Show a slider to control speed.
|
* @property {boolean} [show_percentage_control] - Show a slider to control speed. Defaults to false.
|
||||||
* @property {boolean} [show_oscillate_control=false] Show a button to control oscillation.
|
* @property {boolean} [show_oscillate_control] - Show a button to control oscillation. Defaults to false.
|
||||||
* @property {boolean} [icon_animation=false] Animate the icon when fan is on.
|
* @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
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/fan.md
|
||||||
*/
|
*/
|
||||||
@ -17,8 +17,8 @@ export type FanCardConfig = LovelaceCardConfig &
|
|||||||
EntitySharedConfig &
|
EntitySharedConfig &
|
||||||
AppearanceSharedConfig &
|
AppearanceSharedConfig &
|
||||||
ActionsSharedConfig & {
|
ActionsSharedConfig & {
|
||||||
icon_animation?: boolean;
|
icon_animation?: boolean;
|
||||||
show_percentage_control?: boolean;
|
show_percentage_control?: boolean;
|
||||||
show_oscillate_control?: boolean;
|
show_oscillate_control?: boolean;
|
||||||
collapsible_controls?: boolean;
|
show_direction_control?: boolean;
|
||||||
};
|
};
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
import { AppearanceSharedConfig } from '../shared/config/appearance-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
|
* @property {string} [icon_color] - Custom color for icon and brightness bar when the lights are on and
|
||||||
* use_light_color is false.
|
* `use_light_color` is false; Defaults to 'blue'.
|
||||||
* @property {boolean} [show_brightness_control=false] Show a slider to control brightness.
|
* @property {boolean} [show_brightness_control] - Show a slider to control brightness. Defaults to false.
|
||||||
* @property {boolean} [show_color_temp_control=false] Show a slider to control temperature color.
|
* @property {boolean} [show_color_temp_control] - Show a slider to control temperature color; Defaults to false.
|
||||||
* @property {boolean} [show_color_control=false] Show a slider to control RGB color.
|
* @property {boolean} [show_color_control] - Show a slider to control RGB color. Defaults to false.
|
||||||
* @property {boolean} [collapsible_controls=false] Collapse controls when off.
|
* @property {boolean} [collapsible_controls] - Collapse controls when off; Defaults to false.
|
||||||
* @property {boolean} [use_light_color=false] Colorize the icon and slider according light temperature or color.
|
* @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
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/light.md
|
||||||
*/
|
*/
|
||||||
@ -20,10 +21,10 @@ export type LightCardConfig = LovelaceCardConfig &
|
|||||||
EntitySharedConfig &
|
EntitySharedConfig &
|
||||||
AppearanceSharedConfig &
|
AppearanceSharedConfig &
|
||||||
ActionsSharedConfig & {
|
ActionsSharedConfig & {
|
||||||
icon_color?: string;
|
icon_color?: string;
|
||||||
show_brightness_control?: boolean;
|
show_brightness_control?: boolean;
|
||||||
show_color_temp_control?: boolean;
|
show_color_temp_control?: boolean;
|
||||||
show_color_control?: boolean;
|
show_color_control?: boolean;
|
||||||
collapsible_controls?: boolean;
|
collapsible_controls?: boolean;
|
||||||
use_light_color?: boolean;
|
use_light_color?: boolean;
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
import { AppearanceSharedConfig } from '../shared/config/appearance-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
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/lock.md
|
||||||
*/
|
*/
|
||||||
export type LockCardConfig = LovelaceCardConfig &
|
export type LockCardConfig = LovelaceCardConfig & EntitySharedConfig & AppearanceSharedConfig & ActionsSharedConfig;
|
||||||
EntitySharedConfig &
|
|
||||||
AppearanceSharedConfig &
|
|
||||||
ActionsSharedConfig;
|
|
||||||
|
@ -1,35 +1,37 @@
|
|||||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
import { AppearanceSharedConfig } from '../shared/config/appearance-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 = [
|
export const MEDIA_LAYER_MEDIA_CONTROLS = [
|
||||||
"on_off",
|
'on_off',
|
||||||
"shuffle",
|
'shuffle',
|
||||||
"previous",
|
'previous',
|
||||||
"play_pause_stop",
|
'play_pause_stop',
|
||||||
"next",
|
'next',
|
||||||
"repeat",
|
'repeat',
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
/** Represents a single media control option. */
|
||||||
export type MediaPlayerMediaControl = (typeof MEDIA_LAYER_MEDIA_CONTROLS)[number];
|
export type MediaPlayerMediaControl = (typeof MEDIA_LAYER_MEDIA_CONTROLS)[number];
|
||||||
|
/** List of available volume controls. */
|
||||||
export const MEDIA_PLAYER_VOLUME_CONTROLS = [
|
export const MEDIA_PLAYER_VOLUME_CONTROLS = ['volume_mute', 'volume_set', 'volume_buttons'] as const;
|
||||||
"volume_mute",
|
/** Represents a single volume control option. */
|
||||||
"volume_set",
|
|
||||||
"volume_buttons",
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export type MediaPlayerVolumeControl = (typeof MEDIA_PLAYER_VOLUME_CONTROLS)[number];
|
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} [use_media_info] - 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.
|
* Defaults to false.
|
||||||
* @property {MediaPlayerVolumeControl[]} [volume_controls] List of controls to display (volume_mute, volume_set, volume_buttons)
|
* @property {boolean} [show_volume_level] - Show volume level next to media state when media is playing.
|
||||||
* @property {MediaPlayerMediaControl[]} [media_controls] List of controls to display (on_off, shuffle, previous, play_pause_stop, next, repeat)
|
* Defaults to false.
|
||||||
* @property {boolean} [collapsible_controls=false] Collapse controls when off
|
* @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
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/media-player.md
|
||||||
*/
|
*/
|
||||||
@ -37,9 +39,9 @@ export type MediaPlayerCardConfig = LovelaceCardConfig &
|
|||||||
EntitySharedConfig &
|
EntitySharedConfig &
|
||||||
AppearanceSharedConfig &
|
AppearanceSharedConfig &
|
||||||
ActionsSharedConfig & {
|
ActionsSharedConfig & {
|
||||||
use_media_info?: boolean;
|
use_media_info?: boolean;
|
||||||
show_volume_level?: boolean;
|
show_volume_level?: boolean;
|
||||||
volume_controls?: MediaPlayerVolumeControl[];
|
volume_controls?: MediaPlayerVolumeControl[];
|
||||||
media_controls?: MediaPlayerMediaControl[];
|
media_controls?: MediaPlayerMediaControl[];
|
||||||
collapsible_controls?: boolean;
|
collapsible_controls?: boolean;
|
||||||
};
|
};
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
import { AppearanceSharedConfig } from '../shared/config/appearance-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];
|
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 {string} [icon_color] - Custom color for the icon when the entity state is active. Defaults to 'blue'.
|
||||||
* @property {DisplayMode} [display_mode=slider] Slider or Button controls.
|
* @property {DisplayMode} [display_mode] - Slider or Button controls. Defaults to 'slider'.
|
||||||
*
|
*
|
||||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/number.md
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/number.md
|
||||||
*/
|
*/
|
||||||
@ -19,6 +19,6 @@ export type NumberCardConfig = LovelaceCardConfig &
|
|||||||
EntitySharedConfig &
|
EntitySharedConfig &
|
||||||
AppearanceSharedConfig &
|
AppearanceSharedConfig &
|
||||||
ActionsSharedConfig & {
|
ActionsSharedConfig & {
|
||||||
icon_color?: string;
|
icon_color?: string;
|
||||||
display_mode?: DisplayMode;
|
display_mode?: DisplayMode;
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
import { AppearanceSharedConfig } from '../shared/config/appearance-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
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/person.md
|
||||||
*/
|
*/
|
||||||
export type PersonCardConfig = LovelaceCardConfig &
|
export type PersonCardConfig = LovelaceCardConfig & EntitySharedConfig & AppearanceSharedConfig & ActionsSharedConfig;
|
||||||
EntitySharedConfig &
|
|
||||||
AppearanceSharedConfig &
|
|
||||||
ActionsSharedConfig;
|
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||||
import {EntitySharedConfig} from "../shared/config/entity-config";
|
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
import { EntitySharedConfig } from '../shared/config/entity-config';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select Card Config.
|
* Select Card Configuration
|
||||||
*
|
|
||||||
* @property {string} [icon_color=blue] Custom color for icon when entity state is active.
|
|
||||||
*
|
*
|
||||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/select.md
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/select.md
|
||||||
*/
|
*/
|
||||||
@ -14,5 +12,5 @@ export type SelectCardConfig = LovelaceCardConfig &
|
|||||||
EntitySharedConfig &
|
EntitySharedConfig &
|
||||||
AppearanceSharedConfig &
|
AppearanceSharedConfig &
|
||||||
ActionsSharedConfig & {
|
ActionsSharedConfig & {
|
||||||
icon_color?: string;
|
icon_color?: string;
|
||||||
};
|
};
|
||||||
|
@ -1,36 +1,35 @@
|
|||||||
import {ActionsSharedConfig} from "../shared/config/actions-config";
|
import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card';
|
||||||
import {LovelaceCardConfig} from "../../homeassistant/data/lovelace";
|
import { ActionsSharedConfig } from '../shared/config/actions-config';
|
||||||
import {AppearanceSharedConfig} from "../shared/config/appearance-config";
|
import { AppearanceSharedConfig } from '../shared/config/appearance-config';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template Card Config.
|
* Template Card Configuration
|
||||||
*
|
*
|
||||||
* @property {string} [entity]
|
* @property {string} [entity] - Entity associated with the card.
|
||||||
* @property {string} [icon] Icon to render. May contain templates.
|
* @property {string} [icon] - Icon to render. May contain templates.
|
||||||
* @property {string} [icon_color] Icon color 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} [primary] - Primary info to render. May contain templates.
|
||||||
* @property {string} [secondary] Secondary 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_icon] - Badge icon to render. May contain templates.
|
||||||
* @property {string} [badge_color] Badge icon color 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 {string} [picture] - The picture to render. May contain templates.
|
||||||
* @property {boolean} [multiline_secondary] Enables support for multiline text for the secondary info.
|
* @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.
|
* @property {string | string[]} [entity_id] - Only reacts to the state changes of these entities. This can be used if
|
||||||
* This can be used if the automatic analysis fails to find all relevant
|
* the automatic analysis fails to find all relevant entities.
|
||||||
* entities.
|
|
||||||
*
|
*
|
||||||
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/template.md
|
* @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/template.md
|
||||||
*/
|
*/
|
||||||
export type TemplateCardConfig = LovelaceCardConfig &
|
export type TemplateCardConfig = LovelaceCardConfig &
|
||||||
AppearanceSharedConfig &
|
AppearanceSharedConfig &
|
||||||
ActionsSharedConfig & {
|
ActionsSharedConfig & {
|
||||||
entity?: string;
|
entity?: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
icon_color?: string;
|
icon_color?: string;
|
||||||
primary?: string;
|
primary?: string;
|
||||||
secondary?: string;
|
secondary?: string;
|
||||||
badge_icon?: string;
|
badge_icon?: string;
|
||||||
badge_color?: string;
|
badge_color?: string;
|
||||||
picture?: string;
|
picture?: string;
|
||||||
multiline_secondary?: boolean;
|
multiline_secondary?: boolean;
|
||||||
entity_id?: string | string[];
|
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