From d8bd57901e33a7057e26e782e295099ffcc0da89 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Wed, 6 Sep 2017 23:04:13 -0700 Subject: Removing webapp --- webapp/.babelrc | 7 - webapp/.eslintrc.json | 273 - webapp/Makefile | 59 - webapp/actions/admin_actions.jsx | 397 - webapp/actions/channel_actions.jsx | 413 - webapp/actions/diagnostics_actions.jsx | 24 - webapp/actions/emoji_actions.jsx | 72 - webapp/actions/file_actions.jsx | 93 - webapp/actions/global_actions.jsx | 626 - webapp/actions/integration_actions.jsx | 301 - webapp/actions/job_actions.jsx | 34 - webapp/actions/notification_actions.jsx | 132 - webapp/actions/oauth_actions.jsx | 21 - webapp/actions/post_actions.jsx | 357 - webapp/actions/status_actions.jsx | 128 - webapp/actions/team_actions.jsx | 200 - webapp/actions/user_actions.jsx | 839 - webapp/actions/webrtc_actions.jsx | 38 - webapp/actions/websocket_actions.jsx | 473 - webapp/client/web_websocket_client.jsx | 7 - webapp/client/websocket_client.jsx | 196 - webapp/components/about_build_modal.jsx | 213 - .../access_history_modal/access_history_modal.jsx | 109 - webapp/components/access_history_modal/index.js | 24 - .../activity_log_modal/activity_log_modal.jsx | 338 - webapp/components/activity_log_modal/index.js | 25 - .../add_users_to_team/add_users_to_team.jsx | 264 - webapp/components/add_users_to_team/index.js | 24 - webapp/components/admin_console/admin_console.jsx | 68 - .../admin_console/admin_navbar_dropdown.jsx | 223 - webapp/components/admin_console/admin_settings.jsx | 147 - webapp/components/admin_console/admin_sidebar.jsx | 702 - .../admin_console/admin_sidebar_category.jsx | 86 - .../admin_console/admin_sidebar_header.jsx | 69 - .../admin_console/admin_sidebar_section.jsx | 102 - webapp/components/admin_console/audits/audits.jsx | 101 - webapp/components/admin_console/audits/index.js | 27 - webapp/components/admin_console/banner.jsx | 39 - .../components/admin_console/boolean_setting.jsx | 99 - .../admin_console/brand_image_setting.jsx | 213 - .../admin_console/client_versions_settings.jsx | 169 - .../components/admin_console/cluster_settings.jsx | 273 - webapp/components/admin_console/cluster_table.jsx | 172 - .../admin_console/cluster_table_container.jsx | 72 - webapp/components/admin_console/color_setting.jsx | 119 - .../compliance_reports/compliance_reports.jsx | 394 - .../admin_console/compliance_reports/index.js | 46 - .../admin_console/compliance_settings.jsx | 126 - .../admin_console/configuration_settings.jsx | 356 - .../connection_security_dropdown_setting.jsx | 191 - .../admin_console/connection_settings.jsx | 87 - .../admin_console/custom_brand_settings.jsx | 156 - .../admin_console/custom_emoji_settings.jsx | 121 - .../admin_console/custom_integrations_settings.jsx | 197 - .../components/admin_console/database_settings.jsx | 238 - .../admin_console/developer_settings.jsx | 106 - .../components/admin_console/dropdown_setting.jsx | 66 - .../admin_console/elasticsearch_settings.jsx | 333 - .../admin_console/elasticsearch_status/index.js | 28 - .../admin_console/elasticsearch_status/status.jsx | 361 - .../email_authentication_settings.jsx | 102 - .../admin_console/email_connection_test.jsx | 130 - webapp/components/admin_console/email_settings.jsx | 395 - .../admin_console/external_service_settings.jsx | 66 - .../admin_console/file_upload_setting.jsx | 126 - .../components/admin_console/generated_setting.jsx | 106 - .../components/admin_console/gitlab_settings.jsx | 179 - webapp/components/admin_console/index.js | 27 - webapp/components/admin_console/ldap_settings.jsx | 504 - .../admin_console/legal_and_support_settings.jsx | 159 - .../components/admin_console/license_settings.jsx | 286 - .../admin_console/link_previews_settings.jsx | 64 - .../admin_console/localization_settings.jsx | 134 - webapp/components/admin_console/log_settings.jsx | 282 - .../admin_console/manage_roles_modal/index.js | 25 - .../manage_roles_modal/manage_roles_modal.jsx | 349 - .../manage_teams_modal/manage_teams_dropdown.jsx | 148 - .../manage_teams_modal/manage_teams_modal.jsx | 218 - .../manage_teams_modal/remove_from_team_button.jsx | 54 - .../admin_console/manage_tokens_modal/index.js | 27 - .../manage_tokens_modal/manage_tokens_modal.jsx | 181 - .../components/admin_console/metrics_settings.jsx | 94 - webapp/components/admin_console/mfa_settings.jsx | 97 - .../admin_console/multiselect_settings.jsx | 81 - .../admin_console/native_app_link_settings.jsx | 102 - webapp/components/admin_console/oauth_settings.jsx | 430 - .../components/admin_console/password_settings.jsx | 281 - .../admin_console/plugin_settings/index.js | 27 - .../plugin_settings/plugin_settings.jsx | 293 - .../components/admin_console/policy_settings.jsx | 413 - .../components/admin_console/post_edit_setting.jsx | 101 - .../components/admin_console/privacy_settings.jsx | 83 - .../admin_console/public_link_settings.jsx | 84 - webapp/components/admin_console/push_settings.jsx | 233 - webapp/components/admin_console/radio_setting.jsx | 65 - webapp/components/admin_console/rate_settings.jsx | 179 - .../admin_console/remove_file_setting.jsx | 62 - .../request_button/request_button.jsx | 262 - .../admin_console/reset_password_modal.jsx | 165 - .../admin_console/revoke_token_button/index.js | 24 - .../revoke_token_button/revoke_token_button.jsx | 56 - webapp/components/admin_console/saml_settings.jsx | 584 - webapp/components/admin_console/save_button.jsx | 64 - .../components/admin_console/server_logs/index.js | 27 - .../components/admin_console/server_logs/logs.jsx | 123 - .../components/admin_console/session_settings.jsx | 127 - webapp/components/admin_console/setting.jsx | 35 - webapp/components/admin_console/settings_group.jsx | 44 - .../components/admin_console/signup_settings.jsx | 117 - .../components/admin_console/storage_settings.jsx | 340 - .../components/admin_console/system_users/index.js | 31 - .../admin_console/system_users/system_users.jsx | 372 - .../system_users/system_users_dropdown.jsx | 529 - .../system_users/system_users_list.jsx | 295 - webapp/components/admin_console/text_setting.jsx | 88 - .../admin_console/users_and_teams_settings.jsx | 218 - .../components/admin_console/webrtc_settings.jsx | 218 - .../webserver_mode_dropdown_setting.jsx | 101 - webapp/components/analytics/doughnut_chart.jsx | 90 - webapp/components/analytics/line_chart.jsx | 121 - webapp/components/analytics/statistic_count.jsx | 35 - webapp/components/analytics/system_analytics.jsx | 492 - webapp/components/analytics/table_chart.jsx | 62 - .../components/analytics/team_analytics/index.js | 36 - .../analytics/team_analytics/team_analytics.jsx | 369 - .../announcement_bar/announcement_bar.jsx | 322 - webapp/components/announcement_bar/index.js | 16 - webapp/components/at_mention/at_mention.jsx | 100 - webapp/components/at_mention/index.jsx | 17 - webapp/components/audio_video_preview.jsx | 116 - webapp/components/audit_table.jsx | 644 - webapp/components/authorize.jsx | 156 - webapp/components/autosize_textarea.jsx | 102 - .../components/backstage/backstage_controller.jsx | 82 - .../backstage/components/backstage_category.jsx | 75 - .../backstage/components/backstage_header.jsx | 41 - .../backstage/components/backstage_list.jsx | 114 - .../backstage/components/backstage_navbar.jsx | 43 - .../backstage/components/backstage_section.jsx | 80 - .../backstage/components/backstage_sidebar.jsx | 149 - webapp/components/bootstrap_span.jsx | 22 - webapp/components/change_url_modal.jsx | 248 - webapp/components/channel_header.jsx | 952 - webapp/components/channel_info_modal.jsx | 156 - webapp/components/channel_invite_button.jsx | 73 - .../channel_invite_modal/channel_invite_modal.jsx | 195 - webapp/components/channel_invite_modal/index.js | 26 - .../channel_members_dropdown.jsx | 268 - .../components/channel_members_dropdown/index.js | 24 - webapp/components/channel_members_modal.jsx | 95 - webapp/components/channel_notifications_modal.jsx | 651 - webapp/components/channel_select.jsx | 116 - webapp/components/channel_view.jsx | 120 - webapp/components/claim/claim_controller.jsx | 61 - .../components/claim/components/email_to_ldap.jsx | 273 - .../components/claim/components/email_to_oauth.jsx | 178 - .../components/claim/components/ldap_to_email.jsx | 251 - .../components/claim/components/oauth_to_email.jsx | 147 - webapp/components/code_preview.jsx | 142 - webapp/components/common/comment_icon.jsx | 61 - webapp/components/confirm_modal.jsx | 164 - .../components/create_comment/create_comment.jsx | 629 - webapp/components/create_comment/index.js | 16 - webapp/components/create_post.jsx | 814 - .../create_team/components/display_name.jsx | 131 - .../components/create_team/components/team_url.jsx | 250 - .../create_team/create_team_controller.jsx | 96 - webapp/components/delete_channel_modal.jsx | 107 - webapp/components/delete_modal_trigger.jsx | 72 - webapp/components/delete_post_modal.jsx | 165 - webapp/components/do_verify_email.jsx | 81 - webapp/components/dot_menu/dot_menu.jsx | 241 - webapp/components/dot_menu/dot_menu_edit.jsx | 58 - webapp/components/dot_menu/dot_menu_flag.jsx | 83 - webapp/components/dot_menu/dot_menu_item.jsx | 119 - webapp/components/dot_menu/index.js | 27 - webapp/components/edit_channel_header_modal.jsx | 231 - webapp/components/edit_channel_purpose_modal.jsx | 188 - webapp/components/edit_post_modal.jsx | 312 - webapp/components/emoji/components/add_emoji.jsx | 316 - .../emoji/components/delete_emoji_modal.jsx | 50 - webapp/components/emoji/components/emoji_list.jsx | 228 - .../emoji/components/emoji_list_item.jsx | 103 - .../components/emoji_picker_category.jsx | 43 - .../emoji_picker/components/emoji_picker_item.jsx | 88 - .../components/emoji_picker_preview.jsx | 74 - webapp/components/emoji_picker/emoji_picker.jsx | 520 - .../emoji_picker/emoji_picker_container.jsx | 48 - .../emoji_picker/emoji_picker_overlay.jsx | 73 - webapp/components/error_page.jsx | 212 - webapp/components/file_attachment.jsx | 205 - .../file_attachment_list/file_attachment_list.jsx | 106 - webapp/components/file_attachment_list/index.js | 40 - webapp/components/file_info_preview.jsx | 75 - webapp/components/file_preview.jsx | 126 - webapp/components/file_upload.jsx | 430 - webapp/components/file_upload_overlay.jsx | 50 - webapp/components/filtered_user_list.jsx | 245 - webapp/components/form_error.jsx | 84 - .../components/get_android_app/get_android_app.jsx | 73 - webapp/components/get_ios_app/get_ios_app.jsx | 66 - webapp/components/get_link_modal.jsx | 139 - webapp/components/get_post_link_modal.jsx | 61 - webapp/components/get_public_link_modal.jsx | 76 - webapp/components/get_team_invite_link_modal.jsx | 59 - webapp/components/header_footer_template.jsx | 110 - webapp/components/help/components/attaching.jsx | 84 - webapp/components/help/components/commands.jsx | 77 - webapp/components/help/components/composing.jsx | 77 - webapp/components/help/components/formatting.jsx | 133 - webapp/components/help/components/mentioning.jsx | 79 - webapp/components/help/components/messaging.jsx | 78 - webapp/components/help/help_controller.jsx | 29 - .../components/abstract_incoming_webhook.jsx | 253 - .../components/abstract_outgoing_webhook.jsx | 483 - .../components/add_command/add_command.jsx | 615 - .../integrations/components/add_command/index.js | 25 - .../add_incoming_webhook/add_incoming_webhook.jsx | 68 - .../components/add_incoming_webhook/index.js | 25 - .../components/add_oauth_app/add_oauth_app.jsx | 441 - .../integrations/components/add_oauth_app/index.js | 25 - .../add_outgoing_webhook/add_outgoing_webhook.jsx | 69 - .../components/add_outgoing_webhook/index.js | 25 - .../commands_container/commands_container.jsx | 78 - .../components/commands_container/index.js | 29 - .../confirm_integration/confirm_integration.jsx | 258 - .../components/confirm_integration/index.js | 16 - .../integrations/components/delete_integration.jsx | 51 - .../components/edit_command/edit_command.jsx | 727 - .../integrations/components/edit_command/index.js | 31 - .../edit_incoming_webhook.jsx | 112 - .../components/edit_incoming_webhook/index.js | 30 - .../edit_outgoing_webhook.jsx | 169 - .../components/edit_outgoing_webhook/index.js | 30 - .../integrations/components/installed_command.jsx | 176 - .../components/installed_commands/index.js | 25 - .../installed_commands/installed_commands.jsx | 160 - .../components/installed_incoming_webhook.jsx | 147 - .../components/installed_incoming_webhooks.jsx | 178 - .../components/installed_oauth_app.jsx | 270 - .../components/installed_oauth_apps/index.js | 31 - .../installed_oauth_apps/installed_oauth_apps.jsx | 165 - .../components/installed_outgoing_webhook.jsx | 244 - .../components/installed_outgoing_webhooks.jsx | 182 - .../integrations/components/integration_option.jsx | 41 - .../integrations/components/integrations.jsx | 175 - webapp/components/invite_member_modal.jsx | 538 - webapp/components/leave_team_modal.jsx | 131 - webapp/components/loading_screen.jsx | 51 - webapp/components/logged_in.jsx | 156 - webapp/components/login/components/login_mfa.jsx | 95 - webapp/components/login/login_controller.jsx | 643 - webapp/components/markdown_image.jsx | 67 - webapp/components/member_list_channel/index.js | 24 - .../member_list_channel/member_list_channel.jsx | 173 - webapp/components/member_list_team/index.js | 24 - .../member_list_team/member_list_team.jsx | 168 - webapp/components/message_wrapper.jsx | 42 - webapp/components/mfa/components/confirm.jsx | 79 - webapp/components/mfa/components/setup.jsx | 156 - webapp/components/mfa/mfa_controller.jsx | 89 - .../modals/leave_private_channel_modal.jsx | 120 - webapp/components/more_channels/index.js | 24 - webapp/components/more_channels/more_channels.jsx | 206 - webapp/components/more_direct_channels/index.js | 25 - .../more_direct_channels/more_direct_channels.jsx | 345 - webapp/components/msg_typing.jsx | 99 - webapp/components/multiselect/multiselect.jsx | 271 - webapp/components/multiselect/multiselect_list.jsx | 171 - webapp/components/navbar.jsx | 936 - webapp/components/needs_team/index.js | 25 - webapp/components/needs_team/needs_team.jsx | 242 - webapp/components/new_channel_flow.jsx | 247 - webapp/components/new_channel_modal/index.js | 21 - .../new_channel_modal/new_channel_modal.jsx | 395 - webapp/components/notify_counts.jsx | 46 - webapp/components/password_reset_form.jsx | 131 - webapp/components/password_reset_send_link.jsx | 156 - webapp/components/pdf_preview.jsx | 178 - webapp/components/permalink_view.jsx | 105 - webapp/components/popover_list_members/index.js | 24 - .../popover_list_members/popover_list_members.jsx | 294 - webapp/components/post_deleted_modal.jsx | 71 - .../commented_on_files_message.jsx | 61 - .../post_view/commented_on_files_message/index.js | 36 - webapp/components/post_view/date_separator.jsx | 32 - .../failed_post_options/failed_post_options.jsx | 94 - .../post_view/failed_post_options/index.js | 24 - webapp/components/post_view/floating_timestamp.jsx | 53 - webapp/components/post_view/index.js | 54 - .../components/post_view/new_message_indicator.jsx | 72 - webapp/components/post_view/post/index.js | 34 - webapp/components/post_view/post/post.jsx | 300 - webapp/components/post_view/post_attachment.jsx | 359 - .../components/post_view/post_attachment_list.jsx | 41 - .../post_view/post_attachment_opengraph/index.js | 28 - .../post_attachment_opengraph.jsx | 328 - webapp/components/post_view/post_body/index.js | 30 - .../components/post_view/post_body/post_body.jsx | 200 - .../post_view/post_body_additional_content.jsx | 273 - webapp/components/post_view/post_flag_icon.jsx | 95 - webapp/components/post_view/post_header/index.js | 18 - .../post_view/post_header/post_header.jsx | 159 - webapp/components/post_view/post_image.jsx | 105 - webapp/components/post_view/post_info/index.js | 31 - .../components/post_view/post_info/post_info.jsx | 275 - webapp/components/post_view/post_list.jsx | 582 - .../post_view/post_message_view/index.js | 41 - .../post_message_view/post_message_view.jsx | 215 - .../post_message_view/system_message_helpers.jsx | 232 - webapp/components/post_view/post_time.jsx | 96 - webapp/components/post_view/reaction/index.js | 52 - webapp/components/post_view/reaction/reaction.jsx | 254 - webapp/components/post_view/reaction_list/index.js | 33 - .../post_view/reaction_list/reaction_list.jsx | 88 - .../post_view/scroll_to_bottom_arrows.jsx | 37 - webapp/components/profile_picture.jsx | 115 - webapp/components/profile_popover.jsx | 301 - webapp/components/quick_switch_modal/index.js | 15 - .../quick_switch_modal/quick_switch_modal.jsx | 330 - webapp/components/removed_from_channel_modal.jsx | 145 - webapp/components/rename_channel_modal.jsx | 344 - webapp/components/reset_status_modal/index.js | 34 - .../reset_status_modal/reset_status_modal.jsx | 142 - webapp/components/rhs_comment.jsx | 476 - webapp/components/rhs_header_post.jsx | 217 - webapp/components/rhs_root_post.jsx | 450 - webapp/components/rhs_thread/index.js | 37 - webapp/components/rhs_thread/rhs_thread.jsx | 473 - webapp/components/root.jsx | 147 - webapp/components/search_bar.jsx | 406 - webapp/components/search_results.jsx | 367 - webapp/components/search_results_header.jsx | 153 - webapp/components/search_results_item.jsx | 353 - webapp/components/searchable_channel_list.jsx | 218 - .../searchable_user_list/searchable_user_list.jsx | 250 - .../searchable_user_list_container.jsx | 74 - .../select_team/components/select_team_item.jsx | 80 - webapp/components/select_team/index.js | 24 - webapp/components/select_team/select_team.jsx | 242 - webapp/components/setting_item_max.jsx | 175 - webapp/components/setting_item_min.jsx | 73 - webapp/components/setting_picture.jsx | 222 - webapp/components/setting_upload.jsx | 129 - webapp/components/settings_sidebar.jsx | 69 - webapp/components/shortcuts_modal.jsx | 396 - webapp/components/should_verify_email.jsx | 117 - webapp/components/sidebar.jsx | 994 - webapp/components/sidebar_header.jsx | 132 - webapp/components/sidebar_header_dropdown.jsx | 643 - .../components/sidebar_header_dropdown_button.jsx | 49 - webapp/components/sidebar_right/index.js | 17 - webapp/components/sidebar_right/sidebar_right.jsx | 264 - webapp/components/sidebar_right_menu.jsx | 554 - .../components/signup/components/signup_email.jsx | 520 - .../components/signup/components/signup_ldap.jsx | 268 - webapp/components/signup/signup_controller.jsx | 375 - webapp/components/spinner_button.jsx | 46 - webapp/components/status_dropdown/index.jsx | 33 - .../components/status_dropdown/status_dropdown.jsx | 158 - webapp/components/status_icon.jsx | 51 - .../components/suggestion/at_mention_provider.jsx | 165 - .../suggestion/channel_mention_provider.jsx | 143 - webapp/components/suggestion/command_provider.jsx | 41 - webapp/components/suggestion/emoticon_provider.jsx | 131 - webapp/components/suggestion/provider.jsx | 38 - .../suggestion/search_channel_provider.jsx | 91 - .../suggestion/search_suggestion_list.jsx | 98 - .../components/suggestion/search_user_provider.jsx | 91 - webapp/components/suggestion/suggestion.jsx | 30 - webapp/components/suggestion/suggestion_box.jsx | 441 - webapp/components/suggestion/suggestion_list.jsx | 177 - .../suggestion/switch_channel_provider.jsx | 283 - .../components/suggestion/switch_team_provider.jsx | 96 - webapp/components/team_general_tab.jsx | 602 - webapp/components/team_import_tab.jsx | 227 - webapp/components/team_members_dropdown/index.js | 28 - .../team_members_dropdown.jsx | 398 - webapp/components/team_members_modal.jsx | 85 - webapp/components/team_settings.jsx | 81 - webapp/components/team_settings_modal.jsx | 133 - .../team_sidebar/components/team_button.jsx | 127 - webapp/components/team_sidebar/index.js | 24 - .../team_sidebar/team_sidebar_controller.jsx | 189 - webapp/components/textbox.jsx | 318 - webapp/components/toggle_modal_button.jsx | 82 - .../components/tutorial/tutorial_intro_screens.jsx | 331 - webapp/components/tutorial/tutorial_tip.jsx | 247 - webapp/components/tutorial/tutorial_view.jsx | 49 - webapp/components/unread_channel_indicator.jsx | 41 - webapp/components/user_list.jsx | 84 - webapp/components/user_list_row.jsx | 110 - webapp/components/user_profile.jsx | 121 - .../user_settings/custom_theme_chooser.jsx | 476 - .../desktop_notification_settings.jsx | 464 - .../user_settings/email_notification_setting.jsx | 262 - .../user_settings/import_theme_modal.jsx | 218 - .../components/user_settings/manage_languages.jsx | 135 - .../user_settings/premade_theme_chooser.jsx | 72 - webapp/components/user_settings/user_settings.jsx | 124 - .../user_settings/user_settings_advanced.jsx | 587 - .../user_settings/user_settings_display.jsx | 673 - .../user_settings/user_settings_general/index.js | 24 - .../user_settings_general.jsx | 1245 -- .../user_settings/user_settings_modal.jsx | 309 - .../user_settings/user_settings_notifications.jsx | 911 - .../user_settings/user_settings_security/index.js | 34 - .../user_settings_security.jsx | 1469 -- .../user_settings/user_settings_theme.jsx | 362 - webapp/components/view_image.jsx | 385 - webapp/components/view_image_popover_bar.jsx | 93 - .../components/webrtc/components/webrtc_header.jsx | 102 - .../webrtc/components/webrtc_notification.jsx | 319 - .../webrtc/components/webrtc_sidebar.jsx | 136 - webapp/components/webrtc/webrtc_controller.jsx | 1244 -- webapp/components/youtube_video/index.js | 16 - webapp/components/youtube_video/youtube_video.jsx | 245 - webapp/config/manifest.json | 49 - webapp/dispatcher/app_dispatcher.jsx | 35 - webapp/fonts/FontAwesome.otf | Bin 93888 -> 0 bytes webapp/fonts/fontawesome-webfont.eot | Bin 60767 -> 0 bytes webapp/fonts/fontawesome-webfont.svg | 565 - webapp/fonts/fontawesome-webfont.ttf | Bin 122092 -> 0 bytes webapp/fonts/fontawesome-webfont.woff | Bin 71508 -> 0 bytes webapp/fonts/fontawesome-webfont.woff2 | Bin 56780 -> 0 bytes webapp/fonts/generator_config.txt | 5 - webapp/fonts/glyphicons-halflings-regular.eot | Bin 20127 -> 0 bytes webapp/fonts/glyphicons-halflings-regular.svg | 288 - webapp/fonts/glyphicons-halflings-regular.ttf | Bin 45404 -> 0 bytes webapp/fonts/glyphicons-halflings-regular.woff | Bin 23424 -> 0 bytes webapp/fonts/glyphicons-halflings-regular.woff2 | Bin 18028 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_AMS-Regular.eot | Bin 71656 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_AMS-Regular.ttf | Bin 71428 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_AMS-Regular.woff | Bin 40200 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_AMS-Regular.woff2 | Bin 33188 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Caligraphic-Bold.eot | Bin 19836 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Caligraphic-Bold.ttf | Bin 19588 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Caligraphic-Bold.woff | Bin 12136 -> 0 bytes .../fonts/ktexfonts/KaTeX_Caligraphic-Bold.woff2 | Bin 10604 -> 0 bytes .../fonts/ktexfonts/KaTeX_Caligraphic-Regular.eot | Bin 19220 -> 0 bytes .../fonts/ktexfonts/KaTeX_Caligraphic-Regular.ttf | Bin 18960 -> 0 bytes .../fonts/ktexfonts/KaTeX_Caligraphic-Regular.woff | Bin 11868 -> 0 bytes .../ktexfonts/KaTeX_Caligraphic-Regular.woff2 | Bin 10396 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Fraktur-Bold.eot | Bin 36200 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Fraktur-Bold.ttf | Bin 35968 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Fraktur-Bold.woff | Bin 23388 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Fraktur-Bold.woff2 | Bin 20476 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Fraktur-Regular.eot | Bin 34896 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Fraktur-Regular.ttf | Bin 34652 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Fraktur-Regular.woff | Bin 22844 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Fraktur-Regular.woff2 | Bin 19868 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Bold.eot | Bin 60688 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Bold.ttf | Bin 60468 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Bold.woff | Bin 35480 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Bold.woff2 | Bin 29492 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Italic.eot | Bin 44132 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Italic.ttf | Bin 43904 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Italic.woff | Bin 24880 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Italic.woff2 | Bin 21032 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Regular.eot | Bin 68228 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Regular.ttf | Bin 67996 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Regular.woff | Bin 37620 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Main-Regular.woff2 | Bin 31220 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-BoldItalic.eot | Bin 39990 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-BoldItalic.ttf | Bin 39744 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-BoldItalic.woff | Bin 23192 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-BoldItalic.woff2 | Bin 20036 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-Italic.eot | Bin 41676 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-Italic.ttf | Bin 41448 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-Italic.woff | Bin 23820 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-Italic.woff2 | Bin 20432 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-Regular.eot | Bin 41536 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-Regular.ttf | Bin 41304 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-Regular.woff | Bin 23712 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Math-Regular.woff2 | Bin 20344 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_SansSerif-Bold.eot | Bin 34204 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_SansSerif-Bold.ttf | Bin 33964 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_SansSerif-Bold.woff | Bin 19196 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_SansSerif-Bold.woff2 | Bin 16020 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_SansSerif-Italic.eot | Bin 31320 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_SansSerif-Italic.ttf | Bin 31072 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_SansSerif-Italic.woff | Bin 18080 -> 0 bytes .../fonts/ktexfonts/KaTeX_SansSerif-Italic.woff2 | Bin 15152 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_SansSerif-Regular.eot | Bin 30212 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_SansSerif-Regular.ttf | Bin 29960 -> 0 bytes .../fonts/ktexfonts/KaTeX_SansSerif-Regular.woff | Bin 16744 -> 0 bytes .../fonts/ktexfonts/KaTeX_SansSerif-Regular.woff2 | Bin 13908 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Script-Regular.eot | Bin 25104 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Script-Regular.ttf | Bin 24864 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Script-Regular.woff | Bin 13856 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Script-Regular.woff2 | Bin 12276 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size1-Regular.eot | Bin 13408 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size1-Regular.ttf | Bin 13172 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size1-Regular.woff | Bin 6980 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size1-Regular.woff2 | Bin 5820 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size2-Regular.eot | Bin 12648 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size2-Regular.ttf | Bin 12412 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size2-Regular.woff | Bin 6684 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size2-Regular.woff2 | Bin 5560 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size3-Regular.eot | Bin 8596 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size3-Regular.ttf | Bin 8360 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size3-Regular.woff | Bin 4776 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size3-Regular.woff2 | Bin 3856 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size4-Regular.eot | Bin 11520 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size4-Regular.ttf | Bin 11284 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size4-Regular.woff | Bin 6456 -> 0 bytes webapp/fonts/ktexfonts/KaTeX_Size4-Regular.woff2 | Bin 5172 -> 0 bytes .../fonts/ktexfonts/KaTeX_Typewriter-Regular.eot | Bin 35784 -> 0 bytes .../fonts/ktexfonts/KaTeX_Typewriter-Regular.ttf | Bin 35528 -> 0 bytes .../fonts/ktexfonts/KaTeX_Typewriter-Regular.woff | Bin 20712 -> 0 bytes .../fonts/ktexfonts/KaTeX_Typewriter-Regular.woff2 | Bin 17344 -> 0 bytes webapp/fonts/luximbi.ttf | Bin 69872 -> 0 bytes webapp/fonts/luxisr.ttf | Bin 67548 -> 0 bytes ...ext_greek-ext_greek_cyrillic_vietnamese-300.eot | Bin 99236 -> 0 bytes ...ext_greek-ext_greek_cyrillic_vietnamese-300.svg | 19026 ------------------ ...ext_greek-ext_greek_cyrillic_vietnamese-300.ttf | Bin 222412 -> 0 bytes ...xt_greek-ext_greek_cyrillic_vietnamese-300.woff | Bin 97924 -> 0 bytes ...t_greek-ext_greek_cyrillic_vietnamese-300.woff2 | Bin 63180 -> 0 bytes ...eek-ext_greek_cyrillic_vietnamese-300italic.eot | Bin 96135 -> 0 bytes ...eek-ext_greek_cyrillic_vietnamese-300italic.svg | 19039 ------------------ ...eek-ext_greek_cyrillic_vietnamese-300italic.ttf | Bin 213128 -> 0 bytes ...ek-ext_greek_cyrillic_vietnamese-300italic.woff | Bin 93872 -> 0 bytes ...k-ext_greek_cyrillic_vietnamese-300italic.woff2 | Bin 59176 -> 0 bytes ...ext_greek-ext_greek_cyrillic_vietnamese-600.eot | Bin 100579 -> 0 bytes ...ext_greek-ext_greek_cyrillic_vietnamese-600.svg | 19030 ------------------ ...ext_greek-ext_greek_cyrillic_vietnamese-600.ttf | Bin 221328 -> 0 bytes ...xt_greek-ext_greek_cyrillic_vietnamese-600.woff | Bin 98464 -> 0 bytes ...t_greek-ext_greek_cyrillic_vietnamese-600.woff2 | Bin 63736 -> 0 bytes ...eek-ext_greek_cyrillic_vietnamese-600italic.eot | Bin 98093 -> 0 bytes ...eek-ext_greek_cyrillic_vietnamese-600italic.svg | 19043 ------------------- ...eek-ext_greek_cyrillic_vietnamese-600italic.ttf | Bin 212820 -> 0 bytes ...ek-ext_greek_cyrillic_vietnamese-600italic.woff | Bin 94548 -> 0 bytes ...k-ext_greek_cyrillic_vietnamese-600italic.woff2 | Bin 60928 -> 0 bytes ..._greek-ext_greek_cyrillic_vietnamese-italic.eot | Bin 96859 -> 0 bytes ..._greek-ext_greek_cyrillic_vietnamese-italic.svg | 19043 ------------------- ..._greek-ext_greek_cyrillic_vietnamese-italic.ttf | Bin 212896 -> 0 bytes ...greek-ext_greek_cyrillic_vietnamese-italic.woff | Bin 93880 -> 0 bytes ...reek-ext_greek_cyrillic_vietnamese-italic.woff2 | Bin 59912 -> 0 bytes ...greek-ext_greek_cyrillic_vietnamese-regular.eot | Bin 98682 -> 0 bytes ...greek-ext_greek_cyrillic_vietnamese-regular.svg | 19030 ------------------ ...greek-ext_greek_cyrillic_vietnamese-regular.ttf | Bin 217360 -> 0 bytes ...reek-ext_greek_cyrillic_vietnamese-regular.woff | Bin 96116 -> 0 bytes ...eek-ext_greek_cyrillic_vietnamese-regular.woff2 | Bin 61980 -> 0 bytes webapp/i18n/de.json | 2708 --- webapp/i18n/en.json | 2737 --- webapp/i18n/es.json | 2708 --- webapp/i18n/fr.json | 2708 --- webapp/i18n/i18n.jsx | 208 - webapp/i18n/it.json | 2708 --- webapp/i18n/ja.json | 2708 --- webapp/i18n/ko.json | 2708 --- webapp/i18n/nl.json | 2708 --- webapp/i18n/pl.json | 2708 --- webapp/i18n/pt-BR.json | 2708 --- webapp/i18n/ru.json | 2708 --- webapp/i18n/tr.json | 2708 --- webapp/i18n/zh-CN.json | 2708 --- webapp/i18n/zh-TW.json | 2708 --- webapp/images/app-store-button.png | Bin 11277 -> 0 bytes webapp/images/appIcons.png | Bin 10107 -> 0 bytes webapp/images/arrow-left.png | Bin 3112 -> 0 bytes webapp/images/bing.mp3 | Bin 5760 -> 0 bytes .../bootstrap-colorpicker/alpha-horizontal.png | Bin 3635 -> 0 bytes webapp/images/bootstrap-colorpicker/alpha.png | Bin 3271 -> 0 bytes .../bootstrap-colorpicker/hue-horizontal.png | Bin 2837 -> 0 bytes webapp/images/bootstrap-colorpicker/hue.png | Bin 2972 -> 0 bytes webapp/images/bootstrap-colorpicker/saturation.png | Bin 8817 -> 0 bytes webapp/images/circles.png | Bin 3074 -> 0 bytes webapp/images/close.png | Bin 4353 -> 0 bytes webapp/images/closeSidebar.png | Bin 767 -> 0 bytes webapp/images/ding.mp3 | Bin 34734 -> 0 bytes webapp/images/emoji-sheets/activity.png | Bin 515396 -> 0 bytes webapp/images/emoji-sheets/custom.png | Bin 55365 -> 0 bytes webapp/images/emoji-sheets/flags.png | Bin 1068019 -> 0 bytes webapp/images/emoji-sheets/foods.png | Bin 590481 -> 0 bytes webapp/images/emoji-sheets/nature.png | Bin 1057998 -> 0 bytes webapp/images/emoji-sheets/objects.png | Bin 1080335 -> 0 bytes webapp/images/emoji-sheets/people.png | Bin 1845442 -> 0 bytes webapp/images/emoji-sheets/places.png | Bin 831107 -> 0 bytes webapp/images/emoji-sheets/symbols.png | Bin 982662 -> 0 bytes webapp/images/emoji/0023-fe0f-20e3.png | Bin 3402 -> 0 bytes webapp/images/emoji/002a-fe0f-20e3.png | Bin 3635 -> 0 bytes webapp/images/emoji/0030-fe0f-20e3.png | Bin 3269 -> 0 bytes webapp/images/emoji/0031-fe0f-20e3.png | Bin 2307 -> 0 bytes webapp/images/emoji/0032-fe0f-20e3.png | Bin 3039 -> 0 bytes webapp/images/emoji/0033-fe0f-20e3.png | Bin 3393 -> 0 bytes webapp/images/emoji/0034-fe0f-20e3.png | Bin 2765 -> 0 bytes webapp/images/emoji/0035-fe0f-20e3.png | Bin 3176 -> 0 bytes webapp/images/emoji/0036-fe0f-20e3.png | Bin 3488 -> 0 bytes webapp/images/emoji/0037-fe0f-20e3.png | Bin 2582 -> 0 bytes webapp/images/emoji/0038-fe0f-20e3.png | Bin 3552 -> 0 bytes webapp/images/emoji/0039-fe0f-20e3.png | Bin 3506 -> 0 bytes webapp/images/emoji/00a9-fe0f.png | Bin 2232 -> 0 bytes webapp/images/emoji/00ae-fe0f.png | Bin 2189 -> 0 bytes webapp/images/emoji/1f004-fe0f.png | Bin 4026 -> 0 bytes webapp/images/emoji/1f0cf.png | Bin 4534 -> 0 bytes webapp/images/emoji/1f170-fe0f.png | Bin 3100 -> 0 bytes webapp/images/emoji/1f171-fe0f.png | Bin 3001 -> 0 bytes webapp/images/emoji/1f17e-fe0f.png | Bin 3692 -> 0 bytes webapp/images/emoji/1f17f-fe0f.png | Bin 2412 -> 0 bytes webapp/images/emoji/1f18e.png | Bin 3779 -> 0 bytes webapp/images/emoji/1f191.png | Bin 3403 -> 0 bytes webapp/images/emoji/1f192.png | Bin 3923 -> 0 bytes webapp/images/emoji/1f193.png | Bin 3326 -> 0 bytes webapp/images/emoji/1f194.png | Bin 3255 -> 0 bytes webapp/images/emoji/1f195.png | Bin 3563 -> 0 bytes webapp/images/emoji/1f196.png | Bin 4067 -> 0 bytes webapp/images/emoji/1f197.png | Bin 4120 -> 0 bytes webapp/images/emoji/1f198.png | Bin 4775 -> 0 bytes webapp/images/emoji/1f199.png | Bin 3566 -> 0 bytes webapp/images/emoji/1f19a.png | Bin 3385 -> 0 bytes webapp/images/emoji/1f1e6-1f1e9.png | Bin 4065 -> 0 bytes webapp/images/emoji/1f1e6-1f1ea.png | Bin 3197 -> 0 bytes webapp/images/emoji/1f1e6-1f1eb.png | Bin 3523 -> 0 bytes webapp/images/emoji/1f1e6-1f1ec.png | Bin 4533 -> 0 bytes webapp/images/emoji/1f1e6-1f1ee.png | Bin 5158 -> 0 bytes webapp/images/emoji/1f1e6-1f1f1.png | Bin 4458 -> 0 bytes webapp/images/emoji/1f1e6-1f1f2.png | Bin 3674 -> 0 bytes webapp/images/emoji/1f1e6-1f1f4.png | Bin 3784 -> 0 bytes webapp/images/emoji/1f1e6-1f1f6.png | Bin 3461 -> 0 bytes webapp/images/emoji/1f1e6-1f1f7.png | Bin 4034 -> 0 bytes webapp/images/emoji/1f1e6-1f1f8.png | Bin 4730 -> 0 bytes webapp/images/emoji/1f1e6-1f1f9.png | Bin 3658 -> 0 bytes webapp/images/emoji/1f1e6-1f1fa.png | Bin 5631 -> 0 bytes webapp/images/emoji/1f1e6-1f1fc.png | Bin 4182 -> 0 bytes webapp/images/emoji/1f1e6-1f1fd.png | Bin 4321 -> 0 bytes webapp/images/emoji/1f1e6-1f1ff.png | Bin 4246 -> 0 bytes webapp/images/emoji/1f1e7-1f1e6.png | Bin 4058 -> 0 bytes webapp/images/emoji/1f1e7-1f1e7.png | Bin 3504 -> 0 bytes webapp/images/emoji/1f1e7-1f1e9.png | Bin 3516 -> 0 bytes webapp/images/emoji/1f1e7-1f1ea.png | Bin 2522 -> 0 bytes webapp/images/emoji/1f1e7-1f1eb.png | Bin 3603 -> 0 bytes webapp/images/emoji/1f1e7-1f1ec.png | Bin 3467 -> 0 bytes webapp/images/emoji/1f1e7-1f1ed.png | Bin 3481 -> 0 bytes webapp/images/emoji/1f1e7-1f1ee.png | Bin 5315 -> 0 bytes webapp/images/emoji/1f1e7-1f1ef.png | Bin 3037 -> 0 bytes webapp/images/emoji/1f1e7-1f1f1.png | Bin 4416 -> 0 bytes webapp/images/emoji/1f1e7-1f1f2.png | Bin 5551 -> 0 bytes webapp/images/emoji/1f1e7-1f1f3.png | Bin 5394 -> 0 bytes webapp/images/emoji/1f1e7-1f1f4.png | Bin 4088 -> 0 bytes webapp/images/emoji/1f1e7-1f1f6.png | Bin 3897 -> 0 bytes webapp/images/emoji/1f1e7-1f1f7.png | Bin 4869 -> 0 bytes webapp/images/emoji/1f1e7-1f1f8.png | Bin 4017 -> 0 bytes webapp/images/emoji/1f1e7-1f1f9.png | Bin 5149 -> 0 bytes webapp/images/emoji/1f1e7-1f1fc.png | Bin 4343 -> 0 bytes webapp/images/emoji/1f1e7-1f1fe.png | Bin 3422 -> 0 bytes webapp/images/emoji/1f1e7-1f1ff.png | Bin 5360 -> 0 bytes webapp/images/emoji/1f1e8-1f1e6.png | Bin 3311 -> 0 bytes webapp/images/emoji/1f1e8-1f1e8.png | Bin 3804 -> 0 bytes webapp/images/emoji/1f1e8-1f1e9.png | Bin 5154 -> 0 bytes webapp/images/emoji/1f1e8-1f1eb.png | Bin 4502 -> 0 bytes webapp/images/emoji/1f1e8-1f1ec.png | Bin 3752 -> 0 bytes webapp/images/emoji/1f1e8-1f1ed.png | Bin 2952 -> 0 bytes webapp/images/emoji/1f1e8-1f1ee.png | Bin 2703 -> 0 bytes webapp/images/emoji/1f1e8-1f1f0.png | Bin 5387 -> 0 bytes webapp/images/emoji/1f1e8-1f1f1.png | Bin 3484 -> 0 bytes webapp/images/emoji/1f1e8-1f1f2.png | Bin 3141 -> 0 bytes webapp/images/emoji/1f1e8-1f1f3.png | Bin 3265 -> 0 bytes webapp/images/emoji/1f1e8-1f1f4.png | Bin 3926 -> 0 bytes webapp/images/emoji/1f1e8-1f1f7.png | Bin 4591 -> 0 bytes webapp/images/emoji/1f1e8-1f1fa.png | Bin 5048 -> 0 bytes webapp/images/emoji/1f1e8-1f1fb.png | Bin 4829 -> 0 bytes webapp/images/emoji/1f1e8-1f1fc.png | Bin 4246 -> 0 bytes webapp/images/emoji/1f1e8-1f1fd.png | Bin 4239 -> 0 bytes webapp/images/emoji/1f1e8-1f1fe.png | Bin 3377 -> 0 bytes webapp/images/emoji/1f1e8-1f1ff.png | Bin 3529 -> 0 bytes webapp/images/emoji/1f1e9-1f1ea.png | Bin 2905 -> 0 bytes webapp/images/emoji/1f1e9-1f1ef.png | Bin 3967 -> 0 bytes webapp/images/emoji/1f1e9-1f1f0.png | Bin 4027 -> 0 bytes webapp/images/emoji/1f1e9-1f1f2.png | Bin 4986 -> 0 bytes webapp/images/emoji/1f1e9-1f1f4.png | Bin 4342 -> 0 bytes webapp/images/emoji/1f1e9-1f1ff.png | Bin 3726 -> 0 bytes webapp/images/emoji/1f1ea-1f1e8.png | Bin 4813 -> 0 bytes webapp/images/emoji/1f1ea-1f1ea.png | Bin 3616 -> 0 bytes webapp/images/emoji/1f1ea-1f1ec.png | Bin 3516 -> 0 bytes webapp/images/emoji/1f1ea-1f1ed.png | Bin 3591 -> 0 bytes webapp/images/emoji/1f1ea-1f1f7.png | Bin 4816 -> 0 bytes webapp/images/emoji/1f1ea-1f1f8.png | Bin 4480 -> 0 bytes webapp/images/emoji/1f1ea-1f1f9.png | Bin 4570 -> 0 bytes webapp/images/emoji/1f1ea-1f1fa.png | Bin 3486 -> 0 bytes webapp/images/emoji/1f1eb-1f1ee.png | Bin 3617 -> 0 bytes webapp/images/emoji/1f1eb-1f1ef.png | Bin 5569 -> 0 bytes webapp/images/emoji/1f1eb-1f1f0.png | Bin 5064 -> 0 bytes webapp/images/emoji/1f1eb-1f1f2.png | Bin 3168 -> 0 bytes webapp/images/emoji/1f1eb-1f1f4.png | Bin 4466 -> 0 bytes webapp/images/emoji/1f1eb-1f1f7.png | Bin 2701 -> 0 bytes webapp/images/emoji/1f1ec-1f1e6.png | Bin 3793 -> 0 bytes webapp/images/emoji/1f1ec-1f1e7.png | Bin 6330 -> 0 bytes webapp/images/emoji/1f1ec-1f1e9.png | Bin 4907 -> 0 bytes webapp/images/emoji/1f1ec-1f1ea.png | Bin 4663 -> 0 bytes webapp/images/emoji/1f1ec-1f1eb.png | Bin 3755 -> 0 bytes webapp/images/emoji/1f1ec-1f1ec.png | Bin 3659 -> 0 bytes webapp/images/emoji/1f1ec-1f1ed.png | Bin 3983 -> 0 bytes webapp/images/emoji/1f1ec-1f1ee.png | Bin 4085 -> 0 bytes webapp/images/emoji/1f1ec-1f1f1.png | Bin 3334 -> 0 bytes webapp/images/emoji/1f1ec-1f1f2.png | Bin 4394 -> 0 bytes webapp/images/emoji/1f1ec-1f1f3.png | Bin 2786 -> 0 bytes webapp/images/emoji/1f1ec-1f1f5.png | Bin 4209 -> 0 bytes webapp/images/emoji/1f1ec-1f1f6.png | Bin 4301 -> 0 bytes webapp/images/emoji/1f1ec-1f1f7.png | Bin 5263 -> 0 bytes webapp/images/emoji/1f1ec-1f1f8.png | Bin 5188 -> 0 bytes webapp/images/emoji/1f1ec-1f1f9.png | Bin 3517 -> 0 bytes webapp/images/emoji/1f1ec-1f1fa.png | Bin 3823 -> 0 bytes webapp/images/emoji/1f1ec-1f1fc.png | Bin 3481 -> 0 bytes webapp/images/emoji/1f1ec-1f1fe.png | Bin 5214 -> 0 bytes webapp/images/emoji/1f1ed-1f1f0.png | Bin 4031 -> 0 bytes webapp/images/emoji/1f1ed-1f1f3.png | Bin 4136 -> 0 bytes webapp/images/emoji/1f1ed-1f1f7.png | Bin 4734 -> 0 bytes webapp/images/emoji/1f1ed-1f1f9.png | Bin 3791 -> 0 bytes webapp/images/emoji/1f1ed-1f1fa.png | Bin 3680 -> 0 bytes webapp/images/emoji/1f1ee-1f1e8.png | Bin 2979 -> 0 bytes webapp/images/emoji/1f1ee-1f1e9.png | Bin 3025 -> 0 bytes webapp/images/emoji/1f1ee-1f1ea.png | Bin 2680 -> 0 bytes webapp/images/emoji/1f1ee-1f1f1.png | Bin 4645 -> 0 bytes webapp/images/emoji/1f1ee-1f1f2.png | Bin 3494 -> 0 bytes webapp/images/emoji/1f1ee-1f1f3.png | Bin 4142 -> 0 bytes webapp/images/emoji/1f1ee-1f1f4.png | Bin 7405 -> 0 bytes webapp/images/emoji/1f1ee-1f1f6.png | Bin 3747 -> 0 bytes webapp/images/emoji/1f1ee-1f1f7.png | Bin 4319 -> 0 bytes webapp/images/emoji/1f1ee-1f1f8.png | Bin 4524 -> 0 bytes webapp/images/emoji/1f1ee-1f1f9.png | Bin 2690 -> 0 bytes webapp/images/emoji/1f1ef-1f1ea.png | Bin 4627 -> 0 bytes webapp/images/emoji/1f1ef-1f1f2.png | Bin 4811 -> 0 bytes webapp/images/emoji/1f1ef-1f1f4.png | Bin 3942 -> 0 bytes webapp/images/emoji/1f1ef-1f1f5.png | Bin 2740 -> 0 bytes webapp/images/emoji/1f1f0-1f1ea.png | Bin 4501 -> 0 bytes webapp/images/emoji/1f1f0-1f1ec.png | Bin 3933 -> 0 bytes webapp/images/emoji/1f1f0-1f1ed.png | Bin 4626 -> 0 bytes webapp/images/emoji/1f1f0-1f1ee.png | Bin 5449 -> 0 bytes webapp/images/emoji/1f1f0-1f1f2.png | Bin 5031 -> 0 bytes webapp/images/emoji/1f1f0-1f1f3.png | Bin 4883 -> 0 bytes webapp/images/emoji/1f1f0-1f1f5.png | Bin 4587 -> 0 bytes webapp/images/emoji/1f1f0-1f1f7.png | Bin 4415 -> 0 bytes webapp/images/emoji/1f1f0-1f1fc.png | Bin 3677 -> 0 bytes webapp/images/emoji/1f1f0-1f1fe.png | Bin 5259 -> 0 bytes webapp/images/emoji/1f1f0-1f1ff.png | Bin 4582 -> 0 bytes webapp/images/emoji/1f1f1-1f1e6.png | Bin 4015 -> 0 bytes webapp/images/emoji/1f1f1-1f1e7.png | Bin 4501 -> 0 bytes webapp/images/emoji/1f1f1-1f1e8.png | Bin 3916 -> 0 bytes webapp/images/emoji/1f1f1-1f1ee.png | Bin 3664 -> 0 bytes webapp/images/emoji/1f1f1-1f1f0.png | Bin 4441 -> 0 bytes webapp/images/emoji/1f1f1-1f1f7.png | Bin 6049 -> 0 bytes webapp/images/emoji/1f1f1-1f1f8.png | Bin 4110 -> 0 bytes webapp/images/emoji/1f1f1-1f1f9.png | Bin 3654 -> 0 bytes webapp/images/emoji/1f1f1-1f1fa.png | Bin 3688 -> 0 bytes webapp/images/emoji/1f1f1-1f1fb.png | Bin 3829 -> 0 bytes webapp/images/emoji/1f1f1-1f1fe.png | Bin 4108 -> 0 bytes webapp/images/emoji/1f1f2-1f1e6.png | Bin 3599 -> 0 bytes webapp/images/emoji/1f1f2-1f1e8.png | Bin 2872 -> 0 bytes webapp/images/emoji/1f1f2-1f1e9.png | Bin 3725 -> 0 bytes webapp/images/emoji/1f1f2-1f1ea.png | Bin 3658 -> 0 bytes webapp/images/emoji/1f1f2-1f1ec.png | Bin 3003 -> 0 bytes webapp/images/emoji/1f1f2-1f1ed.png | Bin 4732 -> 0 bytes webapp/images/emoji/1f1f2-1f1f0.png | Bin 5692 -> 0 bytes webapp/images/emoji/1f1f2-1f1f1.png | Bin 2718 -> 0 bytes webapp/images/emoji/1f1f2-1f1f2.png | Bin 3966 -> 0 bytes webapp/images/emoji/1f1f2-1f1f3.png | Bin 3528 -> 0 bytes webapp/images/emoji/1f1f2-1f1f4.png | Bin 4175 -> 0 bytes webapp/images/emoji/1f1f2-1f1f5.png | Bin 5136 -> 0 bytes webapp/images/emoji/1f1f2-1f1f6.png | Bin 5033 -> 0 bytes webapp/images/emoji/1f1f2-1f1f7.png | Bin 3688 -> 0 bytes webapp/images/emoji/1f1f2-1f1f8.png | Bin 5318 -> 0 bytes webapp/images/emoji/1f1f2-1f1f9.png | Bin 2938 -> 0 bytes webapp/images/emoji/1f1f2-1f1fa.png | Bin 3705 -> 0 bytes webapp/images/emoji/1f1f2-1f1fb.png | Bin 3719 -> 0 bytes webapp/images/emoji/1f1f2-1f1fc.png | Bin 3847 -> 0 bytes webapp/images/emoji/1f1f2-1f1fd.png | Bin 3307 -> 0 bytes webapp/images/emoji/1f1f2-1f1fe.png | Bin 6194 -> 0 bytes webapp/images/emoji/1f1f2-1f1ff.png | Bin 4876 -> 0 bytes webapp/images/emoji/1f1f3-1f1e6.png | Bin 5325 -> 0 bytes webapp/images/emoji/1f1f3-1f1e8.png | Bin 4886 -> 0 bytes webapp/images/emoji/1f1f3-1f1ea.png | Bin 4079 -> 0 bytes webapp/images/emoji/1f1f3-1f1eb.png | Bin 3482 -> 0 bytes webapp/images/emoji/1f1f3-1f1ec.png | Bin 2636 -> 0 bytes webapp/images/emoji/1f1f3-1f1ee.png | Bin 4054 -> 0 bytes webapp/images/emoji/1f1f3-1f1f1.png | Bin 3799 -> 0 bytes webapp/images/emoji/1f1f3-1f1f4.png | Bin 4619 -> 0 bytes webapp/images/emoji/1f1f3-1f1f5.png | Bin 3870 -> 0 bytes webapp/images/emoji/1f1f3-1f1f7.png | Bin 3736 -> 0 bytes webapp/images/emoji/1f1f3-1f1fa.png | Bin 4911 -> 0 bytes webapp/images/emoji/1f1f3-1f1ff.png | Bin 4905 -> 0 bytes webapp/images/emoji/1f1f4-1f1f2.png | Bin 3640 -> 0 bytes webapp/images/emoji/1f1f5-1f1e6.png | Bin 3911 -> 0 bytes webapp/images/emoji/1f1f5-1f1ea.png | Bin 2460 -> 0 bytes webapp/images/emoji/1f1f5-1f1eb.png | Bin 4021 -> 0 bytes webapp/images/emoji/1f1f5-1f1ec.png | Bin 4594 -> 0 bytes webapp/images/emoji/1f1f5-1f1ed.png | Bin 4449 -> 0 bytes webapp/images/emoji/1f1f5-1f1f0.png | Bin 3464 -> 0 bytes webapp/images/emoji/1f1f5-1f1f1.png | Bin 3002 -> 0 bytes webapp/images/emoji/1f1f5-1f1f2.png | Bin 6360 -> 0 bytes webapp/images/emoji/1f1f5-1f1f3.png | Bin 5378 -> 0 bytes webapp/images/emoji/1f1f5-1f1f7.png | Bin 5139 -> 0 bytes webapp/images/emoji/1f1f5-1f1f8.png | Bin 3609 -> 0 bytes webapp/images/emoji/1f1f5-1f1f9.png | Bin 3761 -> 0 bytes webapp/images/emoji/1f1f5-1f1fc.png | Bin 3596 -> 0 bytes webapp/images/emoji/1f1f5-1f1fe.png | Bin 4098 -> 0 bytes webapp/images/emoji/1f1f6-1f1e6.png | Bin 3022 -> 0 bytes webapp/images/emoji/1f1f7-1f1ea.png | Bin 6010 -> 0 bytes webapp/images/emoji/1f1f7-1f1f4.png | Bin 2707 -> 0 bytes webapp/images/emoji/1f1f7-1f1f8.png | Bin 4692 -> 0 bytes webapp/images/emoji/1f1f7-1f1fa.png | Bin 3448 -> 0 bytes webapp/images/emoji/1f1f7-1f1fc.png | Bin 4435 -> 0 bytes webapp/images/emoji/1f1f8-1f1e6.png | Bin 4410 -> 0 bytes webapp/images/emoji/1f1f8-1f1e7.png | Bin 4882 -> 0 bytes webapp/images/emoji/1f1f8-1f1e8.png | Bin 4712 -> 0 bytes webapp/images/emoji/1f1f8-1f1e9.png | Bin 3624 -> 0 bytes webapp/images/emoji/1f1f8-1f1ea.png | Bin 4007 -> 0 bytes webapp/images/emoji/1f1f8-1f1ec.png | Bin 3789 -> 0 bytes webapp/images/emoji/1f1f8-1f1ed.png | Bin 4583 -> 0 bytes webapp/images/emoji/1f1f8-1f1ee.png | Bin 3928 -> 0 bytes webapp/images/emoji/1f1f8-1f1f0.png | Bin 4271 -> 0 bytes webapp/images/emoji/1f1f8-1f1f1.png | Bin 3764 -> 0 bytes webapp/images/emoji/1f1f8-1f1f2.png | Bin 4196 -> 0 bytes webapp/images/emoji/1f1f8-1f1f3.png | Bin 3169 -> 0 bytes webapp/images/emoji/1f1f8-1f1f4.png | Bin 3286 -> 0 bytes webapp/images/emoji/1f1f8-1f1f7.png | Bin 4759 -> 0 bytes webapp/images/emoji/1f1f8-1f1f8.png | Bin 4537 -> 0 bytes webapp/images/emoji/1f1f8-1f1f9.png | Bin 4514 -> 0 bytes webapp/images/emoji/1f1f8-1f1fb.png | Bin 4155 -> 0 bytes webapp/images/emoji/1f1f8-1f1fd.png | Bin 4212 -> 0 bytes webapp/images/emoji/1f1f8-1f1fe.png | Bin 3739 -> 0 bytes webapp/images/emoji/1f1f8-1f1ff.png | Bin 5983 -> 0 bytes webapp/images/emoji/1f1f9-1f1e8.png | Bin 5218 -> 0 bytes webapp/images/emoji/1f1f9-1f1e9.png | Bin 2704 -> 0 bytes webapp/images/emoji/1f1f9-1f1eb.png | Bin 3662 -> 0 bytes webapp/images/emoji/1f1f9-1f1ec.png | Bin 4994 -> 0 bytes webapp/images/emoji/1f1f9-1f1ed.png | Bin 4626 -> 0 bytes webapp/images/emoji/1f1f9-1f1ef.png | Bin 4191 -> 0 bytes webapp/images/emoji/1f1f9-1f1f0.png | Bin 3809 -> 0 bytes webapp/images/emoji/1f1f9-1f1f1.png | Bin 4214 -> 0 bytes webapp/images/emoji/1f1f9-1f1f2.png | Bin 4107 -> 0 bytes webapp/images/emoji/1f1f9-1f1f3.png | Bin 3830 -> 0 bytes webapp/images/emoji/1f1f9-1f1f4.png | Bin 3136 -> 0 bytes webapp/images/emoji/1f1f9-1f1f7.png | Bin 3924 -> 0 bytes webapp/images/emoji/1f1f9-1f1f9.png | Bin 4486 -> 0 bytes webapp/images/emoji/1f1f9-1f1fb.png | Bin 5670 -> 0 bytes webapp/images/emoji/1f1f9-1f1fc.png | Bin 3672 -> 0 bytes webapp/images/emoji/1f1f9-1f1ff.png | Bin 4563 -> 0 bytes webapp/images/emoji/1f1fa-1f1e6.png | Bin 3529 -> 0 bytes webapp/images/emoji/1f1fa-1f1ec.png | Bin 4995 -> 0 bytes webapp/images/emoji/1f1fa-1f1f8.png | Bin 6421 -> 0 bytes webapp/images/emoji/1f1fa-1f1fe.png | Bin 5944 -> 0 bytes webapp/images/emoji/1f1fa-1f1ff.png | Bin 4401 -> 0 bytes webapp/images/emoji/1f1fb-1f1e6.png | Bin 3949 -> 0 bytes webapp/images/emoji/1f1fb-1f1e8.png | Bin 3673 -> 0 bytes webapp/images/emoji/1f1fb-1f1ea.png | Bin 4491 -> 0 bytes webapp/images/emoji/1f1fb-1f1ec.png | Bin 5167 -> 0 bytes webapp/images/emoji/1f1fb-1f1ee.png | Bin 6193 -> 0 bytes webapp/images/emoji/1f1fb-1f1f3.png | Bin 3553 -> 0 bytes webapp/images/emoji/1f1fb-1f1fa.png | Bin 4755 -> 0 bytes webapp/images/emoji/1f1fc-1f1eb.png | Bin 3415 -> 0 bytes webapp/images/emoji/1f1fc-1f1f8.png | Bin 3466 -> 0 bytes webapp/images/emoji/1f1fd-1f1f0.png | Bin 3419 -> 0 bytes webapp/images/emoji/1f1fe-1f1ea.png | Bin 3192 -> 0 bytes webapp/images/emoji/1f1fe-1f1f9.png | Bin 4337 -> 0 bytes webapp/images/emoji/1f1ff-1f1e6.png | Bin 5179 -> 0 bytes webapp/images/emoji/1f1ff-1f1f2.png | Bin 2909 -> 0 bytes webapp/images/emoji/1f1ff-1f1fc.png | Bin 5745 -> 0 bytes webapp/images/emoji/1f201.png | Bin 2723 -> 0 bytes webapp/images/emoji/1f202-fe0f.png | Bin 2883 -> 0 bytes webapp/images/emoji/1f21a-fe0f.png | Bin 3956 -> 0 bytes webapp/images/emoji/1f22f-fe0f.png | Bin 3760 -> 0 bytes webapp/images/emoji/1f232.png | Bin 5304 -> 0 bytes webapp/images/emoji/1f233.png | Bin 3391 -> 0 bytes webapp/images/emoji/1f234.png | Bin 3761 -> 0 bytes webapp/images/emoji/1f235.png | Bin 5021 -> 0 bytes webapp/images/emoji/1f236.png | Bin 2832 -> 0 bytes webapp/images/emoji/1f237-fe0f.png | Bin 2504 -> 0 bytes webapp/images/emoji/1f238.png | Bin 2407 -> 0 bytes webapp/images/emoji/1f239.png | Bin 4223 -> 0 bytes webapp/images/emoji/1f23a.png | Bin 3187 -> 0 bytes webapp/images/emoji/1f250.png | Bin 4232 -> 0 bytes webapp/images/emoji/1f251.png | Bin 3099 -> 0 bytes webapp/images/emoji/1f300.png | Bin 4083 -> 0 bytes webapp/images/emoji/1f301.png | Bin 4747 -> 0 bytes webapp/images/emoji/1f302.png | Bin 4607 -> 0 bytes webapp/images/emoji/1f303.png | Bin 5758 -> 0 bytes webapp/images/emoji/1f304.png | Bin 6210 -> 0 bytes webapp/images/emoji/1f305.png | Bin 5202 -> 0 bytes webapp/images/emoji/1f306.png | Bin 5529 -> 0 bytes webapp/images/emoji/1f307.png | Bin 6132 -> 0 bytes webapp/images/emoji/1f308.png | Bin 6575 -> 0 bytes webapp/images/emoji/1f309.png | Bin 6006 -> 0 bytes webapp/images/emoji/1f30a.png | Bin 6966 -> 0 bytes webapp/images/emoji/1f30b.png | Bin 6804 -> 0 bytes webapp/images/emoji/1f30c.png | Bin 5822 -> 0 bytes webapp/images/emoji/1f30d.png | Bin 8533 -> 0 bytes webapp/images/emoji/1f30e.png | Bin 8016 -> 0 bytes webapp/images/emoji/1f30f.png | Bin 8375 -> 0 bytes webapp/images/emoji/1f310.png | Bin 7920 -> 0 bytes webapp/images/emoji/1f311.png | Bin 6126 -> 0 bytes webapp/images/emoji/1f312.png | Bin 6988 -> 0 bytes webapp/images/emoji/1f313.png | Bin 7266 -> 0 bytes webapp/images/emoji/1f314.png | Bin 6995 -> 0 bytes webapp/images/emoji/1f315.png | Bin 6807 -> 0 bytes webapp/images/emoji/1f316.png | Bin 7256 -> 0 bytes webapp/images/emoji/1f317.png | Bin 7421 -> 0 bytes webapp/images/emoji/1f318.png | Bin 7175 -> 0 bytes webapp/images/emoji/1f319.png | Bin 3698 -> 0 bytes webapp/images/emoji/1f31a.png | Bin 5822 -> 0 bytes webapp/images/emoji/1f31b.png | Bin 4203 -> 0 bytes webapp/images/emoji/1f31c.png | Bin 4172 -> 0 bytes webapp/images/emoji/1f31d.png | Bin 7561 -> 0 bytes webapp/images/emoji/1f31e.png | Bin 7801 -> 0 bytes webapp/images/emoji/1f31f.png | Bin 5085 -> 0 bytes webapp/images/emoji/1f320.png | Bin 6436 -> 0 bytes webapp/images/emoji/1f321.png | Bin 4938 -> 0 bytes webapp/images/emoji/1f324.png | Bin 5402 -> 0 bytes webapp/images/emoji/1f325.png | Bin 4198 -> 0 bytes webapp/images/emoji/1f326.png | Bin 5011 -> 0 bytes webapp/images/emoji/1f327.png | Bin 4838 -> 0 bytes webapp/images/emoji/1f328.png | Bin 5391 -> 0 bytes webapp/images/emoji/1f329.png | Bin 3843 -> 0 bytes webapp/images/emoji/1f32a.png | Bin 7887 -> 0 bytes webapp/images/emoji/1f32b.png | Bin 4946 -> 0 bytes webapp/images/emoji/1f32c.png | Bin 4200 -> 0 bytes webapp/images/emoji/1f32d.png | Bin 6286 -> 0 bytes webapp/images/emoji/1f32e.png | Bin 6889 -> 0 bytes webapp/images/emoji/1f32f.png | Bin 6477 -> 0 bytes webapp/images/emoji/1f330.png | Bin 7092 -> 0 bytes webapp/images/emoji/1f331.png | Bin 3643 -> 0 bytes webapp/images/emoji/1f332.png | Bin 6058 -> 0 bytes webapp/images/emoji/1f333.png | Bin 7207 -> 0 bytes webapp/images/emoji/1f334.png | Bin 5961 -> 0 bytes webapp/images/emoji/1f335.png | Bin 5980 -> 0 bytes webapp/images/emoji/1f336.png | Bin 4793 -> 0 bytes webapp/images/emoji/1f337.png | Bin 5691 -> 0 bytes webapp/images/emoji/1f338.png | Bin 7759 -> 0 bytes webapp/images/emoji/1f339.png | Bin 5311 -> 0 bytes webapp/images/emoji/1f33a.png | Bin 8608 -> 0 bytes webapp/images/emoji/1f33b.png | Bin 6369 -> 0 bytes webapp/images/emoji/1f33c.png | Bin 7677 -> 0 bytes webapp/images/emoji/1f33d.png | Bin 7617 -> 0 bytes webapp/images/emoji/1f33e.png | Bin 6448 -> 0 bytes webapp/images/emoji/1f33f.png | Bin 5747 -> 0 bytes webapp/images/emoji/1f340.png | Bin 7092 -> 0 bytes webapp/images/emoji/1f341.png | Bin 5856 -> 0 bytes webapp/images/emoji/1f342.png | Bin 5556 -> 0 bytes webapp/images/emoji/1f343.png | Bin 5726 -> 0 bytes webapp/images/emoji/1f344.png | Bin 5467 -> 0 bytes webapp/images/emoji/1f345.png | Bin 5960 -> 0 bytes webapp/images/emoji/1f346.png | Bin 5208 -> 0 bytes webapp/images/emoji/1f347.png | Bin 8012 -> 0 bytes webapp/images/emoji/1f348.png | Bin 6752 -> 0 bytes webapp/images/emoji/1f349.png | Bin 5373 -> 0 bytes webapp/images/emoji/1f34a.png | Bin 5593 -> 0 bytes webapp/images/emoji/1f34b.png | Bin 5809 -> 0 bytes webapp/images/emoji/1f34c.png | Bin 5196 -> 0 bytes webapp/images/emoji/1f34d.png | Bin 5143 -> 0 bytes webapp/images/emoji/1f34e.png | Bin 6099 -> 0 bytes webapp/images/emoji/1f34f.png | Bin 5842 -> 0 bytes webapp/images/emoji/1f350.png | Bin 5396 -> 0 bytes webapp/images/emoji/1f351.png | Bin 6134 -> 0 bytes webapp/images/emoji/1f352.png | Bin 6403 -> 0 bytes webapp/images/emoji/1f353.png | Bin 6677 -> 0 bytes webapp/images/emoji/1f354.png | Bin 7731 -> 0 bytes webapp/images/emoji/1f355.png | Bin 5937 -> 0 bytes webapp/images/emoji/1f356.png | Bin 6253 -> 0 bytes webapp/images/emoji/1f357.png | Bin 4505 -> 0 bytes webapp/images/emoji/1f358.png | Bin 7167 -> 0 bytes webapp/images/emoji/1f359.png | Bin 7104 -> 0 bytes webapp/images/emoji/1f35a.png | Bin 6224 -> 0 bytes webapp/images/emoji/1f35b.png | Bin 5394 -> 0 bytes webapp/images/emoji/1f35c.png | Bin 6316 -> 0 bytes webapp/images/emoji/1f35d.png | Bin 6444 -> 0 bytes webapp/images/emoji/1f35e.png | Bin 6167 -> 0 bytes webapp/images/emoji/1f35f.png | Bin 6846 -> 0 bytes webapp/images/emoji/1f360.png | Bin 6346 -> 0 bytes webapp/images/emoji/1f361.png | Bin 4156 -> 0 bytes webapp/images/emoji/1f362.png | Bin 5372 -> 0 bytes webapp/images/emoji/1f363.png | Bin 6883 -> 0 bytes webapp/images/emoji/1f364.png | Bin 6897 -> 0 bytes webapp/images/emoji/1f365.png | Bin 6122 -> 0 bytes webapp/images/emoji/1f366.png | Bin 4723 -> 0 bytes webapp/images/emoji/1f367.png | Bin 5642 -> 0 bytes webapp/images/emoji/1f368.png | Bin 6183 -> 0 bytes webapp/images/emoji/1f369.png | Bin 8768 -> 0 bytes webapp/images/emoji/1f36a.png | Bin 6849 -> 0 bytes webapp/images/emoji/1f36b.png | Bin 5281 -> 0 bytes webapp/images/emoji/1f36c.png | Bin 4291 -> 0 bytes webapp/images/emoji/1f36d.png | Bin 7075 -> 0 bytes webapp/images/emoji/1f36e.png | Bin 4983 -> 0 bytes webapp/images/emoji/1f36f.png | Bin 6648 -> 0 bytes webapp/images/emoji/1f370.png | Bin 5205 -> 0 bytes webapp/images/emoji/1f371.png | Bin 8683 -> 0 bytes webapp/images/emoji/1f372.png | Bin 5952 -> 0 bytes webapp/images/emoji/1f373.png | Bin 6203 -> 0 bytes webapp/images/emoji/1f374.png | Bin 3291 -> 0 bytes webapp/images/emoji/1f375.png | Bin 6647 -> 0 bytes webapp/images/emoji/1f376.png | Bin 4616 -> 0 bytes webapp/images/emoji/1f377.png | Bin 4518 -> 0 bytes webapp/images/emoji/1f378.png | Bin 4030 -> 0 bytes webapp/images/emoji/1f379.png | Bin 4890 -> 0 bytes webapp/images/emoji/1f37a.png | Bin 6473 -> 0 bytes webapp/images/emoji/1f37b.png | Bin 5903 -> 0 bytes webapp/images/emoji/1f37c.png | Bin 4811 -> 0 bytes webapp/images/emoji/1f37d.png | Bin 5162 -> 0 bytes webapp/images/emoji/1f37e.png | Bin 4977 -> 0 bytes webapp/images/emoji/1f37f.png | Bin 6034 -> 0 bytes webapp/images/emoji/1f380.png | Bin 6403 -> 0 bytes webapp/images/emoji/1f381.png | Bin 6608 -> 0 bytes webapp/images/emoji/1f382.png | Bin 6491 -> 0 bytes webapp/images/emoji/1f383.png | Bin 5010 -> 0 bytes webapp/images/emoji/1f384.png | Bin 5759 -> 0 bytes webapp/images/emoji/1f385.png | Bin 7188 -> 0 bytes webapp/images/emoji/1f386.png | Bin 7187 -> 0 bytes webapp/images/emoji/1f387.png | Bin 7583 -> 0 bytes webapp/images/emoji/1f388.png | Bin 4084 -> 0 bytes webapp/images/emoji/1f389.png | Bin 8423 -> 0 bytes webapp/images/emoji/1f38a.png | Bin 7779 -> 0 bytes webapp/images/emoji/1f38b.png | Bin 5205 -> 0 bytes webapp/images/emoji/1f38c.png | Bin 5207 -> 0 bytes webapp/images/emoji/1f38d.png | Bin 4438 -> 0 bytes webapp/images/emoji/1f38e.png | Bin 8012 -> 0 bytes webapp/images/emoji/1f38f.png | Bin 7859 -> 0 bytes webapp/images/emoji/1f390.png | Bin 4862 -> 0 bytes webapp/images/emoji/1f391.png | Bin 7494 -> 0 bytes webapp/images/emoji/1f392.png | Bin 6155 -> 0 bytes webapp/images/emoji/1f393.png | Bin 5175 -> 0 bytes webapp/images/emoji/1f396.png | Bin 3787 -> 0 bytes webapp/images/emoji/1f397.png | Bin 3520 -> 0 bytes webapp/images/emoji/1f399.png | Bin 7492 -> 0 bytes webapp/images/emoji/1f39a.png | Bin 4787 -> 0 bytes webapp/images/emoji/1f39b.png | Bin 8688 -> 0 bytes webapp/images/emoji/1f39e.png | Bin 8004 -> 0 bytes webapp/images/emoji/1f39f.png | Bin 5167 -> 0 bytes webapp/images/emoji/1f3a0.png | Bin 7547 -> 0 bytes webapp/images/emoji/1f3a1.png | Bin 7963 -> 0 bytes webapp/images/emoji/1f3a2.png | Bin 5514 -> 0 bytes webapp/images/emoji/1f3a3.png | Bin 5572 -> 0 bytes webapp/images/emoji/1f3a4.png | Bin 4879 -> 0 bytes webapp/images/emoji/1f3a5.png | Bin 7625 -> 0 bytes webapp/images/emoji/1f3a6.png | Bin 3672 -> 0 bytes webapp/images/emoji/1f3a7.png | Bin 6694 -> 0 bytes webapp/images/emoji/1f3a8.png | Bin 6689 -> 0 bytes webapp/images/emoji/1f3a9.png | Bin 4512 -> 0 bytes webapp/images/emoji/1f3aa.png | Bin 6109 -> 0 bytes webapp/images/emoji/1f3ab.png | Bin 5352 -> 0 bytes webapp/images/emoji/1f3ac.png | Bin 5414 -> 0 bytes webapp/images/emoji/1f3ad.png | Bin 6921 -> 0 bytes webapp/images/emoji/1f3ae.png | Bin 6683 -> 0 bytes webapp/images/emoji/1f3af.png | Bin 5675 -> 0 bytes webapp/images/emoji/1f3b0.png | Bin 6985 -> 0 bytes webapp/images/emoji/1f3b1.png | Bin 2875 -> 0 bytes webapp/images/emoji/1f3b2.png | Bin 4509 -> 0 bytes webapp/images/emoji/1f3b3.png | Bin 6421 -> 0 bytes webapp/images/emoji/1f3b4.png | Bin 4653 -> 0 bytes webapp/images/emoji/1f3b5.png | Bin 4080 -> 0 bytes webapp/images/emoji/1f3b6.png | Bin 5826 -> 0 bytes webapp/images/emoji/1f3b7.png | Bin 5513 -> 0 bytes webapp/images/emoji/1f3b8.png | Bin 4707 -> 0 bytes webapp/images/emoji/1f3b9.png | Bin 3376 -> 0 bytes webapp/images/emoji/1f3ba.png | Bin 6185 -> 0 bytes webapp/images/emoji/1f3bb.png | Bin 6652 -> 0 bytes webapp/images/emoji/1f3bc.png | Bin 2633 -> 0 bytes webapp/images/emoji/1f3bd.png | Bin 5743 -> 0 bytes webapp/images/emoji/1f3be.png | Bin 6444 -> 0 bytes webapp/images/emoji/1f3bf.png | Bin 6674 -> 0 bytes webapp/images/emoji/1f3c0.png | Bin 8281 -> 0 bytes webapp/images/emoji/1f3c1.png | Bin 6037 -> 0 bytes webapp/images/emoji/1f3c2.png | Bin 6046 -> 0 bytes webapp/images/emoji/1f3c3-200d-2640-fe0f.png | Bin 4122 -> 0 bytes webapp/images/emoji/1f3c3.png | Bin 3999 -> 0 bytes webapp/images/emoji/1f3c4-200d-2640-fe0f.png | Bin 6231 -> 0 bytes webapp/images/emoji/1f3c4.png | Bin 6032 -> 0 bytes webapp/images/emoji/1f3c5.png | Bin 4961 -> 0 bytes webapp/images/emoji/1f3c6.png | Bin 6051 -> 0 bytes webapp/images/emoji/1f3c7.png | Bin 4860 -> 0 bytes webapp/images/emoji/1f3c8.png | Bin 8435 -> 0 bytes webapp/images/emoji/1f3c9.png | Bin 8115 -> 0 bytes webapp/images/emoji/1f3ca-200d-2640-fe0f.png | Bin 5138 -> 0 bytes webapp/images/emoji/1f3ca.png | Bin 4947 -> 0 bytes webapp/images/emoji/1f3cb-fe0f-200d-2640-fe0f.png | Bin 6286 -> 0 bytes webapp/images/emoji/1f3cb-fe0f.png | Bin 6237 -> 0 bytes webapp/images/emoji/1f3cc-fe0f-200d-2640-fe0f.png | Bin 3922 -> 0 bytes webapp/images/emoji/1f3cc-fe0f.png | Bin 4040 -> 0 bytes webapp/images/emoji/1f3cd.png | Bin 5002 -> 0 bytes webapp/images/emoji/1f3ce.png | Bin 5045 -> 0 bytes webapp/images/emoji/1f3cf.png | Bin 4910 -> 0 bytes webapp/images/emoji/1f3d0.png | Bin 3109 -> 0 bytes webapp/images/emoji/1f3d1.png | Bin 4062 -> 0 bytes webapp/images/emoji/1f3d2.png | Bin 3242 -> 0 bytes webapp/images/emoji/1f3d3.png | Bin 6808 -> 0 bytes webapp/images/emoji/1f3d4.png | Bin 5712 -> 0 bytes webapp/images/emoji/1f3d5.png | Bin 5718 -> 0 bytes webapp/images/emoji/1f3d6.png | Bin 5692 -> 0 bytes webapp/images/emoji/1f3d7.png | Bin 5895 -> 0 bytes webapp/images/emoji/1f3d8.png | Bin 7491 -> 0 bytes webapp/images/emoji/1f3d9.png | Bin 5376 -> 0 bytes webapp/images/emoji/1f3da.png | Bin 7640 -> 0 bytes webapp/images/emoji/1f3db.png | Bin 6183 -> 0 bytes webapp/images/emoji/1f3dc.png | Bin 5091 -> 0 bytes webapp/images/emoji/1f3dd.png | Bin 5585 -> 0 bytes webapp/images/emoji/1f3de.png | Bin 6126 -> 0 bytes webapp/images/emoji/1f3df.png | Bin 8187 -> 0 bytes webapp/images/emoji/1f3e0.png | Bin 6281 -> 0 bytes webapp/images/emoji/1f3e1.png | Bin 6844 -> 0 bytes webapp/images/emoji/1f3e2.png | Bin 7004 -> 0 bytes webapp/images/emoji/1f3e3.png | Bin 6221 -> 0 bytes webapp/images/emoji/1f3e4.png | Bin 7076 -> 0 bytes webapp/images/emoji/1f3e5.png | Bin 7742 -> 0 bytes webapp/images/emoji/1f3e6.png | Bin 7135 -> 0 bytes webapp/images/emoji/1f3e7.png | Bin 3448 -> 0 bytes webapp/images/emoji/1f3e8.png | Bin 7385 -> 0 bytes webapp/images/emoji/1f3e9.png | Bin 7731 -> 0 bytes webapp/images/emoji/1f3ea.png | Bin 6161 -> 0 bytes webapp/images/emoji/1f3eb.png | Bin 6148 -> 0 bytes webapp/images/emoji/1f3ec.png | Bin 6032 -> 0 bytes webapp/images/emoji/1f3ed.png | Bin 6420 -> 0 bytes webapp/images/emoji/1f3ee.png | Bin 4312 -> 0 bytes webapp/images/emoji/1f3ef.png | Bin 7292 -> 0 bytes webapp/images/emoji/1f3f0.png | Bin 7553 -> 0 bytes webapp/images/emoji/1f3f3-fe0f-200d-1f308.png | Bin 3680 -> 0 bytes webapp/images/emoji/1f3f3-fe0f.png | Bin 3835 -> 0 bytes webapp/images/emoji/1f3f4.png | Bin 4416 -> 0 bytes webapp/images/emoji/1f3f5.png | Bin 8124 -> 0 bytes webapp/images/emoji/1f3f7.png | Bin 3470 -> 0 bytes webapp/images/emoji/1f3f8.png | Bin 6922 -> 0 bytes webapp/images/emoji/1f3f9.png | Bin 5595 -> 0 bytes webapp/images/emoji/1f3fa.png | Bin 6160 -> 0 bytes webapp/images/emoji/1f400.png | Bin 5159 -> 0 bytes webapp/images/emoji/1f401.png | Bin 6010 -> 0 bytes webapp/images/emoji/1f402.png | Bin 4413 -> 0 bytes webapp/images/emoji/1f403.png | Bin 4205 -> 0 bytes webapp/images/emoji/1f404.png | Bin 5483 -> 0 bytes webapp/images/emoji/1f405.png | Bin 5540 -> 0 bytes webapp/images/emoji/1f406.png | Bin 6084 -> 0 bytes webapp/images/emoji/1f407.png | Bin 4822 -> 0 bytes webapp/images/emoji/1f408.png | Bin 6795 -> 0 bytes webapp/images/emoji/1f409.png | Bin 8626 -> 0 bytes webapp/images/emoji/1f40a.png | Bin 7024 -> 0 bytes webapp/images/emoji/1f40b.png | Bin 5595 -> 0 bytes webapp/images/emoji/1f40c.png | Bin 7367 -> 0 bytes webapp/images/emoji/1f40d.png | Bin 5855 -> 0 bytes webapp/images/emoji/1f40e.png | Bin 5779 -> 0 bytes webapp/images/emoji/1f40f.png | Bin 5648 -> 0 bytes webapp/images/emoji/1f410.png | Bin 4740 -> 0 bytes webapp/images/emoji/1f411.png | Bin 5601 -> 0 bytes webapp/images/emoji/1f412.png | Bin 6758 -> 0 bytes webapp/images/emoji/1f413.png | Bin 5118 -> 0 bytes webapp/images/emoji/1f414.png | Bin 4308 -> 0 bytes webapp/images/emoji/1f415.png | Bin 5750 -> 0 bytes webapp/images/emoji/1f416.png | Bin 4136 -> 0 bytes webapp/images/emoji/1f417.png | Bin 5382 -> 0 bytes webapp/images/emoji/1f418.png | Bin 4807 -> 0 bytes webapp/images/emoji/1f419.png | Bin 6397 -> 0 bytes webapp/images/emoji/1f41a.png | Bin 6484 -> 0 bytes webapp/images/emoji/1f41b.png | Bin 6902 -> 0 bytes webapp/images/emoji/1f41c.png | Bin 3759 -> 0 bytes webapp/images/emoji/1f41d.png | Bin 6948 -> 0 bytes webapp/images/emoji/1f41e.png | Bin 6976 -> 0 bytes webapp/images/emoji/1f41f.png | Bin 5308 -> 0 bytes webapp/images/emoji/1f420.png | Bin 6246 -> 0 bytes webapp/images/emoji/1f421.png | Bin 7176 -> 0 bytes webapp/images/emoji/1f422.png | Bin 5149 -> 0 bytes webapp/images/emoji/1f423.png | Bin 6045 -> 0 bytes webapp/images/emoji/1f424.png | Bin 3974 -> 0 bytes webapp/images/emoji/1f425.png | Bin 5025 -> 0 bytes webapp/images/emoji/1f426.png | Bin 4617 -> 0 bytes webapp/images/emoji/1f427.png | Bin 4231 -> 0 bytes webapp/images/emoji/1f428.png | Bin 5434 -> 0 bytes webapp/images/emoji/1f429.png | Bin 5615 -> 0 bytes webapp/images/emoji/1f42a.png | Bin 4739 -> 0 bytes webapp/images/emoji/1f42b.png | Bin 5824 -> 0 bytes webapp/images/emoji/1f42c.png | Bin 5446 -> 0 bytes webapp/images/emoji/1f42d.png | Bin 6818 -> 0 bytes webapp/images/emoji/1f42e.png | Bin 5673 -> 0 bytes webapp/images/emoji/1f42f.png | Bin 7055 -> 0 bytes webapp/images/emoji/1f430.png | Bin 6171 -> 0 bytes webapp/images/emoji/1f431.png | Bin 6112 -> 0 bytes webapp/images/emoji/1f432.png | Bin 8080 -> 0 bytes webapp/images/emoji/1f433.png | Bin 5025 -> 0 bytes webapp/images/emoji/1f434.png | Bin 5781 -> 0 bytes webapp/images/emoji/1f435.png | Bin 6933 -> 0 bytes webapp/images/emoji/1f436.png | Bin 6407 -> 0 bytes webapp/images/emoji/1f437.png | Bin 6475 -> 0 bytes webapp/images/emoji/1f438.png | Bin 6825 -> 0 bytes webapp/images/emoji/1f439.png | Bin 7713 -> 0 bytes webapp/images/emoji/1f43a.png | Bin 5624 -> 0 bytes webapp/images/emoji/1f43b.png | Bin 6454 -> 0 bytes webapp/images/emoji/1f43c.png | Bin 6703 -> 0 bytes webapp/images/emoji/1f43d.png | Bin 4894 -> 0 bytes webapp/images/emoji/1f43e.png | Bin 1064 -> 0 bytes webapp/images/emoji/1f43f.png | Bin 7877 -> 0 bytes webapp/images/emoji/1f440.png | Bin 3887 -> 0 bytes webapp/images/emoji/1f441-200d-1f5e8.png | Bin 5758 -> 0 bytes webapp/images/emoji/1f441.png | Bin 5841 -> 0 bytes webapp/images/emoji/1f442.png | Bin 3357 -> 0 bytes webapp/images/emoji/1f443.png | Bin 2996 -> 0 bytes webapp/images/emoji/1f444.png | Bin 4109 -> 0 bytes webapp/images/emoji/1f445.png | Bin 5266 -> 0 bytes webapp/images/emoji/1f446.png | Bin 3202 -> 0 bytes webapp/images/emoji/1f447.png | Bin 2933 -> 0 bytes webapp/images/emoji/1f448.png | Bin 2812 -> 0 bytes webapp/images/emoji/1f449.png | Bin 2767 -> 0 bytes webapp/images/emoji/1f44a.png | Bin 4015 -> 0 bytes webapp/images/emoji/1f44b.png | Bin 6960 -> 0 bytes webapp/images/emoji/1f44c.png | Bin 3801 -> 0 bytes webapp/images/emoji/1f44d.png | Bin 4144 -> 0 bytes webapp/images/emoji/1f44e.png | Bin 4369 -> 0 bytes webapp/images/emoji/1f44f.png | Bin 4698 -> 0 bytes webapp/images/emoji/1f450.png | Bin 4711 -> 0 bytes webapp/images/emoji/1f451.png | Bin 6449 -> 0 bytes webapp/images/emoji/1f452.png | Bin 6347 -> 0 bytes webapp/images/emoji/1f453.png | Bin 3504 -> 0 bytes webapp/images/emoji/1f454.png | Bin 7227 -> 0 bytes webapp/images/emoji/1f455.png | Bin 5315 -> 0 bytes webapp/images/emoji/1f456.png | Bin 5326 -> 0 bytes webapp/images/emoji/1f457.png | Bin 5050 -> 0 bytes webapp/images/emoji/1f458.png | Bin 6641 -> 0 bytes webapp/images/emoji/1f459.png | Bin 4657 -> 0 bytes webapp/images/emoji/1f45a.png | Bin 5004 -> 0 bytes webapp/images/emoji/1f45b.png | Bin 4395 -> 0 bytes webapp/images/emoji/1f45c.png | Bin 6090 -> 0 bytes webapp/images/emoji/1f45d.png | Bin 4445 -> 0 bytes webapp/images/emoji/1f45e.png | Bin 5641 -> 0 bytes webapp/images/emoji/1f45f.png | Bin 5079 -> 0 bytes webapp/images/emoji/1f460.png | Bin 5961 -> 0 bytes webapp/images/emoji/1f461.png | Bin 4286 -> 0 bytes webapp/images/emoji/1f462.png | Bin 4000 -> 0 bytes webapp/images/emoji/1f463.png | Bin 1120 -> 0 bytes webapp/images/emoji/1f464.png | Bin 2738 -> 0 bytes webapp/images/emoji/1f465.png | Bin 3078 -> 0 bytes webapp/images/emoji/1f466.png | Bin 6464 -> 0 bytes webapp/images/emoji/1f467.png | Bin 6724 -> 0 bytes webapp/images/emoji/1f468-200d-1f33e.png | Bin 7914 -> 0 bytes webapp/images/emoji/1f468-200d-1f373.png | Bin 6751 -> 0 bytes webapp/images/emoji/1f468-200d-1f393.png | Bin 6254 -> 0 bytes webapp/images/emoji/1f468-200d-1f3a4.png | Bin 6996 -> 0 bytes webapp/images/emoji/1f468-200d-1f3a8.png | Bin 6964 -> 0 bytes webapp/images/emoji/1f468-200d-1f3eb.png | Bin 7577 -> 0 bytes webapp/images/emoji/1f468-200d-1f3ed.png | Bin 6765 -> 0 bytes .../images/emoji/1f468-200d-1f466-200d-1f466.png | Bin 6729 -> 0 bytes webapp/images/emoji/1f468-200d-1f466.png | Bin 5361 -> 0 bytes .../images/emoji/1f468-200d-1f467-200d-1f466.png | Bin 7199 -> 0 bytes .../images/emoji/1f468-200d-1f467-200d-1f467.png | Bin 7307 -> 0 bytes webapp/images/emoji/1f468-200d-1f467.png | Bin 5605 -> 0 bytes .../1f468-200d-1f468-200d-1f466-200d-1f466.png | Bin 9331 -> 0 bytes .../images/emoji/1f468-200d-1f468-200d-1f466.png | Bin 8021 -> 0 bytes .../1f468-200d-1f468-200d-1f467-200d-1f466.png | Bin 9778 -> 0 bytes .../1f468-200d-1f468-200d-1f467-200d-1f467.png | Bin 8691 -> 0 bytes .../images/emoji/1f468-200d-1f468-200d-1f467.png | Bin 8326 -> 0 bytes .../1f468-200d-1f469-200d-1f466-200d-1f466.png | Bin 9781 -> 0 bytes .../1f468-200d-1f469-200d-1f467-200d-1f466.png | Bin 10168 -> 0 bytes .../1f468-200d-1f469-200d-1f467-200d-1f467.png | Bin 9197 -> 0 bytes .../images/emoji/1f468-200d-1f469-200d-1f467.png | Bin 8703 -> 0 bytes webapp/images/emoji/1f468-200d-1f4bb.png | Bin 4918 -> 0 bytes webapp/images/emoji/1f468-200d-1f4bc.png | Bin 5653 -> 0 bytes webapp/images/emoji/1f468-200d-1f527.png | Bin 6493 -> 0 bytes webapp/images/emoji/1f468-200d-1f52c.png | Bin 6799 -> 0 bytes webapp/images/emoji/1f468-200d-1f680.png | Bin 8220 -> 0 bytes webapp/images/emoji/1f468-200d-1f692.png | Bin 7417 -> 0 bytes webapp/images/emoji/1f468-200d-2695-fe0f.png | Bin 5592 -> 0 bytes webapp/images/emoji/1f468-200d-2696-fe0f.png | Bin 6081 -> 0 bytes webapp/images/emoji/1f468-200d-2708-fe0f.png | Bin 6528 -> 0 bytes .../emoji/1f468-200d-2764-fe0f-200d-1f468.png | Bin 7070 -> 0 bytes .../1f468-200d-2764-fe0f-200d-1f48b-200d-1f468.png | Bin 6215 -> 0 bytes webapp/images/emoji/1f468.png | Bin 5813 -> 0 bytes webapp/images/emoji/1f469-200d-1f33e.png | Bin 8221 -> 0 bytes webapp/images/emoji/1f469-200d-1f373.png | Bin 6841 -> 0 bytes webapp/images/emoji/1f469-200d-1f393.png | Bin 6764 -> 0 bytes webapp/images/emoji/1f469-200d-1f3a4.png | Bin 7286 -> 0 bytes webapp/images/emoji/1f469-200d-1f3a8.png | Bin 7177 -> 0 bytes webapp/images/emoji/1f469-200d-1f3eb.png | Bin 7900 -> 0 bytes webapp/images/emoji/1f469-200d-1f3ed.png | Bin 6957 -> 0 bytes .../images/emoji/1f469-200d-1f466-200d-1f466.png | Bin 7107 -> 0 bytes webapp/images/emoji/1f469-200d-1f466.png | Bin 5809 -> 0 bytes .../images/emoji/1f469-200d-1f467-200d-1f466.png | Bin 7570 -> 0 bytes .../images/emoji/1f469-200d-1f467-200d-1f467.png | Bin 7692 -> 0 bytes webapp/images/emoji/1f469-200d-1f467.png | Bin 6033 -> 0 bytes .../1f469-200d-1f469-200d-1f466-200d-1f466.png | Bin 9951 -> 0 bytes .../images/emoji/1f469-200d-1f469-200d-1f466.png | Bin 8641 -> 0 bytes .../1f469-200d-1f469-200d-1f467-200d-1f466.png | Bin 10352 -> 0 bytes .../1f469-200d-1f469-200d-1f467-200d-1f467.png | Bin 9355 -> 0 bytes .../images/emoji/1f469-200d-1f469-200d-1f467.png | Bin 8907 -> 0 bytes webapp/images/emoji/1f469-200d-1f4bb.png | Bin 5424 -> 0 bytes webapp/images/emoji/1f469-200d-1f4bc.png | Bin 6462 -> 0 bytes webapp/images/emoji/1f469-200d-1f527.png | Bin 7173 -> 0 bytes webapp/images/emoji/1f469-200d-1f52c.png | Bin 7238 -> 0 bytes webapp/images/emoji/1f469-200d-1f680.png | Bin 8149 -> 0 bytes webapp/images/emoji/1f469-200d-1f692.png | Bin 7527 -> 0 bytes webapp/images/emoji/1f469-200d-2695-fe0f.png | Bin 6822 -> 0 bytes webapp/images/emoji/1f469-200d-2696-fe0f.png | Bin 6813 -> 0 bytes webapp/images/emoji/1f469-200d-2708-fe0f.png | Bin 6872 -> 0 bytes .../emoji/1f469-200d-2764-fe0f-200d-1f469.png | Bin 8926 -> 0 bytes .../1f469-200d-2764-fe0f-200d-1f48b-200d-1f469.png | Bin 8101 -> 0 bytes webapp/images/emoji/1f469.png | Bin 8171 -> 0 bytes webapp/images/emoji/1f46a.png | Bin 8389 -> 0 bytes webapp/images/emoji/1f46b.png | Bin 6747 -> 0 bytes webapp/images/emoji/1f46c.png | Bin 6332 -> 0 bytes webapp/images/emoji/1f46d.png | Bin 6828 -> 0 bytes webapp/images/emoji/1f46e-200d-2640-fe0f.png | Bin 6347 -> 0 bytes webapp/images/emoji/1f46e.png | Bin 6521 -> 0 bytes webapp/images/emoji/1f46f-200d-2642-fe0f.png | Bin 5317 -> 0 bytes webapp/images/emoji/1f46f.png | Bin 6754 -> 0 bytes webapp/images/emoji/1f470.png | Bin 7834 -> 0 bytes webapp/images/emoji/1f471-200d-2640-fe0f.png | Bin 6918 -> 0 bytes webapp/images/emoji/1f471.png | Bin 5930 -> 0 bytes webapp/images/emoji/1f472.png | Bin 5264 -> 0 bytes webapp/images/emoji/1f473-200d-2640-fe0f.png | Bin 6170 -> 0 bytes webapp/images/emoji/1f473.png | Bin 6625 -> 0 bytes webapp/images/emoji/1f474.png | Bin 6158 -> 0 bytes webapp/images/emoji/1f475.png | Bin 7123 -> 0 bytes webapp/images/emoji/1f476.png | Bin 6664 -> 0 bytes webapp/images/emoji/1f477-200d-2640-fe0f.png | Bin 5999 -> 0 bytes webapp/images/emoji/1f477.png | Bin 5685 -> 0 bytes webapp/images/emoji/1f478.png | Bin 6226 -> 0 bytes webapp/images/emoji/1f479.png | Bin 9528 -> 0 bytes webapp/images/emoji/1f47a.png | Bin 12225 -> 0 bytes webapp/images/emoji/1f47b.png | Bin 6715 -> 0 bytes webapp/images/emoji/1f47c.png | Bin 6488 -> 0 bytes webapp/images/emoji/1f47d.png | Bin 5815 -> 0 bytes webapp/images/emoji/1f47e.png | Bin 4247 -> 0 bytes webapp/images/emoji/1f47f.png | Bin 7197 -> 0 bytes webapp/images/emoji/1f480.png | Bin 5570 -> 0 bytes webapp/images/emoji/1f481-200d-2642-fe0f.png | Bin 6021 -> 0 bytes webapp/images/emoji/1f481.png | Bin 7111 -> 0 bytes webapp/images/emoji/1f482-200d-2640-fe0f.png | Bin 6110 -> 0 bytes webapp/images/emoji/1f482.png | Bin 6135 -> 0 bytes webapp/images/emoji/1f483.png | Bin 6576 -> 0 bytes webapp/images/emoji/1f484.png | Bin 3310 -> 0 bytes webapp/images/emoji/1f485.png | Bin 5539 -> 0 bytes webapp/images/emoji/1f486-200d-2642-fe0f.png | Bin 6357 -> 0 bytes webapp/images/emoji/1f486.png | Bin 7675 -> 0 bytes webapp/images/emoji/1f487-200d-2642-fe0f.png | Bin 6250 -> 0 bytes webapp/images/emoji/1f487.png | Bin 7479 -> 0 bytes webapp/images/emoji/1f488.png | Bin 4891 -> 0 bytes webapp/images/emoji/1f489.png | Bin 3484 -> 0 bytes webapp/images/emoji/1f48a.png | Bin 5592 -> 0 bytes webapp/images/emoji/1f48b.png | Bin 6049 -> 0 bytes webapp/images/emoji/1f48c.png | Bin 3691 -> 0 bytes webapp/images/emoji/1f48d.png | Bin 5848 -> 0 bytes webapp/images/emoji/1f48e.png | Bin 5543 -> 0 bytes webapp/images/emoji/1f48f.png | Bin 7299 -> 0 bytes webapp/images/emoji/1f490.png | Bin 8301 -> 0 bytes webapp/images/emoji/1f491.png | Bin 8059 -> 0 bytes webapp/images/emoji/1f492.png | Bin 5207 -> 0 bytes webapp/images/emoji/1f493.png | Bin 3601 -> 0 bytes webapp/images/emoji/1f494.png | Bin 4744 -> 0 bytes webapp/images/emoji/1f495.png | Bin 3752 -> 0 bytes webapp/images/emoji/1f496.png | Bin 5413 -> 0 bytes webapp/images/emoji/1f497.png | Bin 6653 -> 0 bytes webapp/images/emoji/1f498.png | Bin 4747 -> 0 bytes webapp/images/emoji/1f499.png | Bin 3750 -> 0 bytes webapp/images/emoji/1f49a.png | Bin 4121 -> 0 bytes webapp/images/emoji/1f49b.png | Bin 3974 -> 0 bytes webapp/images/emoji/1f49c.png | Bin 3612 -> 0 bytes webapp/images/emoji/1f49d.png | Bin 6486 -> 0 bytes webapp/images/emoji/1f49e.png | Bin 4431 -> 0 bytes webapp/images/emoji/1f49f.png | Bin 3194 -> 0 bytes webapp/images/emoji/1f4a0.png | Bin 7513 -> 0 bytes webapp/images/emoji/1f4a1.png | Bin 3361 -> 0 bytes webapp/images/emoji/1f4a2.png | Bin 2973 -> 0 bytes webapp/images/emoji/1f4a3.png | Bin 6178 -> 0 bytes webapp/images/emoji/1f4a4.png | Bin 2024 -> 0 bytes webapp/images/emoji/1f4a5.png | Bin 5371 -> 0 bytes webapp/images/emoji/1f4a6.png | Bin 5322 -> 0 bytes webapp/images/emoji/1f4a7.png | Bin 3413 -> 0 bytes webapp/images/emoji/1f4a8.png | Bin 6105 -> 0 bytes webapp/images/emoji/1f4a9.png | Bin 5378 -> 0 bytes webapp/images/emoji/1f4aa.png | Bin 4185 -> 0 bytes webapp/images/emoji/1f4ab.png | Bin 4554 -> 0 bytes webapp/images/emoji/1f4ac.png | Bin 2289 -> 0 bytes webapp/images/emoji/1f4ad.png | Bin 4284 -> 0 bytes webapp/images/emoji/1f4ae.png | Bin 4785 -> 0 bytes webapp/images/emoji/1f4af.png | Bin 4284 -> 0 bytes webapp/images/emoji/1f4b0.png | Bin 5829 -> 0 bytes webapp/images/emoji/1f4b1.png | Bin 2101 -> 0 bytes webapp/images/emoji/1f4b2.png | Bin 1519 -> 0 bytes webapp/images/emoji/1f4b3.png | Bin 4157 -> 0 bytes webapp/images/emoji/1f4b4.png | Bin 10745 -> 0 bytes webapp/images/emoji/1f4b5.png | Bin 10632 -> 0 bytes webapp/images/emoji/1f4b6.png | Bin 10340 -> 0 bytes webapp/images/emoji/1f4b7.png | Bin 10049 -> 0 bytes webapp/images/emoji/1f4b8.png | Bin 8299 -> 0 bytes webapp/images/emoji/1f4b9.png | Bin 4213 -> 0 bytes webapp/images/emoji/1f4ba.png | Bin 6034 -> 0 bytes webapp/images/emoji/1f4bb.png | Bin 7448 -> 0 bytes webapp/images/emoji/1f4bc.png | Bin 5421 -> 0 bytes webapp/images/emoji/1f4bd.png | Bin 7297 -> 0 bytes webapp/images/emoji/1f4be.png | Bin 2914 -> 0 bytes webapp/images/emoji/1f4bf.png | Bin 6440 -> 0 bytes webapp/images/emoji/1f4c0.png | Bin 7431 -> 0 bytes webapp/images/emoji/1f4c1.png | Bin 4386 -> 0 bytes webapp/images/emoji/1f4c2.png | Bin 4762 -> 0 bytes webapp/images/emoji/1f4c3.png | Bin 2903 -> 0 bytes webapp/images/emoji/1f4c4.png | Bin 3285 -> 0 bytes webapp/images/emoji/1f4c5.png | Bin 3610 -> 0 bytes webapp/images/emoji/1f4c6.png | Bin 4679 -> 0 bytes webapp/images/emoji/1f4c7.png | Bin 5737 -> 0 bytes webapp/images/emoji/1f4c8.png | Bin 6615 -> 0 bytes webapp/images/emoji/1f4c9.png | Bin 6622 -> 0 bytes webapp/images/emoji/1f4ca.png | Bin 5121 -> 0 bytes webapp/images/emoji/1f4cb.png | Bin 4215 -> 0 bytes webapp/images/emoji/1f4cc.png | Bin 4877 -> 0 bytes webapp/images/emoji/1f4cd.png | Bin 3203 -> 0 bytes webapp/images/emoji/1f4ce.png | Bin 5637 -> 0 bytes webapp/images/emoji/1f4cf.png | Bin 3297 -> 0 bytes webapp/images/emoji/1f4d0.png | Bin 4142 -> 0 bytes webapp/images/emoji/1f4d1.png | Bin 3571 -> 0 bytes webapp/images/emoji/1f4d2.png | Bin 6592 -> 0 bytes webapp/images/emoji/1f4d3.png | Bin 5230 -> 0 bytes webapp/images/emoji/1f4d4.png | Bin 5331 -> 0 bytes webapp/images/emoji/1f4d5.png | Bin 5236 -> 0 bytes webapp/images/emoji/1f4d6.png | Bin 6276 -> 0 bytes webapp/images/emoji/1f4d7.png | Bin 5259 -> 0 bytes webapp/images/emoji/1f4d8.png | Bin 5221 -> 0 bytes webapp/images/emoji/1f4d9.png | Bin 4995 -> 0 bytes webapp/images/emoji/1f4da.png | Bin 6144 -> 0 bytes webapp/images/emoji/1f4db.png | Bin 29764 -> 0 bytes webapp/images/emoji/1f4dc.png | Bin 7618 -> 0 bytes webapp/images/emoji/1f4dd.png | Bin 7098 -> 0 bytes webapp/images/emoji/1f4de.png | Bin 4423 -> 0 bytes webapp/images/emoji/1f4df.png | Bin 5689 -> 0 bytes webapp/images/emoji/1f4e0.png | Bin 3767 -> 0 bytes webapp/images/emoji/1f4e1.png | Bin 7195 -> 0 bytes webapp/images/emoji/1f4e2.png | Bin 5461 -> 0 bytes webapp/images/emoji/1f4e3.png | Bin 6070 -> 0 bytes webapp/images/emoji/1f4e4.png | Bin 4534 -> 0 bytes webapp/images/emoji/1f4e5.png | Bin 4443 -> 0 bytes webapp/images/emoji/1f4e6.png | Bin 6158 -> 0 bytes webapp/images/emoji/1f4e7.png | Bin 3209 -> 0 bytes webapp/images/emoji/1f4e8.png | Bin 5269 -> 0 bytes webapp/images/emoji/1f4e9.png | Bin 3558 -> 0 bytes webapp/images/emoji/1f4ea.png | Bin 4333 -> 0 bytes webapp/images/emoji/1f4eb.png | Bin 4440 -> 0 bytes webapp/images/emoji/1f4ec.png | Bin 5050 -> 0 bytes webapp/images/emoji/1f4ed.png | Bin 4338 -> 0 bytes webapp/images/emoji/1f4ee.png | Bin 3808 -> 0 bytes webapp/images/emoji/1f4ef.png | Bin 5040 -> 0 bytes webapp/images/emoji/1f4f0.png | Bin 4487 -> 0 bytes webapp/images/emoji/1f4f1.png | Bin 4085 -> 0 bytes webapp/images/emoji/1f4f2.png | Bin 4793 -> 0 bytes webapp/images/emoji/1f4f3.png | Bin 3276 -> 0 bytes webapp/images/emoji/1f4f4.png | Bin 3577 -> 0 bytes webapp/images/emoji/1f4f5.png | Bin 6451 -> 0 bytes webapp/images/emoji/1f4f6.png | Bin 2803 -> 0 bytes webapp/images/emoji/1f4f7.png | Bin 4620 -> 0 bytes webapp/images/emoji/1f4f8.png | Bin 5964 -> 0 bytes webapp/images/emoji/1f4f9.png | Bin 5450 -> 0 bytes webapp/images/emoji/1f4fa.png | Bin 7701 -> 0 bytes webapp/images/emoji/1f4fb.png | Bin 5561 -> 0 bytes webapp/images/emoji/1f4fc.png | Bin 4087 -> 0 bytes webapp/images/emoji/1f4fd.png | Bin 7363 -> 0 bytes webapp/images/emoji/1f4ff.png | Bin 5137 -> 0 bytes webapp/images/emoji/1f500.png | Bin 3934 -> 0 bytes webapp/images/emoji/1f501.png | Bin 3778 -> 0 bytes webapp/images/emoji/1f502.png | Bin 4052 -> 0 bytes webapp/images/emoji/1f503.png | Bin 3993 -> 0 bytes webapp/images/emoji/1f504.png | Bin 4456 -> 0 bytes webapp/images/emoji/1f505.png | Bin 3143 -> 0 bytes webapp/images/emoji/1f506.png | Bin 3842 -> 0 bytes webapp/images/emoji/1f507.png | Bin 6578 -> 0 bytes webapp/images/emoji/1f508.png | Bin 6212 -> 0 bytes webapp/images/emoji/1f509.png | Bin 7305 -> 0 bytes webapp/images/emoji/1f50a.png | Bin 8397 -> 0 bytes webapp/images/emoji/1f50b.png | Bin 5443 -> 0 bytes webapp/images/emoji/1f50c.png | Bin 4692 -> 0 bytes webapp/images/emoji/1f50d.png | Bin 5646 -> 0 bytes webapp/images/emoji/1f50e.png | Bin 5945 -> 0 bytes webapp/images/emoji/1f50f.png | Bin 7181 -> 0 bytes webapp/images/emoji/1f510.png | Bin 5844 -> 0 bytes webapp/images/emoji/1f511.png | Bin 4937 -> 0 bytes webapp/images/emoji/1f512.png | Bin 4142 -> 0 bytes webapp/images/emoji/1f513.png | Bin 4380 -> 0 bytes webapp/images/emoji/1f514.png | Bin 5815 -> 0 bytes webapp/images/emoji/1f515.png | Bin 6547 -> 0 bytes webapp/images/emoji/1f516.png | Bin 4764 -> 0 bytes webapp/images/emoji/1f517.png | Bin 6040 -> 0 bytes webapp/images/emoji/1f518.png | Bin 3177 -> 0 bytes webapp/images/emoji/1f519.png | Bin 2307 -> 0 bytes webapp/images/emoji/1f51a.png | Bin 1656 -> 0 bytes webapp/images/emoji/1f51b.png | Bin 1972 -> 0 bytes webapp/images/emoji/1f51c.png | Bin 2255 -> 0 bytes webapp/images/emoji/1f51d.png | Bin 1566 -> 0 bytes webapp/images/emoji/1f51e.png | Bin 6714 -> 0 bytes webapp/images/emoji/1f51f.png | Bin 3798 -> 0 bytes webapp/images/emoji/1f520.png | Bin 4890 -> 0 bytes webapp/images/emoji/1f521.png | Bin 4567 -> 0 bytes webapp/images/emoji/1f522.png | Bin 4447 -> 0 bytes webapp/images/emoji/1f523.png | Bin 4578 -> 0 bytes webapp/images/emoji/1f524.png | Bin 3763 -> 0 bytes webapp/images/emoji/1f525.png | Bin 5190 -> 0 bytes webapp/images/emoji/1f526.png | Bin 5354 -> 0 bytes webapp/images/emoji/1f527.png | Bin 3658 -> 0 bytes webapp/images/emoji/1f528.png | Bin 3437 -> 0 bytes webapp/images/emoji/1f529.png | Bin 5507 -> 0 bytes webapp/images/emoji/1f52a.png | Bin 3593 -> 0 bytes webapp/images/emoji/1f52b.png | Bin 4854 -> 0 bytes webapp/images/emoji/1f52c.png | Bin 6408 -> 0 bytes webapp/images/emoji/1f52d.png | Bin 5120 -> 0 bytes webapp/images/emoji/1f52e.png | Bin 7141 -> 0 bytes webapp/images/emoji/1f52f.png | Bin 4578 -> 0 bytes webapp/images/emoji/1f530.png | Bin 4546 -> 0 bytes webapp/images/emoji/1f531.png | Bin 5547 -> 0 bytes webapp/images/emoji/1f532.png | Bin 1117 -> 0 bytes webapp/images/emoji/1f533.png | Bin 809 -> 0 bytes webapp/images/emoji/1f534.png | Bin 2704 -> 0 bytes webapp/images/emoji/1f535.png | Bin 2785 -> 0 bytes webapp/images/emoji/1f536.png | Bin 1848 -> 0 bytes webapp/images/emoji/1f537.png | Bin 2154 -> 0 bytes webapp/images/emoji/1f538.png | Bin 1602 -> 0 bytes webapp/images/emoji/1f539.png | Bin 1762 -> 0 bytes webapp/images/emoji/1f53a.png | Bin 1408 -> 0 bytes webapp/images/emoji/1f53b.png | Bin 1549 -> 0 bytes webapp/images/emoji/1f53c.png | Bin 2570 -> 0 bytes webapp/images/emoji/1f53d.png | Bin 2547 -> 0 bytes webapp/images/emoji/1f549.png | Bin 5086 -> 0 bytes webapp/images/emoji/1f54a.png | Bin 5480 -> 0 bytes webapp/images/emoji/1f54b.png | Bin 4611 -> 0 bytes webapp/images/emoji/1f54c.png | Bin 6277 -> 0 bytes webapp/images/emoji/1f54d.png | Bin 7467 -> 0 bytes webapp/images/emoji/1f54e.png | Bin 5619 -> 0 bytes webapp/images/emoji/1f550.png | Bin 6075 -> 0 bytes webapp/images/emoji/1f551.png | Bin 6156 -> 0 bytes webapp/images/emoji/1f552.png | Bin 5936 -> 0 bytes webapp/images/emoji/1f553.png | Bin 6184 -> 0 bytes webapp/images/emoji/1f554.png | Bin 6054 -> 0 bytes webapp/images/emoji/1f555.png | Bin 5939 -> 0 bytes webapp/images/emoji/1f556.png | Bin 6065 -> 0 bytes webapp/images/emoji/1f557.png | Bin 6147 -> 0 bytes webapp/images/emoji/1f558.png | Bin 5997 -> 0 bytes webapp/images/emoji/1f559.png | Bin 6237 -> 0 bytes webapp/images/emoji/1f55a.png | Bin 6101 -> 0 bytes webapp/images/emoji/1f55b.png | Bin 5973 -> 0 bytes webapp/images/emoji/1f55c.png | Bin 6051 -> 0 bytes webapp/images/emoji/1f55d.png | Bin 6118 -> 0 bytes webapp/images/emoji/1f55e.png | Bin 5976 -> 0 bytes webapp/images/emoji/1f55f.png | Bin 6206 -> 0 bytes webapp/images/emoji/1f560.png | Bin 6022 -> 0 bytes webapp/images/emoji/1f561.png | Bin 5928 -> 0 bytes webapp/images/emoji/1f562.png | Bin 6056 -> 0 bytes webapp/images/emoji/1f563.png | Bin 6117 -> 0 bytes webapp/images/emoji/1f564.png | Bin 5974 -> 0 bytes webapp/images/emoji/1f565.png | Bin 6164 -> 0 bytes webapp/images/emoji/1f566.png | Bin 6033 -> 0 bytes webapp/images/emoji/1f567.png | Bin 5939 -> 0 bytes webapp/images/emoji/1f56f.png | Bin 4310 -> 0 bytes webapp/images/emoji/1f570.png | Bin 7600 -> 0 bytes webapp/images/emoji/1f573.png | Bin 1853 -> 0 bytes webapp/images/emoji/1f574.png | Bin 4614 -> 0 bytes webapp/images/emoji/1f575-fe0f-200d-2640-fe0f.png | Bin 6852 -> 0 bytes webapp/images/emoji/1f575-fe0f.png | Bin 6793 -> 0 bytes webapp/images/emoji/1f576.png | Bin 3010 -> 0 bytes webapp/images/emoji/1f577.png | Bin 4741 -> 0 bytes webapp/images/emoji/1f578.png | Bin 4637 -> 0 bytes webapp/images/emoji/1f579.png | Bin 4460 -> 0 bytes webapp/images/emoji/1f57a.png | Bin 4371 -> 0 bytes webapp/images/emoji/1f587.png | Bin 7106 -> 0 bytes webapp/images/emoji/1f58a.png | Bin 4483 -> 0 bytes webapp/images/emoji/1f58b.png | Bin 4800 -> 0 bytes webapp/images/emoji/1f58c.png | Bin 4598 -> 0 bytes webapp/images/emoji/1f58d.png | Bin 3595 -> 0 bytes webapp/images/emoji/1f590.png | Bin 5064 -> 0 bytes webapp/images/emoji/1f595.png | Bin 2746 -> 0 bytes webapp/images/emoji/1f596.png | Bin 4913 -> 0 bytes webapp/images/emoji/1f5a4.png | Bin 3250 -> 0 bytes webapp/images/emoji/1f5a5.png | Bin 2550 -> 0 bytes webapp/images/emoji/1f5a8.png | Bin 4679 -> 0 bytes webapp/images/emoji/1f5b1.png | Bin 2446 -> 0 bytes webapp/images/emoji/1f5b2.png | Bin 6272 -> 0 bytes webapp/images/emoji/1f5bc.png | Bin 6776 -> 0 bytes webapp/images/emoji/1f5c2.png | Bin 3158 -> 0 bytes webapp/images/emoji/1f5c3.png | Bin 4452 -> 0 bytes webapp/images/emoji/1f5c4.png | Bin 4070 -> 0 bytes webapp/images/emoji/1f5d1.png | Bin 10982 -> 0 bytes webapp/images/emoji/1f5d2.png | Bin 6020 -> 0 bytes webapp/images/emoji/1f5d3.png | Bin 5680 -> 0 bytes webapp/images/emoji/1f5dc.png | Bin 5515 -> 0 bytes webapp/images/emoji/1f5dd.png | Bin 4456 -> 0 bytes webapp/images/emoji/1f5de.png | Bin 4680 -> 0 bytes webapp/images/emoji/1f5e1.png | Bin 3192 -> 0 bytes webapp/images/emoji/1f5e3.png | Bin 4314 -> 0 bytes webapp/images/emoji/1f5ef.png | Bin 5641 -> 0 bytes webapp/images/emoji/1f5f3.png | Bin 5210 -> 0 bytes webapp/images/emoji/1f5fa.png | Bin 8459 -> 0 bytes webapp/images/emoji/1f5fb.png | Bin 3983 -> 0 bytes webapp/images/emoji/1f5fc.png | Bin 4248 -> 0 bytes webapp/images/emoji/1f5fd.png | Bin 4688 -> 0 bytes webapp/images/emoji/1f5fe.png | Bin 3337 -> 0 bytes webapp/images/emoji/1f5ff.png | Bin 6018 -> 0 bytes webapp/images/emoji/1f600.png | Bin 6109 -> 0 bytes webapp/images/emoji/1f601.png | Bin 6551 -> 0 bytes webapp/images/emoji/1f602.png | Bin 6931 -> 0 bytes webapp/images/emoji/1f603.png | Bin 6252 -> 0 bytes webapp/images/emoji/1f604.png | Bin 6282 -> 0 bytes webapp/images/emoji/1f605.png | Bin 6696 -> 0 bytes webapp/images/emoji/1f606.png | Bin 6466 -> 0 bytes webapp/images/emoji/1f607.png | Bin 7469 -> 0 bytes webapp/images/emoji/1f608.png | Bin 7260 -> 0 bytes webapp/images/emoji/1f609.png | Bin 6003 -> 0 bytes webapp/images/emoji/1f60a.png | Bin 5978 -> 0 bytes webapp/images/emoji/1f60b.png | Bin 6087 -> 0 bytes webapp/images/emoji/1f60c.png | Bin 6183 -> 0 bytes webapp/images/emoji/1f60d.png | Bin 6670 -> 0 bytes webapp/images/emoji/1f60e.png | Bin 6565 -> 0 bytes webapp/images/emoji/1f60f.png | Bin 6002 -> 0 bytes webapp/images/emoji/1f610.png | Bin 5393 -> 0 bytes webapp/images/emoji/1f611.png | Bin 5159 -> 0 bytes webapp/images/emoji/1f612.png | Bin 6064 -> 0 bytes webapp/images/emoji/1f613.png | Bin 6324 -> 0 bytes webapp/images/emoji/1f614.png | Bin 5912 -> 0 bytes webapp/images/emoji/1f615.png | Bin 5583 -> 0 bytes webapp/images/emoji/1f616.png | Bin 6107 -> 0 bytes webapp/images/emoji/1f617.png | Bin 5675 -> 0 bytes webapp/images/emoji/1f618.png | Bin 6457 -> 0 bytes webapp/images/emoji/1f619.png | Bin 5951 -> 0 bytes webapp/images/emoji/1f61a.png | Bin 6045 -> 0 bytes webapp/images/emoji/1f61b.png | Bin 6009 -> 0 bytes webapp/images/emoji/1f61c.png | Bin 6701 -> 0 bytes webapp/images/emoji/1f61d.png | Bin 6412 -> 0 bytes webapp/images/emoji/1f61e.png | Bin 5588 -> 0 bytes webapp/images/emoji/1f61f.png | Bin 6106 -> 0 bytes webapp/images/emoji/1f620.png | Bin 5860 -> 0 bytes webapp/images/emoji/1f621.png | Bin 4816 -> 0 bytes webapp/images/emoji/1f622.png | Bin 6367 -> 0 bytes webapp/images/emoji/1f623.png | Bin 6350 -> 0 bytes webapp/images/emoji/1f624.png | Bin 7166 -> 0 bytes webapp/images/emoji/1f625.png | Bin 6344 -> 0 bytes webapp/images/emoji/1f626.png | Bin 5634 -> 0 bytes webapp/images/emoji/1f627.png | Bin 5989 -> 0 bytes webapp/images/emoji/1f628.png | Bin 6393 -> 0 bytes webapp/images/emoji/1f629.png | Bin 6622 -> 0 bytes webapp/images/emoji/1f62a.png | Bin 6558 -> 0 bytes webapp/images/emoji/1f62b.png | Bin 6705 -> 0 bytes webapp/images/emoji/1f62c.png | Bin 6039 -> 0 bytes webapp/images/emoji/1f62d.png | Bin 6587 -> 0 bytes webapp/images/emoji/1f62e.png | Bin 5607 -> 0 bytes webapp/images/emoji/1f62f.png | Bin 5934 -> 0 bytes webapp/images/emoji/1f630.png | Bin 6754 -> 0 bytes webapp/images/emoji/1f631.png | Bin 7062 -> 0 bytes webapp/images/emoji/1f632.png | Bin 6104 -> 0 bytes webapp/images/emoji/1f633.png | Bin 7030 -> 0 bytes webapp/images/emoji/1f634.png | Bin 6491 -> 0 bytes webapp/images/emoji/1f635.png | Bin 6619 -> 0 bytes webapp/images/emoji/1f636.png | Bin 5312 -> 0 bytes webapp/images/emoji/1f637.png | Bin 5992 -> 0 bytes webapp/images/emoji/1f638.png | Bin 6320 -> 0 bytes webapp/images/emoji/1f639.png | Bin 7135 -> 0 bytes webapp/images/emoji/1f63a.png | Bin 6231 -> 0 bytes webapp/images/emoji/1f63b.png | Bin 6529 -> 0 bytes webapp/images/emoji/1f63c.png | Bin 6181 -> 0 bytes webapp/images/emoji/1f63d.png | Bin 6276 -> 0 bytes webapp/images/emoji/1f63e.png | Bin 6254 -> 0 bytes webapp/images/emoji/1f63f.png | Bin 6566 -> 0 bytes webapp/images/emoji/1f640.png | Bin 7374 -> 0 bytes webapp/images/emoji/1f641.png | Bin 5696 -> 0 bytes webapp/images/emoji/1f642.png | Bin 5664 -> 0 bytes webapp/images/emoji/1f643.png | Bin 5651 -> 0 bytes webapp/images/emoji/1f644.png | Bin 6444 -> 0 bytes webapp/images/emoji/1f645-200d-2642-fe0f.png | Bin 7151 -> 0 bytes webapp/images/emoji/1f645.png | Bin 7507 -> 0 bytes webapp/images/emoji/1f646-200d-2642-fe0f.png | Bin 8155 -> 0 bytes webapp/images/emoji/1f646.png | Bin 7837 -> 0 bytes webapp/images/emoji/1f647-200d-2640-fe0f.png | Bin 6699 -> 0 bytes webapp/images/emoji/1f647.png | Bin 7210 -> 0 bytes webapp/images/emoji/1f648.png | Bin 7360 -> 0 bytes webapp/images/emoji/1f649.png | Bin 7365 -> 0 bytes webapp/images/emoji/1f64a.png | Bin 7166 -> 0 bytes webapp/images/emoji/1f64b-200d-2642-fe0f.png | Bin 6403 -> 0 bytes webapp/images/emoji/1f64b.png | Bin 7483 -> 0 bytes webapp/images/emoji/1f64c.png | Bin 5253 -> 0 bytes webapp/images/emoji/1f64d-200d-2642-fe0f.png | Bin 5073 -> 0 bytes webapp/images/emoji/1f64d.png | Bin 6053 -> 0 bytes webapp/images/emoji/1f64e-200d-2642-fe0f.png | Bin 5105 -> 0 bytes webapp/images/emoji/1f64e.png | Bin 6113 -> 0 bytes webapp/images/emoji/1f64f.png | Bin 4302 -> 0 bytes webapp/images/emoji/1f680.png | Bin 6469 -> 0 bytes webapp/images/emoji/1f681.png | Bin 5891 -> 0 bytes webapp/images/emoji/1f682.png | Bin 6659 -> 0 bytes webapp/images/emoji/1f683.png | Bin 5515 -> 0 bytes webapp/images/emoji/1f684.png | Bin 5306 -> 0 bytes webapp/images/emoji/1f685.png | Bin 4893 -> 0 bytes webapp/images/emoji/1f686.png | Bin 6161 -> 0 bytes webapp/images/emoji/1f687.png | Bin 6415 -> 0 bytes webapp/images/emoji/1f688.png | Bin 4908 -> 0 bytes webapp/images/emoji/1f689.png | Bin 5664 -> 0 bytes webapp/images/emoji/1f68a.png | Bin 5213 -> 0 bytes webapp/images/emoji/1f68b.png | Bin 4908 -> 0 bytes webapp/images/emoji/1f68c.png | Bin 6633 -> 0 bytes webapp/images/emoji/1f68d.png | Bin 5883 -> 0 bytes webapp/images/emoji/1f68e.png | Bin 6439 -> 0 bytes webapp/images/emoji/1f68f.png | Bin 4339 -> 0 bytes webapp/images/emoji/1f690.png | Bin 6339 -> 0 bytes webapp/images/emoji/1f691.png | Bin 6219 -> 0 bytes webapp/images/emoji/1f692.png | Bin 6062 -> 0 bytes webapp/images/emoji/1f693.png | Bin 5736 -> 0 bytes webapp/images/emoji/1f694.png | Bin 5338 -> 0 bytes webapp/images/emoji/1f695.png | Bin 6305 -> 0 bytes webapp/images/emoji/1f696.png | Bin 5918 -> 0 bytes webapp/images/emoji/1f697.png | Bin 5627 -> 0 bytes webapp/images/emoji/1f698.png | Bin 5623 -> 0 bytes webapp/images/emoji/1f699.png | Bin 6009 -> 0 bytes webapp/images/emoji/1f69a.png | Bin 4972 -> 0 bytes webapp/images/emoji/1f69b.png | Bin 6057 -> 0 bytes webapp/images/emoji/1f69c.png | Bin 6691 -> 0 bytes webapp/images/emoji/1f69d.png | Bin 5332 -> 0 bytes webapp/images/emoji/1f69e.png | Bin 7559 -> 0 bytes webapp/images/emoji/1f69f.png | Bin 5873 -> 0 bytes webapp/images/emoji/1f6a0.png | Bin 5761 -> 0 bytes webapp/images/emoji/1f6a1.png | Bin 4160 -> 0 bytes webapp/images/emoji/1f6a2.png | Bin 5060 -> 0 bytes webapp/images/emoji/1f6a3-200d-2640-fe0f.png | Bin 3465 -> 0 bytes webapp/images/emoji/1f6a3.png | Bin 3456 -> 0 bytes webapp/images/emoji/1f6a4.png | Bin 3073 -> 0 bytes webapp/images/emoji/1f6a5.png | Bin 4343 -> 0 bytes webapp/images/emoji/1f6a6.png | Bin 4553 -> 0 bytes webapp/images/emoji/1f6a7.png | Bin 6424 -> 0 bytes webapp/images/emoji/1f6a8.png | Bin 6405 -> 0 bytes webapp/images/emoji/1f6a9.png | Bin 3615 -> 0 bytes webapp/images/emoji/1f6aa.png | Bin 3230 -> 0 bytes webapp/images/emoji/1f6ab.png | Bin 6033 -> 0 bytes webapp/images/emoji/1f6ac.png | Bin 4692 -> 0 bytes webapp/images/emoji/1f6ad.png | Bin 6958 -> 0 bytes webapp/images/emoji/1f6ae.png | Bin 3615 -> 0 bytes webapp/images/emoji/1f6af.png | Bin 6702 -> 0 bytes webapp/images/emoji/1f6b0.png | Bin 4906 -> 0 bytes webapp/images/emoji/1f6b1.png | Bin 6618 -> 0 bytes webapp/images/emoji/1f6b2.png | Bin 5545 -> 0 bytes webapp/images/emoji/1f6b3.png | Bin 7493 -> 0 bytes webapp/images/emoji/1f6b4-200d-2640-fe0f.png | Bin 24396 -> 0 bytes webapp/images/emoji/1f6b4.png | Bin 10646 -> 0 bytes webapp/images/emoji/1f6b5-200d-2640-fe0f.png | Bin 11874 -> 0 bytes webapp/images/emoji/1f6b5.png | Bin 12300 -> 0 bytes webapp/images/emoji/1f6b6-200d-2640-fe0f.png | Bin 3290 -> 0 bytes webapp/images/emoji/1f6b6.png | Bin 3226 -> 0 bytes webapp/images/emoji/1f6b7.png | Bin 6520 -> 0 bytes webapp/images/emoji/1f6b8.png | Bin 4072 -> 0 bytes webapp/images/emoji/1f6b9.png | Bin 2637 -> 0 bytes webapp/images/emoji/1f6ba.png | Bin 3343 -> 0 bytes webapp/images/emoji/1f6bb.png | Bin 3777 -> 0 bytes webapp/images/emoji/1f6bc.png | Bin 2637 -> 0 bytes webapp/images/emoji/1f6bd.png | Bin 3796 -> 0 bytes webapp/images/emoji/1f6be.png | Bin 3850 -> 0 bytes webapp/images/emoji/1f6bf.png | Bin 6050 -> 0 bytes webapp/images/emoji/1f6c0.png | Bin 5514 -> 0 bytes webapp/images/emoji/1f6c1.png | Bin 6611 -> 0 bytes webapp/images/emoji/1f6c2.png | Bin 3480 -> 0 bytes webapp/images/emoji/1f6c3.png | Bin 3335 -> 0 bytes webapp/images/emoji/1f6c4.png | Bin 2993 -> 0 bytes webapp/images/emoji/1f6c5.png | Bin 3383 -> 0 bytes webapp/images/emoji/1f6cb.png | Bin 4962 -> 0 bytes webapp/images/emoji/1f6cc.png | Bin 4260 -> 0 bytes webapp/images/emoji/1f6cd.png | Bin 7668 -> 0 bytes webapp/images/emoji/1f6ce.png | Bin 6674 -> 0 bytes webapp/images/emoji/1f6cf.png | Bin 3227 -> 0 bytes webapp/images/emoji/1f6d0.png | Bin 3757 -> 0 bytes webapp/images/emoji/1f6d1.png | Bin 2061 -> 0 bytes webapp/images/emoji/1f6d2.png | Bin 6580 -> 0 bytes webapp/images/emoji/1f6e0.png | Bin 6383 -> 0 bytes webapp/images/emoji/1f6e1.png | Bin 5245 -> 0 bytes webapp/images/emoji/1f6e2.png | Bin 5958 -> 0 bytes webapp/images/emoji/1f6e3.png | Bin 5642 -> 0 bytes webapp/images/emoji/1f6e4.png | Bin 6930 -> 0 bytes webapp/images/emoji/1f6e5.png | Bin 5100 -> 0 bytes webapp/images/emoji/1f6e9.png | Bin 5952 -> 0 bytes webapp/images/emoji/1f6eb.png | Bin 3626 -> 0 bytes webapp/images/emoji/1f6ec.png | Bin 4219 -> 0 bytes webapp/images/emoji/1f6f0.png | Bin 6655 -> 0 bytes webapp/images/emoji/1f6f3.png | Bin 5239 -> 0 bytes webapp/images/emoji/1f6f4.png | Bin 3746 -> 0 bytes webapp/images/emoji/1f6f5.png | Bin 6575 -> 0 bytes webapp/images/emoji/1f6f6.png | Bin 3874 -> 0 bytes webapp/images/emoji/1f910.png | Bin 6739 -> 0 bytes webapp/images/emoji/1f911.png | Bin 6948 -> 0 bytes webapp/images/emoji/1f912.png | Bin 6729 -> 0 bytes webapp/images/emoji/1f913.png | Bin 6985 -> 0 bytes webapp/images/emoji/1f914.png | Bin 6291 -> 0 bytes webapp/images/emoji/1f915.png | Bin 6131 -> 0 bytes webapp/images/emoji/1f916.png | Bin 6319 -> 0 bytes webapp/images/emoji/1f917.png | Bin 7230 -> 0 bytes webapp/images/emoji/1f918.png | Bin 3862 -> 0 bytes webapp/images/emoji/1f919.png | Bin 4209 -> 0 bytes webapp/images/emoji/1f91a.png | Bin 4333 -> 0 bytes webapp/images/emoji/1f91b.png | Bin 3047 -> 0 bytes webapp/images/emoji/1f91c.png | Bin 3086 -> 0 bytes webapp/images/emoji/1f91d.png | Bin 5066 -> 0 bytes webapp/images/emoji/1f91e.png | Bin 4501 -> 0 bytes webapp/images/emoji/1f920.png | Bin 6692 -> 0 bytes webapp/images/emoji/1f921.png | Bin 8660 -> 0 bytes webapp/images/emoji/1f922.png | Bin 5298 -> 0 bytes webapp/images/emoji/1f923.png | Bin 6864 -> 0 bytes webapp/images/emoji/1f924.png | Bin 6241 -> 0 bytes webapp/images/emoji/1f925.png | Bin 6310 -> 0 bytes webapp/images/emoji/1f926-200d-2640-fe0f.png | Bin 7527 -> 0 bytes webapp/images/emoji/1f926-200d-2642-fe0f.png | Bin 6233 -> 0 bytes webapp/images/emoji/1f927.png | Bin 6843 -> 0 bytes webapp/images/emoji/1f930.png | Bin 5494 -> 0 bytes webapp/images/emoji/1f933.png | Bin 3330 -> 0 bytes webapp/images/emoji/1f934.png | Bin 5888 -> 0 bytes webapp/images/emoji/1f935.png | Bin 5547 -> 0 bytes webapp/images/emoji/1f936.png | Bin 6363 -> 0 bytes webapp/images/emoji/1f937-200d-2640-fe0f.png | Bin 6811 -> 0 bytes webapp/images/emoji/1f937-200d-2642-fe0f.png | Bin 6041 -> 0 bytes webapp/images/emoji/1f938-200d-2640-fe0f.png | Bin 3239 -> 0 bytes webapp/images/emoji/1f938-200d-2642-fe0f.png | Bin 3252 -> 0 bytes webapp/images/emoji/1f939-200d-2640-fe0f.png | Bin 6382 -> 0 bytes webapp/images/emoji/1f939-200d-2642-fe0f.png | Bin 6207 -> 0 bytes webapp/images/emoji/1f93a.png | Bin 5328 -> 0 bytes webapp/images/emoji/1f93c-200d-2640-fe0f.png | Bin 7955 -> 0 bytes webapp/images/emoji/1f93c-200d-2642-fe0f.png | Bin 7902 -> 0 bytes webapp/images/emoji/1f93d-200d-2640-fe0f.png | Bin 6072 -> 0 bytes webapp/images/emoji/1f93d-200d-2642-fe0f.png | Bin 5833 -> 0 bytes webapp/images/emoji/1f93e-200d-2640-fe0f.png | Bin 5204 -> 0 bytes webapp/images/emoji/1f93e-200d-2642-fe0f.png | Bin 5204 -> 0 bytes webapp/images/emoji/1f940.png | Bin 6181 -> 0 bytes webapp/images/emoji/1f941.png | Bin 6131 -> 0 bytes webapp/images/emoji/1f942.png | Bin 4212 -> 0 bytes webapp/images/emoji/1f943.png | Bin 5861 -> 0 bytes webapp/images/emoji/1f944.png | Bin 3419 -> 0 bytes webapp/images/emoji/1f945.png | Bin 5360 -> 0 bytes webapp/images/emoji/1f947.png | Bin 4240 -> 0 bytes webapp/images/emoji/1f948.png | Bin 3840 -> 0 bytes webapp/images/emoji/1f949.png | Bin 4828 -> 0 bytes webapp/images/emoji/1f94a.png | Bin 5168 -> 0 bytes webapp/images/emoji/1f94b.png | Bin 6178 -> 0 bytes webapp/images/emoji/1f950.png | Bin 6411 -> 0 bytes webapp/images/emoji/1f951.png | Bin 6946 -> 0 bytes webapp/images/emoji/1f952.png | Bin 6914 -> 0 bytes webapp/images/emoji/1f953.png | Bin 6973 -> 0 bytes webapp/images/emoji/1f954.png | Bin 6253 -> 0 bytes webapp/images/emoji/1f955.png | Bin 4500 -> 0 bytes webapp/images/emoji/1f956.png | Bin 4801 -> 0 bytes webapp/images/emoji/1f957.png | Bin 9882 -> 0 bytes webapp/images/emoji/1f958.png | Bin 8875 -> 0 bytes webapp/images/emoji/1f959.png | Bin 6157 -> 0 bytes webapp/images/emoji/1f95a.png | Bin 3201 -> 0 bytes webapp/images/emoji/1f95b.png | Bin 4163 -> 0 bytes webapp/images/emoji/1f95c.png | Bin 8169 -> 0 bytes webapp/images/emoji/1f95d.png | Bin 7892 -> 0 bytes webapp/images/emoji/1f95e.png | Bin 7129 -> 0 bytes webapp/images/emoji/1f980.png | Bin 7042 -> 0 bytes webapp/images/emoji/1f981.png | Bin 7969 -> 0 bytes webapp/images/emoji/1f982.png | Bin 5817 -> 0 bytes webapp/images/emoji/1f983.png | Bin 7684 -> 0 bytes webapp/images/emoji/1f984.png | Bin 6582 -> 0 bytes webapp/images/emoji/1f985.png | Bin 7045 -> 0 bytes webapp/images/emoji/1f986.png | Bin 5412 -> 0 bytes webapp/images/emoji/1f987.png | Bin 6116 -> 0 bytes webapp/images/emoji/1f988.png | Bin 5772 -> 0 bytes webapp/images/emoji/1f989.png | Bin 6492 -> 0 bytes webapp/images/emoji/1f98a.png | Bin 6521 -> 0 bytes webapp/images/emoji/1f98b.png | Bin 6865 -> 0 bytes webapp/images/emoji/1f98c.png | Bin 5673 -> 0 bytes webapp/images/emoji/1f98d.png | Bin 6454 -> 0 bytes webapp/images/emoji/1f98e.png | Bin 5315 -> 0 bytes webapp/images/emoji/1f98f.png | Bin 5299 -> 0 bytes webapp/images/emoji/1f990.png | Bin 8265 -> 0 bytes webapp/images/emoji/1f991.png | Bin 8416 -> 0 bytes webapp/images/emoji/1f9c0.png | Bin 4466 -> 0 bytes webapp/images/emoji/203c-fe0f.png | Bin 1837 -> 0 bytes webapp/images/emoji/2049-fe0f.png | Bin 2908 -> 0 bytes webapp/images/emoji/2122-fe0f.png | Bin 1047 -> 0 bytes webapp/images/emoji/2139-fe0f.png | Bin 2351 -> 0 bytes webapp/images/emoji/2194-fe0f.png | Bin 3280 -> 0 bytes webapp/images/emoji/2195-fe0f.png | Bin 3197 -> 0 bytes webapp/images/emoji/2196-fe0f.png | Bin 2754 -> 0 bytes webapp/images/emoji/2197-fe0f.png | Bin 2724 -> 0 bytes webapp/images/emoji/2198-fe0f.png | Bin 2752 -> 0 bytes webapp/images/emoji/2199-fe0f.png | Bin 2708 -> 0 bytes webapp/images/emoji/21a9-fe0f.png | Bin 3219 -> 0 bytes webapp/images/emoji/21aa-fe0f.png | Bin 3238 -> 0 bytes webapp/images/emoji/231a-fe0f.png | Bin 3952 -> 0 bytes webapp/images/emoji/231b-fe0f.png | Bin 5982 -> 0 bytes webapp/images/emoji/2328-fe0f.png | Bin 3505 -> 0 bytes webapp/images/emoji/23e9.png | Bin 2813 -> 0 bytes webapp/images/emoji/23ea.png | Bin 3105 -> 0 bytes webapp/images/emoji/23eb.png | Bin 2993 -> 0 bytes webapp/images/emoji/23ec.png | Bin 2994 -> 0 bytes webapp/images/emoji/23ed.png | Bin 3259 -> 0 bytes webapp/images/emoji/23ee.png | Bin 3267 -> 0 bytes webapp/images/emoji/23ef.png | Bin 3044 -> 0 bytes webapp/images/emoji/23f0.png | Bin 9039 -> 0 bytes webapp/images/emoji/23f1.png | Bin 7589 -> 0 bytes webapp/images/emoji/23f2.png | Bin 6514 -> 0 bytes webapp/images/emoji/23f3.png | Bin 6174 -> 0 bytes webapp/images/emoji/23f8.png | Bin 2442 -> 0 bytes webapp/images/emoji/23f9.png | Bin 2079 -> 0 bytes webapp/images/emoji/23fa.png | Bin 2802 -> 0 bytes webapp/images/emoji/24c2-fe0f.png | Bin 3606 -> 0 bytes webapp/images/emoji/25aa-fe0f.png | Bin 611 -> 0 bytes webapp/images/emoji/25ab-fe0f.png | Bin 318 -> 0 bytes webapp/images/emoji/25b6-fe0f.png | Bin 2762 -> 0 bytes webapp/images/emoji/25c0-fe0f.png | Bin 2736 -> 0 bytes webapp/images/emoji/25fb-fe0f.png | Bin 328 -> 0 bytes webapp/images/emoji/25fc-fe0f.png | Bin 342 -> 0 bytes webapp/images/emoji/25fd-fe0f.png | Bin 332 -> 0 bytes webapp/images/emoji/25fe-fe0f.png | Bin 327 -> 0 bytes webapp/images/emoji/2600-fe0f.png | Bin 4712 -> 0 bytes webapp/images/emoji/2601-fe0f.png | Bin 3259 -> 0 bytes webapp/images/emoji/2602-fe0f.png | Bin 3726 -> 0 bytes webapp/images/emoji/2603-fe0f.png | Bin 8122 -> 0 bytes webapp/images/emoji/2604-fe0f.png | Bin 6137 -> 0 bytes webapp/images/emoji/260e-fe0f.png | Bin 7650 -> 0 bytes webapp/images/emoji/2611-fe0f.png | Bin 3376 -> 0 bytes webapp/images/emoji/2614-fe0f.png | Bin 5282 -> 0 bytes webapp/images/emoji/2615-fe0f.png | Bin 5690 -> 0 bytes webapp/images/emoji/2618-fe0f.png | Bin 6576 -> 0 bytes webapp/images/emoji/261d-fe0f.png | Bin 3427 -> 0 bytes webapp/images/emoji/2620-fe0f.png | Bin 6774 -> 0 bytes webapp/images/emoji/2622-fe0f.png | Bin 3755 -> 0 bytes webapp/images/emoji/2623-fe0f.png | Bin 5506 -> 0 bytes webapp/images/emoji/2626-fe0f.png | Bin 2960 -> 0 bytes webapp/images/emoji/262a-fe0f.png | Bin 3988 -> 0 bytes webapp/images/emoji/262e-fe0f.png | Bin 4696 -> 0 bytes webapp/images/emoji/262f-fe0f.png | Bin 4635 -> 0 bytes webapp/images/emoji/2638-fe0f.png | Bin 5679 -> 0 bytes webapp/images/emoji/2639-fe0f.png | Bin 5752 -> 0 bytes webapp/images/emoji/263a-fe0f.png | Bin 5961 -> 0 bytes webapp/images/emoji/2648-fe0f.png | Bin 3934 -> 0 bytes webapp/images/emoji/2649-fe0f.png | Bin 4139 -> 0 bytes webapp/images/emoji/264a-fe0f.png | Bin 3436 -> 0 bytes webapp/images/emoji/264b-fe0f.png | Bin 4973 -> 0 bytes webapp/images/emoji/264c-fe0f.png | Bin 4652 -> 0 bytes webapp/images/emoji/264d-fe0f.png | Bin 4441 -> 0 bytes webapp/images/emoji/264e-fe0f.png | Bin 3553 -> 0 bytes webapp/images/emoji/264f-fe0f.png | Bin 3827 -> 0 bytes webapp/images/emoji/2650-fe0f.png | Bin 3992 -> 0 bytes webapp/images/emoji/2651-fe0f.png | Bin 4110 -> 0 bytes webapp/images/emoji/2652-fe0f.png | Bin 4318 -> 0 bytes webapp/images/emoji/2653-fe0f.png | Bin 3813 -> 0 bytes webapp/images/emoji/2660-fe0f.png | Bin 1932 -> 0 bytes webapp/images/emoji/2663-fe0f.png | Bin 2159 -> 0 bytes webapp/images/emoji/2665-fe0f.png | Bin 2919 -> 0 bytes webapp/images/emoji/2666-fe0f.png | Bin 2452 -> 0 bytes webapp/images/emoji/2668-fe0f.png | Bin 3343 -> 0 bytes webapp/images/emoji/267b-fe0f.png | Bin 3715 -> 0 bytes webapp/images/emoji/267f-fe0f.png | Bin 4258 -> 0 bytes webapp/images/emoji/2692.png | Bin 5365 -> 0 bytes webapp/images/emoji/2693-fe0f.png | Bin 4420 -> 0 bytes webapp/images/emoji/2694-fe0f.png | Bin 5318 -> 0 bytes webapp/images/emoji/2696-fe0f.png | Bin 6182 -> 0 bytes webapp/images/emoji/2697-fe0f.png | Bin 6269 -> 0 bytes webapp/images/emoji/2699-fe0f.png | Bin 6252 -> 0 bytes webapp/images/emoji/269b-fe0f.png | Bin 5915 -> 0 bytes webapp/images/emoji/269c-fe0f.png | Bin 5059 -> 0 bytes webapp/images/emoji/26a0-fe0f.png | Bin 2460 -> 0 bytes webapp/images/emoji/26a1-fe0f.png | Bin 2362 -> 0 bytes webapp/images/emoji/26aa-fe0f.png | Bin 1288 -> 0 bytes webapp/images/emoji/26ab-fe0f.png | Bin 1882 -> 0 bytes webapp/images/emoji/26b0-fe0f.png | Bin 6269 -> 0 bytes webapp/images/emoji/26b1-fe0f.png | Bin 5024 -> 0 bytes webapp/images/emoji/26bd-fe0f.png | Bin 4288 -> 0 bytes webapp/images/emoji/26be-fe0f.png | Bin 7485 -> 0 bytes webapp/images/emoji/26c4-fe0f.png | Bin 6321 -> 0 bytes webapp/images/emoji/26c5-fe0f.png | Bin 4623 -> 0 bytes webapp/images/emoji/26c8.png | Bin 5506 -> 0 bytes webapp/images/emoji/26ce.png | Bin 3864 -> 0 bytes webapp/images/emoji/26cf.png | Bin 3087 -> 0 bytes webapp/images/emoji/26d1.png | Bin 5659 -> 0 bytes webapp/images/emoji/26d3.png | Bin 7260 -> 0 bytes webapp/images/emoji/26d4-fe0f.png | Bin 4833 -> 0 bytes webapp/images/emoji/26e9.png | Bin 3596 -> 0 bytes webapp/images/emoji/26ea-fe0f.png | Bin 5415 -> 0 bytes webapp/images/emoji/26f0.png | Bin 5603 -> 0 bytes webapp/images/emoji/26f1.png | Bin 4587 -> 0 bytes webapp/images/emoji/26f2-fe0f.png | Bin 5692 -> 0 bytes webapp/images/emoji/26f3-fe0f.png | Bin 3452 -> 0 bytes webapp/images/emoji/26f4.png | Bin 5351 -> 0 bytes webapp/images/emoji/26f5-fe0f.png | Bin 4407 -> 0 bytes webapp/images/emoji/26f7.png | Bin 5091 -> 0 bytes webapp/images/emoji/26f8.png | Bin 5658 -> 0 bytes webapp/images/emoji/26f9-fe0f-200d-2640-fe0f.png | Bin 5880 -> 0 bytes webapp/images/emoji/26f9-fe0f.png | Bin 5579 -> 0 bytes webapp/images/emoji/26fa-fe0f.png | Bin 4629 -> 0 bytes webapp/images/emoji/26fd-fe0f.png | Bin 5904 -> 0 bytes webapp/images/emoji/2702-fe0f.png | Bin 6259 -> 0 bytes webapp/images/emoji/2705.png | Bin 2689 -> 0 bytes webapp/images/emoji/2708-fe0f.png | Bin 6996 -> 0 bytes webapp/images/emoji/2709-fe0f.png | Bin 2516 -> 0 bytes webapp/images/emoji/270a.png | Bin 4436 -> 0 bytes webapp/images/emoji/270b.png | Bin 4718 -> 0 bytes webapp/images/emoji/270c-fe0f.png | Bin 4714 -> 0 bytes webapp/images/emoji/270d-fe0f.png | Bin 4523 -> 0 bytes webapp/images/emoji/270f-fe0f.png | Bin 4382 -> 0 bytes webapp/images/emoji/2712-fe0f.png | Bin 4757 -> 0 bytes webapp/images/emoji/2714-fe0f.png | Bin 1176 -> 0 bytes webapp/images/emoji/2716-fe0f.png | Bin 616 -> 0 bytes webapp/images/emoji/271d-fe0f.png | Bin 2349 -> 0 bytes webapp/images/emoji/2721-fe0f.png | Bin 4243 -> 0 bytes webapp/images/emoji/2728.png | Bin 3122 -> 0 bytes webapp/images/emoji/2733-fe0f.png | Bin 3137 -> 0 bytes webapp/images/emoji/2734-fe0f.png | Bin 3629 -> 0 bytes webapp/images/emoji/2744-fe0f.png | Bin 8096 -> 0 bytes webapp/images/emoji/2747-fe0f.png | Bin 2746 -> 0 bytes webapp/images/emoji/274c.png | Bin 1450 -> 0 bytes webapp/images/emoji/274e.png | Bin 2742 -> 0 bytes webapp/images/emoji/2753.png | Bin 1327 -> 0 bytes webapp/images/emoji/2754.png | Bin 1340 -> 0 bytes webapp/images/emoji/2755.png | Bin 1017 -> 0 bytes webapp/images/emoji/2757-fe0f.png | Bin 994 -> 0 bytes webapp/images/emoji/2763-fe0f.png | Bin 3180 -> 0 bytes webapp/images/emoji/2764-fe0f.png | Bin 4520 -> 0 bytes webapp/images/emoji/2795.png | Bin 512 -> 0 bytes webapp/images/emoji/2796.png | Bin 245 -> 0 bytes webapp/images/emoji/2797.png | Bin 497 -> 0 bytes webapp/images/emoji/27a1-fe0f.png | Bin 2685 -> 0 bytes webapp/images/emoji/27b0.png | Bin 1527 -> 0 bytes webapp/images/emoji/27bf.png | Bin 1607 -> 0 bytes webapp/images/emoji/2934-fe0f.png | Bin 2983 -> 0 bytes webapp/images/emoji/2935-fe0f.png | Bin 3012 -> 0 bytes webapp/images/emoji/2b05-fe0f.png | Bin 2701 -> 0 bytes webapp/images/emoji/2b06-fe0f.png | Bin 2704 -> 0 bytes webapp/images/emoji/2b07-fe0f.png | Bin 2720 -> 0 bytes webapp/images/emoji/2b1b-fe0f.png | Bin 907 -> 0 bytes webapp/images/emoji/2b1c-fe0f.png | Bin 318 -> 0 bytes webapp/images/emoji/2b50-fe0f.png | Bin 4296 -> 0 bytes webapp/images/emoji/2b55-fe0f.png | Bin 2931 -> 0 bytes webapp/images/emoji/3030-fe0f.png | Bin 964 -> 0 bytes webapp/images/emoji/303d-fe0f.png | Bin 2103 -> 0 bytes webapp/images/emoji/3297-fe0f.png | Bin 4093 -> 0 bytes webapp/images/emoji/3299-fe0f.png | Bin 5027 -> 0 bytes webapp/images/emoji/bowtie.png | Bin 2724 -> 0 bytes webapp/images/emoji/feelsgood.png | Bin 1135 -> 0 bytes webapp/images/emoji/finnadie.png | Bin 1151 -> 0 bytes webapp/images/emoji/goberserk.png | Bin 1266 -> 0 bytes webapp/images/emoji/godmode.png | Bin 1027 -> 0 bytes webapp/images/emoji/hurtrealbad.png | Bin 1375 -> 0 bytes webapp/images/emoji/mattermost.png | Bin 6576 -> 0 bytes webapp/images/emoji/neckbeard.png | Bin 3204 -> 0 bytes webapp/images/emoji/octocat.png | Bin 2468 -> 0 bytes webapp/images/emoji/rage1.png | Bin 1067 -> 0 bytes webapp/images/emoji/rage2.png | Bin 1066 -> 0 bytes webapp/images/emoji/rage3.png | Bin 1093 -> 0 bytes webapp/images/emoji/rage4.png | Bin 1196 -> 0 bytes webapp/images/emoji/shipit.png | Bin 4612 -> 0 bytes webapp/images/emoji/suspect.png | Bin 1004 -> 0 bytes webapp/images/emoji/trollface.png | Bin 2739 -> 0 bytes webapp/images/favicon/android-chrome-192x192.png | Bin 63268 -> 0 bytes webapp/images/favicon/apple-touch-icon-120x120.png | Bin 39527 -> 0 bytes webapp/images/favicon/apple-touch-icon-144x144.png | Bin 42510 -> 0 bytes webapp/images/favicon/apple-touch-icon-152x152.png | Bin 58512 -> 0 bytes webapp/images/favicon/apple-touch-icon-57x57.png | Bin 33180 -> 0 bytes webapp/images/favicon/apple-touch-icon-60x60.png | Bin 33245 -> 0 bytes webapp/images/favicon/apple-touch-icon-72x72.png | Bin 34794 -> 0 bytes webapp/images/favicon/apple-touch-icon-76x76.png | Bin 35229 -> 0 bytes webapp/images/favicon/favicon-16x16.png | Bin 18480 -> 0 bytes webapp/images/favicon/favicon-32x32.png | Bin 18877 -> 0 bytes webapp/images/favicon/favicon-96x96.png | Bin 20501 -> 0 bytes webapp/images/favicon/redfavicon-16x16.png | Bin 18484 -> 0 bytes webapp/images/filesOverlay.png | Bin 8392 -> 0 bytes webapp/images/gitlabLogo.png | Bin 3306 -> 0 bytes webapp/images/googleLogo.png | Bin 3519 -> 0 bytes webapp/images/icon50x50.png | Bin 16591 -> 0 bytes webapp/images/icon64x64.png | Bin 6576 -> 0 bytes webapp/images/icons/audio.png | Bin 4859 -> 0 bytes webapp/images/icons/code.png | Bin 4669 -> 0 bytes webapp/images/icons/excel.png | Bin 3648 -> 0 bytes webapp/images/icons/generic.png | Bin 6258 -> 0 bytes webapp/images/icons/image.png | Bin 3995 -> 0 bytes webapp/images/icons/patch.png | Bin 4956 -> 0 bytes webapp/images/icons/pdf.png | Bin 5683 -> 0 bytes webapp/images/icons/ppt.png | Bin 5588 -> 0 bytes webapp/images/icons/video.png | Bin 3593 -> 0 bytes webapp/images/icons/word.png | Bin 3674 -> 0 bytes webapp/images/img_trans.gif | Bin 43 -> 0 bytes webapp/images/incoming_webhook.jpg | Bin 5861 -> 0 bytes webapp/images/info__icon.png | Bin 1430 -> 0 bytes webapp/images/iphone-6-mockup.png | Bin 77346 -> 0 bytes webapp/images/load.gif | Bin 23305 -> 0 bytes webapp/images/logo-email.png | Bin 21529 -> 0 bytes webapp/images/logo.png | Bin 25177 -> 0 bytes webapp/images/logoWhite.png | Bin 20570 -> 0 bytes webapp/images/logo_compact.png | Bin 18160 -> 0 bytes webapp/images/next.png | Bin 1350 -> 0 bytes webapp/images/nexus-6p-mockup.png | Bin 60764 -> 0 bytes webapp/images/oauth_icon.png | Bin 22430 -> 0 bytes webapp/images/office365Logo.png | Bin 633 -> 0 bytes webapp/images/outgoing_webhook.jpg | Bin 5891 -> 0 bytes webapp/images/pixel.png | Bin 70 -> 0 bytes webapp/images/prev.png | Bin 1360 -> 0 bytes webapp/images/redfavicon.ico | Bin 15753 -> 0 bytes webapp/images/ring.mp3 | Bin 229995 -> 0 bytes webapp/images/slash_command_icon.jpg | Bin 9218 -> 0 bytes webapp/images/status_green.png | Bin 471 -> 0 bytes webapp/images/status_red.png | Bin 468 -> 0 bytes webapp/images/status_yellow.png | Bin 476 -> 0 bytes webapp/images/test.png | Bin 279591 -> 0 bytes webapp/images/testgif.gif | Bin 38689 -> 0 bytes webapp/images/testjpg.jpg | Bin 70920 -> 0 bytes webapp/images/themes/code_themes/github.png | Bin 83246 -> 0 bytes webapp/images/themes/code_themes/monokai.png | Bin 82658 -> 0 bytes .../images/themes/code_themes/solarized-dark.png | Bin 81942 -> 0 bytes .../images/themes/code_themes/solarized-light.png | Bin 82868 -> 0 bytes webapp/images/themes/mattermost.png | Bin 82860 -> 0 bytes webapp/images/themes/mattermost_dark.png | Bin 104882 -> 0 bytes webapp/images/themes/organization.png | Bin 127558 -> 0 bytes webapp/images/themes/windows_dark.png | Bin 122145 -> 0 bytes webapp/images/tutorialTip.gif | Bin 22502 -> 0 bytes webapp/images/tutorialTipWhite.gif | Bin 6704 -> 0 bytes webapp/images/warning.png | Bin 1046 -> 0 bytes webapp/images/webhook_icon.jpg | Bin 20565 -> 0 bytes webapp/make-emojis | 194 - webapp/non_npm_dependencies/janus/index.js | 2293 --- .../jquery-dragster/jquery.dragster.js | 85 - webapp/non_npm_dependencies/katex/LICENSE.txt | 27 - webapp/non_npm_dependencies/katex/README.md | 68 - webapp/non_npm_dependencies/katex/cli.js | 32 - webapp/non_npm_dependencies/katex/dist/README.md | 68 - .../katex/dist/contrib/auto-render.min.js | 1 - .../katex/dist/fonts/KaTeX_AMS-Regular.eot | Bin 71656 -> 0 bytes .../katex/dist/fonts/KaTeX_AMS-Regular.ttf | Bin 71428 -> 0 bytes .../katex/dist/fonts/KaTeX_AMS-Regular.woff | Bin 40200 -> 0 bytes .../katex/dist/fonts/KaTeX_AMS-Regular.woff2 | Bin 33188 -> 0 bytes .../katex/dist/fonts/KaTeX_Caligraphic-Bold.eot | Bin 19836 -> 0 bytes .../katex/dist/fonts/KaTeX_Caligraphic-Bold.ttf | Bin 19588 -> 0 bytes .../katex/dist/fonts/KaTeX_Caligraphic-Bold.woff | Bin 12136 -> 0 bytes .../katex/dist/fonts/KaTeX_Caligraphic-Bold.woff2 | Bin 10604 -> 0 bytes .../katex/dist/fonts/KaTeX_Caligraphic-Regular.eot | Bin 19220 -> 0 bytes .../katex/dist/fonts/KaTeX_Caligraphic-Regular.ttf | Bin 18960 -> 0 bytes .../dist/fonts/KaTeX_Caligraphic-Regular.woff | Bin 11868 -> 0 bytes .../dist/fonts/KaTeX_Caligraphic-Regular.woff2 | Bin 10396 -> 0 bytes .../katex/dist/fonts/KaTeX_Fraktur-Bold.eot | Bin 36200 -> 0 bytes .../katex/dist/fonts/KaTeX_Fraktur-Bold.ttf | Bin 35968 -> 0 bytes .../katex/dist/fonts/KaTeX_Fraktur-Bold.woff | Bin 23388 -> 0 bytes .../katex/dist/fonts/KaTeX_Fraktur-Bold.woff2 | Bin 20476 -> 0 bytes .../katex/dist/fonts/KaTeX_Fraktur-Regular.eot | Bin 34896 -> 0 bytes .../katex/dist/fonts/KaTeX_Fraktur-Regular.ttf | Bin 34652 -> 0 bytes .../katex/dist/fonts/KaTeX_Fraktur-Regular.woff | Bin 22844 -> 0 bytes .../katex/dist/fonts/KaTeX_Fraktur-Regular.woff2 | Bin 19868 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Bold.eot | Bin 60688 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Bold.ttf | Bin 60468 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Bold.woff | Bin 35480 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Bold.woff2 | Bin 29492 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Italic.eot | Bin 44132 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Italic.ttf | Bin 43904 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Italic.woff | Bin 24880 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Italic.woff2 | Bin 21032 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Regular.eot | Bin 68228 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Regular.ttf | Bin 67996 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Regular.woff | Bin 37620 -> 0 bytes .../katex/dist/fonts/KaTeX_Main-Regular.woff2 | Bin 31220 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-BoldItalic.eot | Bin 39990 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-BoldItalic.ttf | Bin 39744 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-BoldItalic.woff | Bin 23192 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-BoldItalic.woff2 | Bin 20036 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-Italic.eot | Bin 41676 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-Italic.ttf | Bin 41448 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-Italic.woff | Bin 23820 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-Italic.woff2 | Bin 20432 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-Regular.eot | Bin 41536 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-Regular.ttf | Bin 41304 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-Regular.woff | Bin 23712 -> 0 bytes .../katex/dist/fonts/KaTeX_Math-Regular.woff2 | Bin 20344 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Bold.eot | Bin 34204 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Bold.ttf | Bin 33964 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Bold.woff | Bin 19196 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Bold.woff2 | Bin 16020 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Italic.eot | Bin 31320 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Italic.ttf | Bin 31072 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Italic.woff | Bin 18080 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Italic.woff2 | Bin 15152 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Regular.eot | Bin 30212 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Regular.ttf | Bin 29960 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Regular.woff | Bin 16744 -> 0 bytes .../katex/dist/fonts/KaTeX_SansSerif-Regular.woff2 | Bin 13908 -> 0 bytes .../katex/dist/fonts/KaTeX_Script-Regular.eot | Bin 25104 -> 0 bytes .../katex/dist/fonts/KaTeX_Script-Regular.ttf | Bin 24864 -> 0 bytes .../katex/dist/fonts/KaTeX_Script-Regular.woff | Bin 13856 -> 0 bytes .../katex/dist/fonts/KaTeX_Script-Regular.woff2 | Bin 12276 -> 0 bytes .../katex/dist/fonts/KaTeX_Size1-Regular.eot | Bin 13408 -> 0 bytes .../katex/dist/fonts/KaTeX_Size1-Regular.ttf | Bin 13172 -> 0 bytes .../katex/dist/fonts/KaTeX_Size1-Regular.woff | Bin 6980 -> 0 bytes .../katex/dist/fonts/KaTeX_Size1-Regular.woff2 | Bin 5820 -> 0 bytes .../katex/dist/fonts/KaTeX_Size2-Regular.eot | Bin 12648 -> 0 bytes .../katex/dist/fonts/KaTeX_Size2-Regular.ttf | Bin 12412 -> 0 bytes .../katex/dist/fonts/KaTeX_Size2-Regular.woff | Bin 6684 -> 0 bytes .../katex/dist/fonts/KaTeX_Size2-Regular.woff2 | Bin 5560 -> 0 bytes .../katex/dist/fonts/KaTeX_Size3-Regular.eot | Bin 8596 -> 0 bytes .../katex/dist/fonts/KaTeX_Size3-Regular.ttf | Bin 8360 -> 0 bytes .../katex/dist/fonts/KaTeX_Size3-Regular.woff | Bin 4776 -> 0 bytes .../katex/dist/fonts/KaTeX_Size3-Regular.woff2 | Bin 3856 -> 0 bytes .../katex/dist/fonts/KaTeX_Size4-Regular.eot | Bin 11520 -> 0 bytes .../katex/dist/fonts/KaTeX_Size4-Regular.ttf | Bin 11284 -> 0 bytes .../katex/dist/fonts/KaTeX_Size4-Regular.woff | Bin 6456 -> 0 bytes .../katex/dist/fonts/KaTeX_Size4-Regular.woff2 | Bin 5172 -> 0 bytes .../katex/dist/fonts/KaTeX_Typewriter-Regular.eot | Bin 35784 -> 0 bytes .../katex/dist/fonts/KaTeX_Typewriter-Regular.ttf | Bin 35528 -> 0 bytes .../katex/dist/fonts/KaTeX_Typewriter-Regular.woff | Bin 20712 -> 0 bytes .../dist/fonts/KaTeX_Typewriter-Regular.woff2 | Bin 17344 -> 0 bytes .../non_npm_dependencies/katex/dist/katex.min.css | 1 - .../non_npm_dependencies/katex/dist/katex.min.js | 4 - webapp/non_npm_dependencies/katex/katex.js | 74 - webapp/non_npm_dependencies/katex/package.json | 41 - webapp/non_npm_dependencies/katex/src/Lexer.js | 162 - webapp/non_npm_dependencies/katex/src/Options.js | 189 - .../non_npm_dependencies/katex/src/ParseError.js | 40 - webapp/non_npm_dependencies/katex/src/Parser.js | 737 - webapp/non_npm_dependencies/katex/src/Settings.js | 28 - webapp/non_npm_dependencies/katex/src/Style.js | 126 - .../non_npm_dependencies/katex/src/buildCommon.js | 450 - webapp/non_npm_dependencies/katex/src/buildHTML.js | 1375 -- .../non_npm_dependencies/katex/src/buildMathML.js | 519 - webapp/non_npm_dependencies/katex/src/buildTree.js | 40 - webapp/non_npm_dependencies/katex/src/delimiter.js | 542 - webapp/non_npm_dependencies/katex/src/domTree.js | 269 - .../non_npm_dependencies/katex/src/environments.js | 221 - .../non_npm_dependencies/katex/src/fontMetrics.js | 147 - .../katex/src/fontMetricsData.js | 1752 -- webapp/non_npm_dependencies/katex/src/functions.js | 569 - .../non_npm_dependencies/katex/src/mathMLTree.js | 102 - webapp/non_npm_dependencies/katex/src/parseData.js | 13 - webapp/non_npm_dependencies/katex/src/parseTree.js | 17 - webapp/non_npm_dependencies/katex/src/symbols.js | 620 - webapp/non_npm_dependencies/katex/src/utils.js | 106 - webapp/package.json | 141 - webapp/plugins/index.js | 51 - webapp/plugins/jira/components/settings.jsx | 252 - webapp/plugins/jira/components/style.scss | 45 - webapp/plugins/pluggable/index.js | 17 - webapp/plugins/pluggable/pluggable.jsx | 57 - webapp/reducers/index.js | 10 - webapp/reducers/plugins/index.js | 22 - webapp/reducers/views/channel.js | 81 - webapp/reducers/views/index.js | 12 - webapp/reducers/views/rhs.js | 63 - webapp/root.html | 104 - webapp/root.jsx | 133 - webapp/routes/route_admin_console.jsx | 275 - webapp/routes/route_claim.jsx | 36 - webapp/routes/route_create_team.jsx | 25 - webapp/routes/route_emoji.jsx | 24 - webapp/routes/route_help.jsx | 66 - webapp/routes/route_integrations.jsx | 117 - webapp/routes/route_mfa.jsx | 24 - webapp/routes/route_root.jsx | 181 - webapp/routes/route_team.jsx | 347 - webapp/routes/route_utils.jsx | 43 - webapp/sass/base/_module.scss | 3 - webapp/sass/base/_structure.scss | 70 - webapp/sass/base/_typography.scss | 137 - webapp/sass/components/_alerts.scss | 13 - webapp/sass/components/_buttons.scss | 55 - webapp/sass/components/_dropdown.scss | 54 - webapp/sass/components/_emojisprite.scss | 1489 -- webapp/sass/components/_emoticons.scss | 233 - webapp/sass/components/_error-bar.scss | 55 - webapp/sass/components/_files.scss | 298 - webapp/sass/components/_inputs.scss | 71 - webapp/sass/components/_links.scss | 22 - webapp/sass/components/_mentions.scss | 112 - webapp/sass/components/_modal.scss | 700 - webapp/sass/components/_module.scss | 25 - webapp/sass/components/_multi-select.scss | 58 - webapp/sass/components/_oauth.scss | 47 - webapp/sass/components/_popover.scss | 348 - webapp/sass/components/_save-button.scss | 7 - webapp/sass/components/_scrollbar.scss | 78 - webapp/sass/components/_search.scss | 163 - webapp/sass/components/_spinner-button.scss | 8 - webapp/sass/components/_status-dropdown.scss | 5 - webapp/sass/components/_status-icon.scss | 97 - webapp/sass/components/_suggestion-list.scss | 92 - webapp/sass/components/_tooltip.scss | 22 - webapp/sass/components/_tutorial.scss | 239 - webapp/sass/components/_videos.scss | 95 - webapp/sass/components/_webrtc.scss | 331 - webapp/sass/layout/_content.scss | 95 - webapp/sass/layout/_footer.scss | 30 - webapp/sass/layout/_forms.scss | 93 - webapp/sass/layout/_headers.scss | 534 - webapp/sass/layout/_markdown.scss | 223 - webapp/sass/layout/_module.scss | 14 - webapp/sass/layout/_navigation.scss | 190 - webapp/sass/layout/_post-right.scss | 156 - webapp/sass/layout/_post.scss | 1642 -- webapp/sass/layout/_sidebar-left.scss | 372 - webapp/sass/layout/_sidebar-menu.scss | 95 - webapp/sass/layout/_sidebar-right.scss | 291 - webapp/sass/layout/_team-sidebar.scss | 124 - webapp/sass/layout/_webhooks.scss | 303 - webapp/sass/responsive/_desktop.scss | 96 - webapp/sass/responsive/_mobile.scss | 1886 -- webapp/sass/responsive/_module.scss | 4 - webapp/sass/responsive/_tablet.scss | 378 - webapp/sass/routes/_about-modal.scss | 116 - webapp/sass/routes/_access-history.scss | 32 - webapp/sass/routes/_activity-log.scss | 57 - webapp/sass/routes/_admin-console.scss | 673 - webapp/sass/routes/_backstage.scss | 437 - webapp/sass/routes/_compliance.scss | 39 - webapp/sass/routes/_docs.scss | 19 - webapp/sass/routes/_error-page.scss | 35 - webapp/sass/routes/_get-app.scss | 97 - webapp/sass/routes/_loading.scss | 51 - webapp/sass/routes/_module.scss | 16 - webapp/sass/routes/_print.scss | 123 - webapp/sass/routes/_settings.scss | 555 - webapp/sass/routes/_shortcuts-modal.scss | 102 - webapp/sass/routes/_signup.scss | 535 - webapp/sass/routes/_statistics.scss | 120 - webapp/sass/styles.scss | 20 - webapp/sass/utils/_animations.scss | 21 - webapp/sass/utils/_functions.scss | 33 - webapp/sass/utils/_mixins.scss | 38 - webapp/sass/utils/_modifiers.scss | 109 - webapp/sass/utils/_module.scss | 6 - webapp/sass/utils/_variables.scss | 29 - webapp/store/index.js | 117 - webapp/store/utils.js | 42 - webapp/stores/analytics_store.jsx | 58 - webapp/stores/browser_store.jsx | 208 - webapp/stores/channel_store.jsx | 585 - webapp/stores/emoji_store.jsx | 206 - webapp/stores/error_store.jsx | 110 - webapp/stores/integration_store.jsx | 103 - webapp/stores/localization_store.jsx | 60 - webapp/stores/message_history_store.jsx | 79 - webapp/stores/modal_store.jsx | 56 - webapp/stores/notification_store.jsx | 45 - webapp/stores/opengraph_store.jsx | 68 - webapp/stores/post_store.jsx | 242 - webapp/stores/preference_store.jsx | 181 - webapp/stores/redux_store.jsx | 19 - webapp/stores/search_store.jsx | 230 - webapp/stores/suggestion_store.jsx | 329 - webapp/stores/team_store.jsx | 470 - webapp/stores/user_store.jsx | 515 - webapp/stores/user_typing_store.jsx | 108 - webapp/stores/webrtc_store.jsx | 110 - webapp/tests/.eslintrc.json | 15 - .../__snapshots__/about_build_modal.test.jsx.snap | 370 - .../__snapshots__/new_channel_modal.test.jsx.snap | 751 - .../__snapshots__/reset_status_modal.test.jsx.snap | 54 - .../__snapshots__/shortcuts_modal.test.jsx.snap | 237 - .../__snapshots__/spinner_button.test.jsx.snap | 27 - webapp/tests/components/about_build_modal.test.jsx | 129 - .../__snapshots__/color_setting.test.jsx.snap | 95 - .../admin_console/color_setting.test.jsx | 55 - .../__snapshots__/request_button.test.jsx.snap | 496 - .../request_button/request_button.test.jsx | 215 - .../__snapshots__/backstage_header.test.jsx.snap | 31 - .../backstage/components/backstage_header.test.jsx | 26 - .../__snapshots__/add_command.test.jsx.snap | 396 - .../__snapshots__/add_incoming_hook.test.jsx.snap | 26 - .../__snapshots__/add_oauth_app.test.jsx.snap | 613 - .../__snapshots__/add_outgoing_hook.test.jsx.snap | 27 - .../__snapshots__/edit_command.test.jsx.snap | 424 - .../__snapshots__/edit_incoming_hook.test.jsx.snap | 7 - .../__snapshots__/edit_outgoing_hook.test.jsx.snap | 7 - .../__snapshots__/installed_command.test.jsx.snap | 103 - .../installed_oauth_app.test.jsx.snap | 155 - .../installed_oauth_apps.test.jsx.snap | 100 - .../components/integrations/add_command.test.jsx | 30 - .../integrations/add_incoming_hook.test.jsx | 29 - .../components/integrations/add_oauth_app.test.jsx | 81 - .../integrations/add_outgoing_hook.test.jsx | 29 - .../components/integrations/edit_command.test.jsx | 36 - .../integrations/edit_incoming_hook.test.jsx | 30 - .../integrations/edit_outgoing_hook.test.jsx | 31 - .../integrations/installed_command.test.jsx | 83 - .../integrations/installed_oauth_app.test.jsx | 71 - .../integrations/installed_oauth_apps.test.jsx | 57 - webapp/tests/components/new_channel_modal.test.jsx | 79 - .../__snapshots__/post_info.test.jsx.snap | 515 - .../post_view/post_info/post_info.test.jsx | 225 - .../tests/components/reset_status_modal.test.jsx | 29 - webapp/tests/components/shortcuts_modal.test.jsx | 25 - webapp/tests/components/spinner_button.test.jsx | 53 - .../components/suggestion/suggestion_box.test.jsx | 16 - webapp/tests/helpers/client-test-helper.jsx | 176 - webapp/tests/helpers/intl-test-helper.jsx | 22 - .../plugins/__snapshots__/pluggable.test.jsx.snap | 111 - webapp/tests/plugins/pluggable.test.jsx | 50 - webapp/tests/utils/channel_utils.test.jsx | 782 - webapp/tests/utils/emoticons.test.jsx | 36 - webapp/tests/utils/formatting_at_mentions.test.jsx | 58 - .../tests/utils/formatting_channel_links.test.jsx | 49 - webapp/tests/utils/formatting_hashtags.test.jsx | 198 - webapp/tests/utils/formatting_imgs.test.jsx | 53 - webapp/tests/utils/formatting_links.test.jsx | 516 - webapp/tests/utils/latinise.test.jsx | 23 - webapp/tests/utils/post_utils.test.jsx | 147 - .../tests/utils/utils_get_nearest_point.test.jsx | 31 - webapp/utils/channel_intro_messages.jsx | 389 - webapp/utils/channel_utils.jsx | 325 - webapp/utils/commons.jsx | 20 - webapp/utils/constants.jsx | 1004 - webapp/utils/delayed_action.jsx | 31 - webapp/utils/emoji.jsx | 15 - webapp/utils/emoticons.jsx | 66 - webapp/utils/event_types.jsx | 8 - webapp/utils/file_utils.jsx | 24 - webapp/utils/global_event_emitter.jsx | 27 - webapp/utils/latinise.jsx | 1003 - webapp/utils/license_utils.jsx | 39 - webapp/utils/markdown.jsx | 270 - webapp/utils/post_utils.jsx | 127 - webapp/utils/syntax_highlighting.jsx | 171 - webapp/utils/team_utils.jsx | 27 - webapp/utils/text_formatting.jsx | 504 - webapp/utils/url.jsx | 29 - webapp/utils/user_agent.jsx | 115 - webapp/utils/utils.jsx | 1441 -- webapp/webpack.config.js | 331 - webapp/yarn.lock | 8251 -------- 2396 files changed, 285726 deletions(-) delete mode 100644 webapp/.babelrc delete mode 100644 webapp/.eslintrc.json delete mode 100644 webapp/Makefile delete mode 100644 webapp/actions/admin_actions.jsx delete mode 100644 webapp/actions/channel_actions.jsx delete mode 100644 webapp/actions/diagnostics_actions.jsx delete mode 100644 webapp/actions/emoji_actions.jsx delete mode 100644 webapp/actions/file_actions.jsx delete mode 100644 webapp/actions/global_actions.jsx delete mode 100644 webapp/actions/integration_actions.jsx delete mode 100644 webapp/actions/job_actions.jsx delete mode 100644 webapp/actions/notification_actions.jsx delete mode 100644 webapp/actions/oauth_actions.jsx delete mode 100644 webapp/actions/post_actions.jsx delete mode 100644 webapp/actions/status_actions.jsx delete mode 100644 webapp/actions/team_actions.jsx delete mode 100644 webapp/actions/user_actions.jsx delete mode 100644 webapp/actions/webrtc_actions.jsx delete mode 100644 webapp/actions/websocket_actions.jsx delete mode 100644 webapp/client/web_websocket_client.jsx delete mode 100644 webapp/client/websocket_client.jsx delete mode 100644 webapp/components/about_build_modal.jsx delete mode 100644 webapp/components/access_history_modal/access_history_modal.jsx delete mode 100644 webapp/components/access_history_modal/index.js delete mode 100644 webapp/components/activity_log_modal/activity_log_modal.jsx delete mode 100644 webapp/components/activity_log_modal/index.js delete mode 100644 webapp/components/add_users_to_team/add_users_to_team.jsx delete mode 100644 webapp/components/add_users_to_team/index.js delete mode 100644 webapp/components/admin_console/admin_console.jsx delete mode 100644 webapp/components/admin_console/admin_navbar_dropdown.jsx delete mode 100644 webapp/components/admin_console/admin_settings.jsx delete mode 100644 webapp/components/admin_console/admin_sidebar.jsx delete mode 100644 webapp/components/admin_console/admin_sidebar_category.jsx delete mode 100644 webapp/components/admin_console/admin_sidebar_header.jsx delete mode 100644 webapp/components/admin_console/admin_sidebar_section.jsx delete mode 100644 webapp/components/admin_console/audits/audits.jsx delete mode 100644 webapp/components/admin_console/audits/index.js delete mode 100644 webapp/components/admin_console/banner.jsx delete mode 100644 webapp/components/admin_console/boolean_setting.jsx delete mode 100644 webapp/components/admin_console/brand_image_setting.jsx delete mode 100644 webapp/components/admin_console/client_versions_settings.jsx delete mode 100644 webapp/components/admin_console/cluster_settings.jsx delete mode 100644 webapp/components/admin_console/cluster_table.jsx delete mode 100644 webapp/components/admin_console/cluster_table_container.jsx delete mode 100644 webapp/components/admin_console/color_setting.jsx delete mode 100644 webapp/components/admin_console/compliance_reports/compliance_reports.jsx delete mode 100644 webapp/components/admin_console/compliance_reports/index.js delete mode 100644 webapp/components/admin_console/compliance_settings.jsx delete mode 100644 webapp/components/admin_console/configuration_settings.jsx delete mode 100644 webapp/components/admin_console/connection_security_dropdown_setting.jsx delete mode 100644 webapp/components/admin_console/connection_settings.jsx delete mode 100644 webapp/components/admin_console/custom_brand_settings.jsx delete mode 100644 webapp/components/admin_console/custom_emoji_settings.jsx delete mode 100644 webapp/components/admin_console/custom_integrations_settings.jsx delete mode 100644 webapp/components/admin_console/database_settings.jsx delete mode 100644 webapp/components/admin_console/developer_settings.jsx delete mode 100644 webapp/components/admin_console/dropdown_setting.jsx delete mode 100644 webapp/components/admin_console/elasticsearch_settings.jsx delete mode 100644 webapp/components/admin_console/elasticsearch_status/index.js delete mode 100644 webapp/components/admin_console/elasticsearch_status/status.jsx delete mode 100644 webapp/components/admin_console/email_authentication_settings.jsx delete mode 100644 webapp/components/admin_console/email_connection_test.jsx delete mode 100644 webapp/components/admin_console/email_settings.jsx delete mode 100644 webapp/components/admin_console/external_service_settings.jsx delete mode 100644 webapp/components/admin_console/file_upload_setting.jsx delete mode 100644 webapp/components/admin_console/generated_setting.jsx delete mode 100644 webapp/components/admin_console/gitlab_settings.jsx delete mode 100644 webapp/components/admin_console/index.js delete mode 100644 webapp/components/admin_console/ldap_settings.jsx delete mode 100644 webapp/components/admin_console/legal_and_support_settings.jsx delete mode 100644 webapp/components/admin_console/license_settings.jsx delete mode 100644 webapp/components/admin_console/link_previews_settings.jsx delete mode 100644 webapp/components/admin_console/localization_settings.jsx delete mode 100644 webapp/components/admin_console/log_settings.jsx delete mode 100644 webapp/components/admin_console/manage_roles_modal/index.js delete mode 100644 webapp/components/admin_console/manage_roles_modal/manage_roles_modal.jsx delete mode 100644 webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx delete mode 100644 webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx delete mode 100644 webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx delete mode 100644 webapp/components/admin_console/manage_tokens_modal/index.js delete mode 100644 webapp/components/admin_console/manage_tokens_modal/manage_tokens_modal.jsx delete mode 100644 webapp/components/admin_console/metrics_settings.jsx delete mode 100644 webapp/components/admin_console/mfa_settings.jsx delete mode 100644 webapp/components/admin_console/multiselect_settings.jsx delete mode 100644 webapp/components/admin_console/native_app_link_settings.jsx delete mode 100644 webapp/components/admin_console/oauth_settings.jsx delete mode 100644 webapp/components/admin_console/password_settings.jsx delete mode 100644 webapp/components/admin_console/plugin_settings/index.js delete mode 100644 webapp/components/admin_console/plugin_settings/plugin_settings.jsx delete mode 100644 webapp/components/admin_console/policy_settings.jsx delete mode 100644 webapp/components/admin_console/post_edit_setting.jsx delete mode 100644 webapp/components/admin_console/privacy_settings.jsx delete mode 100644 webapp/components/admin_console/public_link_settings.jsx delete mode 100644 webapp/components/admin_console/push_settings.jsx delete mode 100644 webapp/components/admin_console/radio_setting.jsx delete mode 100644 webapp/components/admin_console/rate_settings.jsx delete mode 100644 webapp/components/admin_console/remove_file_setting.jsx delete mode 100644 webapp/components/admin_console/request_button/request_button.jsx delete mode 100644 webapp/components/admin_console/reset_password_modal.jsx delete mode 100644 webapp/components/admin_console/revoke_token_button/index.js delete mode 100644 webapp/components/admin_console/revoke_token_button/revoke_token_button.jsx delete mode 100644 webapp/components/admin_console/saml_settings.jsx delete mode 100644 webapp/components/admin_console/save_button.jsx delete mode 100644 webapp/components/admin_console/server_logs/index.js delete mode 100644 webapp/components/admin_console/server_logs/logs.jsx delete mode 100644 webapp/components/admin_console/session_settings.jsx delete mode 100644 webapp/components/admin_console/setting.jsx delete mode 100644 webapp/components/admin_console/settings_group.jsx delete mode 100644 webapp/components/admin_console/signup_settings.jsx delete mode 100644 webapp/components/admin_console/storage_settings.jsx delete mode 100644 webapp/components/admin_console/system_users/index.js delete mode 100644 webapp/components/admin_console/system_users/system_users.jsx delete mode 100644 webapp/components/admin_console/system_users/system_users_dropdown.jsx delete mode 100644 webapp/components/admin_console/system_users/system_users_list.jsx delete mode 100644 webapp/components/admin_console/text_setting.jsx delete mode 100644 webapp/components/admin_console/users_and_teams_settings.jsx delete mode 100644 webapp/components/admin_console/webrtc_settings.jsx delete mode 100644 webapp/components/admin_console/webserver_mode_dropdown_setting.jsx delete mode 100644 webapp/components/analytics/doughnut_chart.jsx delete mode 100644 webapp/components/analytics/line_chart.jsx delete mode 100644 webapp/components/analytics/statistic_count.jsx delete mode 100644 webapp/components/analytics/system_analytics.jsx delete mode 100644 webapp/components/analytics/table_chart.jsx delete mode 100644 webapp/components/analytics/team_analytics/index.js delete mode 100644 webapp/components/analytics/team_analytics/team_analytics.jsx delete mode 100644 webapp/components/announcement_bar/announcement_bar.jsx delete mode 100644 webapp/components/announcement_bar/index.js delete mode 100644 webapp/components/at_mention/at_mention.jsx delete mode 100644 webapp/components/at_mention/index.jsx delete mode 100644 webapp/components/audio_video_preview.jsx delete mode 100644 webapp/components/audit_table.jsx delete mode 100644 webapp/components/authorize.jsx delete mode 100644 webapp/components/autosize_textarea.jsx delete mode 100644 webapp/components/backstage/backstage_controller.jsx delete mode 100644 webapp/components/backstage/components/backstage_category.jsx delete mode 100644 webapp/components/backstage/components/backstage_header.jsx delete mode 100644 webapp/components/backstage/components/backstage_list.jsx delete mode 100644 webapp/components/backstage/components/backstage_navbar.jsx delete mode 100644 webapp/components/backstage/components/backstage_section.jsx delete mode 100644 webapp/components/backstage/components/backstage_sidebar.jsx delete mode 100644 webapp/components/bootstrap_span.jsx delete mode 100644 webapp/components/change_url_modal.jsx delete mode 100644 webapp/components/channel_header.jsx delete mode 100644 webapp/components/channel_info_modal.jsx delete mode 100644 webapp/components/channel_invite_button.jsx delete mode 100644 webapp/components/channel_invite_modal/channel_invite_modal.jsx delete mode 100644 webapp/components/channel_invite_modal/index.js delete mode 100644 webapp/components/channel_members_dropdown/channel_members_dropdown.jsx delete mode 100644 webapp/components/channel_members_dropdown/index.js delete mode 100644 webapp/components/channel_members_modal.jsx delete mode 100644 webapp/components/channel_notifications_modal.jsx delete mode 100644 webapp/components/channel_select.jsx delete mode 100644 webapp/components/channel_view.jsx delete mode 100644 webapp/components/claim/claim_controller.jsx delete mode 100644 webapp/components/claim/components/email_to_ldap.jsx delete mode 100644 webapp/components/claim/components/email_to_oauth.jsx delete mode 100644 webapp/components/claim/components/ldap_to_email.jsx delete mode 100644 webapp/components/claim/components/oauth_to_email.jsx delete mode 100644 webapp/components/code_preview.jsx delete mode 100644 webapp/components/common/comment_icon.jsx delete mode 100644 webapp/components/confirm_modal.jsx delete mode 100644 webapp/components/create_comment/create_comment.jsx delete mode 100644 webapp/components/create_comment/index.js delete mode 100644 webapp/components/create_post.jsx delete mode 100644 webapp/components/create_team/components/display_name.jsx delete mode 100644 webapp/components/create_team/components/team_url.jsx delete mode 100644 webapp/components/create_team/create_team_controller.jsx delete mode 100644 webapp/components/delete_channel_modal.jsx delete mode 100644 webapp/components/delete_modal_trigger.jsx delete mode 100644 webapp/components/delete_post_modal.jsx delete mode 100644 webapp/components/do_verify_email.jsx delete mode 100644 webapp/components/dot_menu/dot_menu.jsx delete mode 100644 webapp/components/dot_menu/dot_menu_edit.jsx delete mode 100644 webapp/components/dot_menu/dot_menu_flag.jsx delete mode 100644 webapp/components/dot_menu/dot_menu_item.jsx delete mode 100644 webapp/components/dot_menu/index.js delete mode 100644 webapp/components/edit_channel_header_modal.jsx delete mode 100644 webapp/components/edit_channel_purpose_modal.jsx delete mode 100644 webapp/components/edit_post_modal.jsx delete mode 100644 webapp/components/emoji/components/add_emoji.jsx delete mode 100644 webapp/components/emoji/components/delete_emoji_modal.jsx delete mode 100644 webapp/components/emoji/components/emoji_list.jsx delete mode 100644 webapp/components/emoji/components/emoji_list_item.jsx delete mode 100644 webapp/components/emoji_picker/components/emoji_picker_category.jsx delete mode 100644 webapp/components/emoji_picker/components/emoji_picker_item.jsx delete mode 100644 webapp/components/emoji_picker/components/emoji_picker_preview.jsx delete mode 100644 webapp/components/emoji_picker/emoji_picker.jsx delete mode 100644 webapp/components/emoji_picker/emoji_picker_container.jsx delete mode 100644 webapp/components/emoji_picker/emoji_picker_overlay.jsx delete mode 100644 webapp/components/error_page.jsx delete mode 100644 webapp/components/file_attachment.jsx delete mode 100644 webapp/components/file_attachment_list/file_attachment_list.jsx delete mode 100644 webapp/components/file_attachment_list/index.js delete mode 100644 webapp/components/file_info_preview.jsx delete mode 100644 webapp/components/file_preview.jsx delete mode 100644 webapp/components/file_upload.jsx delete mode 100644 webapp/components/file_upload_overlay.jsx delete mode 100644 webapp/components/filtered_user_list.jsx delete mode 100644 webapp/components/form_error.jsx delete mode 100644 webapp/components/get_android_app/get_android_app.jsx delete mode 100644 webapp/components/get_ios_app/get_ios_app.jsx delete mode 100644 webapp/components/get_link_modal.jsx delete mode 100644 webapp/components/get_post_link_modal.jsx delete mode 100644 webapp/components/get_public_link_modal.jsx delete mode 100644 webapp/components/get_team_invite_link_modal.jsx delete mode 100644 webapp/components/header_footer_template.jsx delete mode 100644 webapp/components/help/components/attaching.jsx delete mode 100644 webapp/components/help/components/commands.jsx delete mode 100644 webapp/components/help/components/composing.jsx delete mode 100644 webapp/components/help/components/formatting.jsx delete mode 100644 webapp/components/help/components/mentioning.jsx delete mode 100644 webapp/components/help/components/messaging.jsx delete mode 100644 webapp/components/help/help_controller.jsx delete mode 100644 webapp/components/integrations/components/abstract_incoming_webhook.jsx delete mode 100644 webapp/components/integrations/components/abstract_outgoing_webhook.jsx delete mode 100644 webapp/components/integrations/components/add_command/add_command.jsx delete mode 100644 webapp/components/integrations/components/add_command/index.js delete mode 100644 webapp/components/integrations/components/add_incoming_webhook/add_incoming_webhook.jsx delete mode 100644 webapp/components/integrations/components/add_incoming_webhook/index.js delete mode 100644 webapp/components/integrations/components/add_oauth_app/add_oauth_app.jsx delete mode 100644 webapp/components/integrations/components/add_oauth_app/index.js delete mode 100644 webapp/components/integrations/components/add_outgoing_webhook/add_outgoing_webhook.jsx delete mode 100644 webapp/components/integrations/components/add_outgoing_webhook/index.js delete mode 100644 webapp/components/integrations/components/commands_container/commands_container.jsx delete mode 100644 webapp/components/integrations/components/commands_container/index.js delete mode 100644 webapp/components/integrations/components/confirm_integration/confirm_integration.jsx delete mode 100644 webapp/components/integrations/components/confirm_integration/index.js delete mode 100644 webapp/components/integrations/components/delete_integration.jsx delete mode 100644 webapp/components/integrations/components/edit_command/edit_command.jsx delete mode 100644 webapp/components/integrations/components/edit_command/index.js delete mode 100644 webapp/components/integrations/components/edit_incoming_webhook/edit_incoming_webhook.jsx delete mode 100644 webapp/components/integrations/components/edit_incoming_webhook/index.js delete mode 100644 webapp/components/integrations/components/edit_outgoing_webhook/edit_outgoing_webhook.jsx delete mode 100644 webapp/components/integrations/components/edit_outgoing_webhook/index.js delete mode 100644 webapp/components/integrations/components/installed_command.jsx delete mode 100644 webapp/components/integrations/components/installed_commands/index.js delete mode 100644 webapp/components/integrations/components/installed_commands/installed_commands.jsx delete mode 100644 webapp/components/integrations/components/installed_incoming_webhook.jsx delete mode 100644 webapp/components/integrations/components/installed_incoming_webhooks.jsx delete mode 100644 webapp/components/integrations/components/installed_oauth_app.jsx delete mode 100644 webapp/components/integrations/components/installed_oauth_apps/index.js delete mode 100644 webapp/components/integrations/components/installed_oauth_apps/installed_oauth_apps.jsx delete mode 100644 webapp/components/integrations/components/installed_outgoing_webhook.jsx delete mode 100644 webapp/components/integrations/components/installed_outgoing_webhooks.jsx delete mode 100644 webapp/components/integrations/components/integration_option.jsx delete mode 100644 webapp/components/integrations/components/integrations.jsx delete mode 100644 webapp/components/invite_member_modal.jsx delete mode 100644 webapp/components/leave_team_modal.jsx delete mode 100644 webapp/components/loading_screen.jsx delete mode 100644 webapp/components/logged_in.jsx delete mode 100644 webapp/components/login/components/login_mfa.jsx delete mode 100644 webapp/components/login/login_controller.jsx delete mode 100644 webapp/components/markdown_image.jsx delete mode 100644 webapp/components/member_list_channel/index.js delete mode 100644 webapp/components/member_list_channel/member_list_channel.jsx delete mode 100644 webapp/components/member_list_team/index.js delete mode 100644 webapp/components/member_list_team/member_list_team.jsx delete mode 100644 webapp/components/message_wrapper.jsx delete mode 100644 webapp/components/mfa/components/confirm.jsx delete mode 100644 webapp/components/mfa/components/setup.jsx delete mode 100644 webapp/components/mfa/mfa_controller.jsx delete mode 100644 webapp/components/modals/leave_private_channel_modal.jsx delete mode 100644 webapp/components/more_channels/index.js delete mode 100644 webapp/components/more_channels/more_channels.jsx delete mode 100644 webapp/components/more_direct_channels/index.js delete mode 100644 webapp/components/more_direct_channels/more_direct_channels.jsx delete mode 100644 webapp/components/msg_typing.jsx delete mode 100644 webapp/components/multiselect/multiselect.jsx delete mode 100644 webapp/components/multiselect/multiselect_list.jsx delete mode 100644 webapp/components/navbar.jsx delete mode 100644 webapp/components/needs_team/index.js delete mode 100644 webapp/components/needs_team/needs_team.jsx delete mode 100644 webapp/components/new_channel_flow.jsx delete mode 100644 webapp/components/new_channel_modal/index.js delete mode 100644 webapp/components/new_channel_modal/new_channel_modal.jsx delete mode 100644 webapp/components/notify_counts.jsx delete mode 100644 webapp/components/password_reset_form.jsx delete mode 100644 webapp/components/password_reset_send_link.jsx delete mode 100644 webapp/components/pdf_preview.jsx delete mode 100644 webapp/components/permalink_view.jsx delete mode 100644 webapp/components/popover_list_members/index.js delete mode 100644 webapp/components/popover_list_members/popover_list_members.jsx delete mode 100644 webapp/components/post_deleted_modal.jsx delete mode 100644 webapp/components/post_view/commented_on_files_message/commented_on_files_message.jsx delete mode 100644 webapp/components/post_view/commented_on_files_message/index.js delete mode 100644 webapp/components/post_view/date_separator.jsx delete mode 100644 webapp/components/post_view/failed_post_options/failed_post_options.jsx delete mode 100644 webapp/components/post_view/failed_post_options/index.js delete mode 100644 webapp/components/post_view/floating_timestamp.jsx delete mode 100644 webapp/components/post_view/index.js delete mode 100644 webapp/components/post_view/new_message_indicator.jsx delete mode 100644 webapp/components/post_view/post/index.js delete mode 100644 webapp/components/post_view/post/post.jsx delete mode 100644 webapp/components/post_view/post_attachment.jsx delete mode 100644 webapp/components/post_view/post_attachment_list.jsx delete mode 100644 webapp/components/post_view/post_attachment_opengraph/index.js delete mode 100644 webapp/components/post_view/post_attachment_opengraph/post_attachment_opengraph.jsx delete mode 100644 webapp/components/post_view/post_body/index.js delete mode 100644 webapp/components/post_view/post_body/post_body.jsx delete mode 100644 webapp/components/post_view/post_body_additional_content.jsx delete mode 100644 webapp/components/post_view/post_flag_icon.jsx delete mode 100644 webapp/components/post_view/post_header/index.js delete mode 100644 webapp/components/post_view/post_header/post_header.jsx delete mode 100644 webapp/components/post_view/post_image.jsx delete mode 100644 webapp/components/post_view/post_info/index.js delete mode 100644 webapp/components/post_view/post_info/post_info.jsx delete mode 100644 webapp/components/post_view/post_list.jsx delete mode 100644 webapp/components/post_view/post_message_view/index.js delete mode 100644 webapp/components/post_view/post_message_view/post_message_view.jsx delete mode 100644 webapp/components/post_view/post_message_view/system_message_helpers.jsx delete mode 100644 webapp/components/post_view/post_time.jsx delete mode 100644 webapp/components/post_view/reaction/index.js delete mode 100644 webapp/components/post_view/reaction/reaction.jsx delete mode 100644 webapp/components/post_view/reaction_list/index.js delete mode 100644 webapp/components/post_view/reaction_list/reaction_list.jsx delete mode 100644 webapp/components/post_view/scroll_to_bottom_arrows.jsx delete mode 100644 webapp/components/profile_picture.jsx delete mode 100644 webapp/components/profile_popover.jsx delete mode 100644 webapp/components/quick_switch_modal/index.js delete mode 100644 webapp/components/quick_switch_modal/quick_switch_modal.jsx delete mode 100644 webapp/components/removed_from_channel_modal.jsx delete mode 100644 webapp/components/rename_channel_modal.jsx delete mode 100644 webapp/components/reset_status_modal/index.js delete mode 100644 webapp/components/reset_status_modal/reset_status_modal.jsx delete mode 100644 webapp/components/rhs_comment.jsx delete mode 100644 webapp/components/rhs_header_post.jsx delete mode 100644 webapp/components/rhs_root_post.jsx delete mode 100644 webapp/components/rhs_thread/index.js delete mode 100644 webapp/components/rhs_thread/rhs_thread.jsx delete mode 100644 webapp/components/root.jsx delete mode 100644 webapp/components/search_bar.jsx delete mode 100644 webapp/components/search_results.jsx delete mode 100644 webapp/components/search_results_header.jsx delete mode 100644 webapp/components/search_results_item.jsx delete mode 100644 webapp/components/searchable_channel_list.jsx delete mode 100644 webapp/components/searchable_user_list/searchable_user_list.jsx delete mode 100644 webapp/components/searchable_user_list/searchable_user_list_container.jsx delete mode 100644 webapp/components/select_team/components/select_team_item.jsx delete mode 100644 webapp/components/select_team/index.js delete mode 100644 webapp/components/select_team/select_team.jsx delete mode 100644 webapp/components/setting_item_max.jsx delete mode 100644 webapp/components/setting_item_min.jsx delete mode 100644 webapp/components/setting_picture.jsx delete mode 100644 webapp/components/setting_upload.jsx delete mode 100644 webapp/components/settings_sidebar.jsx delete mode 100644 webapp/components/shortcuts_modal.jsx delete mode 100644 webapp/components/should_verify_email.jsx delete mode 100644 webapp/components/sidebar.jsx delete mode 100644 webapp/components/sidebar_header.jsx delete mode 100644 webapp/components/sidebar_header_dropdown.jsx delete mode 100644 webapp/components/sidebar_header_dropdown_button.jsx delete mode 100644 webapp/components/sidebar_right/index.js delete mode 100644 webapp/components/sidebar_right/sidebar_right.jsx delete mode 100644 webapp/components/sidebar_right_menu.jsx delete mode 100644 webapp/components/signup/components/signup_email.jsx delete mode 100644 webapp/components/signup/components/signup_ldap.jsx delete mode 100644 webapp/components/signup/signup_controller.jsx delete mode 100644 webapp/components/spinner_button.jsx delete mode 100644 webapp/components/status_dropdown/index.jsx delete mode 100644 webapp/components/status_dropdown/status_dropdown.jsx delete mode 100644 webapp/components/status_icon.jsx delete mode 100644 webapp/components/suggestion/at_mention_provider.jsx delete mode 100644 webapp/components/suggestion/channel_mention_provider.jsx delete mode 100644 webapp/components/suggestion/command_provider.jsx delete mode 100644 webapp/components/suggestion/emoticon_provider.jsx delete mode 100644 webapp/components/suggestion/provider.jsx delete mode 100644 webapp/components/suggestion/search_channel_provider.jsx delete mode 100644 webapp/components/suggestion/search_suggestion_list.jsx delete mode 100644 webapp/components/suggestion/search_user_provider.jsx delete mode 100644 webapp/components/suggestion/suggestion.jsx delete mode 100644 webapp/components/suggestion/suggestion_box.jsx delete mode 100644 webapp/components/suggestion/suggestion_list.jsx delete mode 100644 webapp/components/suggestion/switch_channel_provider.jsx delete mode 100644 webapp/components/suggestion/switch_team_provider.jsx delete mode 100644 webapp/components/team_general_tab.jsx delete mode 100644 webapp/components/team_import_tab.jsx delete mode 100644 webapp/components/team_members_dropdown/index.js delete mode 100644 webapp/components/team_members_dropdown/team_members_dropdown.jsx delete mode 100644 webapp/components/team_members_modal.jsx delete mode 100644 webapp/components/team_settings.jsx delete mode 100644 webapp/components/team_settings_modal.jsx delete mode 100644 webapp/components/team_sidebar/components/team_button.jsx delete mode 100644 webapp/components/team_sidebar/index.js delete mode 100644 webapp/components/team_sidebar/team_sidebar_controller.jsx delete mode 100644 webapp/components/textbox.jsx delete mode 100644 webapp/components/toggle_modal_button.jsx delete mode 100644 webapp/components/tutorial/tutorial_intro_screens.jsx delete mode 100644 webapp/components/tutorial/tutorial_tip.jsx delete mode 100644 webapp/components/tutorial/tutorial_view.jsx delete mode 100644 webapp/components/unread_channel_indicator.jsx delete mode 100644 webapp/components/user_list.jsx delete mode 100644 webapp/components/user_list_row.jsx delete mode 100644 webapp/components/user_profile.jsx delete mode 100644 webapp/components/user_settings/custom_theme_chooser.jsx delete mode 100644 webapp/components/user_settings/desktop_notification_settings.jsx delete mode 100644 webapp/components/user_settings/email_notification_setting.jsx delete mode 100644 webapp/components/user_settings/import_theme_modal.jsx delete mode 100644 webapp/components/user_settings/manage_languages.jsx delete mode 100644 webapp/components/user_settings/premade_theme_chooser.jsx delete mode 100644 webapp/components/user_settings/user_settings.jsx delete mode 100644 webapp/components/user_settings/user_settings_advanced.jsx delete mode 100644 webapp/components/user_settings/user_settings_display.jsx delete mode 100644 webapp/components/user_settings/user_settings_general/index.js delete mode 100644 webapp/components/user_settings/user_settings_general/user_settings_general.jsx delete mode 100644 webapp/components/user_settings/user_settings_modal.jsx delete mode 100644 webapp/components/user_settings/user_settings_notifications.jsx delete mode 100644 webapp/components/user_settings/user_settings_security/index.js delete mode 100644 webapp/components/user_settings/user_settings_security/user_settings_security.jsx delete mode 100644 webapp/components/user_settings/user_settings_theme.jsx delete mode 100644 webapp/components/view_image.jsx delete mode 100644 webapp/components/view_image_popover_bar.jsx delete mode 100644 webapp/components/webrtc/components/webrtc_header.jsx delete mode 100644 webapp/components/webrtc/components/webrtc_notification.jsx delete mode 100644 webapp/components/webrtc/components/webrtc_sidebar.jsx delete mode 100644 webapp/components/webrtc/webrtc_controller.jsx delete mode 100644 webapp/components/youtube_video/index.js delete mode 100644 webapp/components/youtube_video/youtube_video.jsx delete mode 100644 webapp/config/manifest.json delete mode 100644 webapp/dispatcher/app_dispatcher.jsx delete mode 100644 webapp/fonts/FontAwesome.otf delete mode 100644 webapp/fonts/fontawesome-webfont.eot delete mode 100644 webapp/fonts/fontawesome-webfont.svg delete mode 100644 webapp/fonts/fontawesome-webfont.ttf delete mode 100644 webapp/fonts/fontawesome-webfont.woff delete mode 100644 webapp/fonts/fontawesome-webfont.woff2 delete mode 100755 webapp/fonts/generator_config.txt delete mode 100644 webapp/fonts/glyphicons-halflings-regular.eot delete mode 100644 webapp/fonts/glyphicons-halflings-regular.svg delete mode 100644 webapp/fonts/glyphicons-halflings-regular.ttf delete mode 100644 webapp/fonts/glyphicons-halflings-regular.woff delete mode 100644 webapp/fonts/glyphicons-halflings-regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_AMS-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_AMS-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_AMS-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_AMS-Regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Caligraphic-Bold.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Caligraphic-Bold.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Caligraphic-Bold.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Caligraphic-Bold.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Caligraphic-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Caligraphic-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Caligraphic-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Caligraphic-Regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Fraktur-Bold.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Fraktur-Bold.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Fraktur-Bold.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Fraktur-Bold.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Fraktur-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Fraktur-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Fraktur-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Fraktur-Regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Bold.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Bold.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Bold.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Bold.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Italic.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Italic.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Italic.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Italic.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Main-Regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-BoldItalic.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-BoldItalic.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-BoldItalic.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-BoldItalic.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-Italic.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-Italic.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-Italic.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-Italic.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Math-Regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Bold.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Bold.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Bold.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Bold.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Italic.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Italic.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Italic.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Italic.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_SansSerif-Regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Script-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Script-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Script-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Script-Regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size1-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size1-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size1-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size1-Regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size2-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size2-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size2-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size2-Regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size3-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size3-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size3-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size3-Regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size4-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size4-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size4-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Size4-Regular.woff2 delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Typewriter-Regular.eot delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Typewriter-Regular.ttf delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Typewriter-Regular.woff delete mode 100644 webapp/fonts/ktexfonts/KaTeX_Typewriter-Regular.woff2 delete mode 100644 webapp/fonts/luximbi.ttf delete mode 100644 webapp/fonts/luxisr.ttf delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-300.eot delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-300.svg delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-300.ttf delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-300.woff delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-300.woff2 delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-300italic.eot delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-300italic.svg delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-300italic.ttf delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-300italic.woff delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-300italic.woff2 delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-600.eot delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-600.svg delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-600.ttf delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-600.woff delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-600.woff2 delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-600italic.eot delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-600italic.svg delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-600italic.ttf delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-600italic.woff delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-600italic.woff2 delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-italic.eot delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-italic.svg delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-italic.ttf delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-italic.woff delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-italic.woff2 delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-regular.eot delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-regular.svg delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-regular.ttf delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-regular.woff delete mode 100644 webapp/fonts/open-sans-v13-latin-ext_latin_cyrillic-ext_greek-ext_greek_cyrillic_vietnamese-regular.woff2 delete mode 100644 webapp/i18n/de.json delete mode 100755 webapp/i18n/en.json delete mode 100644 webapp/i18n/es.json delete mode 100644 webapp/i18n/fr.json delete mode 100644 webapp/i18n/i18n.jsx delete mode 100644 webapp/i18n/it.json delete mode 100644 webapp/i18n/ja.json delete mode 100644 webapp/i18n/ko.json delete mode 100644 webapp/i18n/nl.json delete mode 100644 webapp/i18n/pl.json delete mode 100644 webapp/i18n/pt-BR.json delete mode 100644 webapp/i18n/ru.json delete mode 100644 webapp/i18n/tr.json delete mode 100644 webapp/i18n/zh-CN.json delete mode 100644 webapp/i18n/zh-TW.json delete mode 100644 webapp/images/app-store-button.png delete mode 100644 webapp/images/appIcons.png delete mode 100644 webapp/images/arrow-left.png delete mode 100644 webapp/images/bing.mp3 delete mode 100755 webapp/images/bootstrap-colorpicker/alpha-horizontal.png delete mode 100755 webapp/images/bootstrap-colorpicker/alpha.png delete mode 100755 webapp/images/bootstrap-colorpicker/hue-horizontal.png delete mode 100755 webapp/images/bootstrap-colorpicker/hue.png delete mode 100755 webapp/images/bootstrap-colorpicker/saturation.png delete mode 100644 webapp/images/circles.png delete mode 100644 webapp/images/close.png delete mode 100644 webapp/images/closeSidebar.png delete mode 100644 webapp/images/ding.mp3 delete mode 100644 webapp/images/emoji-sheets/activity.png delete mode 100644 webapp/images/emoji-sheets/custom.png delete mode 100644 webapp/images/emoji-sheets/flags.png delete mode 100644 webapp/images/emoji-sheets/foods.png delete mode 100644 webapp/images/emoji-sheets/nature.png delete mode 100644 webapp/images/emoji-sheets/objects.png delete mode 100644 webapp/images/emoji-sheets/people.png delete mode 100644 webapp/images/emoji-sheets/places.png delete mode 100644 webapp/images/emoji-sheets/symbols.png delete mode 100644 webapp/images/emoji/0023-fe0f-20e3.png delete mode 100644 webapp/images/emoji/002a-fe0f-20e3.png delete mode 100644 webapp/images/emoji/0030-fe0f-20e3.png delete mode 100644 webapp/images/emoji/0031-fe0f-20e3.png delete mode 100644 webapp/images/emoji/0032-fe0f-20e3.png delete mode 100644 webapp/images/emoji/0033-fe0f-20e3.png delete mode 100644 webapp/images/emoji/0034-fe0f-20e3.png delete mode 100644 webapp/images/emoji/0035-fe0f-20e3.png delete mode 100644 webapp/images/emoji/0036-fe0f-20e3.png delete mode 100644 webapp/images/emoji/0037-fe0f-20e3.png delete mode 100644 webapp/images/emoji/0038-fe0f-20e3.png delete mode 100644 webapp/images/emoji/0039-fe0f-20e3.png delete mode 100644 webapp/images/emoji/00a9-fe0f.png delete mode 100644 webapp/images/emoji/00ae-fe0f.png delete mode 100644 webapp/images/emoji/1f004-fe0f.png delete mode 100644 webapp/images/emoji/1f0cf.png delete mode 100644 webapp/images/emoji/1f170-fe0f.png delete mode 100644 webapp/images/emoji/1f171-fe0f.png delete mode 100644 webapp/images/emoji/1f17e-fe0f.png delete mode 100644 webapp/images/emoji/1f17f-fe0f.png delete mode 100644 webapp/images/emoji/1f18e.png delete mode 100644 webapp/images/emoji/1f191.png delete mode 100644 webapp/images/emoji/1f192.png delete mode 100644 webapp/images/emoji/1f193.png delete mode 100644 webapp/images/emoji/1f194.png delete mode 100644 webapp/images/emoji/1f195.png delete mode 100644 webapp/images/emoji/1f196.png delete mode 100644 webapp/images/emoji/1f197.png delete mode 100644 webapp/images/emoji/1f198.png delete mode 100644 webapp/images/emoji/1f199.png delete mode 100644 webapp/images/emoji/1f19a.png delete mode 100644 webapp/images/emoji/1f1e6-1f1e9.png delete mode 100644 webapp/images/emoji/1f1e6-1f1ea.png delete mode 100644 webapp/images/emoji/1f1e6-1f1eb.png delete mode 100644 webapp/images/emoji/1f1e6-1f1ec.png delete mode 100644 webapp/images/emoji/1f1e6-1f1ee.png delete mode 100644 webapp/images/emoji/1f1e6-1f1f1.png delete mode 100644 webapp/images/emoji/1f1e6-1f1f2.png delete mode 100644 webapp/images/emoji/1f1e6-1f1f4.png delete mode 100644 webapp/images/emoji/1f1e6-1f1f6.png delete mode 100644 webapp/images/emoji/1f1e6-1f1f7.png delete mode 100644 webapp/images/emoji/1f1e6-1f1f8.png delete mode 100644 webapp/images/emoji/1f1e6-1f1f9.png delete mode 100644 webapp/images/emoji/1f1e6-1f1fa.png delete mode 100644 webapp/images/emoji/1f1e6-1f1fc.png delete mode 100644 webapp/images/emoji/1f1e6-1f1fd.png delete mode 100644 webapp/images/emoji/1f1e6-1f1ff.png delete mode 100644 webapp/images/emoji/1f1e7-1f1e6.png delete mode 100644 webapp/images/emoji/1f1e7-1f1e7.png delete mode 100644 webapp/images/emoji/1f1e7-1f1e9.png delete mode 100644 webapp/images/emoji/1f1e7-1f1ea.png delete mode 100644 webapp/images/emoji/1f1e7-1f1eb.png delete mode 100644 webapp/images/emoji/1f1e7-1f1ec.png delete mode 100644 webapp/images/emoji/1f1e7-1f1ed.png delete mode 100644 webapp/images/emoji/1f1e7-1f1ee.png delete mode 100644 webapp/images/emoji/1f1e7-1f1ef.png delete mode 100644 webapp/images/emoji/1f1e7-1f1f1.png delete mode 100644 webapp/images/emoji/1f1e7-1f1f2.png delete mode 100644 webapp/images/emoji/1f1e7-1f1f3.png delete mode 100644 webapp/images/emoji/1f1e7-1f1f4.png delete mode 100644 webapp/images/emoji/1f1e7-1f1f6.png delete mode 100644 webapp/images/emoji/1f1e7-1f1f7.png delete mode 100644 webapp/images/emoji/1f1e7-1f1f8.png delete mode 100644 webapp/images/emoji/1f1e7-1f1f9.png delete mode 100644 webapp/images/emoji/1f1e7-1f1fc.png delete mode 100644 webapp/images/emoji/1f1e7-1f1fe.png delete mode 100644 webapp/images/emoji/1f1e7-1f1ff.png delete mode 100644 webapp/images/emoji/1f1e8-1f1e6.png delete mode 100644 webapp/images/emoji/1f1e8-1f1e8.png delete mode 100644 webapp/images/emoji/1f1e8-1f1e9.png delete mode 100644 webapp/images/emoji/1f1e8-1f1eb.png delete mode 100644 webapp/images/emoji/1f1e8-1f1ec.png delete mode 100644 webapp/images/emoji/1f1e8-1f1ed.png delete mode 100644 webapp/images/emoji/1f1e8-1f1ee.png delete mode 100644 webapp/images/emoji/1f1e8-1f1f0.png delete mode 100644 webapp/images/emoji/1f1e8-1f1f1.png delete mode 100644 webapp/images/emoji/1f1e8-1f1f2.png delete mode 100644 webapp/images/emoji/1f1e8-1f1f3.png delete mode 100644 webapp/images/emoji/1f1e8-1f1f4.png delete mode 100644 webapp/images/emoji/1f1e8-1f1f7.png delete mode 100644 webapp/images/emoji/1f1e8-1f1fa.png delete mode 100644 webapp/images/emoji/1f1e8-1f1fb.png delete mode 100644 webapp/images/emoji/1f1e8-1f1fc.png delete mode 100644 webapp/images/emoji/1f1e8-1f1fd.png delete mode 100644 webapp/images/emoji/1f1e8-1f1fe.png delete mode 100644 webapp/images/emoji/1f1e8-1f1ff.png delete mode 100644 webapp/images/emoji/1f1e9-1f1ea.png delete mode 100644 webapp/images/emoji/1f1e9-1f1ef.png delete mode 100644 webapp/images/emoji/1f1e9-1f1f0.png delete mode 100644 webapp/images/emoji/1f1e9-1f1f2.png delete mode 100644 webapp/images/emoji/1f1e9-1f1f4.png delete mode 100644 webapp/images/emoji/1f1e9-1f1ff.png delete mode 100644 webapp/images/emoji/1f1ea-1f1e8.png delete mode 100644 webapp/images/emoji/1f1ea-1f1ea.png delete mode 100644 webapp/images/emoji/1f1ea-1f1ec.png delete mode 100644 webapp/images/emoji/1f1ea-1f1ed.png delete mode 100644 webapp/images/emoji/1f1ea-1f1f7.png delete mode 100644 webapp/images/emoji/1f1ea-1f1f8.png delete mode 100644 webapp/images/emoji/1f1ea-1f1f9.png delete mode 100644 webapp/images/emoji/1f1ea-1f1fa.png delete mode 100644 webapp/images/emoji/1f1eb-1f1ee.png delete mode 100644 webapp/images/emoji/1f1eb-1f1ef.png delete mode 100644 webapp/images/emoji/1f1eb-1f1f0.png delete mode 100644 webapp/images/emoji/1f1eb-1f1f2.png delete mode 100644 webapp/images/emoji/1f1eb-1f1f4.png delete mode 100644 webapp/images/emoji/1f1eb-1f1f7.png delete mode 100644 webapp/images/emoji/1f1ec-1f1e6.png delete mode 100644 webapp/images/emoji/1f1ec-1f1e7.png delete mode 100644 webapp/images/emoji/1f1ec-1f1e9.png delete mode 100644 webapp/images/emoji/1f1ec-1f1ea.png delete mode 100644 webapp/images/emoji/1f1ec-1f1eb.png delete mode 100644 webapp/images/emoji/1f1ec-1f1ec.png delete mode 100644 webapp/images/emoji/1f1ec-1f1ed.png delete mode 100644 webapp/images/emoji/1f1ec-1f1ee.png delete mode 100644 webapp/images/emoji/1f1ec-1f1f1.png delete mode 100644 webapp/images/emoji/1f1ec-1f1f2.png delete mode 100644 webapp/images/emoji/1f1ec-1f1f3.png delete mode 100644 webapp/images/emoji/1f1ec-1f1f5.png delete mode 100644 webapp/images/emoji/1f1ec-1f1f6.png delete mode 100644 webapp/images/emoji/1f1ec-1f1f7.png delete mode 100644 webapp/images/emoji/1f1ec-1f1f8.png delete mode 100644 webapp/images/emoji/1f1ec-1f1f9.png delete mode 100644 webapp/images/emoji/1f1ec-1f1fa.png delete mode 100644 webapp/images/emoji/1f1ec-1f1fc.png delete mode 100644 webapp/images/emoji/1f1ec-1f1fe.png delete mode 100644 webapp/images/emoji/1f1ed-1f1f0.png delete mode 100644 webapp/images/emoji/1f1ed-1f1f3.png delete mode 100644 webapp/images/emoji/1f1ed-1f1f7.png delete mode 100644 webapp/images/emoji/1f1ed-1f1f9.png delete mode 100644 webapp/images/emoji/1f1ed-1f1fa.png delete mode 100644 webapp/images/emoji/1f1ee-1f1e8.png delete mode 100644 webapp/images/emoji/1f1ee-1f1e9.png delete mode 100644 webapp/images/emoji/1f1ee-1f1ea.png delete mode 100644 webapp/images/emoji/1f1ee-1f1f1.png delete mode 100644 webapp/images/emoji/1f1ee-1f1f2.png delete mode 100644 webapp/images/emoji/1f1ee-1f1f3.png delete mode 100644 webapp/images/emoji/1f1ee-1f1f4.png delete mode 100644 webapp/images/emoji/1f1ee-1f1f6.png delete mode 100644 webapp/images/emoji/1f1ee-1f1f7.png delete mode 100644 webapp/images/emoji/1f1ee-1f1f8.png delete mode 100644 webapp/images/emoji/1f1ee-1f1f9.png delete mode 100644 webapp/images/emoji/1f1ef-1f1ea.png delete mode 100644 webapp/images/emoji/1f1ef-1f1f2.png delete mode 100644 webapp/images/emoji/1f1ef-1f1f4.png delete mode 100644 webapp/images/emoji/1f1ef-1f1f5.png delete mode 100644 webapp/images/emoji/1f1f0-1f1ea.png delete mode 100644 webapp/images/emoji/1f1f0-1f1ec.png delete mode 100644 webapp/images/emoji/1f1f0-1f1ed.png delete mode 100644 webapp/images/emoji/1f1f0-1f1ee.png delete mode 100644 webapp/images/emoji/1f1f0-1f1f2.png delete mode 100644 webapp/images/emoji/1f1f0-1f1f3.png delete mode 100644 webapp/images/emoji/1f1f0-1f1f5.png delete mode 100644 webapp/images/emoji/1f1f0-1f1f7.png delete mode 100644 webapp/images/emoji/1f1f0-1f1fc.png delete mode 100644 webapp/images/emoji/1f1f0-1f1fe.png delete mode 100644 webapp/images/emoji/1f1f0-1f1ff.png delete mode 100644 webapp/images/emoji/1f1f1-1f1e6.png delete mode 100644 webapp/images/emoji/1f1f1-1f1e7.png delete mode 100644 webapp/images/emoji/1f1f1-1f1e8.png delete mode 100644 webapp/images/emoji/1f1f1-1f1ee.png delete mode 100644 webapp/images/emoji/1f1f1-1f1f0.png delete mode 100644 webapp/images/emoji/1f1f1-1f1f7.png delete mode 100644 webapp/images/emoji/1f1f1-1f1f8.png delete mode 100644 webapp/images/emoji/1f1f1-1f1f9.png delete mode 100644 webapp/images/emoji/1f1f1-1f1fa.png delete mode 100644 webapp/images/emoji/1f1f1-1f1fb.png delete mode 100644 webapp/images/emoji/1f1f1-1f1fe.png delete mode 100644 webapp/images/emoji/1f1f2-1f1e6.png delete mode 100644 webapp/images/emoji/1f1f2-1f1e8.png delete mode 100644 webapp/images/emoji/1f1f2-1f1e9.png delete mode 100644 webapp/images/emoji/1f1f2-1f1ea.png delete mode 100644 webapp/images/emoji/1f1f2-1f1ec.png delete mode 100644 webapp/images/emoji/1f1f2-1f1ed.png delete mode 100644 webapp/images/emoji/1f1f2-1f1f0.png delete mode 100644 webapp/images/emoji/1f1f2-1f1f1.png delete mode 100644 webapp/images/emoji/1f1f2-1f1f2.png delete mode 100644 webapp/images/emoji/1f1f2-1f1f3.png delete mode 100644 webapp/images/emoji/1f1f2-1f1f4.png delete mode 100644 webapp/images/emoji/1f1f2-1f1f5.png delete mode 100644 webapp/images/emoji/1f1f2-1f1f6.png delete mode 100644 webapp/images/emoji/1f1f2-1f1f7.png delete mode 100644 webapp/images/emoji/1f1f2-1f1f8.png delete mode 100644 webapp/images/emoji/1f1f2-1f1f9.png delete mode 100644 webapp/images/emoji/1f1f2-1f1fa.png delete mode 100644 webapp/images/emoji/1f1f2-1f1fb.png delete mode 100644 webapp/images/emoji/1f1f2-1f1fc.png delete mode 100644 webapp/images/emoji/1f1f2-1f1fd.png delete mode 100644 webapp/images/emoji/1f1f2-1f1fe.png delete mode 100644 webapp/images/emoji/1f1f2-1f1ff.png delete mode 100644 webapp/images/emoji/1f1f3-1f1e6.png delete mode 100644 webapp/images/emoji/1f1f3-1f1e8.png delete mode 100644 webapp/images/emoji/1f1f3-1f1ea.png delete mode 100644 webapp/images/emoji/1f1f3-1f1eb.png delete mode 100644 webapp/images/emoji/1f1f3-1f1ec.png delete mode 100644 webapp/images/emoji/1f1f3-1f1ee.png delete mode 100644 webapp/images/emoji/1f1f3-1f1f1.png delete mode 100644 webapp/images/emoji/1f1f3-1f1f4.png delete mode 100644 webapp/images/emoji/1f1f3-1f1f5.png delete mode 100644 webapp/images/emoji/1f1f3-1f1f7.png delete mode 100644 webapp/images/emoji/1f1f3-1f1fa.png delete mode 100644 webapp/images/emoji/1f1f3-1f1ff.png delete mode 100644 webapp/images/emoji/1f1f4-1f1f2.png delete mode 100644 webapp/images/emoji/1f1f5-1f1e6.png delete mode 100644 webapp/images/emoji/1f1f5-1f1ea.png delete mode 100644 webapp/images/emoji/1f1f5-1f1eb.png delete mode 100644 webapp/images/emoji/1f1f5-1f1ec.png delete mode 100644 webapp/images/emoji/1f1f5-1f1ed.png delete mode 100644 webapp/images/emoji/1f1f5-1f1f0.png delete mode 100644 webapp/images/emoji/1f1f5-1f1f1.png delete mode 100644 webapp/images/emoji/1f1f5-1f1f2.png delete mode 100644 webapp/images/emoji/1f1f5-1f1f3.png delete mode 100644 webapp/images/emoji/1f1f5-1f1f7.png delete mode 100644 webapp/images/emoji/1f1f5-1f1f8.png delete mode 100644 webapp/images/emoji/1f1f5-1f1f9.png delete mode 100644 webapp/images/emoji/1f1f5-1f1fc.png delete mode 100644 webapp/images/emoji/1f1f5-1f1fe.png delete mode 100644 webapp/images/emoji/1f1f6-1f1e6.png delete mode 100644 webapp/images/emoji/1f1f7-1f1ea.png delete mode 100644 webapp/images/emoji/1f1f7-1f1f4.png delete mode 100644 webapp/images/emoji/1f1f7-1f1f8.png delete mode 100644 webapp/images/emoji/1f1f7-1f1fa.png delete mode 100644 webapp/images/emoji/1f1f7-1f1fc.png delete mode 100644 webapp/images/emoji/1f1f8-1f1e6.png delete mode 100644 webapp/images/emoji/1f1f8-1f1e7.png delete mode 100644 webapp/images/emoji/1f1f8-1f1e8.png delete mode 100644 webapp/images/emoji/1f1f8-1f1e9.png delete mode 100644 webapp/images/emoji/1f1f8-1f1ea.png delete mode 100644 webapp/images/emoji/1f1f8-1f1ec.png delete mode 100644 webapp/images/emoji/1f1f8-1f1ed.png delete mode 100644 webapp/images/emoji/1f1f8-1f1ee.png delete mode 100644 webapp/images/emoji/1f1f8-1f1f0.png delete mode 100644 webapp/images/emoji/1f1f8-1f1f1.png delete mode 100644 webapp/images/emoji/1f1f8-1f1f2.png delete mode 100644 webapp/images/emoji/1f1f8-1f1f3.png delete mode 100644 webapp/images/emoji/1f1f8-1f1f4.png delete mode 100644 webapp/images/emoji/1f1f8-1f1f7.png delete mode 100644 webapp/images/emoji/1f1f8-1f1f8.png delete mode 100644 webapp/images/emoji/1f1f8-1f1f9.png delete mode 100644 webapp/images/emoji/1f1f8-1f1fb.png delete mode 100644 webapp/images/emoji/1f1f8-1f1fd.png delete mode 100644 webapp/images/emoji/1f1f8-1f1fe.png delete mode 100644 webapp/images/emoji/1f1f8-1f1ff.png delete mode 100644 webapp/images/emoji/1f1f9-1f1e8.png delete mode 100644 webapp/images/emoji/1f1f9-1f1e9.png delete mode 100644 webapp/images/emoji/1f1f9-1f1eb.png delete mode 100644 webapp/images/emoji/1f1f9-1f1ec.png delete mode 100644 webapp/images/emoji/1f1f9-1f1ed.png delete mode 100644 webapp/images/emoji/1f1f9-1f1ef.png delete mode 100644 webapp/images/emoji/1f1f9-1f1f0.png delete mode 100644 webapp/images/emoji/1f1f9-1f1f1.png delete mode 100644 webapp/images/emoji/1f1f9-1f1f2.png delete mode 100644 webapp/images/emoji/1f1f9-1f1f3.png delete mode 100644 webapp/images/emoji/1f1f9-1f1f4.png delete mode 100644 webapp/images/emoji/1f1f9-1f1f7.png delete mode 100644 webapp/images/emoji/1f1f9-1f1f9.png delete mode 100644 webapp/images/emoji/1f1f9-1f1fb.png delete mode 100644 webapp/images/emoji/1f1f9-1f1fc.png delete mode 100644 webapp/images/emoji/1f1f9-1f1ff.png delete mode 100644 webapp/images/emoji/1f1fa-1f1e6.png delete mode 100644 webapp/images/emoji/1f1fa-1f1ec.png delete mode 100644 webapp/images/emoji/1f1fa-1f1f8.png delete mode 100644 webapp/images/emoji/1f1fa-1f1fe.png delete mode 100644 webapp/images/emoji/1f1fa-1f1ff.png delete mode 100644 webapp/images/emoji/1f1fb-1f1e6.png delete mode 100644 webapp/images/emoji/1f1fb-1f1e8.png delete mode 100644 webapp/images/emoji/1f1fb-1f1ea.png delete mode 100644 webapp/images/emoji/1f1fb-1f1ec.png delete mode 100644 webapp/images/emoji/1f1fb-1f1ee.png delete mode 100644 webapp/images/emoji/1f1fb-1f1f3.png delete mode 100644 webapp/images/emoji/1f1fb-1f1fa.png delete mode 100644 webapp/images/emoji/1f1fc-1f1eb.png delete mode 100644 webapp/images/emoji/1f1fc-1f1f8.png delete mode 100644 webapp/images/emoji/1f1fd-1f1f0.png delete mode 100644 webapp/images/emoji/1f1fe-1f1ea.png delete mode 100644 webapp/images/emoji/1f1fe-1f1f9.png delete mode 100644 webapp/images/emoji/1f1ff-1f1e6.png delete mode 100644 webapp/images/emoji/1f1ff-1f1f2.png delete mode 100644 webapp/images/emoji/1f1ff-1f1fc.png delete mode 100644 webapp/images/emoji/1f201.png delete mode 100644 webapp/images/emoji/1f202-fe0f.png delete mode 100644 webapp/images/emoji/1f21a-fe0f.png delete mode 100644 webapp/images/emoji/1f22f-fe0f.png delete mode 100644 webapp/images/emoji/1f232.png delete mode 100644 webapp/images/emoji/1f233.png delete mode 100644 webapp/images/emoji/1f234.png delete mode 100644 webapp/images/emoji/1f235.png delete mode 100644 webapp/images/emoji/1f236.png delete mode 100644 webapp/images/emoji/1f237-fe0f.png delete mode 100644 webapp/images/emoji/1f238.png delete mode 100644 webapp/images/emoji/1f239.png delete mode 100644 webapp/images/emoji/1f23a.png delete mode 100644 webapp/images/emoji/1f250.png delete mode 100644 webapp/images/emoji/1f251.png delete mode 100644 webapp/images/emoji/1f300.png delete mode 100644 webapp/images/emoji/1f301.png delete mode 100644 webapp/images/emoji/1f302.png delete mode 100644 webapp/images/emoji/1f303.png delete mode 100644 webapp/images/emoji/1f304.png delete mode 100644 webapp/images/emoji/1f305.png delete mode 100644 webapp/images/emoji/1f306.png delete mode 100644 webapp/images/emoji/1f307.png delete mode 100644 webapp/images/emoji/1f308.png delete mode 100644 webapp/images/emoji/1f309.png delete mode 100644 webapp/images/emoji/1f30a.png delete mode 100644 webapp/images/emoji/1f30b.png delete mode 100644 webapp/images/emoji/1f30c.png delete mode 100644 webapp/images/emoji/1f30d.png delete mode 100644 webapp/images/emoji/1f30e.png delete mode 100644 webapp/images/emoji/1f30f.png delete mode 100644 webapp/images/emoji/1f310.png delete mode 100644 webapp/images/emoji/1f311.png delete mode 100644 webapp/images/emoji/1f312.png delete mode 100644 webapp/images/emoji/1f313.png delete mode 100644 webapp/images/emoji/1f314.png delete mode 100644 webapp/images/emoji/1f315.png delete mode 100644 webapp/images/emoji/1f316.png delete mode 100644 webapp/images/emoji/1f317.png delete mode 100644 webapp/images/emoji/1f318.png delete mode 100644 webapp/images/emoji/1f319.png delete mode 100644 webapp/images/emoji/1f31a.png delete mode 100644 webapp/images/emoji/1f31b.png delete mode 100644 webapp/images/emoji/1f31c.png delete mode 100644 webapp/images/emoji/1f31d.png delete mode 100644 webapp/images/emoji/1f31e.png delete mode 100644 webapp/images/emoji/1f31f.png delete mode 100644 webapp/images/emoji/1f320.png delete mode 100644 webapp/images/emoji/1f321.png delete mode 100644 webapp/images/emoji/1f324.png delete mode 100644 webapp/images/emoji/1f325.png delete mode 100644 webapp/images/emoji/1f326.png delete mode 100644 webapp/images/emoji/1f327.png delete mode 100644 webapp/images/emoji/1f328.png delete mode 100644 webapp/images/emoji/1f329.png delete mode 100644 webapp/images/emoji/1f32a.png delete mode 100644 webapp/images/emoji/1f32b.png delete mode 100644 webapp/images/emoji/1f32c.png delete mode 100644 webapp/images/emoji/1f32d.png delete mode 100644 webapp/images/emoji/1f32e.png delete mode 100644 webapp/images/emoji/1f32f.png delete mode 100644 webapp/images/emoji/1f330.png delete mode 100644 webapp/images/emoji/1f331.png delete mode 100644 webapp/images/emoji/1f332.png delete mode 100644 webapp/images/emoji/1f333.png delete mode 100644 webapp/images/emoji/1f334.png delete mode 100644 webapp/images/emoji/1f335.png delete mode 100644 webapp/images/emoji/1f336.png delete mode 100644 webapp/images/emoji/1f337.png delete mode 100644 webapp/images/emoji/1f338.png delete mode 100644 webapp/images/emoji/1f339.png delete mode 100644 webapp/images/emoji/1f33a.png delete mode 100644 webapp/images/emoji/1f33b.png delete mode 100644 webapp/images/emoji/1f33c.png delete mode 100644 webapp/images/emoji/1f33d.png delete mode 100644 webapp/images/emoji/1f33e.png delete mode 100644 webapp/images/emoji/1f33f.png delete mode 100644 webapp/images/emoji/1f340.png delete mode 100644 webapp/images/emoji/1f341.png delete mode 100644 webapp/images/emoji/1f342.png delete mode 100644 webapp/images/emoji/1f343.png delete mode 100644 webapp/images/emoji/1f344.png delete mode 100644 webapp/images/emoji/1f345.png delete mode 100644 webapp/images/emoji/1f346.png delete mode 100644 webapp/images/emoji/1f347.png delete mode 100644 webapp/images/emoji/1f348.png delete mode 100644 webapp/images/emoji/1f349.png delete mode 100644 webapp/images/emoji/1f34a.png delete mode 100644 webapp/images/emoji/1f34b.png delete mode 100644 webapp/images/emoji/1f34c.png delete mode 100644 webapp/images/emoji/1f34d.png delete mode 100644 webapp/images/emoji/1f34e.png delete mode 100644 webapp/images/emoji/1f34f.png delete mode 100644 webapp/images/emoji/1f350.png delete mode 100644 webapp/images/emoji/1f351.png delete mode 100644 webapp/images/emoji/1f352.png delete mode 100644 webapp/images/emoji/1f353.png delete mode 100644 webapp/images/emoji/1f354.png delete mode 100644 webapp/images/emoji/1f355.png delete mode 100644 webapp/images/emoji/1f356.png delete mode 100644 webapp/images/emoji/1f357.png delete mode 100644 webapp/images/emoji/1f358.png delete mode 100644 webapp/images/emoji/1f359.png delete mode 100644 webapp/images/emoji/1f35a.png delete mode 100644 webapp/images/emoji/1f35b.png delete mode 100644 webapp/images/emoji/1f35c.png delete mode 100644 webapp/images/emoji/1f35d.png delete mode 100644 webapp/images/emoji/1f35e.png delete mode 100644 webapp/images/emoji/1f35f.png delete mode 100644 webapp/images/emoji/1f360.png delete mode 100644 webapp/images/emoji/1f361.png delete mode 100644 webapp/images/emoji/1f362.png delete mode 100644 webapp/images/emoji/1f363.png delete mode 100644 webapp/images/emoji/1f364.png delete mode 100644 webapp/images/emoji/1f365.png delete mode 100644 webapp/images/emoji/1f366.png delete mode 100644 webapp/images/emoji/1f367.png delete mode 100644 webapp/images/emoji/1f368.png delete mode 100644 webapp/images/emoji/1f369.png delete mode 100644 webapp/images/emoji/1f36a.png delete mode 100644 webapp/images/emoji/1f36b.png delete mode 100644 webapp/images/emoji/1f36c.png delete mode 100644 webapp/images/emoji/1f36d.png delete mode 100644 webapp/images/emoji/1f36e.png delete mode 100644 webapp/images/emoji/1f36f.png delete mode 100644 webapp/images/emoji/1f370.png delete mode 100644 webapp/images/emoji/1f371.png delete mode 100644 webapp/images/emoji/1f372.png delete mode 100644 webapp/images/emoji/1f373.png delete mode 100644 webapp/images/emoji/1f374.png delete mode 100644 webapp/images/emoji/1f375.png delete mode 100644 webapp/images/emoji/1f376.png delete mode 100644 webapp/images/emoji/1f377.png delete mode 100644 webapp/images/emoji/1f378.png delete mode 100644 webapp/images/emoji/1f379.png delete mode 100644 webapp/images/emoji/1f37a.png delete mode 100644 webapp/images/emoji/1f37b.png delete mode 100644 webapp/images/emoji/1f37c.png delete mode 100644 webapp/images/emoji/1f37d.png delete mode 100644 webapp/images/emoji/1f37e.png delete mode 100644 webapp/images/emoji/1f37f.png delete mode 100644 webapp/images/emoji/1f380.png delete mode 100644 webapp/images/emoji/1f381.png delete mode 100644 webapp/images/emoji/1f382.png delete mode 100644 webapp/images/emoji/1f383.png delete mode 100644 webapp/images/emoji/1f384.png delete mode 100644 webapp/images/emoji/1f385.png delete mode 100644 webapp/images/emoji/1f386.png delete mode 100644 webapp/images/emoji/1f387.png delete mode 100644 webapp/images/emoji/1f388.png delete mode 100644 webapp/images/emoji/1f389.png delete mode 100644 webapp/images/emoji/1f38a.png delete mode 100644 webapp/images/emoji/1f38b.png delete mode 100644 webapp/images/emoji/1f38c.png delete mode 100644 webapp/images/emoji/1f38d.png delete mode 100644 webapp/images/emoji/1f38e.png delete mode 100644 webapp/images/emoji/1f38f.png delete mode 100644 webapp/images/emoji/1f390.png delete mode 100644 webapp/images/emoji/1f391.png delete mode 100644 webapp/images/emoji/1f392.png delete mode 100644 webapp/images/emoji/1f393.png delete mode 100644 webapp/images/emoji/1f396.png delete mode 100644 webapp/images/emoji/1f397.png delete mode 100644 webapp/images/emoji/1f399.png delete mode 100644 webapp/images/emoji/1f39a.png delete mode 100644 webapp/images/emoji/1f39b.png delete mode 100644 webapp/images/emoji/1f39e.png delete mode 100644 webapp/images/emoji/1f39f.png delete mode 100644 webapp/images/emoji/1f3a0.png delete mode 100644 webapp/images/emoji/1f3a1.png delete mode 100644 webapp/images/emoji/1f3a2.png delete mode 100644 webapp/images/emoji/1f3a3.png delete mode 100644 webapp/images/emoji/1f3a4.png delete mode 100644 webapp/images/emoji/1f3a5.png delete mode 100644 webapp/images/emoji/1f3a6.png delete mode 100644 webapp/images/emoji/1f3a7.png delete mode 100644 webapp/images/emoji/1f3a8.png delete mode 100644 webapp/images/emoji/1f3a9.png delete mode 100644 webapp/images/emoji/1f3aa.png delete mode 100644 webapp/images/emoji/1f3ab.png delete mode 100644 webapp/images/emoji/1f3ac.png delete mode 100644 webapp/images/emoji/1f3ad.png delete mode 100644 webapp/images/emoji/1f3ae.png delete mode 100644 webapp/images/emoji/1f3af.png delete mode 100644 webapp/images/emoji/1f3b0.png delete mode 100644 webapp/images/emoji/1f3b1.png delete mode 100644 webapp/images/emoji/1f3b2.png delete mode 100644 webapp/images/emoji/1f3b3.png delete mode 100644 webapp/images/emoji/1f3b4.png delete mode 100644 webapp/images/emoji/1f3b5.png delete mode 100644 webapp/images/emoji/1f3b6.png delete mode 100644 webapp/images/emoji/1f3b7.png delete mode 100644 webapp/images/emoji/1f3b8.png delete mode 100644 webapp/images/emoji/1f3b9.png delete mode 100644 webapp/images/emoji/1f3ba.png delete mode 100644 webapp/images/emoji/1f3bb.png delete mode 100644 webapp/images/emoji/1f3bc.png delete mode 100644 webapp/images/emoji/1f3bd.png delete mode 100644 webapp/images/emoji/1f3be.png delete mode 100644 webapp/images/emoji/1f3bf.png delete mode 100644 webapp/images/emoji/1f3c0.png delete mode 100644 webapp/images/emoji/1f3c1.png delete mode 100644 webapp/images/emoji/1f3c2.png delete mode 100644 webapp/images/emoji/1f3c3-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f3c3.png delete mode 100644 webapp/images/emoji/1f3c4-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f3c4.png delete mode 100644 webapp/images/emoji/1f3c5.png delete mode 100644 webapp/images/emoji/1f3c6.png delete mode 100644 webapp/images/emoji/1f3c7.png delete mode 100644 webapp/images/emoji/1f3c8.png delete mode 100644 webapp/images/emoji/1f3c9.png delete mode 100644 webapp/images/emoji/1f3ca-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f3ca.png delete mode 100644 webapp/images/emoji/1f3cb-fe0f-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f3cb-fe0f.png delete mode 100644 webapp/images/emoji/1f3cc-fe0f-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f3cc-fe0f.png delete mode 100644 webapp/images/emoji/1f3cd.png delete mode 100644 webapp/images/emoji/1f3ce.png delete mode 100644 webapp/images/emoji/1f3cf.png delete mode 100644 webapp/images/emoji/1f3d0.png delete mode 100644 webapp/images/emoji/1f3d1.png delete mode 100644 webapp/images/emoji/1f3d2.png delete mode 100644 webapp/images/emoji/1f3d3.png delete mode 100644 webapp/images/emoji/1f3d4.png delete mode 100644 webapp/images/emoji/1f3d5.png delete mode 100644 webapp/images/emoji/1f3d6.png delete mode 100644 webapp/images/emoji/1f3d7.png delete mode 100644 webapp/images/emoji/1f3d8.png delete mode 100644 webapp/images/emoji/1f3d9.png delete mode 100644 webapp/images/emoji/1f3da.png delete mode 100644 webapp/images/emoji/1f3db.png delete mode 100644 webapp/images/emoji/1f3dc.png delete mode 100644 webapp/images/emoji/1f3dd.png delete mode 100644 webapp/images/emoji/1f3de.png delete mode 100644 webapp/images/emoji/1f3df.png delete mode 100644 webapp/images/emoji/1f3e0.png delete mode 100644 webapp/images/emoji/1f3e1.png delete mode 100644 webapp/images/emoji/1f3e2.png delete mode 100644 webapp/images/emoji/1f3e3.png delete mode 100644 webapp/images/emoji/1f3e4.png delete mode 100644 webapp/images/emoji/1f3e5.png delete mode 100644 webapp/images/emoji/1f3e6.png delete mode 100644 webapp/images/emoji/1f3e7.png delete mode 100644 webapp/images/emoji/1f3e8.png delete mode 100644 webapp/images/emoji/1f3e9.png delete mode 100644 webapp/images/emoji/1f3ea.png delete mode 100644 webapp/images/emoji/1f3eb.png delete mode 100644 webapp/images/emoji/1f3ec.png delete mode 100644 webapp/images/emoji/1f3ed.png delete mode 100644 webapp/images/emoji/1f3ee.png delete mode 100644 webapp/images/emoji/1f3ef.png delete mode 100644 webapp/images/emoji/1f3f0.png delete mode 100644 webapp/images/emoji/1f3f3-fe0f-200d-1f308.png delete mode 100644 webapp/images/emoji/1f3f3-fe0f.png delete mode 100644 webapp/images/emoji/1f3f4.png delete mode 100644 webapp/images/emoji/1f3f5.png delete mode 100644 webapp/images/emoji/1f3f7.png delete mode 100644 webapp/images/emoji/1f3f8.png delete mode 100644 webapp/images/emoji/1f3f9.png delete mode 100644 webapp/images/emoji/1f3fa.png delete mode 100644 webapp/images/emoji/1f400.png delete mode 100644 webapp/images/emoji/1f401.png delete mode 100644 webapp/images/emoji/1f402.png delete mode 100644 webapp/images/emoji/1f403.png delete mode 100644 webapp/images/emoji/1f404.png delete mode 100644 webapp/images/emoji/1f405.png delete mode 100644 webapp/images/emoji/1f406.png delete mode 100644 webapp/images/emoji/1f407.png delete mode 100644 webapp/images/emoji/1f408.png delete mode 100644 webapp/images/emoji/1f409.png delete mode 100644 webapp/images/emoji/1f40a.png delete mode 100644 webapp/images/emoji/1f40b.png delete mode 100644 webapp/images/emoji/1f40c.png delete mode 100644 webapp/images/emoji/1f40d.png delete mode 100644 webapp/images/emoji/1f40e.png delete mode 100644 webapp/images/emoji/1f40f.png delete mode 100644 webapp/images/emoji/1f410.png delete mode 100644 webapp/images/emoji/1f411.png delete mode 100644 webapp/images/emoji/1f412.png delete mode 100644 webapp/images/emoji/1f413.png delete mode 100644 webapp/images/emoji/1f414.png delete mode 100644 webapp/images/emoji/1f415.png delete mode 100644 webapp/images/emoji/1f416.png delete mode 100644 webapp/images/emoji/1f417.png delete mode 100644 webapp/images/emoji/1f418.png delete mode 100644 webapp/images/emoji/1f419.png delete mode 100644 webapp/images/emoji/1f41a.png delete mode 100644 webapp/images/emoji/1f41b.png delete mode 100644 webapp/images/emoji/1f41c.png delete mode 100644 webapp/images/emoji/1f41d.png delete mode 100644 webapp/images/emoji/1f41e.png delete mode 100644 webapp/images/emoji/1f41f.png delete mode 100644 webapp/images/emoji/1f420.png delete mode 100644 webapp/images/emoji/1f421.png delete mode 100644 webapp/images/emoji/1f422.png delete mode 100644 webapp/images/emoji/1f423.png delete mode 100644 webapp/images/emoji/1f424.png delete mode 100644 webapp/images/emoji/1f425.png delete mode 100644 webapp/images/emoji/1f426.png delete mode 100644 webapp/images/emoji/1f427.png delete mode 100644 webapp/images/emoji/1f428.png delete mode 100644 webapp/images/emoji/1f429.png delete mode 100644 webapp/images/emoji/1f42a.png delete mode 100644 webapp/images/emoji/1f42b.png delete mode 100644 webapp/images/emoji/1f42c.png delete mode 100644 webapp/images/emoji/1f42d.png delete mode 100644 webapp/images/emoji/1f42e.png delete mode 100644 webapp/images/emoji/1f42f.png delete mode 100644 webapp/images/emoji/1f430.png delete mode 100644 webapp/images/emoji/1f431.png delete mode 100644 webapp/images/emoji/1f432.png delete mode 100644 webapp/images/emoji/1f433.png delete mode 100644 webapp/images/emoji/1f434.png delete mode 100644 webapp/images/emoji/1f435.png delete mode 100644 webapp/images/emoji/1f436.png delete mode 100644 webapp/images/emoji/1f437.png delete mode 100644 webapp/images/emoji/1f438.png delete mode 100644 webapp/images/emoji/1f439.png delete mode 100644 webapp/images/emoji/1f43a.png delete mode 100644 webapp/images/emoji/1f43b.png delete mode 100644 webapp/images/emoji/1f43c.png delete mode 100644 webapp/images/emoji/1f43d.png delete mode 100644 webapp/images/emoji/1f43e.png delete mode 100644 webapp/images/emoji/1f43f.png delete mode 100644 webapp/images/emoji/1f440.png delete mode 100644 webapp/images/emoji/1f441-200d-1f5e8.png delete mode 100644 webapp/images/emoji/1f441.png delete mode 100644 webapp/images/emoji/1f442.png delete mode 100644 webapp/images/emoji/1f443.png delete mode 100644 webapp/images/emoji/1f444.png delete mode 100644 webapp/images/emoji/1f445.png delete mode 100644 webapp/images/emoji/1f446.png delete mode 100644 webapp/images/emoji/1f447.png delete mode 100644 webapp/images/emoji/1f448.png delete mode 100644 webapp/images/emoji/1f449.png delete mode 100644 webapp/images/emoji/1f44a.png delete mode 100644 webapp/images/emoji/1f44b.png delete mode 100644 webapp/images/emoji/1f44c.png delete mode 100644 webapp/images/emoji/1f44d.png delete mode 100644 webapp/images/emoji/1f44e.png delete mode 100644 webapp/images/emoji/1f44f.png delete mode 100644 webapp/images/emoji/1f450.png delete mode 100644 webapp/images/emoji/1f451.png delete mode 100644 webapp/images/emoji/1f452.png delete mode 100644 webapp/images/emoji/1f453.png delete mode 100644 webapp/images/emoji/1f454.png delete mode 100644 webapp/images/emoji/1f455.png delete mode 100644 webapp/images/emoji/1f456.png delete mode 100644 webapp/images/emoji/1f457.png delete mode 100644 webapp/images/emoji/1f458.png delete mode 100644 webapp/images/emoji/1f459.png delete mode 100644 webapp/images/emoji/1f45a.png delete mode 100644 webapp/images/emoji/1f45b.png delete mode 100644 webapp/images/emoji/1f45c.png delete mode 100644 webapp/images/emoji/1f45d.png delete mode 100644 webapp/images/emoji/1f45e.png delete mode 100644 webapp/images/emoji/1f45f.png delete mode 100644 webapp/images/emoji/1f460.png delete mode 100644 webapp/images/emoji/1f461.png delete mode 100644 webapp/images/emoji/1f462.png delete mode 100644 webapp/images/emoji/1f463.png delete mode 100644 webapp/images/emoji/1f464.png delete mode 100644 webapp/images/emoji/1f465.png delete mode 100644 webapp/images/emoji/1f466.png delete mode 100644 webapp/images/emoji/1f467.png delete mode 100644 webapp/images/emoji/1f468-200d-1f33e.png delete mode 100644 webapp/images/emoji/1f468-200d-1f373.png delete mode 100644 webapp/images/emoji/1f468-200d-1f393.png delete mode 100644 webapp/images/emoji/1f468-200d-1f3a4.png delete mode 100644 webapp/images/emoji/1f468-200d-1f3a8.png delete mode 100644 webapp/images/emoji/1f468-200d-1f3eb.png delete mode 100644 webapp/images/emoji/1f468-200d-1f3ed.png delete mode 100644 webapp/images/emoji/1f468-200d-1f466-200d-1f466.png delete mode 100644 webapp/images/emoji/1f468-200d-1f466.png delete mode 100644 webapp/images/emoji/1f468-200d-1f467-200d-1f466.png delete mode 100644 webapp/images/emoji/1f468-200d-1f467-200d-1f467.png delete mode 100644 webapp/images/emoji/1f468-200d-1f467.png delete mode 100644 webapp/images/emoji/1f468-200d-1f468-200d-1f466-200d-1f466.png delete mode 100644 webapp/images/emoji/1f468-200d-1f468-200d-1f466.png delete mode 100644 webapp/images/emoji/1f468-200d-1f468-200d-1f467-200d-1f466.png delete mode 100644 webapp/images/emoji/1f468-200d-1f468-200d-1f467-200d-1f467.png delete mode 100644 webapp/images/emoji/1f468-200d-1f468-200d-1f467.png delete mode 100644 webapp/images/emoji/1f468-200d-1f469-200d-1f466-200d-1f466.png delete mode 100644 webapp/images/emoji/1f468-200d-1f469-200d-1f467-200d-1f466.png delete mode 100644 webapp/images/emoji/1f468-200d-1f469-200d-1f467-200d-1f467.png delete mode 100644 webapp/images/emoji/1f468-200d-1f469-200d-1f467.png delete mode 100644 webapp/images/emoji/1f468-200d-1f4bb.png delete mode 100644 webapp/images/emoji/1f468-200d-1f4bc.png delete mode 100644 webapp/images/emoji/1f468-200d-1f527.png delete mode 100644 webapp/images/emoji/1f468-200d-1f52c.png delete mode 100644 webapp/images/emoji/1f468-200d-1f680.png delete mode 100644 webapp/images/emoji/1f468-200d-1f692.png delete mode 100644 webapp/images/emoji/1f468-200d-2695-fe0f.png delete mode 100644 webapp/images/emoji/1f468-200d-2696-fe0f.png delete mode 100644 webapp/images/emoji/1f468-200d-2708-fe0f.png delete mode 100644 webapp/images/emoji/1f468-200d-2764-fe0f-200d-1f468.png delete mode 100644 webapp/images/emoji/1f468-200d-2764-fe0f-200d-1f48b-200d-1f468.png delete mode 100644 webapp/images/emoji/1f468.png delete mode 100644 webapp/images/emoji/1f469-200d-1f33e.png delete mode 100644 webapp/images/emoji/1f469-200d-1f373.png delete mode 100644 webapp/images/emoji/1f469-200d-1f393.png delete mode 100644 webapp/images/emoji/1f469-200d-1f3a4.png delete mode 100644 webapp/images/emoji/1f469-200d-1f3a8.png delete mode 100644 webapp/images/emoji/1f469-200d-1f3eb.png delete mode 100644 webapp/images/emoji/1f469-200d-1f3ed.png delete mode 100644 webapp/images/emoji/1f469-200d-1f466-200d-1f466.png delete mode 100644 webapp/images/emoji/1f469-200d-1f466.png delete mode 100644 webapp/images/emoji/1f469-200d-1f467-200d-1f466.png delete mode 100644 webapp/images/emoji/1f469-200d-1f467-200d-1f467.png delete mode 100644 webapp/images/emoji/1f469-200d-1f467.png delete mode 100644 webapp/images/emoji/1f469-200d-1f469-200d-1f466-200d-1f466.png delete mode 100644 webapp/images/emoji/1f469-200d-1f469-200d-1f466.png delete mode 100644 webapp/images/emoji/1f469-200d-1f469-200d-1f467-200d-1f466.png delete mode 100644 webapp/images/emoji/1f469-200d-1f469-200d-1f467-200d-1f467.png delete mode 100644 webapp/images/emoji/1f469-200d-1f469-200d-1f467.png delete mode 100644 webapp/images/emoji/1f469-200d-1f4bb.png delete mode 100644 webapp/images/emoji/1f469-200d-1f4bc.png delete mode 100644 webapp/images/emoji/1f469-200d-1f527.png delete mode 100644 webapp/images/emoji/1f469-200d-1f52c.png delete mode 100644 webapp/images/emoji/1f469-200d-1f680.png delete mode 100644 webapp/images/emoji/1f469-200d-1f692.png delete mode 100644 webapp/images/emoji/1f469-200d-2695-fe0f.png delete mode 100644 webapp/images/emoji/1f469-200d-2696-fe0f.png delete mode 100644 webapp/images/emoji/1f469-200d-2708-fe0f.png delete mode 100644 webapp/images/emoji/1f469-200d-2764-fe0f-200d-1f469.png delete mode 100644 webapp/images/emoji/1f469-200d-2764-fe0f-200d-1f48b-200d-1f469.png delete mode 100644 webapp/images/emoji/1f469.png delete mode 100644 webapp/images/emoji/1f46a.png delete mode 100644 webapp/images/emoji/1f46b.png delete mode 100644 webapp/images/emoji/1f46c.png delete mode 100644 webapp/images/emoji/1f46d.png delete mode 100644 webapp/images/emoji/1f46e-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f46e.png delete mode 100644 webapp/images/emoji/1f46f-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f46f.png delete mode 100644 webapp/images/emoji/1f470.png delete mode 100644 webapp/images/emoji/1f471-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f471.png delete mode 100644 webapp/images/emoji/1f472.png delete mode 100644 webapp/images/emoji/1f473-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f473.png delete mode 100644 webapp/images/emoji/1f474.png delete mode 100644 webapp/images/emoji/1f475.png delete mode 100644 webapp/images/emoji/1f476.png delete mode 100644 webapp/images/emoji/1f477-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f477.png delete mode 100644 webapp/images/emoji/1f478.png delete mode 100644 webapp/images/emoji/1f479.png delete mode 100644 webapp/images/emoji/1f47a.png delete mode 100644 webapp/images/emoji/1f47b.png delete mode 100644 webapp/images/emoji/1f47c.png delete mode 100644 webapp/images/emoji/1f47d.png delete mode 100644 webapp/images/emoji/1f47e.png delete mode 100644 webapp/images/emoji/1f47f.png delete mode 100644 webapp/images/emoji/1f480.png delete mode 100644 webapp/images/emoji/1f481-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f481.png delete mode 100644 webapp/images/emoji/1f482-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f482.png delete mode 100644 webapp/images/emoji/1f483.png delete mode 100644 webapp/images/emoji/1f484.png delete mode 100644 webapp/images/emoji/1f485.png delete mode 100644 webapp/images/emoji/1f486-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f486.png delete mode 100644 webapp/images/emoji/1f487-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f487.png delete mode 100644 webapp/images/emoji/1f488.png delete mode 100644 webapp/images/emoji/1f489.png delete mode 100644 webapp/images/emoji/1f48a.png delete mode 100644 webapp/images/emoji/1f48b.png delete mode 100644 webapp/images/emoji/1f48c.png delete mode 100644 webapp/images/emoji/1f48d.png delete mode 100644 webapp/images/emoji/1f48e.png delete mode 100644 webapp/images/emoji/1f48f.png delete mode 100644 webapp/images/emoji/1f490.png delete mode 100644 webapp/images/emoji/1f491.png delete mode 100644 webapp/images/emoji/1f492.png delete mode 100644 webapp/images/emoji/1f493.png delete mode 100644 webapp/images/emoji/1f494.png delete mode 100644 webapp/images/emoji/1f495.png delete mode 100644 webapp/images/emoji/1f496.png delete mode 100644 webapp/images/emoji/1f497.png delete mode 100644 webapp/images/emoji/1f498.png delete mode 100644 webapp/images/emoji/1f499.png delete mode 100644 webapp/images/emoji/1f49a.png delete mode 100644 webapp/images/emoji/1f49b.png delete mode 100644 webapp/images/emoji/1f49c.png delete mode 100644 webapp/images/emoji/1f49d.png delete mode 100644 webapp/images/emoji/1f49e.png delete mode 100644 webapp/images/emoji/1f49f.png delete mode 100644 webapp/images/emoji/1f4a0.png delete mode 100644 webapp/images/emoji/1f4a1.png delete mode 100644 webapp/images/emoji/1f4a2.png delete mode 100644 webapp/images/emoji/1f4a3.png delete mode 100644 webapp/images/emoji/1f4a4.png delete mode 100644 webapp/images/emoji/1f4a5.png delete mode 100644 webapp/images/emoji/1f4a6.png delete mode 100644 webapp/images/emoji/1f4a7.png delete mode 100644 webapp/images/emoji/1f4a8.png delete mode 100644 webapp/images/emoji/1f4a9.png delete mode 100644 webapp/images/emoji/1f4aa.png delete mode 100644 webapp/images/emoji/1f4ab.png delete mode 100644 webapp/images/emoji/1f4ac.png delete mode 100644 webapp/images/emoji/1f4ad.png delete mode 100644 webapp/images/emoji/1f4ae.png delete mode 100644 webapp/images/emoji/1f4af.png delete mode 100644 webapp/images/emoji/1f4b0.png delete mode 100644 webapp/images/emoji/1f4b1.png delete mode 100644 webapp/images/emoji/1f4b2.png delete mode 100644 webapp/images/emoji/1f4b3.png delete mode 100644 webapp/images/emoji/1f4b4.png delete mode 100644 webapp/images/emoji/1f4b5.png delete mode 100644 webapp/images/emoji/1f4b6.png delete mode 100644 webapp/images/emoji/1f4b7.png delete mode 100644 webapp/images/emoji/1f4b8.png delete mode 100644 webapp/images/emoji/1f4b9.png delete mode 100644 webapp/images/emoji/1f4ba.png delete mode 100644 webapp/images/emoji/1f4bb.png delete mode 100644 webapp/images/emoji/1f4bc.png delete mode 100644 webapp/images/emoji/1f4bd.png delete mode 100644 webapp/images/emoji/1f4be.png delete mode 100644 webapp/images/emoji/1f4bf.png delete mode 100644 webapp/images/emoji/1f4c0.png delete mode 100644 webapp/images/emoji/1f4c1.png delete mode 100644 webapp/images/emoji/1f4c2.png delete mode 100644 webapp/images/emoji/1f4c3.png delete mode 100644 webapp/images/emoji/1f4c4.png delete mode 100644 webapp/images/emoji/1f4c5.png delete mode 100644 webapp/images/emoji/1f4c6.png delete mode 100644 webapp/images/emoji/1f4c7.png delete mode 100644 webapp/images/emoji/1f4c8.png delete mode 100644 webapp/images/emoji/1f4c9.png delete mode 100644 webapp/images/emoji/1f4ca.png delete mode 100644 webapp/images/emoji/1f4cb.png delete mode 100644 webapp/images/emoji/1f4cc.png delete mode 100644 webapp/images/emoji/1f4cd.png delete mode 100644 webapp/images/emoji/1f4ce.png delete mode 100644 webapp/images/emoji/1f4cf.png delete mode 100644 webapp/images/emoji/1f4d0.png delete mode 100644 webapp/images/emoji/1f4d1.png delete mode 100644 webapp/images/emoji/1f4d2.png delete mode 100644 webapp/images/emoji/1f4d3.png delete mode 100644 webapp/images/emoji/1f4d4.png delete mode 100644 webapp/images/emoji/1f4d5.png delete mode 100644 webapp/images/emoji/1f4d6.png delete mode 100644 webapp/images/emoji/1f4d7.png delete mode 100644 webapp/images/emoji/1f4d8.png delete mode 100644 webapp/images/emoji/1f4d9.png delete mode 100644 webapp/images/emoji/1f4da.png delete mode 100644 webapp/images/emoji/1f4db.png delete mode 100644 webapp/images/emoji/1f4dc.png delete mode 100644 webapp/images/emoji/1f4dd.png delete mode 100644 webapp/images/emoji/1f4de.png delete mode 100644 webapp/images/emoji/1f4df.png delete mode 100644 webapp/images/emoji/1f4e0.png delete mode 100644 webapp/images/emoji/1f4e1.png delete mode 100644 webapp/images/emoji/1f4e2.png delete mode 100644 webapp/images/emoji/1f4e3.png delete mode 100644 webapp/images/emoji/1f4e4.png delete mode 100644 webapp/images/emoji/1f4e5.png delete mode 100644 webapp/images/emoji/1f4e6.png delete mode 100644 webapp/images/emoji/1f4e7.png delete mode 100644 webapp/images/emoji/1f4e8.png delete mode 100644 webapp/images/emoji/1f4e9.png delete mode 100644 webapp/images/emoji/1f4ea.png delete mode 100644 webapp/images/emoji/1f4eb.png delete mode 100644 webapp/images/emoji/1f4ec.png delete mode 100644 webapp/images/emoji/1f4ed.png delete mode 100644 webapp/images/emoji/1f4ee.png delete mode 100644 webapp/images/emoji/1f4ef.png delete mode 100644 webapp/images/emoji/1f4f0.png delete mode 100644 webapp/images/emoji/1f4f1.png delete mode 100644 webapp/images/emoji/1f4f2.png delete mode 100644 webapp/images/emoji/1f4f3.png delete mode 100644 webapp/images/emoji/1f4f4.png delete mode 100644 webapp/images/emoji/1f4f5.png delete mode 100644 webapp/images/emoji/1f4f6.png delete mode 100644 webapp/images/emoji/1f4f7.png delete mode 100644 webapp/images/emoji/1f4f8.png delete mode 100644 webapp/images/emoji/1f4f9.png delete mode 100644 webapp/images/emoji/1f4fa.png delete mode 100644 webapp/images/emoji/1f4fb.png delete mode 100644 webapp/images/emoji/1f4fc.png delete mode 100644 webapp/images/emoji/1f4fd.png delete mode 100644 webapp/images/emoji/1f4ff.png delete mode 100644 webapp/images/emoji/1f500.png delete mode 100644 webapp/images/emoji/1f501.png delete mode 100644 webapp/images/emoji/1f502.png delete mode 100644 webapp/images/emoji/1f503.png delete mode 100644 webapp/images/emoji/1f504.png delete mode 100644 webapp/images/emoji/1f505.png delete mode 100644 webapp/images/emoji/1f506.png delete mode 100644 webapp/images/emoji/1f507.png delete mode 100644 webapp/images/emoji/1f508.png delete mode 100644 webapp/images/emoji/1f509.png delete mode 100644 webapp/images/emoji/1f50a.png delete mode 100644 webapp/images/emoji/1f50b.png delete mode 100644 webapp/images/emoji/1f50c.png delete mode 100644 webapp/images/emoji/1f50d.png delete mode 100644 webapp/images/emoji/1f50e.png delete mode 100644 webapp/images/emoji/1f50f.png delete mode 100644 webapp/images/emoji/1f510.png delete mode 100644 webapp/images/emoji/1f511.png delete mode 100644 webapp/images/emoji/1f512.png delete mode 100644 webapp/images/emoji/1f513.png delete mode 100644 webapp/images/emoji/1f514.png delete mode 100644 webapp/images/emoji/1f515.png delete mode 100644 webapp/images/emoji/1f516.png delete mode 100644 webapp/images/emoji/1f517.png delete mode 100644 webapp/images/emoji/1f518.png delete mode 100644 webapp/images/emoji/1f519.png delete mode 100644 webapp/images/emoji/1f51a.png delete mode 100644 webapp/images/emoji/1f51b.png delete mode 100644 webapp/images/emoji/1f51c.png delete mode 100644 webapp/images/emoji/1f51d.png delete mode 100644 webapp/images/emoji/1f51e.png delete mode 100644 webapp/images/emoji/1f51f.png delete mode 100644 webapp/images/emoji/1f520.png delete mode 100644 webapp/images/emoji/1f521.png delete mode 100644 webapp/images/emoji/1f522.png delete mode 100644 webapp/images/emoji/1f523.png delete mode 100644 webapp/images/emoji/1f524.png delete mode 100644 webapp/images/emoji/1f525.png delete mode 100644 webapp/images/emoji/1f526.png delete mode 100644 webapp/images/emoji/1f527.png delete mode 100644 webapp/images/emoji/1f528.png delete mode 100644 webapp/images/emoji/1f529.png delete mode 100644 webapp/images/emoji/1f52a.png delete mode 100644 webapp/images/emoji/1f52b.png delete mode 100644 webapp/images/emoji/1f52c.png delete mode 100644 webapp/images/emoji/1f52d.png delete mode 100644 webapp/images/emoji/1f52e.png delete mode 100644 webapp/images/emoji/1f52f.png delete mode 100644 webapp/images/emoji/1f530.png delete mode 100644 webapp/images/emoji/1f531.png delete mode 100644 webapp/images/emoji/1f532.png delete mode 100644 webapp/images/emoji/1f533.png delete mode 100644 webapp/images/emoji/1f534.png delete mode 100644 webapp/images/emoji/1f535.png delete mode 100644 webapp/images/emoji/1f536.png delete mode 100644 webapp/images/emoji/1f537.png delete mode 100644 webapp/images/emoji/1f538.png delete mode 100644 webapp/images/emoji/1f539.png delete mode 100644 webapp/images/emoji/1f53a.png delete mode 100644 webapp/images/emoji/1f53b.png delete mode 100644 webapp/images/emoji/1f53c.png delete mode 100644 webapp/images/emoji/1f53d.png delete mode 100644 webapp/images/emoji/1f549.png delete mode 100644 webapp/images/emoji/1f54a.png delete mode 100644 webapp/images/emoji/1f54b.png delete mode 100644 webapp/images/emoji/1f54c.png delete mode 100644 webapp/images/emoji/1f54d.png delete mode 100644 webapp/images/emoji/1f54e.png delete mode 100644 webapp/images/emoji/1f550.png delete mode 100644 webapp/images/emoji/1f551.png delete mode 100644 webapp/images/emoji/1f552.png delete mode 100644 webapp/images/emoji/1f553.png delete mode 100644 webapp/images/emoji/1f554.png delete mode 100644 webapp/images/emoji/1f555.png delete mode 100644 webapp/images/emoji/1f556.png delete mode 100644 webapp/images/emoji/1f557.png delete mode 100644 webapp/images/emoji/1f558.png delete mode 100644 webapp/images/emoji/1f559.png delete mode 100644 webapp/images/emoji/1f55a.png delete mode 100644 webapp/images/emoji/1f55b.png delete mode 100644 webapp/images/emoji/1f55c.png delete mode 100644 webapp/images/emoji/1f55d.png delete mode 100644 webapp/images/emoji/1f55e.png delete mode 100644 webapp/images/emoji/1f55f.png delete mode 100644 webapp/images/emoji/1f560.png delete mode 100644 webapp/images/emoji/1f561.png delete mode 100644 webapp/images/emoji/1f562.png delete mode 100644 webapp/images/emoji/1f563.png delete mode 100644 webapp/images/emoji/1f564.png delete mode 100644 webapp/images/emoji/1f565.png delete mode 100644 webapp/images/emoji/1f566.png delete mode 100644 webapp/images/emoji/1f567.png delete mode 100644 webapp/images/emoji/1f56f.png delete mode 100644 webapp/images/emoji/1f570.png delete mode 100644 webapp/images/emoji/1f573.png delete mode 100644 webapp/images/emoji/1f574.png delete mode 100644 webapp/images/emoji/1f575-fe0f-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f575-fe0f.png delete mode 100644 webapp/images/emoji/1f576.png delete mode 100644 webapp/images/emoji/1f577.png delete mode 100644 webapp/images/emoji/1f578.png delete mode 100644 webapp/images/emoji/1f579.png delete mode 100644 webapp/images/emoji/1f57a.png delete mode 100644 webapp/images/emoji/1f587.png delete mode 100644 webapp/images/emoji/1f58a.png delete mode 100644 webapp/images/emoji/1f58b.png delete mode 100644 webapp/images/emoji/1f58c.png delete mode 100644 webapp/images/emoji/1f58d.png delete mode 100644 webapp/images/emoji/1f590.png delete mode 100644 webapp/images/emoji/1f595.png delete mode 100644 webapp/images/emoji/1f596.png delete mode 100644 webapp/images/emoji/1f5a4.png delete mode 100644 webapp/images/emoji/1f5a5.png delete mode 100644 webapp/images/emoji/1f5a8.png delete mode 100644 webapp/images/emoji/1f5b1.png delete mode 100644 webapp/images/emoji/1f5b2.png delete mode 100644 webapp/images/emoji/1f5bc.png delete mode 100644 webapp/images/emoji/1f5c2.png delete mode 100644 webapp/images/emoji/1f5c3.png delete mode 100644 webapp/images/emoji/1f5c4.png delete mode 100644 webapp/images/emoji/1f5d1.png delete mode 100644 webapp/images/emoji/1f5d2.png delete mode 100644 webapp/images/emoji/1f5d3.png delete mode 100644 webapp/images/emoji/1f5dc.png delete mode 100644 webapp/images/emoji/1f5dd.png delete mode 100644 webapp/images/emoji/1f5de.png delete mode 100644 webapp/images/emoji/1f5e1.png delete mode 100644 webapp/images/emoji/1f5e3.png delete mode 100644 webapp/images/emoji/1f5ef.png delete mode 100644 webapp/images/emoji/1f5f3.png delete mode 100644 webapp/images/emoji/1f5fa.png delete mode 100644 webapp/images/emoji/1f5fb.png delete mode 100644 webapp/images/emoji/1f5fc.png delete mode 100644 webapp/images/emoji/1f5fd.png delete mode 100644 webapp/images/emoji/1f5fe.png delete mode 100644 webapp/images/emoji/1f5ff.png delete mode 100644 webapp/images/emoji/1f600.png delete mode 100644 webapp/images/emoji/1f601.png delete mode 100644 webapp/images/emoji/1f602.png delete mode 100644 webapp/images/emoji/1f603.png delete mode 100644 webapp/images/emoji/1f604.png delete mode 100644 webapp/images/emoji/1f605.png delete mode 100644 webapp/images/emoji/1f606.png delete mode 100644 webapp/images/emoji/1f607.png delete mode 100644 webapp/images/emoji/1f608.png delete mode 100644 webapp/images/emoji/1f609.png delete mode 100644 webapp/images/emoji/1f60a.png delete mode 100644 webapp/images/emoji/1f60b.png delete mode 100644 webapp/images/emoji/1f60c.png delete mode 100644 webapp/images/emoji/1f60d.png delete mode 100644 webapp/images/emoji/1f60e.png delete mode 100644 webapp/images/emoji/1f60f.png delete mode 100644 webapp/images/emoji/1f610.png delete mode 100644 webapp/images/emoji/1f611.png delete mode 100644 webapp/images/emoji/1f612.png delete mode 100644 webapp/images/emoji/1f613.png delete mode 100644 webapp/images/emoji/1f614.png delete mode 100644 webapp/images/emoji/1f615.png delete mode 100644 webapp/images/emoji/1f616.png delete mode 100644 webapp/images/emoji/1f617.png delete mode 100644 webapp/images/emoji/1f618.png delete mode 100644 webapp/images/emoji/1f619.png delete mode 100644 webapp/images/emoji/1f61a.png delete mode 100644 webapp/images/emoji/1f61b.png delete mode 100644 webapp/images/emoji/1f61c.png delete mode 100644 webapp/images/emoji/1f61d.png delete mode 100644 webapp/images/emoji/1f61e.png delete mode 100644 webapp/images/emoji/1f61f.png delete mode 100644 webapp/images/emoji/1f620.png delete mode 100644 webapp/images/emoji/1f621.png delete mode 100644 webapp/images/emoji/1f622.png delete mode 100644 webapp/images/emoji/1f623.png delete mode 100644 webapp/images/emoji/1f624.png delete mode 100644 webapp/images/emoji/1f625.png delete mode 100644 webapp/images/emoji/1f626.png delete mode 100644 webapp/images/emoji/1f627.png delete mode 100644 webapp/images/emoji/1f628.png delete mode 100644 webapp/images/emoji/1f629.png delete mode 100644 webapp/images/emoji/1f62a.png delete mode 100644 webapp/images/emoji/1f62b.png delete mode 100644 webapp/images/emoji/1f62c.png delete mode 100644 webapp/images/emoji/1f62d.png delete mode 100644 webapp/images/emoji/1f62e.png delete mode 100644 webapp/images/emoji/1f62f.png delete mode 100644 webapp/images/emoji/1f630.png delete mode 100644 webapp/images/emoji/1f631.png delete mode 100644 webapp/images/emoji/1f632.png delete mode 100644 webapp/images/emoji/1f633.png delete mode 100644 webapp/images/emoji/1f634.png delete mode 100644 webapp/images/emoji/1f635.png delete mode 100644 webapp/images/emoji/1f636.png delete mode 100644 webapp/images/emoji/1f637.png delete mode 100644 webapp/images/emoji/1f638.png delete mode 100644 webapp/images/emoji/1f639.png delete mode 100644 webapp/images/emoji/1f63a.png delete mode 100644 webapp/images/emoji/1f63b.png delete mode 100644 webapp/images/emoji/1f63c.png delete mode 100644 webapp/images/emoji/1f63d.png delete mode 100644 webapp/images/emoji/1f63e.png delete mode 100644 webapp/images/emoji/1f63f.png delete mode 100644 webapp/images/emoji/1f640.png delete mode 100644 webapp/images/emoji/1f641.png delete mode 100644 webapp/images/emoji/1f642.png delete mode 100644 webapp/images/emoji/1f643.png delete mode 100644 webapp/images/emoji/1f644.png delete mode 100644 webapp/images/emoji/1f645-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f645.png delete mode 100644 webapp/images/emoji/1f646-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f646.png delete mode 100644 webapp/images/emoji/1f647-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f647.png delete mode 100644 webapp/images/emoji/1f648.png delete mode 100644 webapp/images/emoji/1f649.png delete mode 100644 webapp/images/emoji/1f64a.png delete mode 100644 webapp/images/emoji/1f64b-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f64b.png delete mode 100644 webapp/images/emoji/1f64c.png delete mode 100644 webapp/images/emoji/1f64d-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f64d.png delete mode 100644 webapp/images/emoji/1f64e-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f64e.png delete mode 100644 webapp/images/emoji/1f64f.png delete mode 100644 webapp/images/emoji/1f680.png delete mode 100644 webapp/images/emoji/1f681.png delete mode 100644 webapp/images/emoji/1f682.png delete mode 100644 webapp/images/emoji/1f683.png delete mode 100644 webapp/images/emoji/1f684.png delete mode 100644 webapp/images/emoji/1f685.png delete mode 100644 webapp/images/emoji/1f686.png delete mode 100644 webapp/images/emoji/1f687.png delete mode 100644 webapp/images/emoji/1f688.png delete mode 100644 webapp/images/emoji/1f689.png delete mode 100644 webapp/images/emoji/1f68a.png delete mode 100644 webapp/images/emoji/1f68b.png delete mode 100644 webapp/images/emoji/1f68c.png delete mode 100644 webapp/images/emoji/1f68d.png delete mode 100644 webapp/images/emoji/1f68e.png delete mode 100644 webapp/images/emoji/1f68f.png delete mode 100644 webapp/images/emoji/1f690.png delete mode 100644 webapp/images/emoji/1f691.png delete mode 100644 webapp/images/emoji/1f692.png delete mode 100644 webapp/images/emoji/1f693.png delete mode 100644 webapp/images/emoji/1f694.png delete mode 100644 webapp/images/emoji/1f695.png delete mode 100644 webapp/images/emoji/1f696.png delete mode 100644 webapp/images/emoji/1f697.png delete mode 100644 webapp/images/emoji/1f698.png delete mode 100644 webapp/images/emoji/1f699.png delete mode 100644 webapp/images/emoji/1f69a.png delete mode 100644 webapp/images/emoji/1f69b.png delete mode 100644 webapp/images/emoji/1f69c.png delete mode 100644 webapp/images/emoji/1f69d.png delete mode 100644 webapp/images/emoji/1f69e.png delete mode 100644 webapp/images/emoji/1f69f.png delete mode 100644 webapp/images/emoji/1f6a0.png delete mode 100644 webapp/images/emoji/1f6a1.png delete mode 100644 webapp/images/emoji/1f6a2.png delete mode 100644 webapp/images/emoji/1f6a3-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f6a3.png delete mode 100644 webapp/images/emoji/1f6a4.png delete mode 100644 webapp/images/emoji/1f6a5.png delete mode 100644 webapp/images/emoji/1f6a6.png delete mode 100644 webapp/images/emoji/1f6a7.png delete mode 100644 webapp/images/emoji/1f6a8.png delete mode 100644 webapp/images/emoji/1f6a9.png delete mode 100644 webapp/images/emoji/1f6aa.png delete mode 100644 webapp/images/emoji/1f6ab.png delete mode 100644 webapp/images/emoji/1f6ac.png delete mode 100644 webapp/images/emoji/1f6ad.png delete mode 100644 webapp/images/emoji/1f6ae.png delete mode 100644 webapp/images/emoji/1f6af.png delete mode 100644 webapp/images/emoji/1f6b0.png delete mode 100644 webapp/images/emoji/1f6b1.png delete mode 100644 webapp/images/emoji/1f6b2.png delete mode 100644 webapp/images/emoji/1f6b3.png delete mode 100644 webapp/images/emoji/1f6b4-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f6b4.png delete mode 100644 webapp/images/emoji/1f6b5-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f6b5.png delete mode 100644 webapp/images/emoji/1f6b6-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f6b6.png delete mode 100644 webapp/images/emoji/1f6b7.png delete mode 100644 webapp/images/emoji/1f6b8.png delete mode 100644 webapp/images/emoji/1f6b9.png delete mode 100644 webapp/images/emoji/1f6ba.png delete mode 100644 webapp/images/emoji/1f6bb.png delete mode 100644 webapp/images/emoji/1f6bc.png delete mode 100644 webapp/images/emoji/1f6bd.png delete mode 100644 webapp/images/emoji/1f6be.png delete mode 100644 webapp/images/emoji/1f6bf.png delete mode 100644 webapp/images/emoji/1f6c0.png delete mode 100644 webapp/images/emoji/1f6c1.png delete mode 100644 webapp/images/emoji/1f6c2.png delete mode 100644 webapp/images/emoji/1f6c3.png delete mode 100644 webapp/images/emoji/1f6c4.png delete mode 100644 webapp/images/emoji/1f6c5.png delete mode 100644 webapp/images/emoji/1f6cb.png delete mode 100644 webapp/images/emoji/1f6cc.png delete mode 100644 webapp/images/emoji/1f6cd.png delete mode 100644 webapp/images/emoji/1f6ce.png delete mode 100644 webapp/images/emoji/1f6cf.png delete mode 100644 webapp/images/emoji/1f6d0.png delete mode 100644 webapp/images/emoji/1f6d1.png delete mode 100644 webapp/images/emoji/1f6d2.png delete mode 100644 webapp/images/emoji/1f6e0.png delete mode 100644 webapp/images/emoji/1f6e1.png delete mode 100644 webapp/images/emoji/1f6e2.png delete mode 100644 webapp/images/emoji/1f6e3.png delete mode 100644 webapp/images/emoji/1f6e4.png delete mode 100644 webapp/images/emoji/1f6e5.png delete mode 100644 webapp/images/emoji/1f6e9.png delete mode 100644 webapp/images/emoji/1f6eb.png delete mode 100644 webapp/images/emoji/1f6ec.png delete mode 100644 webapp/images/emoji/1f6f0.png delete mode 100644 webapp/images/emoji/1f6f3.png delete mode 100644 webapp/images/emoji/1f6f4.png delete mode 100644 webapp/images/emoji/1f6f5.png delete mode 100644 webapp/images/emoji/1f6f6.png delete mode 100644 webapp/images/emoji/1f910.png delete mode 100644 webapp/images/emoji/1f911.png delete mode 100644 webapp/images/emoji/1f912.png delete mode 100644 webapp/images/emoji/1f913.png delete mode 100644 webapp/images/emoji/1f914.png delete mode 100644 webapp/images/emoji/1f915.png delete mode 100644 webapp/images/emoji/1f916.png delete mode 100644 webapp/images/emoji/1f917.png delete mode 100644 webapp/images/emoji/1f918.png delete mode 100644 webapp/images/emoji/1f919.png delete mode 100644 webapp/images/emoji/1f91a.png delete mode 100644 webapp/images/emoji/1f91b.png delete mode 100644 webapp/images/emoji/1f91c.png delete mode 100644 webapp/images/emoji/1f91d.png delete mode 100644 webapp/images/emoji/1f91e.png delete mode 100644 webapp/images/emoji/1f920.png delete mode 100644 webapp/images/emoji/1f921.png delete mode 100644 webapp/images/emoji/1f922.png delete mode 100644 webapp/images/emoji/1f923.png delete mode 100644 webapp/images/emoji/1f924.png delete mode 100644 webapp/images/emoji/1f925.png delete mode 100644 webapp/images/emoji/1f926-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f926-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f927.png delete mode 100644 webapp/images/emoji/1f930.png delete mode 100644 webapp/images/emoji/1f933.png delete mode 100644 webapp/images/emoji/1f934.png delete mode 100644 webapp/images/emoji/1f935.png delete mode 100644 webapp/images/emoji/1f936.png delete mode 100644 webapp/images/emoji/1f937-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f937-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f938-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f938-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f939-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f939-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f93a.png delete mode 100644 webapp/images/emoji/1f93c-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f93c-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f93d-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f93d-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f93e-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/1f93e-200d-2642-fe0f.png delete mode 100644 webapp/images/emoji/1f940.png delete mode 100644 webapp/images/emoji/1f941.png delete mode 100644 webapp/images/emoji/1f942.png delete mode 100644 webapp/images/emoji/1f943.png delete mode 100644 webapp/images/emoji/1f944.png delete mode 100644 webapp/images/emoji/1f945.png delete mode 100644 webapp/images/emoji/1f947.png delete mode 100644 webapp/images/emoji/1f948.png delete mode 100644 webapp/images/emoji/1f949.png delete mode 100644 webapp/images/emoji/1f94a.png delete mode 100644 webapp/images/emoji/1f94b.png delete mode 100644 webapp/images/emoji/1f950.png delete mode 100644 webapp/images/emoji/1f951.png delete mode 100644 webapp/images/emoji/1f952.png delete mode 100644 webapp/images/emoji/1f953.png delete mode 100644 webapp/images/emoji/1f954.png delete mode 100644 webapp/images/emoji/1f955.png delete mode 100644 webapp/images/emoji/1f956.png delete mode 100644 webapp/images/emoji/1f957.png delete mode 100644 webapp/images/emoji/1f958.png delete mode 100644 webapp/images/emoji/1f959.png delete mode 100644 webapp/images/emoji/1f95a.png delete mode 100644 webapp/images/emoji/1f95b.png delete mode 100644 webapp/images/emoji/1f95c.png delete mode 100644 webapp/images/emoji/1f95d.png delete mode 100644 webapp/images/emoji/1f95e.png delete mode 100644 webapp/images/emoji/1f980.png delete mode 100644 webapp/images/emoji/1f981.png delete mode 100644 webapp/images/emoji/1f982.png delete mode 100644 webapp/images/emoji/1f983.png delete mode 100644 webapp/images/emoji/1f984.png delete mode 100644 webapp/images/emoji/1f985.png delete mode 100644 webapp/images/emoji/1f986.png delete mode 100644 webapp/images/emoji/1f987.png delete mode 100644 webapp/images/emoji/1f988.png delete mode 100644 webapp/images/emoji/1f989.png delete mode 100644 webapp/images/emoji/1f98a.png delete mode 100644 webapp/images/emoji/1f98b.png delete mode 100644 webapp/images/emoji/1f98c.png delete mode 100644 webapp/images/emoji/1f98d.png delete mode 100644 webapp/images/emoji/1f98e.png delete mode 100644 webapp/images/emoji/1f98f.png delete mode 100644 webapp/images/emoji/1f990.png delete mode 100644 webapp/images/emoji/1f991.png delete mode 100644 webapp/images/emoji/1f9c0.png delete mode 100644 webapp/images/emoji/203c-fe0f.png delete mode 100644 webapp/images/emoji/2049-fe0f.png delete mode 100644 webapp/images/emoji/2122-fe0f.png delete mode 100644 webapp/images/emoji/2139-fe0f.png delete mode 100644 webapp/images/emoji/2194-fe0f.png delete mode 100644 webapp/images/emoji/2195-fe0f.png delete mode 100644 webapp/images/emoji/2196-fe0f.png delete mode 100644 webapp/images/emoji/2197-fe0f.png delete mode 100644 webapp/images/emoji/2198-fe0f.png delete mode 100644 webapp/images/emoji/2199-fe0f.png delete mode 100644 webapp/images/emoji/21a9-fe0f.png delete mode 100644 webapp/images/emoji/21aa-fe0f.png delete mode 100644 webapp/images/emoji/231a-fe0f.png delete mode 100644 webapp/images/emoji/231b-fe0f.png delete mode 100644 webapp/images/emoji/2328-fe0f.png delete mode 100644 webapp/images/emoji/23e9.png delete mode 100644 webapp/images/emoji/23ea.png delete mode 100644 webapp/images/emoji/23eb.png delete mode 100644 webapp/images/emoji/23ec.png delete mode 100644 webapp/images/emoji/23ed.png delete mode 100644 webapp/images/emoji/23ee.png delete mode 100644 webapp/images/emoji/23ef.png delete mode 100644 webapp/images/emoji/23f0.png delete mode 100644 webapp/images/emoji/23f1.png delete mode 100644 webapp/images/emoji/23f2.png delete mode 100644 webapp/images/emoji/23f3.png delete mode 100644 webapp/images/emoji/23f8.png delete mode 100644 webapp/images/emoji/23f9.png delete mode 100644 webapp/images/emoji/23fa.png delete mode 100644 webapp/images/emoji/24c2-fe0f.png delete mode 100644 webapp/images/emoji/25aa-fe0f.png delete mode 100644 webapp/images/emoji/25ab-fe0f.png delete mode 100644 webapp/images/emoji/25b6-fe0f.png delete mode 100644 webapp/images/emoji/25c0-fe0f.png delete mode 100644 webapp/images/emoji/25fb-fe0f.png delete mode 100644 webapp/images/emoji/25fc-fe0f.png delete mode 100644 webapp/images/emoji/25fd-fe0f.png delete mode 100644 webapp/images/emoji/25fe-fe0f.png delete mode 100644 webapp/images/emoji/2600-fe0f.png delete mode 100644 webapp/images/emoji/2601-fe0f.png delete mode 100644 webapp/images/emoji/2602-fe0f.png delete mode 100644 webapp/images/emoji/2603-fe0f.png delete mode 100644 webapp/images/emoji/2604-fe0f.png delete mode 100644 webapp/images/emoji/260e-fe0f.png delete mode 100644 webapp/images/emoji/2611-fe0f.png delete mode 100644 webapp/images/emoji/2614-fe0f.png delete mode 100644 webapp/images/emoji/2615-fe0f.png delete mode 100644 webapp/images/emoji/2618-fe0f.png delete mode 100644 webapp/images/emoji/261d-fe0f.png delete mode 100644 webapp/images/emoji/2620-fe0f.png delete mode 100644 webapp/images/emoji/2622-fe0f.png delete mode 100644 webapp/images/emoji/2623-fe0f.png delete mode 100644 webapp/images/emoji/2626-fe0f.png delete mode 100644 webapp/images/emoji/262a-fe0f.png delete mode 100644 webapp/images/emoji/262e-fe0f.png delete mode 100644 webapp/images/emoji/262f-fe0f.png delete mode 100644 webapp/images/emoji/2638-fe0f.png delete mode 100644 webapp/images/emoji/2639-fe0f.png delete mode 100644 webapp/images/emoji/263a-fe0f.png delete mode 100644 webapp/images/emoji/2648-fe0f.png delete mode 100644 webapp/images/emoji/2649-fe0f.png delete mode 100644 webapp/images/emoji/264a-fe0f.png delete mode 100644 webapp/images/emoji/264b-fe0f.png delete mode 100644 webapp/images/emoji/264c-fe0f.png delete mode 100644 webapp/images/emoji/264d-fe0f.png delete mode 100644 webapp/images/emoji/264e-fe0f.png delete mode 100644 webapp/images/emoji/264f-fe0f.png delete mode 100644 webapp/images/emoji/2650-fe0f.png delete mode 100644 webapp/images/emoji/2651-fe0f.png delete mode 100644 webapp/images/emoji/2652-fe0f.png delete mode 100644 webapp/images/emoji/2653-fe0f.png delete mode 100644 webapp/images/emoji/2660-fe0f.png delete mode 100644 webapp/images/emoji/2663-fe0f.png delete mode 100644 webapp/images/emoji/2665-fe0f.png delete mode 100644 webapp/images/emoji/2666-fe0f.png delete mode 100644 webapp/images/emoji/2668-fe0f.png delete mode 100644 webapp/images/emoji/267b-fe0f.png delete mode 100644 webapp/images/emoji/267f-fe0f.png delete mode 100644 webapp/images/emoji/2692.png delete mode 100644 webapp/images/emoji/2693-fe0f.png delete mode 100644 webapp/images/emoji/2694-fe0f.png delete mode 100644 webapp/images/emoji/2696-fe0f.png delete mode 100644 webapp/images/emoji/2697-fe0f.png delete mode 100644 webapp/images/emoji/2699-fe0f.png delete mode 100644 webapp/images/emoji/269b-fe0f.png delete mode 100644 webapp/images/emoji/269c-fe0f.png delete mode 100644 webapp/images/emoji/26a0-fe0f.png delete mode 100644 webapp/images/emoji/26a1-fe0f.png delete mode 100644 webapp/images/emoji/26aa-fe0f.png delete mode 100644 webapp/images/emoji/26ab-fe0f.png delete mode 100644 webapp/images/emoji/26b0-fe0f.png delete mode 100644 webapp/images/emoji/26b1-fe0f.png delete mode 100644 webapp/images/emoji/26bd-fe0f.png delete mode 100644 webapp/images/emoji/26be-fe0f.png delete mode 100644 webapp/images/emoji/26c4-fe0f.png delete mode 100644 webapp/images/emoji/26c5-fe0f.png delete mode 100644 webapp/images/emoji/26c8.png delete mode 100644 webapp/images/emoji/26ce.png delete mode 100644 webapp/images/emoji/26cf.png delete mode 100644 webapp/images/emoji/26d1.png delete mode 100644 webapp/images/emoji/26d3.png delete mode 100644 webapp/images/emoji/26d4-fe0f.png delete mode 100644 webapp/images/emoji/26e9.png delete mode 100644 webapp/images/emoji/26ea-fe0f.png delete mode 100644 webapp/images/emoji/26f0.png delete mode 100644 webapp/images/emoji/26f1.png delete mode 100644 webapp/images/emoji/26f2-fe0f.png delete mode 100644 webapp/images/emoji/26f3-fe0f.png delete mode 100644 webapp/images/emoji/26f4.png delete mode 100644 webapp/images/emoji/26f5-fe0f.png delete mode 100644 webapp/images/emoji/26f7.png delete mode 100644 webapp/images/emoji/26f8.png delete mode 100644 webapp/images/emoji/26f9-fe0f-200d-2640-fe0f.png delete mode 100644 webapp/images/emoji/26f9-fe0f.png delete mode 100644 webapp/images/emoji/26fa-fe0f.png delete mode 100644 webapp/images/emoji/26fd-fe0f.png delete mode 100644 webapp/images/emoji/2702-fe0f.png delete mode 100644 webapp/images/emoji/2705.png delete mode 100644 webapp/images/emoji/2708-fe0f.png delete mode 100644 webapp/images/emoji/2709-fe0f.png delete mode 100644 webapp/images/emoji/270a.png delete mode 100644 webapp/images/emoji/270b.png delete mode 100644 webapp/images/emoji/270c-fe0f.png delete mode 100644 webapp/images/emoji/270d-fe0f.png delete mode 100644 webapp/images/emoji/270f-fe0f.png delete mode 100644 webapp/images/emoji/2712-fe0f.png delete mode 100644 webapp/images/emoji/2714-fe0f.png delete mode 100644 webapp/images/emoji/2716-fe0f.png delete mode 100644 webapp/images/emoji/271d-fe0f.png delete mode 100644 webapp/images/emoji/2721-fe0f.png delete mode 100644 webapp/images/emoji/2728.png delete mode 100644 webapp/images/emoji/2733-fe0f.png delete mode 100644 webapp/images/emoji/2734-fe0f.png delete mode 100644 webapp/images/emoji/2744-fe0f.png delete mode 100644 webapp/images/emoji/2747-fe0f.png delete mode 100644 webapp/images/emoji/274c.png delete mode 100644 webapp/images/emoji/274e.png delete mode 100644 webapp/images/emoji/2753.png delete mode 100644 webapp/images/emoji/2754.png delete mode 100644 webapp/images/emoji/2755.png delete mode 100644 webapp/images/emoji/2757-fe0f.png delete mode 100644 webapp/images/emoji/2763-fe0f.png delete mode 100644 webapp/images/emoji/2764-fe0f.png delete mode 100644 webapp/images/emoji/2795.png delete mode 100644 webapp/images/emoji/2796.png delete mode 100644 webapp/images/emoji/2797.png delete mode 100644 webapp/images/emoji/27a1-fe0f.png delete mode 100644 webapp/images/emoji/27b0.png delete mode 100644 webapp/images/emoji/27bf.png delete mode 100644 webapp/images/emoji/2934-fe0f.png delete mode 100644 webapp/images/emoji/2935-fe0f.png delete mode 100644 webapp/images/emoji/2b05-fe0f.png delete mode 100644 webapp/images/emoji/2b06-fe0f.png delete mode 100644 webapp/images/emoji/2b07-fe0f.png delete mode 100644 webapp/images/emoji/2b1b-fe0f.png delete mode 100644 webapp/images/emoji/2b1c-fe0f.png delete mode 100644 webapp/images/emoji/2b50-fe0f.png delete mode 100644 webapp/images/emoji/2b55-fe0f.png delete mode 100644 webapp/images/emoji/3030-fe0f.png delete mode 100644 webapp/images/emoji/303d-fe0f.png delete mode 100644 webapp/images/emoji/3297-fe0f.png delete mode 100644 webapp/images/emoji/3299-fe0f.png delete mode 100644 webapp/images/emoji/bowtie.png delete mode 100644 webapp/images/emoji/feelsgood.png delete mode 100644 webapp/images/emoji/finnadie.png delete mode 100644 webapp/images/emoji/goberserk.png delete mode 100644 webapp/images/emoji/godmode.png delete mode 100644 webapp/images/emoji/hurtrealbad.png delete mode 100644 webapp/images/emoji/mattermost.png delete mode 100644 webapp/images/emoji/neckbeard.png delete mode 100644 webapp/images/emoji/octocat.png delete mode 100644 webapp/images/emoji/rage1.png delete mode 100644 webapp/images/emoji/rage2.png delete mode 100644 webapp/images/emoji/rage3.png delete mode 100644 webapp/images/emoji/rage4.png delete mode 100644 webapp/images/emoji/shipit.png delete mode 100644 webapp/images/emoji/suspect.png delete mode 100644 webapp/images/emoji/trollface.png delete mode 100644 webapp/images/favicon/android-chrome-192x192.png delete mode 100644 webapp/images/favicon/apple-touch-icon-120x120.png delete mode 100644 webapp/images/favicon/apple-touch-icon-144x144.png delete mode 100644 webapp/images/favicon/apple-touch-icon-152x152.png delete mode 100644 webapp/images/favicon/apple-touch-icon-57x57.png delete mode 100644 webapp/images/favicon/apple-touch-icon-60x60.png delete mode 100644 webapp/images/favicon/apple-touch-icon-72x72.png delete mode 100644 webapp/images/favicon/apple-touch-icon-76x76.png delete mode 100644 webapp/images/favicon/favicon-16x16.png delete mode 100644 webapp/images/favicon/favicon-32x32.png delete mode 100644 webapp/images/favicon/favicon-96x96.png delete mode 100644 webapp/images/favicon/redfavicon-16x16.png delete mode 100644 webapp/images/filesOverlay.png delete mode 100644 webapp/images/gitlabLogo.png delete mode 100644 webapp/images/googleLogo.png delete mode 100644 webapp/images/icon50x50.png delete mode 100644 webapp/images/icon64x64.png delete mode 100644 webapp/images/icons/audio.png delete mode 100644 webapp/images/icons/code.png delete mode 100644 webapp/images/icons/excel.png delete mode 100644 webapp/images/icons/generic.png delete mode 100644 webapp/images/icons/image.png delete mode 100644 webapp/images/icons/patch.png delete mode 100644 webapp/images/icons/pdf.png delete mode 100644 webapp/images/icons/ppt.png delete mode 100644 webapp/images/icons/video.png delete mode 100644 webapp/images/icons/word.png delete mode 100644 webapp/images/img_trans.gif delete mode 100644 webapp/images/incoming_webhook.jpg delete mode 100644 webapp/images/info__icon.png delete mode 100644 webapp/images/iphone-6-mockup.png delete mode 100644 webapp/images/load.gif delete mode 100644 webapp/images/logo-email.png delete mode 100644 webapp/images/logo.png delete mode 100644 webapp/images/logoWhite.png delete mode 100644 webapp/images/logo_compact.png delete mode 100644 webapp/images/next.png delete mode 100644 webapp/images/nexus-6p-mockup.png delete mode 100644 webapp/images/oauth_icon.png delete mode 100644 webapp/images/office365Logo.png delete mode 100644 webapp/images/outgoing_webhook.jpg delete mode 100644 webapp/images/pixel.png delete mode 100644 webapp/images/prev.png delete mode 100644 webapp/images/redfavicon.ico delete mode 100644 webapp/images/ring.mp3 delete mode 100644 webapp/images/slash_command_icon.jpg delete mode 100644 webapp/images/status_green.png delete mode 100644 webapp/images/status_red.png delete mode 100644 webapp/images/status_yellow.png delete mode 100644 webapp/images/test.png delete mode 100755 webapp/images/testgif.gif delete mode 100755 webapp/images/testjpg.jpg delete mode 100644 webapp/images/themes/code_themes/github.png delete mode 100644 webapp/images/themes/code_themes/monokai.png delete mode 100644 webapp/images/themes/code_themes/solarized-dark.png delete mode 100644 webapp/images/themes/code_themes/solarized-light.png delete mode 100644 webapp/images/themes/mattermost.png delete mode 100644 webapp/images/themes/mattermost_dark.png delete mode 100644 webapp/images/themes/organization.png delete mode 100644 webapp/images/themes/windows_dark.png delete mode 100644 webapp/images/tutorialTip.gif delete mode 100644 webapp/images/tutorialTipWhite.gif delete mode 100644 webapp/images/warning.png delete mode 100644 webapp/images/webhook_icon.jpg delete mode 100755 webapp/make-emojis delete mode 100644 webapp/non_npm_dependencies/janus/index.js delete mode 100644 webapp/non_npm_dependencies/jquery-dragster/jquery.dragster.js delete mode 100644 webapp/non_npm_dependencies/katex/LICENSE.txt delete mode 100644 webapp/non_npm_dependencies/katex/README.md delete mode 100755 webapp/non_npm_dependencies/katex/cli.js delete mode 100644 webapp/non_npm_dependencies/katex/dist/README.md delete mode 100644 webapp/non_npm_dependencies/katex/dist/contrib/auto-render.min.js delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_AMS-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_AMS-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_AMS-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_AMS-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Caligraphic-Bold.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Caligraphic-Bold.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Caligraphic-Bold.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Caligraphic-Bold.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Caligraphic-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Caligraphic-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Caligraphic-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Caligraphic-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Fraktur-Bold.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Fraktur-Bold.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Fraktur-Bold.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Fraktur-Bold.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Fraktur-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Fraktur-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Fraktur-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Fraktur-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Bold.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Bold.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Bold.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Bold.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Italic.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Italic.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Italic.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Italic.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Main-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-BoldItalic.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-BoldItalic.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-BoldItalic.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-BoldItalic.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-Italic.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-Italic.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-Italic.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-Italic.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Math-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Bold.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Bold.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Bold.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Bold.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Italic.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Italic.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Italic.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Italic.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_SansSerif-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Script-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Script-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Script-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Script-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size1-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size1-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size1-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size1-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size2-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size2-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size2-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size2-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size3-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size3-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size3-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size3-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size4-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size4-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size4-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Size4-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Typewriter-Regular.eot delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Typewriter-Regular.ttf delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Typewriter-Regular.woff delete mode 100644 webapp/non_npm_dependencies/katex/dist/fonts/KaTeX_Typewriter-Regular.woff2 delete mode 100644 webapp/non_npm_dependencies/katex/dist/katex.min.css delete mode 100644 webapp/non_npm_dependencies/katex/dist/katex.min.js delete mode 100644 webapp/non_npm_dependencies/katex/katex.js delete mode 100644 webapp/non_npm_dependencies/katex/package.json delete mode 100644 webapp/non_npm_dependencies/katex/src/Lexer.js delete mode 100644 webapp/non_npm_dependencies/katex/src/Options.js delete mode 100644 webapp/non_npm_dependencies/katex/src/ParseError.js delete mode 100644 webapp/non_npm_dependencies/katex/src/Parser.js delete mode 100644 webapp/non_npm_dependencies/katex/src/Settings.js delete mode 100644 webapp/non_npm_dependencies/katex/src/Style.js delete mode 100644 webapp/non_npm_dependencies/katex/src/buildCommon.js delete mode 100644 webapp/non_npm_dependencies/katex/src/buildHTML.js delete mode 100644 webapp/non_npm_dependencies/katex/src/buildMathML.js delete mode 100644 webapp/non_npm_dependencies/katex/src/buildTree.js delete mode 100644 webapp/non_npm_dependencies/katex/src/delimiter.js delete mode 100644 webapp/non_npm_dependencies/katex/src/domTree.js delete mode 100644 webapp/non_npm_dependencies/katex/src/environments.js delete mode 100644 webapp/non_npm_dependencies/katex/src/fontMetrics.js delete mode 100644 webapp/non_npm_dependencies/katex/src/fontMetricsData.js delete mode 100644 webapp/non_npm_dependencies/katex/src/functions.js delete mode 100644 webapp/non_npm_dependencies/katex/src/mathMLTree.js delete mode 100644 webapp/non_npm_dependencies/katex/src/parseData.js delete mode 100644 webapp/non_npm_dependencies/katex/src/parseTree.js delete mode 100644 webapp/non_npm_dependencies/katex/src/symbols.js delete mode 100644 webapp/non_npm_dependencies/katex/src/utils.js delete mode 100644 webapp/package.json delete mode 100644 webapp/plugins/index.js delete mode 100644 webapp/plugins/jira/components/settings.jsx delete mode 100644 webapp/plugins/jira/components/style.scss delete mode 100644 webapp/plugins/pluggable/index.js delete mode 100644 webapp/plugins/pluggable/pluggable.jsx delete mode 100644 webapp/reducers/index.js delete mode 100644 webapp/reducers/plugins/index.js delete mode 100644 webapp/reducers/views/channel.js delete mode 100644 webapp/reducers/views/index.js delete mode 100644 webapp/reducers/views/rhs.js delete mode 100644 webapp/root.html delete mode 100644 webapp/root.jsx delete mode 100644 webapp/routes/route_admin_console.jsx delete mode 100644 webapp/routes/route_claim.jsx delete mode 100644 webapp/routes/route_create_team.jsx delete mode 100644 webapp/routes/route_emoji.jsx delete mode 100644 webapp/routes/route_help.jsx delete mode 100644 webapp/routes/route_integrations.jsx delete mode 100644 webapp/routes/route_mfa.jsx delete mode 100644 webapp/routes/route_root.jsx delete mode 100644 webapp/routes/route_team.jsx delete mode 100644 webapp/routes/route_utils.jsx delete mode 100644 webapp/sass/base/_module.scss delete mode 100644 webapp/sass/base/_structure.scss delete mode 100644 webapp/sass/base/_typography.scss delete mode 100644 webapp/sass/components/_alerts.scss delete mode 100644 webapp/sass/components/_buttons.scss delete mode 100644 webapp/sass/components/_dropdown.scss delete mode 100644 webapp/sass/components/_emojisprite.scss delete mode 100644 webapp/sass/components/_emoticons.scss delete mode 100644 webapp/sass/components/_error-bar.scss delete mode 100644 webapp/sass/components/_files.scss delete mode 100644 webapp/sass/components/_inputs.scss delete mode 100644 webapp/sass/components/_links.scss delete mode 100644 webapp/sass/components/_mentions.scss delete mode 100644 webapp/sass/components/_modal.scss delete mode 100644 webapp/sass/components/_module.scss delete mode 100644 webapp/sass/components/_multi-select.scss delete mode 100644 webapp/sass/components/_oauth.scss delete mode 100644 webapp/sass/components/_popover.scss delete mode 100644 webapp/sass/components/_save-button.scss delete mode 100644 webapp/sass/components/_scrollbar.scss delete mode 100644 webapp/sass/components/_search.scss delete mode 100644 webapp/sass/components/_spinner-button.scss delete mode 100644 webapp/sass/components/_status-dropdown.scss delete mode 100644 webapp/sass/components/_status-icon.scss delete mode 100644 webapp/sass/components/_suggestion-list.scss delete mode 100644 webapp/sass/components/_tooltip.scss delete mode 100644 webapp/sass/components/_tutorial.scss delete mode 100644 webapp/sass/components/_videos.scss delete mode 100644 webapp/sass/components/_webrtc.scss delete mode 100644 webapp/sass/layout/_content.scss delete mode 100644 webapp/sass/layout/_footer.scss delete mode 100644 webapp/sass/layout/_forms.scss delete mode 100644 webapp/sass/layout/_headers.scss delete mode 100644 webapp/sass/layout/_markdown.scss delete mode 100644 webapp/sass/layout/_module.scss delete mode 100644 webapp/sass/layout/_navigation.scss delete mode 100644 webapp/sass/layout/_post-right.scss delete mode 100644 webapp/sass/layout/_post.scss delete mode 100644 webapp/sass/layout/_sidebar-left.scss delete mode 100644 webapp/sass/layout/_sidebar-menu.scss delete mode 100644 webapp/sass/layout/_sidebar-right.scss delete mode 100644 webapp/sass/layout/_team-sidebar.scss delete mode 100644 webapp/sass/layout/_webhooks.scss delete mode 100644 webapp/sass/responsive/_desktop.scss delete mode 100644 webapp/sass/responsive/_mobile.scss delete mode 100644 webapp/sass/responsive/_module.scss delete mode 100644 webapp/sass/responsive/_tablet.scss delete mode 100644 webapp/sass/routes/_about-modal.scss delete mode 100644 webapp/sass/routes/_access-history.scss delete mode 100644 webapp/sass/routes/_activity-log.scss delete mode 100644 webapp/sass/routes/_admin-console.scss delete mode 100644 webapp/sass/routes/_backstage.scss delete mode 100644 webapp/sass/routes/_compliance.scss delete mode 100644 webapp/sass/routes/_docs.scss delete mode 100644 webapp/sass/routes/_error-page.scss delete mode 100644 webapp/sass/routes/_get-app.scss delete mode 100644 webapp/sass/routes/_loading.scss delete mode 100644 webapp/sass/routes/_module.scss delete mode 100644 webapp/sass/routes/_print.scss delete mode 100644 webapp/sass/routes/_settings.scss delete mode 100644 webapp/sass/routes/_shortcuts-modal.scss delete mode 100644 webapp/sass/routes/_signup.scss delete mode 100644 webapp/sass/routes/_statistics.scss delete mode 100644 webapp/sass/styles.scss delete mode 100644 webapp/sass/utils/_animations.scss delete mode 100644 webapp/sass/utils/_functions.scss delete mode 100644 webapp/sass/utils/_mixins.scss delete mode 100644 webapp/sass/utils/_modifiers.scss delete mode 100644 webapp/sass/utils/_module.scss delete mode 100644 webapp/sass/utils/_variables.scss delete mode 100644 webapp/store/index.js delete mode 100644 webapp/store/utils.js delete mode 100644 webapp/stores/analytics_store.jsx delete mode 100644 webapp/stores/browser_store.jsx delete mode 100644 webapp/stores/channel_store.jsx delete mode 100644 webapp/stores/emoji_store.jsx delete mode 100644 webapp/stores/error_store.jsx delete mode 100644 webapp/stores/integration_store.jsx delete mode 100644 webapp/stores/localization_store.jsx delete mode 100644 webapp/stores/message_history_store.jsx delete mode 100644 webapp/stores/modal_store.jsx delete mode 100644 webapp/stores/notification_store.jsx delete mode 100644 webapp/stores/opengraph_store.jsx delete mode 100644 webapp/stores/post_store.jsx delete mode 100644 webapp/stores/preference_store.jsx delete mode 100644 webapp/stores/redux_store.jsx delete mode 100644 webapp/stores/search_store.jsx delete mode 100644 webapp/stores/suggestion_store.jsx delete mode 100644 webapp/stores/team_store.jsx delete mode 100644 webapp/stores/user_store.jsx delete mode 100644 webapp/stores/user_typing_store.jsx delete mode 100644 webapp/stores/webrtc_store.jsx delete mode 100644 webapp/tests/.eslintrc.json delete mode 100644 webapp/tests/components/__snapshots__/about_build_modal.test.jsx.snap delete mode 100644 webapp/tests/components/__snapshots__/new_channel_modal.test.jsx.snap delete mode 100644 webapp/tests/components/__snapshots__/reset_status_modal.test.jsx.snap delete mode 100644 webapp/tests/components/__snapshots__/shortcuts_modal.test.jsx.snap delete mode 100644 webapp/tests/components/__snapshots__/spinner_button.test.jsx.snap delete mode 100644 webapp/tests/components/about_build_modal.test.jsx delete mode 100644 webapp/tests/components/admin_console/__snapshots__/color_setting.test.jsx.snap delete mode 100644 webapp/tests/components/admin_console/color_setting.test.jsx delete mode 100644 webapp/tests/components/admin_console/request_button/__snapshots__/request_button.test.jsx.snap delete mode 100644 webapp/tests/components/admin_console/request_button/request_button.test.jsx delete mode 100644 webapp/tests/components/backstage/components/__snapshots__/backstage_header.test.jsx.snap delete mode 100644 webapp/tests/components/backstage/components/backstage_header.test.jsx delete mode 100644 webapp/tests/components/integrations/__snapshots__/add_command.test.jsx.snap delete mode 100644 webapp/tests/components/integrations/__snapshots__/add_incoming_hook.test.jsx.snap delete mode 100644 webapp/tests/components/integrations/__snapshots__/add_oauth_app.test.jsx.snap delete mode 100644 webapp/tests/components/integrations/__snapshots__/add_outgoing_hook.test.jsx.snap delete mode 100644 webapp/tests/components/integrations/__snapshots__/edit_command.test.jsx.snap delete mode 100644 webapp/tests/components/integrations/__snapshots__/edit_incoming_hook.test.jsx.snap delete mode 100644 webapp/tests/components/integrations/__snapshots__/edit_outgoing_hook.test.jsx.snap delete mode 100644 webapp/tests/components/integrations/__snapshots__/installed_command.test.jsx.snap delete mode 100644 webapp/tests/components/integrations/__snapshots__/installed_oauth_app.test.jsx.snap delete mode 100644 webapp/tests/components/integrations/__snapshots__/installed_oauth_apps.test.jsx.snap delete mode 100644 webapp/tests/components/integrations/add_command.test.jsx delete mode 100644 webapp/tests/components/integrations/add_incoming_hook.test.jsx delete mode 100644 webapp/tests/components/integrations/add_oauth_app.test.jsx delete mode 100644 webapp/tests/components/integrations/add_outgoing_hook.test.jsx delete mode 100644 webapp/tests/components/integrations/edit_command.test.jsx delete mode 100644 webapp/tests/components/integrations/edit_incoming_hook.test.jsx delete mode 100644 webapp/tests/components/integrations/edit_outgoing_hook.test.jsx delete mode 100644 webapp/tests/components/integrations/installed_command.test.jsx delete mode 100644 webapp/tests/components/integrations/installed_oauth_app.test.jsx delete mode 100644 webapp/tests/components/integrations/installed_oauth_apps.test.jsx delete mode 100644 webapp/tests/components/new_channel_modal.test.jsx delete mode 100644 webapp/tests/components/post_view/post_info/__snapshots__/post_info.test.jsx.snap delete mode 100644 webapp/tests/components/post_view/post_info/post_info.test.jsx delete mode 100644 webapp/tests/components/reset_status_modal.test.jsx delete mode 100644 webapp/tests/components/shortcuts_modal.test.jsx delete mode 100644 webapp/tests/components/spinner_button.test.jsx delete mode 100644 webapp/tests/components/suggestion/suggestion_box.test.jsx delete mode 100644 webapp/tests/helpers/client-test-helper.jsx delete mode 100644 webapp/tests/helpers/intl-test-helper.jsx delete mode 100644 webapp/tests/plugins/__snapshots__/pluggable.test.jsx.snap delete mode 100644 webapp/tests/plugins/pluggable.test.jsx delete mode 100644 webapp/tests/utils/channel_utils.test.jsx delete mode 100644 webapp/tests/utils/emoticons.test.jsx delete mode 100644 webapp/tests/utils/formatting_at_mentions.test.jsx delete mode 100644 webapp/tests/utils/formatting_channel_links.test.jsx delete mode 100644 webapp/tests/utils/formatting_hashtags.test.jsx delete mode 100644 webapp/tests/utils/formatting_imgs.test.jsx delete mode 100644 webapp/tests/utils/formatting_links.test.jsx delete mode 100644 webapp/tests/utils/latinise.test.jsx delete mode 100644 webapp/tests/utils/post_utils.test.jsx delete mode 100644 webapp/tests/utils/utils_get_nearest_point.test.jsx delete mode 100644 webapp/utils/channel_intro_messages.jsx delete mode 100644 webapp/utils/channel_utils.jsx delete mode 100644 webapp/utils/commons.jsx delete mode 100644 webapp/utils/constants.jsx delete mode 100644 webapp/utils/delayed_action.jsx delete mode 100644 webapp/utils/emoji.jsx delete mode 100644 webapp/utils/emoticons.jsx delete mode 100644 webapp/utils/event_types.jsx delete mode 100644 webapp/utils/file_utils.jsx delete mode 100644 webapp/utils/global_event_emitter.jsx delete mode 100644 webapp/utils/latinise.jsx delete mode 100644 webapp/utils/license_utils.jsx delete mode 100644 webapp/utils/markdown.jsx delete mode 100644 webapp/utils/post_utils.jsx delete mode 100644 webapp/utils/syntax_highlighting.jsx delete mode 100644 webapp/utils/team_utils.jsx delete mode 100644 webapp/utils/text_formatting.jsx delete mode 100644 webapp/utils/url.jsx delete mode 100644 webapp/utils/user_agent.jsx delete mode 100644 webapp/utils/utils.jsx delete mode 100644 webapp/webpack.config.js delete mode 100644 webapp/yarn.lock diff --git a/webapp/.babelrc b/webapp/.babelrc deleted file mode 100644 index 3c45d7307..000000000 --- a/webapp/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "es2015", - "react", - "stage-0" - ] -} diff --git a/webapp/.eslintrc.json b/webapp/.eslintrc.json deleted file mode 100644 index b53682153..000000000 --- a/webapp/.eslintrc.json +++ /dev/null @@ -1,273 +0,0 @@ -{ - "extends": "eslint:recommended", - "parserOptions": { - "ecmaVersion": 8, - "sourceType": "module", - "ecmaFeatures": { - "jsx": true, - "impliedStrict": true, - "modules": true, - "experimentalObjectRestSpread": true - } - }, - "parser": "babel-eslint", - "plugins": [ - "react" - ], - "env": { - "browser": true, - "node": true, - "jquery": true, - "es6": true - }, - "globals": { - "jest": true, - "describe": true, - "it": true, - "expect": true, - "before": true, - "after": true - }, - "rules": { - "array-bracket-spacing": [2, "never"], - "array-callback-return": 2, - "arrow-body-style": 0, - "arrow-parens": [2, "always"], - "arrow-spacing": [2, { "before": true, "after": true }], - "block-scoped-var": 2, - "brace-style": [2, "1tbs", { "allowSingleLine": false }], - "camelcase": [2, {"properties": "never"}], - "capitalized-comments": 0, - "class-methods-use-this": 1, - "comma-dangle": [2, "never"], - "comma-spacing": [2, {"before": false, "after": true}], - "comma-style": [2, "last"], - "complexity": [1, 10], - "computed-property-spacing": [2, "never"], - "consistent-return": 2, - "consistent-this": [2, "self"], - "constructor-super": 2, - "curly": [2, "all"], - "dot-location": [2, "object"], - "dot-notation": 2, - "eqeqeq": [2, "smart"], - "func-call-spacing": [2, "never"], - "func-name-matching": 0, - "func-names": 2, - "func-style": [2, "declaration"], - "generator-star-spacing": [2, {"before": false, "after": true}], - "global-require": 2, - "guard-for-in": 2, - "id-blacklist": 0, - "indent": [2, 4, {"SwitchCase": 0}], - "jsx-quotes": [2, "prefer-single"], - "key-spacing": [2, {"beforeColon": false, "afterColon": true, "mode": "strict"}], - "keyword-spacing": [2, {"before": true, "after": true, "overrides": {}}], - "line-comment-position": 0, - "linebreak-style": 2, - "lines-around-comment": [2, { "beforeBlockComment": true, "beforeLineComment": true, "allowBlockStart": true, "allowBlockEnd": true }], - "max-lines": [1, {"max": 450, "skipBlankLines": true, "skipComments": false}], - "max-nested-callbacks": [1, {"max":1}], - "max-nested-callbacks": [2, {"max":2}], - "max-statements-per-line": [2, {"max": 1}], - "multiline-ternary": [1, "never"], - "new-cap": 2, - "new-parens": 2, - "newline-before-return": 0, - "newline-per-chained-call": 0, - "no-alert": 2, - "no-array-constructor": 2, - "no-await-in-loop": 2, - "no-caller": 2, - "no-case-declarations": 2, - "no-class-assign": 2, - "no-compare-neg-zero": 2, - "no-cond-assign": [2, "except-parens"], - "no-confusing-arrow": 2, - "no-console": 2, - "no-const-assign": 2, - "no-constant-condition": 2, - "no-debugger": 2, - "no-div-regex": 2, - "no-dupe-args": 2, - "no-dupe-class-members": 2, - "no-dupe-keys": 2, - "no-duplicate-case": 2, - "no-duplicate-imports": [2, {"includeExports": true}], - "no-else-return": 2, - "no-empty": 2, - "no-empty-function": 2, - "no-empty-pattern": 2, - "no-eval": 2, - "no-ex-assign": 2, - "no-extend-native": 2, - "no-extra-bind": 2, - "no-extra-label": 2, - "no-extra-parens": 0, - "no-extra-semi": 2, - "no-fallthrough": 2, - "no-floating-decimal": 2, - "no-func-assign": 2, - "no-global-assign": 2, - "no-implicit-coercion": 2, - "no-implicit-globals": 0, - "no-implied-eval": 2, - "no-inner-declarations": 0, - "no-invalid-regexp": 2, - "no-irregular-whitespace": 2, - "no-iterator": 2, - "no-labels": 2, - "no-lone-blocks": 2, - "no-lonely-if": 2, - "no-loop-func": 2, - "no-magic-numbers": [1, { "ignore": [-1, 0, 1, 2], "enforceConst": true, "detectObjects": true } ], - "no-mixed-operators": [2, {"allowSamePrecedence": false}], - "no-mixed-spaces-and-tabs": 2, - "no-multi-assign": 2, - "no-multi-spaces": [2, { "exceptions": { "Property": false } }], - "no-multi-str": 0, - "no-multiple-empty-lines": [2, {"max": 1}], - "no-native-reassign": 2, - "no-negated-condition": 2, - "no-nested-ternary": 2, - "no-new": 2, - "no-new-func": 2, - "no-new-object": 2, - "no-new-symbol": 2, - "no-new-wrappers": 2, - "no-octal-escape": 2, - "no-param-reassign": 2, - "no-process-env": 2, - "no-process-exit": 2, - "no-proto": 2, - "no-redeclare": 2, - "no-return-assign": [2, "always"], - "no-return-await": 2, - "no-script-url": 2, - "no-self-assign": [2, {"props": true}], - "no-self-compare": 2, - "no-sequences": 2, - "no-shadow": [2, {"hoist": "functions"}], - "no-shadow-restricted-names": 2, - "no-spaced-func": 2, - "no-tabs": 0, - "no-template-curly-in-string": 2, - "no-ternary": 0, - "no-this-before-super": 2, - "no-throw-literal": 2, - "no-trailing-spaces": [2, { "skipBlankLines": false }], - "no-undef-init": 2, - "no-undefined": 2, - "no-underscore-dangle": 2, - "no-unexpected-multiline": 2, - "no-unmodified-loop-condition": 2, - "no-unneeded-ternary": [2, {"defaultAssignment": false}], - "no-unreachable": 2, - "no-unsafe-finally": 2, - "no-unsafe-negation": 2, - "no-unused-expressions": 2, - "no-unused-vars": [2, {"vars": "all", "args": "after-used"}], - "no-use-before-define": [2, "nofunc"], - "no-useless-computed-key": 2, - "no-useless-concat": 2, - "no-useless-constructor": 2, - "no-useless-escape": 2, - "no-useless-rename": 2, - "no-useless-return": 2, - "no-var": 0, - "no-void": 2, - "no-warning-comments": 1, - "no-whitespace-before-property": 2, - "no-with": 2, - "object-curly-newline": 0, - "object-curly-spacing": [2, "never"], - "object-property-newline": [2, {"allowMultiplePropertiesPerLine": true}], - "object-shorthand": [2, "always"], - "one-var": [2, "never"], - "one-var-declaration-per-line": 0, - "operator-assignment": [2, "always"], - "operator-linebreak": [2, "after"], - "padded-blocks": [2, "never"], - "prefer-arrow-callback": 2, - "prefer-const": 2, - "prefer-destructuring": 0, - "prefer-numeric-literals": 2, - "prefer-promise-reject-errors": 2, - "prefer-rest-params": 2, - "prefer-spread": 2, - "prefer-template": 0, - "quote-props": [2, "as-needed"], - "quotes": [2, "single", "avoid-escape"], - "radix": 2, - "react/display-name": [2, { "ignoreTranspilerName": false }], - "react/forbid-component-props": 0, - "react/forbid-elements": [2, { "forbid": ["embed"] }], - "react/jsx-boolean-value": [2, "always"], - "react/jsx-closing-bracket-location": [2, { "location": "tag-aligned" }], - "react/jsx-curly-spacing": [2, "never"], - "react/jsx-equals-spacing": [2, "never"], - "react/jsx-filename-extension": 2, - "react/jsx-first-prop-new-line": [2, "multiline"], - "react/jsx-handler-names": 0, - "react/jsx-indent": [2, 4], - "react/jsx-indent-props": [2, 4], - "react/jsx-key": 2, - "react/jsx-max-props-per-line": [2, { "maximum": 1 }], - "react/jsx-no-bind": 0, - "react/jsx-no-comment-textnodes": 2, - "react/jsx-no-duplicate-props": [2, { "ignoreCase": false }], - "react/jsx-no-literals": 2, - "react/jsx-no-target-blank": 2, - "react/jsx-no-undef": 2, - "react/jsx-pascal-case": 2, - "react/jsx-space-before-closing": [2, "never"], - "react/jsx-tag-spacing": [2, { "closingSlash": "never", "beforeSelfClosing": "never", "afterOpening": "never" }], - "react/jsx-uses-react": 2, - "react/jsx-uses-vars": 2, - "react/jsx-wrap-multilines": 2, - "react/no-array-index-key": 1, - "react/no-children-prop": 2, - "react/no-danger": 0, - "react/no-danger-with-children": 2, - "react/no-deprecated": 2, - "react/no-did-mount-set-state": 2, - "react/no-did-update-set-state": 2, - "react/no-direct-mutation-state": 2, - "react/no-find-dom-node": 1, - "react/no-is-mounted": 2, - "react/no-multi-comp": [2, { "ignoreStateless": true }], - "react/no-render-return-value": 2, - "react/no-set-state": 0, - "react/no-string-refs": 0, - "react/no-unescaped-entities": 2, - "react/no-unknown-property": 2, - "react/no-unused-prop-types": [1, {"skipShapeProps": true}], - "react/prefer-es6-class": 2, - "react/prefer-stateless-function": 0, - "react/prop-types": 2, - "react/require-default-props": 0, - "react/require-optimization": 1, - "react/require-render-return": 2, - "react/self-closing-comp": 2, - "react/sort-comp": 0, - "react/style-prop-object": 2, - "require-yield": 2, - "rest-spread-spacing": [2, "never"], - "semi": [2, "always"], - "semi-spacing": [2, {"before": false, "after": true}], - "sort-imports": 0, - "sort-keys": 0, - "space-before-blocks": [2, "always"], - "space-before-function-paren": [2, {"anonymous": "never", "named": "never", "asyncArrow": "always"}], - "space-in-parens": [2, "never"], - "space-infix-ops": 2, - "space-unary-ops": [2, { "words": true, "nonwords": false }], - "symbol-description": 2, - "template-curly-spacing": [2, "never"], - "valid-typeof": [2, {"requireStringLiterals": false}], - "vars-on-top": 0, - "wrap-iife": [2, "outside"], - "wrap-regex": 2, - "yoda": [2, "never", {"exceptRange": false, "onlyEquality": false}] - } -} diff --git a/webapp/Makefile b/webapp/Makefile deleted file mode 100644 index 8bb7a83d1..000000000 --- a/webapp/Makefile +++ /dev/null @@ -1,59 +0,0 @@ -.PHONY: build test run clean stop check-style run-unit emojis - -BUILD_SERVER_DIR = .. - -check-style: .yarninstall - @echo Checking for style guide compliance - - yarn run check - -test: .yarninstall - cd $(BUILD_SERVER_DIR) && $(MAKE) internal-test-web-client - -.yarninstall: package.json - @echo Getting dependencies using yarn - - yarn install - - touch $@ - -build: .yarninstall - @echo Building mattermost Webapp - - rm -rf dist - - yarn run build - -run: .yarninstall - @echo Running mattermost Webapp for development - - yarn run run & - -run-fullmap: .yarninstall - @echo FULL SOURCE MAP Running mattermost Webapp for development FULL SOURCE MAP - - yarn run run-fullmap & - -stop: - @echo Stopping changes watching - -ifeq ($(OS),Windows_NT) - wmic process where "Caption='node.exe' and CommandLine like '%webpack%'" call terminate -else - @for PROCID in $$(ps -ef | grep "[n]ode.*[w]ebpack" | awk '{ print $$2 }'); do \ - echo stopping webpack watch $$PROCID; \ - kill $$PROCID; \ - done -endif - -clean: - @echo Cleaning Webapp - - yarn cache clean - - rm -rf dist - rm -rf node_modules - rm -f .yarninstall - -emojis: - ./make-emojis diff --git a/webapp/actions/admin_actions.jsx b/webapp/actions/admin_actions.jsx deleted file mode 100644 index 4dd0f848f..000000000 --- a/webapp/actions/admin_actions.jsx +++ /dev/null @@ -1,397 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {clientLogout} from 'actions/global_actions.jsx'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import * as AdminActions from 'mattermost-redux/actions/admin'; -import * as UserActions from 'mattermost-redux/actions/users'; -import {Client4} from 'mattermost-redux/client'; - -export function saveConfig(config, success, error) { - AdminActions.updateConfig(config)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.updateConfig.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function reloadConfig(success, error) { - AdminActions.reloadConfig()(dispatch, getState).then( - (data) => { - if (data && success) { - AdminActions.getConfig()(dispatch, getState); - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.reloadConfig.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function adminResetMfa(userId, success, error) { - UserActions.updateUserMfa(userId, false)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getClusterStatus(success, error) { - AdminActions.getClusterStatus()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.getClusterStatus.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function testEmail(config, success, error) { - AdminActions.testEmail(config)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.testEmail.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function ldapTest(success, error) { - AdminActions.testLdap()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.testLdap.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function invalidateAllCaches(success, error) { - AdminActions.invalidateCaches()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.invalidateCaches.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function recycleDatabaseConnection(success, error) { - AdminActions.recycleDatabase()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.recycleDatabase.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function adminResetPassword(userId, password, success, error) { - UserActions.updateUserPassword(userId, '', password)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function samlCertificateStatus(success, error) { - AdminActions.getSamlCertificateStatus()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.getSamlCertificateStatus.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function ldapSyncNow(success, error) { - AdminActions.syncLdap()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.syncLdap.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getOAuthAppInfo(clientId, success, error) { - Client4.getOAuthAppInfo(clientId).then( - (data) => { - if (success) { - success(data); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function allowOAuth2(params, success, error) { - const responseType = params.response_type; - const clientId = params.client_id; - const redirectUri = params.redirect_uri; - const state = params.state; - const scope = params.scope; - - Client4.authorizeOAuthApp(responseType, clientId, redirectUri, state, scope).then( - (data) => { - if (success) { - success(data); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function emailToLdap(loginId, password, token, ldapId, ldapPassword, success, error) { - UserActions.switchEmailToLdap(loginId, password, ldapId, ldapPassword, token)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.switchLogin.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function emailToOAuth(loginId, password, token, newType, success, error) { - UserActions.switchEmailToOAuth(newType, loginId, password, token)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.switchLogin.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function oauthToEmail(currentService, email, password, success, error) { - UserActions.switchOAuthToEmail(currentService, email, password)(dispatch, getState).then( - (data) => { - if (data) { - if (data.follow_link) { - clientLogout(data.follow_link); - } - if (success) { - success(data); - } - } else if (data == null && error) { - const serverError = getState().requests.users.switchLogin.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function uploadBrandImage(brandImage, success, error) { - AdminActions.uploadBrandImage(brandImage)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.uploadBrandImage.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function uploadLicenseFile(file, success, error) { - AdminActions.uploadLicense(file)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.uploadLicense.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function removeLicenseFile(success, error) { - AdminActions.removeLicense()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.removeLicense.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function uploadPublicSamlCertificate(file, success, error) { - AdminActions.uploadPublicSamlCertificate(file)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.uploadPublicSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function uploadPrivateSamlCertificate(file, success, error) { - AdminActions.uploadPrivateSamlCertificate(file)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.uploadPrivateSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function uploadIdpSamlCertificate(file, success, error) { - AdminActions.uploadIdpSamlCertificate(file)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.uploadIdpSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function removePublicSamlCertificate(success, error) { - AdminActions.removePublicSamlCertificate()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.removePublicSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function removePrivateSamlCertificate(success, error) { - AdminActions.removePrivateSamlCertificate()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.removePrivateSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function removeIdpSamlCertificate(success, error) { - AdminActions.removeIdpSamlCertificate()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.removeIdpSamlCertificate.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getStandardAnalytics(teamId) { - AdminActions.getStandardAnalytics(teamId)(dispatch, getState); -} - -export function getAdvancedAnalytics(teamId) { - AdminActions.getAdvancedAnalytics(teamId)(dispatch, getState); -} - -export function getPostsPerDayAnalytics(teamId) { - AdminActions.getPostsPerDayAnalytics(teamId)(dispatch, getState); -} - -export function getUsersPerDayAnalytics(teamId) { - AdminActions.getUsersPerDayAnalytics(teamId)(dispatch, getState); -} - -export function elasticsearchTest(config, success, error) { - AdminActions.testElasticsearch(config)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.testElasticsearch.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function elasticsearchPurgeIndexes(success, error) { - AdminActions.purgeElasticsearchIndexes()(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.admin.purgeElasticsearchIndexes.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/channel_actions.jsx b/webapp/actions/channel_actions.jsx deleted file mode 100644 index 1df0d12f5..000000000 --- a/webapp/actions/channel_actions.jsx +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import TeamStore from 'stores/team_store.jsx'; -import UserStore from 'stores/user_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; -import * as ChannelUtils from 'utils/channel_utils.jsx'; -import PreferenceStore from 'stores/preference_store.jsx'; - -import * as GlobalActions from 'actions/global_actions.jsx'; -import * as PostActions from 'actions/post_actions.jsx'; - -import {loadProfilesForSidebar, loadNewDMIfNeeded, loadNewGMIfNeeded} from 'actions/user_actions.jsx'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; - -import * as UserAgent from 'utils/user_agent.jsx'; -import * as Utils from 'utils/utils.jsx'; -import {Constants, Preferences} from 'utils/constants.jsx'; - -import {browserHistory} from 'react-router/es6'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import * as ChannelActions from 'mattermost-redux/actions/channels'; -import {savePreferences, deletePreferences} from 'mattermost-redux/actions/preferences'; -import {Client4} from 'mattermost-redux/client'; - -import {getMyChannelMemberships} from 'mattermost-redux/selectors/entities/channels'; - -export function goToChannel(channel) { - if (channel.fake) { - const user = UserStore.getProfileByUsername(channel.display_name); - if (!user) { - return; - } - openDirectChannelToUser( - user.id, - () => { - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + channel.name); - }, - null - ); - } else { - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + channel.name); - } -} - -export function executeCommand(message, args, success, error) { - let msg = message; - - let cmdLength = msg.indexOf(' '); - if (cmdLength < 0) { - cmdLength = msg.length; - } - const cmd = msg.substring(0, cmdLength).toLowerCase(); - msg = cmd + msg.substring(cmdLength, msg.length); - - switch (cmd) { - case '/search': - PostActions.searchForTerm(msg.substring(cmdLength + 1, msg.length)); - return; - case '/shortcuts': - if (UserAgent.isMobile()) { - const err = {message: Utils.localizeMessage('create_post.shortcutsNotSupported', 'Keyboard shortcuts are not supported on your device')}; - error(err); - return; - } - - GlobalActions.showShortcutsModal(); - return; - case '/leave': { - // /leave command not supported in reply threads. - if (args.channel_id && (args.root_id || args.parent_id)) { - GlobalActions.sendEphemeralPost('/leave is not supported in reply threads. Use it in the center channel instead.', args.channel_id, args.parent_id); - return; - } - const channel = ChannelStore.getCurrent(); - if (channel.type === Constants.PRIVATE_CHANNEL) { - GlobalActions.showLeavePrivateChannelModal(channel); - return; - } else if ( - channel.type === Constants.DM_CHANNEL || - channel.type === Constants.GM_CHANNEL - ) { - let name; - let category; - if (channel.type === Constants.DM_CHANNEL) { - name = Utils.getUserIdFromChannelName(channel); - category = Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW; - } else { - name = channel.id; - category = Constants.Preferences.CATEGORY_GROUP_CHANNEL_SHOW; - } - const currentUserId = UserStore.getCurrentId(); - savePreferences(currentUserId, [{category, name, user_id: currentUserId, value: 'false'}])(dispatch, getState); - if (ChannelUtils.isFavoriteChannel(channel)) { - unmarkFavorite(channel.id); - } - browserHistory.push(`${TeamStore.getCurrentTeamRelativeUrl()}/channels/town-square`); - return; - } - break; - } - case '/settings': - GlobalActions.showAccountSettingsModal(); - return; - } - - Client4.executeCommand(msg, args).then(success).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function setChannelAsRead(channelIdParam) { - const channelId = channelIdParam || ChannelStore.getCurrentId(); - ChannelActions.viewChannel(channelId)(dispatch, getState); - ChannelStore.resetCounts([channelId]); - ChannelStore.emitChange(); - if (channelId === ChannelStore.getCurrentId()) { - ChannelStore.emitLastViewed(Number.MAX_VALUE, false); - } -} - -export function addUserToChannel(channelId, userId, success, error) { - ChannelActions.addChannelMember(channelId, userId)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.addChannelMember.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function removeUserFromChannel(channelId, userId, success, error) { - ChannelActions.removeChannelMember(channelId, userId)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.removeChannelMember.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function makeUserChannelAdmin(channelId, userId, success, error) { - ChannelActions.updateChannelMemberRoles(channelId, userId, 'channel_user channel_admin')(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.updateChannelMember.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function makeUserChannelMember(channelId, userId, success, error) { - ChannelActions.updateChannelMemberRoles(channelId, userId, 'channel_user')(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.updateChannelMember.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function openDirectChannelToUser(userId, success, error) { - const channelName = Utils.getDirectChannelName(UserStore.getCurrentId(), userId); - const channel = ChannelStore.getByName(channelName); - - if (channel) { - trackEvent('api', 'api_channels_join_direct'); - PreferenceStore.setPreference(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, userId, 'true'); - loadProfilesForSidebar(); - - const currentUserId = UserStore.getCurrentId(); - savePreferences(currentUserId, [{user_id: currentUserId, category: Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, name: userId, value: 'true'}])(dispatch, getState); - - if (success) { - success(channel, true); - } - - return; - } - - ChannelActions.createDirectChannel(UserStore.getCurrentId(), userId)(dispatch, getState).then( - (result) => { - loadProfilesForSidebar(); - if (result.data && success) { - success(result.data, false); - } else if (result.error && error) { - error({id: result.error.server_error_id, ...result.error}); - } - } - ); -} - -export function openGroupChannelToUsers(userIds, success, error) { - ChannelActions.createGroupChannel(userIds)(dispatch, getState).then( - (result) => { - loadProfilesForSidebar(); - if (result.data && success) { - success(result.data, false); - } else if (result.error && error) { - browserHistory.push(TeamStore.getCurrentTeamUrl()); - error({id: result.error.server_error_id, ...result.error}); - } - } - ); -} - -export function markFavorite(channelId) { - trackEvent('api', 'api_channels_favorited'); - const currentUserId = UserStore.getCurrentId(); - savePreferences(currentUserId, [{user_id: currentUserId, category: Preferences.CATEGORY_FAVORITE_CHANNEL, name: channelId, value: 'true'}])(dispatch, getState); -} - -export function unmarkFavorite(channelId) { - trackEvent('api', 'api_channels_unfavorited'); - const currentUserId = UserStore.getCurrentId(); - - const pref = { - user_id: currentUserId, - category: Preferences.CATEGORY_FAVORITE_CHANNEL, - name: channelId - }; - - deletePreferences(currentUserId, [pref])(dispatch, getState); -} - -export function loadChannelsForCurrentUser() { - ChannelActions.fetchMyChannelsAndMembers(TeamStore.getCurrentId())(dispatch, getState).then( - () => { - loadDMsAndGMsForUnreads(); - } - ); -} - -export function loadDMsAndGMsForUnreads() { - const unreads = ChannelStore.getUnreadCounts(); - for (const id in unreads) { - if (!unreads.hasOwnProperty(id)) { - continue; - } - - if (unreads[id].msgs > 0 || unreads[id].mentions > 0) { - const channel = ChannelStore.get(id); - if (channel && channel.type === Constants.DM_CHANNEL) { - loadNewDMIfNeeded(channel.id); - } else if (channel && channel.type === Constants.GM_CHANNEL) { - loadNewGMIfNeeded(channel.id); - } - } - } -} - -export async function joinChannel(channel, success, error) { - const {data, serverError} = await ChannelActions.joinChannel(UserStore.getCurrentId(), null, channel.id)(dispatch, getState); - - if (data && success) { - success(data); - } else if (data == null && error) { - error({id: serverError.server_error_id, ...serverError}); - } -} - -export function updateChannel(channel, success, error) { - ChannelActions.updateChannel(channel)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.updateChannel.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function searchMoreChannels(term, success, error) { - ChannelActions.searchChannels(TeamStore.getCurrentId(), term)(dispatch, getState).then( - (data) => { - if (data && success) { - const myMembers = getMyChannelMemberships(getState()); - const channels = data.filter((c) => !myMembers[c.id]); - success(channels); - } else if (data == null && error) { - const serverError = getState().requests.channels.getChannels.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function autocompleteChannels(term, success, error) { - ChannelActions.searchChannels(TeamStore.getCurrentId(), term)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.getChannels.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateChannelNotifyProps(data, options, success, error) { - ChannelActions.updateChannelNotifyProps(data.user_id, data.channel_id, Object.assign({}, data, options))(dispatch, getState).then( - (result) => { - if (result && success) { - success(result); - } else if (result == null && error) { - const serverError = getState().requests.channels.updateChannelNotifyProps.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function createChannel(channel, success, error) { - ChannelActions.createChannel(channel)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.createChannel.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateChannelPurpose(channelId, purpose, success, error) { - ChannelActions.patchChannel(channelId, {purpose})(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.updateChannel.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateChannelHeader(channelId, header, success, error) { - ChannelActions.patchChannel(channelId, {header})(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.updateChannel.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getChannelMembersForUserIds(channelId, userIds, success, error) { - ChannelActions.getChannelMembersByIds(channelId, userIds)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.channels.members.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function leaveChannel(channelId, success) { - ChannelActions.leaveChannel(channelId)(dispatch, getState).then( - () => { - if (ChannelUtils.isFavoriteChannelId(channelId)) { - unmarkFavorite(channelId); - } - - const townsquare = ChannelStore.getByName('town-square'); - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + townsquare.name); - - if (success) { - success(); - } - } - ); -} - -export async function deleteChannel(channelId, success, error) { - const {data, serverError} = await ChannelActions.deleteChannel(channelId)(dispatch, getState); - - if (data && success) { - success(data); - } else if (serverError && error) { - error({id: serverError.server_error_id, ...serverError}); - } -} diff --git a/webapp/actions/diagnostics_actions.jsx b/webapp/actions/diagnostics_actions.jsx deleted file mode 100644 index 72cf387b4..000000000 --- a/webapp/actions/diagnostics_actions.jsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import UserStore from 'stores/user_store.jsx'; - -export function trackEvent(category, event, props) { - if (global.window && global.window.analytics) { - const properties = Object.assign({category, type: event, user_actual_id: UserStore.getCurrentId()}, props); - const options = { - context: { - ip: '0.0.0.0' - }, - page: { - path: '', - referrer: '', - search: '', - title: '', - url: '' - }, - anonymousId: '00000000000000000000000000' - }; - global.window.analytics.track('event', properties, options); - } -} diff --git a/webapp/actions/emoji_actions.jsx b/webapp/actions/emoji_actions.jsx deleted file mode 100644 index 1c0d8b5ea..000000000 --- a/webapp/actions/emoji_actions.jsx +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import UserStore from 'stores/user_store.jsx'; - -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; -import {ActionTypes} from 'utils/constants.jsx'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; -import {getProfilesByIds} from 'mattermost-redux/actions/users'; -import * as EmojiActions from 'mattermost-redux/actions/emojis'; - -export async function loadEmoji(getProfiles = true) { - const data = await EmojiActions.getAllCustomEmojis()(dispatch, getState); - - if (data && getProfiles) { - loadProfilesForEmoji(data); - } -} - -function loadProfilesForEmoji(emojiList) { - const profilesToLoad = {}; - for (let i = 0; i < emojiList.length; i++) { - const emoji = emojiList[i]; - if (!UserStore.hasProfile(emoji.creator_id)) { - profilesToLoad[emoji.creator_id] = true; - } - } - - const list = Object.keys(profilesToLoad); - if (list.length === 0) { - return; - } - - getProfilesByIds(list)(dispatch, getState); -} - -export function addEmoji(emoji, image, success, error) { - EmojiActions.createCustomEmoji(emoji, image)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.emojis.createCustomEmoji.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function deleteEmoji(emojiId, success, error) { - EmojiActions.deleteCustomEmoji(emojiId)(dispatch, getState).then( - (data) => { - if (data) { - // Needed to remove recently used emoji - AppDispatcher.handleServerAction({ - type: ActionTypes.REMOVED_CUSTOM_EMOJI, - id: emojiId - }); - - if (success) { - success(data); - } - } else if (data == null && error) { - const serverError = getState().requests.emojis.deleteCustomEmoji.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/file_actions.jsx b/webapp/actions/file_actions.jsx deleted file mode 100644 index 1d9617901..000000000 --- a/webapp/actions/file_actions.jsx +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {batchActions} from 'redux-batched-actions'; -import request from 'superagent'; - -import store from 'stores/redux_store.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import {FileTypes} from 'mattermost-redux/action_types'; -import {forceLogoutIfNecessary} from 'mattermost-redux/actions/helpers'; -import {getLogErrorAction} from 'mattermost-redux/actions/errors'; -import {Client4} from 'mattermost-redux/client'; - -export function uploadFile(file, name, channelId, clientId, successCallback, errorCallback) { - const {dispatch, getState} = store; - - function handleResponse(err, res) { - if (err) { - let e; - if (res && res.body && res.body.id) { - e = res.body; - } else if (err.status === 0 || !err.status) { - e = {message: Utils.localizeMessage('channel_loader.connection_error', 'There appears to be a problem with your internet connection.')}; - } else { - e = {message: Utils.localizeMessage('channel_loader.unknown_error', 'We received an unexpected status code from the server.') + ' (' + err.status + ')'}; - } - - forceLogoutIfNecessary(err, dispatch); - - const failure = { - type: FileTypes.UPLOAD_FILES_FAILURE, - clientIds: [clientId], - channelId, - rootId: null, - error: err - }; - - dispatch(batchActions([failure, getLogErrorAction(err)]), getState); - - if (errorCallback) { - errorCallback(e, err, res); - } - } else if (res) { - const data = res.body.file_infos.map((fileInfo, index) => { - return { - ...fileInfo, - clientId: res.body.client_ids[index] - }; - }); - - dispatch(batchActions([ - { - type: FileTypes.RECEIVED_UPLOAD_FILES, - data, - channelId, - rootId: null - }, - { - type: FileTypes.UPLOAD_FILES_SUCCESS - } - ]), getState); - - if (successCallback) { - successCallback(res.body, res); - } - } - } - - dispatch({type: FileTypes.UPLOAD_FILES_REQUEST}, getState); - - return request. - post(Client4.getFilesRoute()). - set(Client4.getOptions().headers). - attach('files', file, name). - field('channel_id', channelId). - field('client_ids', clientId). - accept('application/json'). - end(handleResponse); -} - -export async function getPublicLink(fileId, success) { - Client4.getFilePublicLink(fileId).then( - (data) => { - if (data && success) { - success(data.link); - } - } - ).catch( - () => {} //eslint-disable-line no-empty-function - ); -} diff --git a/webapp/actions/global_actions.jsx b/webapp/actions/global_actions.jsx deleted file mode 100644 index 73a57e0b0..000000000 --- a/webapp/actions/global_actions.jsx +++ /dev/null @@ -1,626 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; - -import ChannelStore from 'stores/channel_store.jsx'; -import UserStore from 'stores/user_store.jsx'; -import BrowserStore from 'stores/browser_store.jsx'; -import ErrorStore from 'stores/error_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; -import SearchStore from 'stores/search_store.jsx'; - -import {handleNewPost} from 'actions/post_actions.jsx'; -import {loadProfilesForSidebar, loadNewDMIfNeeded, loadNewGMIfNeeded} from 'actions/user_actions.jsx'; -import {loadChannelsForCurrentUser} from 'actions/channel_actions.jsx'; -import {stopPeriodicStatusUpdates} from 'actions/status_actions.jsx'; -import * as WebsocketActions from 'actions/websocket_actions.jsx'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; - -import {ActionTypes, Constants, ErrorPageTypes} from 'utils/constants.jsx'; -import EventTypes from 'utils/event_types.jsx'; - -import WebSocketClient from 'client/web_websocket_client.jsx'; -import {sortTeamsByDisplayName} from 'utils/team_utils.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import en from 'i18n/en.json'; -import * as I18n from 'i18n/i18n.jsx'; -import {browserHistory} from 'react-router/es6'; - -// Redux actions -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {Client4} from 'mattermost-redux/client'; - -import {removeUserFromTeam} from 'mattermost-redux/actions/teams'; -import {viewChannel, getChannelStats, getMyChannelMember, getChannelAndMyMember, createDirectChannel, joinChannel} from 'mattermost-redux/actions/channels'; -import {getPostThread} from 'mattermost-redux/actions/posts'; - -export function emitChannelClickEvent(channel) { - function userVisitedFakeChannel(chan, success, fail) { - const currentUserId = UserStore.getCurrentId(); - const otherUserId = Utils.getUserIdFromChannelName(chan); - createDirectChannel(currentUserId, otherUserId)(dispatch, getState).then( - (result) => { - const receivedChannel = result.data; - - if (receivedChannel) { - success(receivedChannel); - } else { - fail(); - } - } - ); - } - function switchToChannel(chan) { - const channelMember = ChannelStore.getMyMember(chan.id); - const getMyChannelMemberPromise = getMyChannelMember(chan.id)(dispatch, getState); - const oldChannelId = ChannelStore.getCurrentId(); - - getMyChannelMemberPromise.then(() => { - getChannelStats(chan.id)(dispatch, getState); - viewChannel(chan.id, oldChannelId)(dispatch, getState); - - // Mark previous and next channel as read - ChannelStore.resetCounts([chan.id, oldChannelId]); - reloadIfServerVersionChanged(); - }); - - // Subtract mentions for the team - const {msgs, mentions} = ChannelStore.getUnreadCounts()[chan.id] || {msgs: 0, mentions: 0}; - TeamStore.subtractUnread(chan.team_id, msgs, mentions); - - BrowserStore.setGlobalItem(chan.team_id, chan.id); - - loadProfilesForSidebar(); - - AppDispatcher.handleViewAction({ - type: ActionTypes.CLICK_CHANNEL, - name: chan.name, - id: chan.id, - team_id: chan.team_id, - total_msg_count: chan.total_msg_count, - channelMember, - prev: oldChannelId - }); - } - - if (channel.fake) { - userVisitedFakeChannel( - channel, - (data) => { - switchToChannel(data); - }, - () => { - browserHistory.push('/' + this.state.currentTeam.name); - } - ); - } else { - switchToChannel(channel); - } -} - -export async function doFocusPost(channelId, postId, data) { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_FOCUSED_POST, - postId, - channelId, - post_list: data - }); - - dispatch({ - type: ActionTypes.RECEIVED_FOCUSED_POST, - data: postId, - channelId - }); - - const member = getState().entities.channels.myMembers[channelId]; - if (member == null) { - await joinChannel(UserStore.getCurrentId(), null, channelId)(dispatch, getState); - } - - loadChannelsForCurrentUser(); - getChannelStats(channelId)(dispatch, getState); -} - -export function emitPostFocusEvent(postId, onSuccess) { - loadChannelsForCurrentUser(); - getPostThread(postId)(dispatch, getState).then( - (data) => { - if (data) { - const channelId = data.posts[data.order[0]].channel_id; - const channel = ChannelStore.getChannelById(channelId); - if (channel && channel.type === Constants.DM_CHANNEL) { - loadNewDMIfNeeded(channel.id); - } else if (channel && channel.type === Constants.GM_CHANNEL) { - loadNewGMIfNeeded(channel.id); - } - - doFocusPost(channelId, postId, data).then(() => { - if (onSuccess) { - onSuccess(); - } - }); - } else { - browserHistory.push('/error?type=' + ErrorPageTypes.PERMALINK_NOT_FOUND); - } - } - ); -} - -export function emitCloseRightHandSide() { - SearchStore.storeSearchResults(null, false, false); - SearchStore.emitSearchChange(); - - dispatch({ - type: ActionTypes.SELECT_POST, - postId: '' - }); -} - -export function emitPostFocusRightHandSideFromSearch(post, isMentionSearch) { - getPostThread(post.id)(dispatch, getState).then( - () => { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST_SELECTED, - postId: Utils.getRootId(post), - from_search: SearchStore.getSearchTerm(), - from_flagged_posts: SearchStore.getIsFlaggedPosts(), - from_pinned_posts: SearchStore.getIsPinnedPosts() - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: null, - is_mention_search: isMentionSearch - }); - } - ); -} - -export function emitLeaveTeam() { - removeUserFromTeam(TeamStore.getCurrentId(), UserStore.getCurrentId())(dispatch, getState); -} - -export function emitUserPostedEvent(post) { - AppDispatcher.handleServerAction({ - type: ActionTypes.CREATE_POST, - post - }); -} - -export function emitUserCommentedEvent(post) { - AppDispatcher.handleServerAction({ - type: ActionTypes.CREATE_COMMENT, - post - }); -} - -export function showAccountSettingsModal() { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_ACCOUNT_SETTINGS_MODAL, - value: true - }); -} - -export function showShortcutsModal() { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_SHORTCUTS_MODAL, - value: true - }); -} - -export function showDeletePostModal(post, commentCount = 0) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_DELETE_POST_MODAL, - value: true, - post, - commentCount - }); -} - -export function showChannelHeaderUpdateModal(channel) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_CHANNEL_HEADER_UPDATE_MODAL, - value: true, - channel - }); -} - -export function showChannelPurposeUpdateModal(channel) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_CHANNEL_PURPOSE_UPDATE_MODAL, - value: true, - channel - }); -} - -export function showChannelNameUpdateModal(channel) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_CHANNEL_NAME_UPDATE_MODAL, - value: true, - channel - }); -} - -export function showGetPostLinkModal(post) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_GET_POST_LINK_MODAL, - value: true, - post - }); -} - -export function showGetPublicLinkModal(fileId) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_GET_PUBLIC_LINK_MODAL, - value: true, - fileId - }); -} - -export function showGetTeamInviteLinkModal() { - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.TOGGLE_GET_TEAM_INVITE_LINK_MODAL, - value: true - }); -} - -export function showInviteMemberModal() { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_INVITE_MEMBER_MODAL, - value: true - }); -} - -export function showLeaveTeamModal() { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_LEAVE_TEAM_MODAL, - value: true - }); -} - -export function showLeavePrivateChannelModal(channel) { - AppDispatcher.handleViewAction({ - type: ActionTypes.TOGGLE_LEAVE_PRIVATE_CHANNEL_MODAL, - value: channel - }); -} - -export function emitSuggestionPretextChanged(suggestionId, pretext) { - AppDispatcher.handleViewAction({ - type: ActionTypes.SUGGESTION_PRETEXT_CHANGED, - id: suggestionId, - pretext - }); -} - -export function emitSelectNextSuggestion(suggestionId) { - AppDispatcher.handleViewAction({ - type: ActionTypes.SUGGESTION_SELECT_NEXT, - id: suggestionId - }); -} - -export function emitSelectPreviousSuggestion(suggestionId) { - AppDispatcher.handleViewAction({ - type: ActionTypes.SUGGESTION_SELECT_PREVIOUS, - id: suggestionId - }); -} - -export function emitCompleteWordSuggestion(suggestionId, term = '') { - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.SUGGESTION_COMPLETE_WORD, - id: suggestionId, - term - }); -} - -export function emitClearSuggestions(suggestionId) { - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.SUGGESTION_CLEAR_SUGGESTIONS, - id: suggestionId - }); -} - -export function emitPreferenceChangedEvent(preference) { - AppDispatcher.handleServerAction({ - type: Constants.ActionTypes.RECEIVED_PREFERENCE, - preference - }); - - if (addedNewDmUser(preference)) { - loadProfilesForSidebar(); - } -} - -export function emitPreferencesChangedEvent(preferences) { - AppDispatcher.handleServerAction({ - type: Constants.ActionTypes.RECEIVED_PREFERENCES, - preferences - }); - - if (preferences.findIndex(addedNewDmUser) !== -1) { - loadProfilesForSidebar(); - } -} - -function addedNewDmUser(preference) { - return preference.category === Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW && preference.value === 'true'; -} - -export function emitPreferencesDeletedEvent(preferences) { - AppDispatcher.handleServerAction({ - type: Constants.ActionTypes.DELETED_PREFERENCES, - preferences - }); -} - -export function sendEphemeralPost(message, channelId, parentId) { - const timestamp = Utils.getTimestamp(); - const post = { - id: Utils.generateId(), - user_id: '0', - channel_id: channelId || ChannelStore.getCurrentId(), - message, - type: Constants.PostTypes.EPHEMERAL, - create_at: timestamp, - update_at: timestamp, - root_id: parentId, - parent_id: parentId, - props: {} - }; - - handleNewPost(post); -} - -export function newLocalizationSelected(locale) { - const localeInfo = I18n.getLanguageInfo(locale); - - if (locale === 'en' || !localeInfo) { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_LOCALE, - locale, - translations: en - }); - } else { - Client4.getTranslations(localeInfo.url).then( - (data, res) => { - let translations = data; - if (!data && res.text) { - translations = JSON.parse(res.text); - } - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_LOCALE, - locale, - translations - }); - } - ).catch( - () => {} //eslint-disable-line no-empty-function - ); - } -} - -export function loadCurrentLocale() { - const user = UserStore.getCurrentUser(); - - if (user && user.locale) { - newLocalizationSelected(user.locale); - } else { - loadDefaultLocale(); - } -} - -export function loadDefaultLocale() { - let locale = global.window.mm_config.DefaultClientLocale; - - if (!I18n.getLanguageInfo(locale)) { - locale = 'en'; - } - - return newLocalizationSelected(locale); -} - -let lastTimeTypingSent = 0; -export function emitLocalUserTypingEvent(channelId, parentId) { - const t = Date.now(); - const membersInChannel = ChannelStore.getStats(channelId).member_count; - - if (global.mm_license.IsLicensed === 'true' && global.mm_config.ExperimentalTownSquareIsReadOnly === 'true') { - const channel = ChannelStore.getChannelById(channelId); - if (channel && ChannelStore.isDefault(channel)) { - return; - } - } - - if (((t - lastTimeTypingSent) > global.window.mm_config.TimeBetweenUserTypingUpdatesMilliseconds) && membersInChannel < global.window.mm_config.MaxNotificationsPerChannel && global.window.mm_config.EnableUserTypingMessages === 'true') { - WebSocketClient.userTyping(channelId, parentId); - lastTimeTypingSent = t; - } -} - -export function emitRemoteUserTypingEvent(channelId, userId, postParentId) { - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.USER_TYPING, - channelId, - userId, - postParentId - }); -} - -export function emitUserLoggedOutEvent(redirectTo = '/', shouldSignalLogout = true) { - Client4.logout().then( - () => { - if (shouldSignalLogout) { - BrowserStore.signalLogout(); - } - - clientLogout(redirectTo); - } - ).catch( - () => { - browserHistory.push(redirectTo); - } - ); -} - -export function clientLogout(redirectTo = '/') { - BrowserStore.clear(); - ErrorStore.clearLastError(); - ChannelStore.clear(); - stopPeriodicStatusUpdates(); - WebsocketActions.close(); - document.cookie = 'MMUSERID=;expires=Thu, 01 Jan 1970 00:00:01 GMT;'; - window.location.href = redirectTo; -} - -export function emitSearchMentionsEvent(user) { - let terms = ''; - if (user.notify_props) { - const termKeys = UserStore.getMentionKeys(user.id); - - if (termKeys.indexOf('@channel') !== -1) { - termKeys[termKeys.indexOf('@channel')] = ''; - } - - if (termKeys.indexOf('@all') !== -1) { - termKeys[termKeys.indexOf('@all')] = ''; - } - - terms = termKeys.join(' '); - } - - trackEvent('api', 'api_posts_search_mention'); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH_TERM, - term: terms, - do_search: true, - is_mention_search: true - }); -} - -export function toggleSideBarAction(visible) { - if (!visible) { - //Array of actions resolving in the closing of the sidebar - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: null - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH_TERM, - term: null, - do_search: false, - is_mention_search: false - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST_SELECTED, - postId: null - }); - } -} - -export function toggleSideBarRightMenuAction() { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: null - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST_SELECTED, - postId: null - }); - - document.querySelector('.app__body .inner-wrap').classList.remove('move--right', 'move--left', 'move--left-small'); - document.querySelector('.app__body .sidebar--left').classList.remove('move--right'); - document.querySelector('.app__body .sidebar--right').classList.remove('move--left'); - document.querySelector('.app__body .sidebar--menu').classList.remove('move--left'); -} - -export function emitBrowserFocus(focus) { - AppDispatcher.handleViewAction({ - type: ActionTypes.BROWSER_CHANGE_FOCUS, - focus - }); -} - -export function redirectUserToDefaultTeam() { - const teams = TeamStore.getAll(); - const teamMembers = TeamStore.getMyTeamMembers(); - let teamId = BrowserStore.getGlobalItem('team'); - - function redirect(teamName, channelName) { - browserHistory.push(`/${teamName}/channels/${channelName}`); - } - - if (!teams[teamId] && teamMembers.length > 0) { - let myTeams = []; - for (const index in teamMembers) { - if (teamMembers.hasOwnProperty(index)) { - const teamMember = teamMembers[index]; - myTeams.push(teams[teamMember.team_id]); - } - } - - if (myTeams.length > 0) { - myTeams = myTeams.sort(sortTeamsByDisplayName); - teamId = myTeams[0].id; - } - } - - if (teams[teamId]) { - const channelId = BrowserStore.getGlobalItem(teamId); - const channel = ChannelStore.getChannelById(channelId); - if (channel) { - redirect(teams[teamId].name, channel); - } else if (channelId) { - getChannelAndMyMember(channelId)(dispatch, getState).then( - (data) => { - if (data) { - redirect(teams[teamId].name, data.channel.name); - } else { - redirect(teams[teamId].name, 'town-square'); - } - } - ); - } else { - redirect(teams[teamId].name, 'town-square'); - } - } else { - browserHistory.push('/select_team'); - } -} - -export function postListScrollChange(forceScrollToBottom = false) { - AppDispatcher.handleViewAction({ - type: EventTypes.POST_LIST_SCROLL_CHANGE, - value: forceScrollToBottom - }); -} - -export function emitPopoverMentionKeyClick(isRHS, mentionKey) { - AppDispatcher.handleViewAction({ - type: ActionTypes.POPOVER_MENTION_KEY_CLICK, - isRHS, - mentionKey - }); -} - -let serverVersion = ''; - -export function reloadIfServerVersionChanged() { - const newServerVersion = Client4.getServerVersion(); - if (serverVersion && serverVersion !== newServerVersion) { - console.log('Detected version update refreshing the page'); //eslint-disable-line no-console - window.location.reload(true); - } - - serverVersion = newServerVersion; -} diff --git a/webapp/actions/integration_actions.jsx b/webapp/actions/integration_actions.jsx deleted file mode 100644 index cc20b3ab8..000000000 --- a/webapp/actions/integration_actions.jsx +++ /dev/null @@ -1,301 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import UserStore from 'stores/user_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; - -import * as UserAgent from 'utils/user_agent.jsx'; -import {ActionTypes} from 'utils/constants.jsx'; -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {Client4} from 'mattermost-redux/client'; - -import {getProfilesByIds} from 'mattermost-redux/actions/users'; -import * as IntegrationActions from 'mattermost-redux/actions/integrations'; - -import request from 'superagent'; - -export function loadIncomingHooks(complete) { - IntegrationActions.getIncomingHooks('', 0, 10000)(dispatch, getState).then( - (data) => { - if (data) { - loadProfilesForIncomingHooks(data); - } - - if (complete) { - complete(data); - } - } - ); -} - -export function loadIncomingHooksForTeam(teamId, complete) { - IntegrationActions.getIncomingHooks(teamId, 0, 10000)(dispatch, getState).then( - (data) => { - if (data) { - loadProfilesForIncomingHooks(data); - } - - if (complete) { - complete(data); - } - } - ); -} - -function loadProfilesForIncomingHooks(hooks) { - const profilesToLoad = {}; - for (let i = 0; i < hooks.length; i++) { - const hook = hooks[i]; - if (!UserStore.hasProfile(hook.user_id)) { - profilesToLoad[hook.user_id] = true; - } - } - - const list = Object.keys(profilesToLoad); - if (list.length === 0) { - return; - } - - getProfilesByIds(list)(dispatch, getState); -} - -export function loadOutgoingHooks(complete) { - IntegrationActions.getOutgoingHooks('', '', 0, 10000)(dispatch, getState).then( - (data) => { - if (data) { - loadProfilesForOutgoingHooks(data); - } - - if (complete) { - complete(data); - } - } - ); -} - -export function loadOutgoingHooksForTeam(teamId, complete) { - IntegrationActions.getOutgoingHooks('', teamId, 0, 10000)(dispatch, getState).then( - (data) => { - if (data) { - loadProfilesForOutgoingHooks(data); - } - - if (complete) { - complete(data); - } - } - ); -} - -function loadProfilesForOutgoingHooks(hooks) { - const profilesToLoad = {}; - for (let i = 0; i < hooks.length; i++) { - const hook = hooks[i]; - if (!UserStore.hasProfile(hook.creator_id)) { - profilesToLoad[hook.creator_id] = true; - } - } - - const list = Object.keys(profilesToLoad); - if (list.length === 0) { - return; - } - - getProfilesByIds(list)(dispatch, getState); -} - -export function loadTeamCommands(complete) { - IntegrationActions.getCustomTeamCommands(TeamStore.getCurrentId())(dispatch, getState).then( - (data) => { - if (data) { - loadProfilesForCommands(data); - } - - if (complete) { - complete(data); - } - } - ); -} - -function loadProfilesForCommands(commands) { - const profilesToLoad = {}; - for (let i = 0; i < commands.length; i++) { - const command = commands[i]; - if (!UserStore.hasProfile(command.creator_id)) { - profilesToLoad[command.creator_id] = true; - } - } - - const list = Object.keys(profilesToLoad); - if (list.length === 0) { - return; - } - - getProfilesByIds(list)(dispatch, getState); -} - -export function addIncomingHook(hook, success, error) { - IntegrationActions.createIncomingHook(hook)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.createIncomingHook.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateIncomingHook(hook, success, error) { - IntegrationActions.updateIncomingHook(hook)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.updateIncomingHook.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function addOutgoingHook(hook, success, error) { - IntegrationActions.createOutgoingHook(hook)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.createOutgoingHook.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateOutgoingHook(hook, success, error) { - IntegrationActions.updateOutgoingHook(hook)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.updateOutgoingHook.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function deleteIncomingHook(id) { - IntegrationActions.removeIncomingHook(id)(dispatch, getState); -} - -export function deleteOutgoingHook(id) { - IntegrationActions.removeOutgoingHook(id)(dispatch, getState); -} - -export function regenOutgoingHookToken(id) { - IntegrationActions.regenOutgoingHookToken(id)(dispatch, getState); -} - -export function addCommand(command, success, error) { - IntegrationActions.addCommand(command)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.addCommand.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function editCommand(command, success, error) { - IntegrationActions.editCommand(command)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.editCommand.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function deleteCommand(id) { - IntegrationActions.deleteCommand(id)(dispatch, getState); -} - -export function regenCommandToken(id) { - IntegrationActions.regenCommandToken(id)(dispatch, getState); -} - -export function getSuggestedCommands(command, suggestionId, component) { - Client4.getCommandsList(TeamStore.getCurrentId()).then( - (data) => { - let matches = []; - data.forEach((cmd) => { - if (!cmd.auto_complete) { - return; - } - - if (cmd.trigger !== 'shortcuts' || !UserAgent.isMobile()) { - if (('/' + cmd.trigger).indexOf(command) === 0) { - const s = '/' + cmd.trigger; - let hint = ''; - if (cmd.auto_complete_hint && cmd.auto_complete_hint.length !== 0) { - hint = cmd.auto_complete_hint; - } - matches.push({ - suggestion: s, - hint, - description: cmd.auto_complete_desc - }); - } - } - }); - - matches = matches.sort((a, b) => a.suggestion.localeCompare(b.suggestion)); - - // pull out the suggested commands from the returned data - const terms = matches.map((suggestion) => suggestion.suggestion); - - if (terms.length > 0) { - AppDispatcher.handleServerAction({ - type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS, - id: suggestionId, - matchedPretext: command, - terms, - items: matches, - component - }); - } - } - ).catch( - () => {} //eslint-disable-line no-empty-function - ); -} - -export function getYoutubeVideoInfo(googleKey, videoId, success, error) { - request.get('https://www.googleapis.com/youtube/v3/videos'). - query({part: 'snippet', id: videoId, key: googleKey}). - end((err, res) => { - if (err) { - return error(err); - } - - if (!res.body) { - console.error('Missing response body for getYoutubeVideoInfo'); // eslint-disable-line no-console - } - - return success(res.body); - }); -} diff --git a/webapp/actions/job_actions.jsx b/webapp/actions/job_actions.jsx deleted file mode 100644 index 75d70faec..000000000 --- a/webapp/actions/job_actions.jsx +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import * as JobsActions from 'mattermost-redux/actions/jobs'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -export function createJob(job, success, error) { - JobsActions.createJob(job)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.jobs.createJob.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function cancelJob(jobId, success, error) { - JobsActions.cancelJob(jobId)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.jobs.cancelJob.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/notification_actions.jsx b/webapp/actions/notification_actions.jsx deleted file mode 100644 index 33709458a..000000000 --- a/webapp/actions/notification_actions.jsx +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import Constants from 'utils/constants.jsx'; -import UserStore from 'stores/user_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; -import NotificationStore from 'stores/notification_store.jsx'; - -import {isSystemMessage} from 'utils/post_utils.jsx'; -import {buildGroupChannelName} from 'utils/channel_utils.jsx'; -import {isWindowsApp, isMacApp, isMobileApp} from 'utils/user_agent.jsx'; -import * as Utils from 'utils/utils.jsx'; - -export function sendDesktopNotification(post, msgProps) { - if ((UserStore.getCurrentId() === post.user_id && post.props.from_webhook !== 'true')) { - return; - } - - if (isSystemMessage(post)) { - return; - } - - let mentions = []; - if (msgProps.mentions) { - mentions = JSON.parse(msgProps.mentions); - } - const teamId = msgProps.team_id; - - let channel = ChannelStore.get(post.channel_id); - const user = UserStore.getCurrentUser(); - const member = ChannelStore.getMyMember(post.channel_id); - - let notifyLevel = member && member.notify_props ? member.notify_props.desktop : 'default'; - if (notifyLevel === 'default') { - notifyLevel = user.notify_props.desktop; - } - - if (notifyLevel === 'none') { - return; - } else if (notifyLevel === 'mention' && mentions.indexOf(user.id) === -1 && msgProps.channel_type !== Constants.DM_CHANNEL) { - return; - } - - let username = Utils.localizeMessage('channel_loader.someone', 'Someone'); - if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') { - username = post.props.override_username; - } else if (msgProps.sender_name) { - username = msgProps.sender_name; - } else if (UserStore.hasProfile(post.user_id)) { - username = UserStore.getProfile(post.user_id).username; - } - - let title = Utils.localizeMessage('channel_loader.posted', 'Posted'); - if (!channel) { - title = msgProps.channel_display_name; - channel = { - name: msgProps.channel_name, - type: msgProps.channel_type - }; - } else if (channel.type === Constants.DM_CHANNEL) { - title = Utils.localizeMessage('notification.dm', 'Direct Message'); - } else if (channel.type === Constants.GM_CHANNEL) { - title = buildGroupChannelName(channel.id); - } else { - title = channel.display_name; - } - - if (title === '') { - if (msgProps.channel_type === Constants.DM_CHANNEL) { - title = Utils.localizeMessage('notification.dm', 'Direct Message'); - } else { - title = msgProps.channel_display_name; - } - } - - let notifyText = post.message; - - const msgPropsPost = JSON.parse(msgProps.post); - const attachments = msgPropsPost && msgPropsPost.props && msgPropsPost.props.attachments ? msgPropsPost.props.attachments : []; - let image = false; - attachments.forEach((attachment) => { - if (notifyText.length === 0) { - notifyText = attachment.fallback || - attachment.pretext || - attachment.text; - } - image |= attachment.image_url.length > 0; - }); - - notifyText = notifyText.replace(/\n+/g, ' '); - if (notifyText.length > 50) { - notifyText = notifyText.substring(0, 49) + '...'; - } - - let body = ''; - if (notifyText.length === 0) { - if (msgProps.image) { - body = username + Utils.localizeMessage('channel_loader.uploadedImage', ' uploaded an image'); - } else if (msgProps.otherFile) { - body = username + Utils.localizeMessage('channel_loader.uploadedFile', ' uploaded a file'); - } else if (image) { - body = username + Utils.localizeMessage('channel_loader.postedImage', ' posted an image'); - } else { - body = username + Utils.localizeMessage('channel_loader.something', ' did something new'); - } - } else { - body = username + Utils.localizeMessage('channel_loader.wrote', ' wrote: ') + notifyText; - } - - let duration = Constants.DEFAULT_NOTIFICATION_DURATION; - if (user.notify_props && user.notify_props.desktop_duration) { - duration = parseInt(user.notify_props.desktop_duration, 10) * 1000; - } - - //Play a sound if explicitly set in settings - const sound = !user.notify_props || user.notify_props.desktop_sound === 'true'; - - // Notify if you're not looking in the right channel or when - // the window itself is not active - const activeChannel = ChannelStore.getCurrent(); - const channelId = channel ? channel.id : null; - const notify = (activeChannel && activeChannel.id !== channelId) || !NotificationStore.getFocus(); - - if (notify) { - Utils.notifyMe(title, body, channel, teamId, duration, !sound); - - //Don't add extra sounds on native desktop clients - if (sound && !isWindowsApp() && !isMacApp() && !isMobileApp()) { - Utils.ding(); - } - } -} diff --git a/webapp/actions/oauth_actions.jsx b/webapp/actions/oauth_actions.jsx deleted file mode 100644 index 54823a324..000000000 --- a/webapp/actions/oauth_actions.jsx +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import * as IntegrationActions from 'mattermost-redux/actions/integrations'; - -export function deleteOAuthApp(id, success, error) { - IntegrationActions.deleteOAuthApp(id)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.integrations.deleteOAuthApp.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/post_actions.jsx b/webapp/actions/post_actions.jsx deleted file mode 100644 index cb111ec39..000000000 --- a/webapp/actions/post_actions.jsx +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; - -import ChannelStore from 'stores/channel_store.jsx'; -import UserStore from 'stores/user_store.jsx'; -import PostStore from 'stores/post_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; - -import {loadNewDMIfNeeded, loadNewGMIfNeeded} from 'actions/user_actions.jsx'; -import {sendDesktopNotification} from 'actions/notification_actions.jsx'; - -import {ActionTypes, Constants} from 'utils/constants.jsx'; -import {EMOJI_PATTERN} from 'utils/emoticons.jsx'; - -import {browserHistory} from 'react-router/es6'; - -// Redux actions -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import * as PostActions from 'mattermost-redux/actions/posts'; -import {getMyChannelMember} from 'mattermost-redux/actions/channels'; - -import {Client4} from 'mattermost-redux/client'; - -import {PostTypes} from 'mattermost-redux/action_types'; -import * as Selectors from 'mattermost-redux/selectors/entities/posts'; -import {batchActions} from 'redux-batched-actions'; - -export function handleNewPost(post, msg) { - let websocketMessageProps = {}; - if (msg) { - websocketMessageProps = msg.data; - } - - if (ChannelStore.getMyMember(post.channel_id)) { - completePostReceive(post, websocketMessageProps); - } else { - getMyChannelMember(post.channel_id)(dispatch, getState).then(() => completePostReceive(post, websocketMessageProps)); - } - - if (msg && msg.data) { - if (msg.data.channel_type === Constants.DM_CHANNEL) { - loadNewDMIfNeeded(post.channel_id); - } else if (msg.data.channel_type === Constants.GM_CHANNEL) { - loadNewGMIfNeeded(post.channel_id); - } - } -} - -function completePostReceive(post, websocketMessageProps) { - if (post.root_id && Selectors.getPost(getState(), post.root_id) == null) { - PostActions.getPostThread(post.root_id)(dispatch, getState).then( - (data) => { - dispatchPostActions(post, websocketMessageProps); - PostActions.getProfilesAndStatusesForPosts(data.posts, dispatch, getState); - } - ); - - return; - } - - dispatchPostActions(post, websocketMessageProps); -} - -function dispatchPostActions(post, websocketMessageProps) { - const {currentChannelId} = getState().entities.channels; - - if (post.channel_id === currentChannelId) { - dispatch({ - type: ActionTypes.INCREASE_POST_VISIBILITY, - data: post.channel_id, - amount: 1 - }); - } - - // Need manual dispatch to remove pending post - dispatch({ - type: PostTypes.RECEIVED_POSTS, - data: { - order: [], - posts: { - [post.id]: post - } - }, - channelId: post.channel_id - }); - - // Still needed to update unreads - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST, - post, - websocketMessageProps - }); - - sendDesktopNotification(post, websocketMessageProps); -} - -export function flagPost(postId) { - PostActions.flagPost(postId)(dispatch, getState); -} - -export function unflagPost(postId) { - PostActions.unflagPost(postId)(dispatch, getState); -} - -export function getFlaggedPosts() { - Client4.getFlaggedPosts(UserStore.getCurrentId(), '', TeamStore.getCurrentId()).then( - (data) => { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH_TERM, - term: null, - do_search: false, - is_mention_search: false - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: data, - is_flagged_posts: true, - is_pinned_posts: false - }); - - PostActions.getProfilesAndStatusesForPosts(data.posts, dispatch, getState); - } - ).catch( - () => {} //eslint-disable-line no-empty-function - ); -} - -export function getPinnedPosts(channelId = ChannelStore.getCurrentId()) { - Client4.getPinnedPosts(channelId).then( - (data) => { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH_TERM, - term: null, - do_search: false, - is_mention_search: false - }); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: data, - is_flagged_posts: false, - is_pinned_posts: true - }); - - PostActions.getProfilesAndStatusesForPosts(data.posts, dispatch, getState); - } - ).catch( - () => {} //eslint-disable-line no-empty-function - ); -} - -export function addReaction(channelId, postId, emojiName) { - PostActions.addReaction(postId, emojiName)(dispatch, getState); -} - -export function removeReaction(channelId, postId, emojiName) { - PostActions.removeReaction(postId, emojiName)(dispatch, getState); -} - -export function createPost(post, files, success) { - // parse message and emit emoji event - const emojis = post.message.match(EMOJI_PATTERN); - if (emojis) { - for (const emoji of emojis) { - const trimmed = emoji.substring(1, emoji.length - 1); - emitEmojiPosted(trimmed); - } - } - - PostActions.createPost(post, files)(dispatch, getState).then(() => { - if (post.root_id) { - PostStore.storeCommentDraft(post.root_id, null); - } else { - PostStore.storeDraft(post.channel_id, null); - } - - if (success) { - success(); - } - }); -} - -export function updatePost(post, success) { - PostActions.editPost(post)(dispatch, getState).then( - (data) => { - if (data && success) { - success(); - } else { - const serverError = getState().requests.posts.editPost.error; - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_ERROR, - err: {id: serverError.server_error_id, ...serverError}, - method: 'editPost' - }); - } - } - ); -} - -export function emitEmojiPosted(emoji) { - AppDispatcher.handleServerAction({ - type: ActionTypes.EMOJI_POSTED, - alias: emoji - }); -} - -export function deletePost(channelId, post, success) { - const {currentUserId} = getState().entities.users; - - let hardDelete = false; - if (post.user_id === currentUserId) { - hardDelete = true; - } - - PostActions.deletePost(post, hardDelete)(dispatch, getState).then( - () => { - if (post.id === getState().views.rhs.selectedPostId) { - dispatch({ - type: ActionTypes.SELECT_POST, - postId: '' - }); - } - - dispatch({ - type: PostTypes.REMOVE_POST, - data: post - }); - - // Needed for search store - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.REMOVE_POST, - post - }); - - const {focusedPostId} = getState().views.channel; - const channel = getState().entities.channels.channels[post.channel_id]; - if (post.id === focusedPostId && channel) { - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + channel.name); - } - - if (success) { - success(); - } - } - ); -} - -export function performSearch(terms, isMentionSearch, success, error) { - Client4.searchPosts(TeamStore.getCurrentId(), terms, isMentionSearch).then( - (data) => { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH, - results: data, - is_mention_search: isMentionSearch - }); - - PostActions.getProfilesAndStatusesForPosts(data.posts, dispatch, getState); - - if (success) { - success(data); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -const POST_INCREASE_AMOUNT = Constants.POST_CHUNK_SIZE / 2; - -// Returns true if there are more posts to load -export function increasePostVisibility(channelId, focusedPostId) { - return async (doDispatch, doGetState) => { - if (doGetState().views.channel.loadingPosts[channelId]) { - return true; - } - - const currentPostVisibility = doGetState().views.channel.postVisibility[channelId]; - - if (currentPostVisibility >= Constants.MAX_POST_VISIBILITY) { - return true; - } - - doDispatch(batchActions([ - { - type: ActionTypes.LOADING_POSTS, - data: true, - channelId - }, - { - type: ActionTypes.INCREASE_POST_VISIBILITY, - data: channelId, - amount: POST_INCREASE_AMOUNT - } - ])); - - const page = Math.floor(currentPostVisibility / POST_INCREASE_AMOUNT); - - let posts; - if (focusedPostId) { - posts = await PostActions.getPostsBefore(channelId, focusedPostId, page, POST_INCREASE_AMOUNT)(dispatch, getState); - } else { - posts = await PostActions.getPosts(channelId, page, POST_INCREASE_AMOUNT)(doDispatch, doGetState); - } - - doDispatch({ - type: ActionTypes.LOADING_POSTS, - data: false, - channelId - }); - - return posts.order.length >= POST_INCREASE_AMOUNT; - }; -} - -export function searchForTerm(term) { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_SEARCH_TERM, - term, - do_search: true - }); -} - -export function pinPost(postId) { - return async (doDispatch, doGetState) => { - await PostActions.pinPost(postId)(doDispatch, doGetState); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST_PINNED, - postId - }); - }; -} - -export function unpinPost(postId) { - return async (doDispatch, doGetState) => { - await PostActions.unpinPost(postId)(doDispatch, doGetState); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST_UNPINNED, - postId - }); - }; -} - -export function doPostAction(postId, actionId) { - PostActions.doPostAction(postId, actionId)(dispatch, getState); -} diff --git a/webapp/actions/status_actions.jsx b/webapp/actions/status_actions.jsx deleted file mode 100644 index e8559bd65..000000000 --- a/webapp/actions/status_actions.jsx +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import ChannelStore from 'stores/channel_store.jsx'; -import PostStore from 'stores/post_store.jsx'; -import PreferenceStore from 'stores/preference_store.jsx'; -import UserStore from 'stores/user_store.jsx'; - -import {Preferences, Constants} from 'utils/constants.jsx'; - -// Redux actions -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {getStatusesByIds} from 'mattermost-redux/actions/users'; - -export function loadStatusesForChannel(channelId = ChannelStore.getCurrentId()) { - const postList = PostStore.getVisiblePosts(channelId); - if (!postList || !postList.posts) { - return; - } - - const statuses = UserStore.getStatuses(); - const statusesToLoad = {}; - for (const pid in postList.posts) { - if (!postList.posts.hasOwnProperty(pid)) { - continue; - } - - const post = postList.posts[pid]; - if (statuses[post.user_id] == null) { - statusesToLoad[post.user_id] = true; - } - } - - loadStatusesByIds(Object.keys(statusesToLoad)); -} - -export function loadStatusesForDMSidebar() { - const dmPrefs = PreferenceStore.getCategory(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW); - const statusesToLoad = []; - - for (const [key, value] of dmPrefs) { - if (value === 'true') { - statusesToLoad.push(key); - } - } - - loadStatusesByIds(statusesToLoad); -} - -export function loadStatusesForChannelAndSidebar() { - const statusesToLoad = {}; - - const channelId = ChannelStore.getCurrentId(); - const posts = PostStore.getVisiblePosts(channelId) || []; - for (const post of posts) { - statusesToLoad[post.user_id] = true; - } - - const dmPrefs = PreferenceStore.getCategory(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW); - - for (const [key, value] of dmPrefs) { - if (value === 'true') { - statusesToLoad[key] = true; - } - } - - const {currentUserId} = getState().entities.users; - statusesToLoad[currentUserId] = true; - - loadStatusesByIds(Object.keys(statusesToLoad)); -} - -export function loadStatusesForProfilesList(users) { - if (users == null) { - return; - } - - const statusesToLoad = []; - for (let i = 0; i < users.length; i++) { - statusesToLoad.push(users[i].id); - } - - loadStatusesByIds(statusesToLoad); -} - -export function loadStatusesForProfilesMap(users) { - if (users == null) { - return; - } - - const statusesToLoad = []; - for (const userId in users) { - if (!users.hasOwnProperty(userId)) { - return; - } - statusesToLoad.push(userId); - } - - loadStatusesByIds(statusesToLoad); -} - -export function loadStatusesByIds(userIds) { - if (userIds.length === 0) { - return; - } - - getStatusesByIds(userIds)(dispatch, getState); -} - -let intervalId = ''; - -export function startPeriodicStatusUpdates() { - clearInterval(intervalId); - - intervalId = setInterval( - () => { - loadStatusesForChannelAndSidebar(); - }, - Constants.STATUS_INTERVAL - ); -} - -export function stopPeriodicStatusUpdates() { - clearInterval(intervalId); -} diff --git a/webapp/actions/team_actions.jsx b/webapp/actions/team_actions.jsx deleted file mode 100644 index af132b139..000000000 --- a/webapp/actions/team_actions.jsx +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import TeamStore from 'stores/team_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; - -import {browserHistory} from 'react-router/es6'; - -// Redux actions -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {Client4} from 'mattermost-redux/client'; - -import {getUser} from 'mattermost-redux/actions/users'; -import {viewChannel} from 'mattermost-redux/actions/channels'; -import * as TeamActions from 'mattermost-redux/actions/teams'; - -import {TeamTypes} from 'mattermost-redux/action_types'; - -export function checkIfTeamExists(teamName, onSuccess, onError) { - TeamActions.checkIfTeamExists(teamName)(dispatch, getState).then( - (exists) => { - if (exists != null && onSuccess) { - onSuccess(exists); - } else if (exists == null && onError) { - const serverError = getState().requests.teams.getTeam.error; - onError({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function createTeam(team, onSuccess, onError) { - TeamActions.createTeam(team)(dispatch, getState).then( - (rteam) => { - if (rteam && onSuccess) { - browserHistory.push('/' + rteam.name + '/channels/town-square'); - onSuccess(rteam); - } else if (rteam == null && onError) { - const serverError = getState().requests.teams.createTeam.error; - onError({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateTeam(team, onSuccess, onError) { - TeamActions.updateTeam(team)(dispatch, getState).then( - (rteam) => { - if (rteam && onSuccess) { - browserHistory.push('/' + rteam.name + '/channels/town-square'); - onSuccess(rteam); - } else if (rteam == null && onError) { - const serverError = getState().requests.teams.updateTeam.error; - onError({id: serverError.server_error_id, ...serverError}); - } - }, - ); -} - -export function removeUserFromTeam(teamId, userId, success, error) { - TeamActions.removeUserFromTeam(teamId, userId)(dispatch, getState).then( - (data) => { - getUser(userId)(dispatch, getState); - TeamActions.getTeamStats(teamId)(dispatch, getState); - - if (data && success) { - success(); - } else if (data == null && error) { - const serverError = getState().requests.teams.removeUserFromTeam.error; - error({id: serverError.server_error_id, ...serverError}); - } - }, - ); -} - -export function updateTeamMemberRoles(teamId, userId, newRoles, success, error) { - TeamActions.updateTeamMemberRoles(teamId, userId, newRoles)(dispatch, getState).then( - (data) => { - if (data && success) { - success(); - } else if (data == null && error) { - const serverError = getState().requests.teams.updateTeamMember.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function addUserToTeamFromInvite(data, hash, inviteId, success, error) { - Client4.addToTeamFromInvite(hash, data, inviteId).then( - (member) => { - TeamActions.getTeam(member.team_id)(dispatch, getState).then( - (team) => { - dispatch({ - type: TeamTypes.RECEIVED_MY_TEAM_MEMBER, - data: { - ...member, - delete_at: 0, - msg_count: 0, - mention_count: 0 - } - }); - - if (success) { - success(team); - } - } - ); - }, - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function addUsersToTeam(teamId, userIds, success, error) { - TeamActions.addUsersToTeam(teamId, userIds)(dispatch, getState).then( - (teamMembers) => { - if (teamMembers && success) { - success(teamMembers); - } else if (teamMembers == null && error) { - const serverError = getState().requests.teams.addUserToTeam.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getInviteInfo(inviteId, success, error) { - Client4.getTeamInviteInfo(inviteId).then( - (inviteData) => { - if (success) { - success(inviteData); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function inviteMembers(data, success, error) { - if (!data.invites) { - success(); - } - const emails = []; - data.invites.forEach((i) => { - emails.push(i.email); - }); - TeamActions.sendEmailInvitesToTeam(TeamStore.getCurrentId(), emails)(dispatch, getState).then( - (result) => { - if (result && success) { - success(); - } else if (result == null && error) { - const serverError = getState().requests.teams.emailInvite.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function switchTeams(url) { - viewChannel(ChannelStore.getCurrentId())(dispatch, getState); - browserHistory.push(url); -} - -export function getTeamsForUser(userId, success, error) { - TeamActions.getTeamsForUser(userId)(dispatch, getState).then( - (result) => { - if (result && success) { - success(result); - } else if (result == null && error) { - const serverError = getState().requests.teams.getTeams.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getTeamMembersForUser(userId, success, error) { - TeamActions.getTeamMembersForUser(userId)(dispatch, getState).then( - (result) => { - if (result && success) { - success(result); - } else if (result == null && error) { - const serverError = getState().requests.teams.getTeamMembers.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/user_actions.jsx b/webapp/actions/user_actions.jsx deleted file mode 100644 index 7c8f0afd5..000000000 --- a/webapp/actions/user_actions.jsx +++ /dev/null @@ -1,839 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import PreferenceStore from 'stores/preference_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; -import UserStore from 'stores/user_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; - -import {getChannelMembersForUserIds} from 'actions/channel_actions.jsx'; -import {loadCurrentLocale, clientLogout} from 'actions/global_actions.jsx'; -import {loadStatusesForProfilesList, loadStatusesForProfilesMap} from 'actions/status_actions.jsx'; - -import {getDirectChannelName, getUserIdFromChannelName} from 'utils/utils.jsx'; - -import {Constants, ActionTypes, Preferences} from 'utils/constants.jsx'; -import {browserHistory} from 'react-router/es6'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import * as Selectors from 'mattermost-redux/selectors/entities/users'; -import {getBool} from 'mattermost-redux/selectors/entities/preferences'; - -import * as UserActions from 'mattermost-redux/actions/users'; -import {Client4} from 'mattermost-redux/client'; - -import {getClientConfig, getLicenseConfig} from 'mattermost-redux/actions/general'; -import {getTeamMembersByIds, getMyTeamMembers, getMyTeamUnreads} from 'mattermost-redux/actions/teams'; -import {getChannelAndMyMember} from 'mattermost-redux/actions/channels'; -import {savePreferences as savePreferencesRedux, deletePreferences} from 'mattermost-redux/actions/preferences'; - -import {Preferences as PreferencesRedux} from 'mattermost-redux/constants'; - -export async function loadMe() { - await UserActions.loadMe()(dispatch, getState); - - if (window.mm_config) { - loadCurrentLocale(); - } -} - -export function loadMeAndConfig(callback) { - getClientConfig()(store.dispatch, store.getState).then((config) => { - global.window.mm_config = config; - - if (global.window && global.window.analytics) { - global.window.analytics.identify(global.window.mm_config.DiagnosticId, {}, { - context: { - ip: '0.0.0.0' - }, - page: { - path: '', - referrer: '', - search: '', - title: '', - url: '' - }, - anonymousId: '00000000000000000000000000' - }); - } - - Promise.all([ - loadMe(), - getLicenseConfig()(store.dispatch, store.getState).then( - (license) => { - global.window.mm_license = license; - } - ) - ]).then(callback); - }); -} - -export function switchFromLdapToEmail(email, password, token, ldapPassword, success, error) { - UserActions.switchLdapToEmail(ldapPassword, email, password, token)(dispatch, getState).then( - (data) => { - if (data) { - if (data.follow_link) { - clientLogout(data.follow_link); - } - if (success) { - success(data); - } - } else if (data == null && error) { - const serverError = getState().requests.users.switchLogin.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function loadProfilesAndTeamMembers(page, perPage, teamId = TeamStore.getCurrentId(), success) { - UserActions.getProfilesInTeam(teamId, page, perPage)(dispatch, getState).then( - (data) => { - loadTeamMembersForProfilesList(data, teamId, success); - loadStatusesForProfilesList(data); - } - ); -} - -export function loadProfilesAndTeamMembersAndChannelMembers(page, perPage, teamId = TeamStore.getCurrentId(), channelId = ChannelStore.getCurrentId(), success, error) { - UserActions.getProfilesInChannel(channelId, page, perPage)(dispatch, getState).then( - (data) => { - loadTeamMembersForProfilesList( - data, - teamId, - () => { - loadChannelMembersForProfilesList(data, channelId, success, error); - loadStatusesForProfilesList(data); - } - ); - } - ); -} - -export function loadTeamMembersForProfilesList(profiles, teamId = TeamStore.getCurrentId(), success, error) { - const membersToLoad = {}; - for (let i = 0; i < profiles.length; i++) { - const pid = profiles[i].id; - - if (!TeamStore.hasActiveMemberInTeam(teamId, pid)) { - membersToLoad[pid] = true; - } - } - - const list = Object.keys(membersToLoad); - if (list.length === 0) { - if (success) { - success({}); - } - return; - } - - loadTeamMembersForProfiles(list, teamId, success, error); -} - -export function loadProfilesWithoutTeam(page, perPage, success) { - UserActions.getProfilesWithoutTeam(page, perPage)(dispatch, getState).then( - (data) => { - loadStatusesForProfilesMap(data); - - if (success) { - success(data); - } - } - ); -} - -function loadTeamMembersForProfiles(userIds, teamId, success, error) { - getTeamMembersByIds(teamId, userIds)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.teams.getTeamMembers.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function loadChannelMembersForProfilesMap(profiles, channelId = ChannelStore.getCurrentId(), success, error) { - const membersToLoad = {}; - for (const pid in profiles) { - if (!profiles.hasOwnProperty(pid)) { - continue; - } - - if (!ChannelStore.hasActiveMemberInChannel(channelId, pid)) { - membersToLoad[pid] = true; - } - } - - const list = Object.keys(membersToLoad); - if (list.length === 0) { - if (success) { - success({}); - } - return; - } - - getChannelMembersForUserIds(channelId, list, success, error); -} - -export function loadTeamMembersAndChannelMembersForProfilesList(profiles, teamId = TeamStore.getCurrentId(), channelId = ChannelStore.getCurrentId(), success, error) { - loadTeamMembersForProfilesList(profiles, teamId, () => { - loadChannelMembersForProfilesList(profiles, channelId, success, error); - }, error); -} - -export function loadChannelMembersForProfilesList(profiles, channelId = ChannelStore.getCurrentId(), success, error) { - const membersToLoad = {}; - for (let i = 0; i < profiles.length; i++) { - const pid = profiles[i].id; - - if (!ChannelStore.hasActiveMemberInChannel(channelId, pid)) { - membersToLoad[pid] = true; - } - } - - const list = Object.keys(membersToLoad); - if (list.length === 0) { - if (success) { - success({}); - } - return; - } - - getChannelMembersForUserIds(channelId, list, success, error); -} - -function populateDMChannelsWithProfiles(userIds) { - const currentUserId = UserStore.getCurrentId(); - - for (let i = 0; i < userIds.length; i++) { - const channelName = getDirectChannelName(currentUserId, userIds[i]); - const channel = ChannelStore.getByName(channelName); - const profilesInChannel = Selectors.getUserIdsInChannels(getState())[channel.id] || new Set(); - if (channel && !profilesInChannel.has(userIds[i])) { - UserStore.saveUserIdInChannel(channel.id, userIds[i]); - } - } -} - -function populateChannelWithProfiles(channelId, users) { - for (let i = 0; i < users.length; i++) { - UserStore.saveUserIdInChannel(channelId, users[i].id); - } - UserStore.emitInChannelChange(); -} - -export function loadNewDMIfNeeded(channelId) { - function checkPreference(channel) { - const userId = getUserIdFromChannelName(channel); - - if (!userId) { - return; - } - - const pref = PreferenceStore.getBool(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, userId, false); - if (pref === false) { - PreferenceStore.setPreference(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, userId, 'true'); - const currentUserId = UserStore.getCurrentId(); - savePreferencesRedux(currentUserId, [{user_id: currentUserId, category: Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, name: userId, value: 'true'}])(dispatch, getState); - loadProfilesForDM(); - } - } - - const channel = ChannelStore.get(channelId); - if (channel) { - checkPreference(channel); - } else { - getChannelAndMyMember(channelId)(dispatch, getState).then( - (data) => { - if (data) { - checkPreference(data.channel); - } - } - ); - } -} - -export function loadNewGMIfNeeded(channelId) { - function checkPreference() { - const pref = PreferenceStore.getBool(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, channelId, false); - if (pref === false) { - PreferenceStore.setPreference(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, channelId, 'true'); - const currentUserId = UserStore.getCurrentId(); - savePreferencesRedux(currentUserId, [{user_id: currentUserId, category: Preferences.CATEGORY_GROUP_CHANNEL_SHOW, name: channelId, value: 'true'}])(dispatch, getState); - loadProfilesForGM(); - } - } - - const channel = ChannelStore.get(channelId); - if (channel) { - checkPreference(); - } else { - getChannelAndMyMember(channelId)(dispatch, getState).then( - () => { - checkPreference(); - } - ); - } -} - -export function loadProfilesForSidebar() { - loadProfilesForDM(); - loadProfilesForGM(); -} - -export function loadProfilesForGM() { - const channels = ChannelStore.getChannels(); - const newPreferences = []; - - for (let i = 0; i < channels.length; i++) { - const channel = channels[i]; - if (channel.type !== Constants.GM_CHANNEL) { - continue; - } - - if (UserStore.getProfileListInChannel(channel.id).length >= Constants.MIN_USERS_IN_GM) { - continue; - } - - const isVisible = PreferenceStore.getBool(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, channel.id); - - if (!isVisible) { - const member = ChannelStore.getMyMember(channel.id); - if (!member || (member.mention_count === 0 && member.msg_count >= channel.total_msg_count)) { - continue; - } - - newPreferences.push({ - user_id: UserStore.getCurrentId(), - category: Preferences.CATEGORY_GROUP_CHANNEL_SHOW, - name: channel.id, - value: 'true' - }); - } - - UserActions.getProfilesInChannel(channel.id, 0, Constants.MAX_USERS_IN_GM)(dispatch, getState).then( - (data) => { - populateChannelWithProfiles(channel.id, data); - } - ); - } - - if (newPreferences.length > 0) { - const currentUserId = UserStore.getCurrentId(); - savePreferencesRedux(currentUserId, newPreferences)(dispatch, getState); - } -} - -export function loadProfilesForDM() { - const channels = ChannelStore.getChannels(); - const newPreferences = []; - const profilesToLoad = []; - const profileIds = []; - - for (let i = 0; i < channels.length; i++) { - const channel = channels[i]; - if (channel.type !== Constants.DM_CHANNEL) { - continue; - } - - const teammateId = channel.name.replace(UserStore.getCurrentId(), '').replace('__', ''); - const isVisible = PreferenceStore.getBool(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, teammateId); - - if (!isVisible) { - const member = ChannelStore.getMyMember(channel.id); - if (!member || member.mention_count === 0) { - continue; - } - - newPreferences.push({ - user_id: UserStore.getCurrentId(), - category: Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, - name: teammateId, - value: 'true' - }); - } - - if (!UserStore.hasProfile(teammateId)) { - profilesToLoad.push(teammateId); - } - profileIds.push(teammateId); - } - - if (newPreferences.length > 0) { - const currentUserId = UserStore.getCurrentId(); - savePreferencesRedux(currentUserId, newPreferences)(dispatch, getState); - } - - if (profilesToLoad.length > 0) { - UserActions.getProfilesByIds(profilesToLoad)(dispatch, getState).then( - () => { - populateDMChannelsWithProfiles(profileIds); - }, - ); - } else { - populateDMChannelsWithProfiles(profileIds); - } -} - -export function saveTheme(teamId, theme, cb) { - const currentUserId = UserStore.getCurrentId(); - const preference = [{ - user_id: currentUserId, - category: Preferences.CATEGORY_THEME, - name: teamId, - value: JSON.stringify(theme) - }]; - - savePreferencesRedux(currentUserId, preference)(dispatch, getState).then( - () => { - onThemeSaved(teamId, theme, cb); - } - ); -} - -function onThemeSaved(teamId, theme, onSuccess) { - const themePreferences = PreferenceStore.getCategory(Preferences.CATEGORY_THEME); - - if (teamId !== '' && themePreferences.size > 1) { - // no extra handling to be done to delete team-specific themes - onSuccess(); - return; - } - - const toDelete = []; - - for (const [name] of themePreferences) { - if (name === '' || name === teamId) { - continue; - } - - toDelete.push({ - user_id: UserStore.getCurrentId(), - category: Preferences.CATEGORY_THEME, - name - }); - } - - if (toDelete.length > 0) { - // we're saving a new global theme so delete any team-specific ones - const currentUserId = UserStore.getCurrentId(); - deletePreferences(currentUserId, toDelete)(dispatch, getState); - } - - onSuccess(); -} - -export function searchUsers(term, teamId = TeamStore.getCurrentId(), options = {}, success) { - UserActions.searchProfiles(term, {team_id: teamId, ...options})(dispatch, getState).then( - (data) => { - loadStatusesForProfilesList(data); - - if (success) { - success(data); - } - } - ); -} - -export function searchUsersNotInTeam(term, teamId = TeamStore.getCurrentId(), options = {}, success) { - UserActions.searchProfiles(term, {not_in_team_id: teamId, ...options})(dispatch, getState).then( - (data) => { - loadStatusesForProfilesList(data); - - if (success) { - success(data); - } - } - ); -} - -export function autocompleteUsersInChannel(username, channelId, success) { - const channel = ChannelStore.get(channelId); - const teamId = channel ? channel.team_id : TeamStore.getCurrentId(); - UserActions.autocompleteUsers(username, teamId, channelId)(dispatch, getState).then( - (data) => { - if (success) { - success(data); - } - } - ); -} - -export function autocompleteUsersInTeam(username, success) { - UserActions.autocompleteUsers(username, TeamStore.getCurrentId())(dispatch, getState).then( - (data) => { - if (success) { - success(data); - } - } - ); -} - -export function autocompleteUsers(username, success) { - UserActions.autocompleteUsers(username)(dispatch, getState).then( - (data) => { - if (success) { - success(data); - } - } - ); -} - -export function updateUser(user, type, success, error) { - UserActions.updateMe(user)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateMe.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function generateMfaSecret(success, error) { - UserActions.generateMfaSecret(UserStore.getCurrentId())(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.generateMfaSecret.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateUserNotifyProps(props, success, error) { - UserActions.updateMe({notify_props: props})(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateMe.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateUserRoles(userId, newRoles, success, error) { - UserActions.updateUserRoles(userId, newRoles)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function activateMfa(code, success, error) { - UserActions.updateUserMfa(UserStore.getCurrentId(), true, code)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - }, - ); -} - -export function deactivateMfa(success, error) { - UserActions.updateUserMfa(UserStore.getCurrentId(), false)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - }, - ); -} - -export function checkMfa(loginId, success, error) { - if (global.window.mm_config.EnableMultifactorAuthentication !== 'true') { - success(false); - return; - } - - UserActions.checkMfa(loginId)(dispatch, getState).then( - (data) => { - if (data != null && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.checkMfa.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updateActive(userId, active, success, error) { - UserActions.updateUserActive(userId, active)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function updatePassword(userId, currentPassword, newPassword, success, error) { - UserActions.updateUserPassword(userId, currentPassword, newPassword)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function verifyEmail(token, success, error) { - UserActions.verifyUserEmail(token)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.verifyEmail.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function resetPassword(token, password, success, error) { - UserActions.resetUserPassword(token, password)(dispatch, getState).then( - (data) => { - if (data) { - browserHistory.push('/login?extra=' + ActionTypes.PASSWORD_CHANGE); - if (success) { - success(data); - } - } else if (data == null && error) { - const serverError = getState().requests.users.passwordReset.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function resendVerification(email, success, error) { - UserActions.sendVerificationEmail(email)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.verifyEmail.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function loginById(userId, password, mfaToken, success, error) { - UserActions.loginById(userId, password, mfaToken)(dispatch, getState).then( - (ok) => { - if (ok && success) { - success(); - } else if (!ok && error) { - const serverError = getState().requests.users.login.error; - if (serverError.server_error_id === 'api.context.mfa_required.app_error') { - if (success) { - success(); - } - return; - } - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function createUserWithInvite(user, data, emailHash, inviteId, success, error) { - UserActions.createUser(user, data, emailHash, inviteId)(dispatch, getState).then( - (resp) => { - if (resp && success) { - success(resp); - } else if (resp == null && error) { - const serverError = getState().requests.users.create.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function webLogin(loginId, password, token, success, error) { - UserActions.login(loginId, password, token)(dispatch, getState).then( - (ok) => { - if (ok && success) { - success(); - } else if (!ok && error) { - const serverError = getState().requests.users.login.error; - if (serverError.server_error_id === 'api.context.mfa_required.app_error') { - if (success) { - success(); - } - return; - } - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function webLoginByLdap(loginId, password, token, success, error) { - UserActions.login(loginId, password, token, true)(dispatch, getState).then( - (ok) => { - if (ok && success) { - success(); - } else if (!ok && error) { - const serverError = getState().requests.users.login.error; - if (serverError.server_error_id === 'api.context.mfa_required.app_error') { - if (success) { - success(); - } - return; - } - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function getAuthorizedApps(success, error) { - Client4.getAuthorizedOAuthApps(getState().entities.users.currentUserId).then( - (authorizedApps) => { - if (success) { - success(authorizedApps); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function deauthorizeOAuthApp(appId, success, error) { - Client4.deauthorizeOAuthApp(appId).then( - () => { - if (success) { - success(); - } - } - ).catch( - (err) => { - if (error) { - error(err); - } - } - ); -} - -export function uploadProfileImage(userPicture, success, error) { - UserActions.uploadProfileImage(Selectors.getCurrentUserId(getState()), userPicture)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.updateUser.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} - -export function loadProfiles(page, perPage, success) { - UserActions.getProfiles(page, perPage)(dispatch, getState).then( - (data) => { - if (success) { - success(data); - } - } - ); -} - -export function getMissingProfiles(ids) { - const missingIds = ids.filter((id) => !UserStore.hasProfile(id)); - - if (missingIds.length === 0) { - return; - } - - UserActions.getProfilesByIds(missingIds)(dispatch, getState); -} - -export function loadMyTeamMembers() { - getMyTeamMembers()(dispatch, getState).then( - () => { - getMyTeamUnreads()(dispatch, getState); - } - ); -} - -export function savePreferences(prefs, callback) { - const currentUserId = UserStore.getCurrentId(); - savePreferencesRedux(currentUserId, prefs)(dispatch, getState).then( - () => callback() - ); -} - -export async function savePreference(category, name, value) { - const currentUserId = UserStore.getCurrentId(); - return savePreferencesRedux(currentUserId, [{user_id: currentUserId, category, name, value}])(dispatch, getState); -} - -export function autoResetStatus() { - return async (doDispatch, doGetState) => { - const {currentUserId} = getState().entities.users; - const userStatus = await UserActions.getStatus(currentUserId)(doDispatch, doGetState); - - if (!userStatus.manual) { - return userStatus; - } - - const autoReset = getBool(getState(), PreferencesRedux.CATEGORY_AUTO_RESET_MANUAL_STATUS, currentUserId, false); - - if (autoReset) { - UserActions.setStatus({user_id: currentUserId, status: 'online'})(doDispatch, doGetState); - return userStatus; - } - - return userStatus; - }; -} - -export function sendPasswordResetEmail(email, success, error) { - UserActions.sendPasswordResetEmail(email)(dispatch, getState).then( - (data) => { - if (data && success) { - success(data); - } else if (data == null && error) { - const serverError = getState().requests.users.passwordReset.error; - error({id: serverError.server_error_id, ...serverError}); - } - } - ); -} diff --git a/webapp/actions/webrtc_actions.jsx b/webapp/actions/webrtc_actions.jsx deleted file mode 100644 index 244de289b..000000000 --- a/webapp/actions/webrtc_actions.jsx +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; -import {WebrtcActionTypes} from 'utils/constants.jsx'; - -import {Client4} from 'mattermost-redux/client'; - -export function initWebrtc(userId, isCalling) { - AppDispatcher.handleServerAction({ - type: WebrtcActionTypes.INITIALIZE, - user_id: userId, - is_calling: isCalling - }); -} - -export function handle(message) { - AppDispatcher.handleServerAction({ - type: message.action, - message - }); -} - -export function webrtcToken(success, error) { - Client4.webrtcToken().then( - (data) => { - if (success) { - success(data); - } - } - ).catch( - () => { - if (error) { - error(); - } - } - ); -} diff --git a/webapp/actions/websocket_actions.jsx b/webapp/actions/websocket_actions.jsx deleted file mode 100644 index 1e75b1758..000000000 --- a/webapp/actions/websocket_actions.jsx +++ /dev/null @@ -1,473 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; - -import UserStore from 'stores/user_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; -import PreferenceStore from 'stores/preference_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; -import BrowserStore from 'stores/browser_store.jsx'; -import ErrorStore from 'stores/error_store.jsx'; -import NotificationStore from 'stores/notification_store.jsx'; //eslint-disable-line no-unused-vars - -import WebSocketClient from 'client/web_websocket_client.jsx'; -import * as WebrtcActions from './webrtc_actions.jsx'; - -import * as GlobalActions from 'actions/global_actions.jsx'; -import {handleNewPost} from 'actions/post_actions.jsx'; -import {loadProfilesForSidebar} from 'actions/user_actions.jsx'; -import {loadChannelsForCurrentUser} from 'actions/channel_actions.jsx'; -import * as StatusActions from 'actions/status_actions.jsx'; - -import {Constants, Preferences, SocketEvents, UserStatuses, ErrorBarTypes} from 'utils/constants.jsx'; - -import {browserHistory} from 'react-router/es6'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {batchActions} from 'redux-batched-actions'; -import {Client4} from 'mattermost-redux/client'; -import {getSiteURL} from 'utils/url.jsx'; - -import * as TeamActions from 'mattermost-redux/actions/teams'; -import {viewChannel, getChannelAndMyMember, getChannelStats} from 'mattermost-redux/actions/channels'; -import {getPosts, getProfilesAndStatusesForPosts} from 'mattermost-redux/actions/posts'; -import {setServerVersion} from 'mattermost-redux/actions/general'; -import {ChannelTypes, TeamTypes, UserTypes, PostTypes, EmojiTypes} from 'mattermost-redux/action_types'; - -const MAX_WEBSOCKET_FAILS = 7; - -export function initialize() { - if (!window.WebSocket) { - console.log('Browser does not support websocket'); //eslint-disable-line no-console - return; - } - - let connUrl = getSiteURL(); - - // replace the protocol with a websocket one - if (connUrl.startsWith('https:')) { - connUrl = connUrl.replace(/^https:/, 'wss:'); - } else { - connUrl = connUrl.replace(/^http:/, 'ws:'); - } - - // append a port number if one isn't already specified - if (!(/:\d+$/).test(connUrl)) { - if (connUrl.startsWith('wss:')) { - connUrl += ':' + global.window.mm_config.WebsocketSecurePort; - } else { - connUrl += ':' + global.window.mm_config.WebsocketPort; - } - } - - connUrl += Client4.getUrlVersion() + '/websocket'; - - WebSocketClient.setEventCallback(handleEvent); - WebSocketClient.setFirstConnectCallback(handleFirstConnect); - WebSocketClient.setReconnectCallback(() => reconnect(false)); - WebSocketClient.setMissedEventCallback(() => reconnect(false)); - WebSocketClient.setCloseCallback(handleClose); - WebSocketClient.initialize(connUrl); -} - -export function close() { - WebSocketClient.close(); -} - -function reconnectWebSocket() { - close(); - initialize(); -} - -export function reconnect(includeWebSocket = true) { - if (includeWebSocket) { - reconnectWebSocket(); - } - - loadChannelsForCurrentUser(); - getPosts(ChannelStore.getCurrentId())(dispatch, getState); - StatusActions.loadStatusesForChannelAndSidebar(); - - ErrorStore.clearLastError(); - ErrorStore.emitChange(); -} - -let intervalId = ''; -const SYNC_INTERVAL_MILLISECONDS = 1000 * 60 * 15; // 15 minutes - -export function startPeriodicSync() { - clearInterval(intervalId); - - intervalId = setInterval( - () => { - if (UserStore.getCurrentUser() != null) { - reconnect(false); - } - }, - SYNC_INTERVAL_MILLISECONDS - ); -} - -export function stopPeriodicSync() { - clearInterval(intervalId); -} - -function handleFirstConnect() { - ErrorStore.clearLastError(); - ErrorStore.emitChange(); -} - -function handleClose(failCount) { - if (failCount > MAX_WEBSOCKET_FAILS) { - ErrorStore.storeLastError({message: ErrorBarTypes.WEBSOCKET_PORT_ERROR}); - } - - ErrorStore.setConnectionErrorCount(failCount); - ErrorStore.emitChange(); -} - -function handleEvent(msg) { - switch (msg.event) { - case SocketEvents.POSTED: - case SocketEvents.EPHEMERAL_MESSAGE: - handleNewPostEvent(msg); - break; - - case SocketEvents.POST_EDITED: - handlePostEditEvent(msg); - break; - - case SocketEvents.POST_DELETED: - handlePostDeleteEvent(msg); - break; - - case SocketEvents.LEAVE_TEAM: - handleLeaveTeamEvent(msg); - break; - - case SocketEvents.UPDATE_TEAM: - handleUpdateTeamEvent(msg); - break; - - case SocketEvents.ADDED_TO_TEAM: - handleTeamAddedEvent(msg); - break; - - case SocketEvents.USER_ADDED: - handleUserAddedEvent(msg); - break; - - case SocketEvents.USER_REMOVED: - handleUserRemovedEvent(msg); - break; - - case SocketEvents.USER_UPDATED: - handleUserUpdatedEvent(msg); - break; - - case SocketEvents.MEMBERROLE_UPDATED: - handleUpdateMemberRoleEvent(msg); - break; - - case SocketEvents.CHANNEL_CREATED: - handleChannelCreatedEvent(msg); - break; - - case SocketEvents.CHANNEL_DELETED: - handleChannelDeletedEvent(msg); - break; - - case SocketEvents.CHANNEL_UPDATED: - handleChannelUpdatedEvent(msg); - break; - - case SocketEvents.DIRECT_ADDED: - handleDirectAddedEvent(msg); - break; - - case SocketEvents.PREFERENCE_CHANGED: - handlePreferenceChangedEvent(msg); - break; - - case SocketEvents.PREFERENCES_CHANGED: - handlePreferencesChangedEvent(msg); - break; - - case SocketEvents.PREFERENCES_DELETED: - handlePreferencesDeletedEvent(msg); - break; - - case SocketEvents.TYPING: - handleUserTypingEvent(msg); - break; - - case SocketEvents.STATUS_CHANGED: - handleStatusChangedEvent(msg); - break; - - case SocketEvents.HELLO: - handleHelloEvent(msg); - break; - - case SocketEvents.WEBRTC: - handleWebrtc(msg); - break; - - case SocketEvents.REACTION_ADDED: - handleReactionAddedEvent(msg); - break; - - case SocketEvents.REACTION_REMOVED: - handleReactionRemovedEvent(msg); - break; - - case SocketEvents.EMOJI_ADDED: - handleAddEmoji(msg); - break; - - case SocketEvents.CHANNEL_VIEWED: - handleChannelViewedEvent(msg); - break; - - default: - } -} - -function handleChannelUpdatedEvent(msg) { - const channel = JSON.parse(msg.data.channel); - dispatch({type: ChannelTypes.RECEIVED_CHANNEL, data: channel}); -} - -function handleNewPostEvent(msg) { - const post = JSON.parse(msg.data.post); - handleNewPost(post, msg); - - getProfilesAndStatusesForPosts([post], dispatch, getState); - - if (post.user_id !== UserStore.getCurrentId()) { - UserStore.setStatus(post.user_id, UserStatuses.ONLINE); - } -} - -function handlePostEditEvent(msg) { - // Store post - const post = JSON.parse(msg.data.post); - dispatch({type: PostTypes.RECEIVED_POST, data: post}); - - // Update channel state - if (ChannelStore.getCurrentId() === msg.broadcast.channel_id) { - if (window.isActive) { - viewChannel(ChannelStore.getCurrentId())(dispatch, getState); - } - } - - // Needed for search store - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.POST_UPDATED, - post - }); -} - -function handlePostDeleteEvent(msg) { - const post = JSON.parse(msg.data.post); - dispatch({type: PostTypes.POST_DELETED, data: post}); - - // Needed for search store - AppDispatcher.handleViewAction({ - type: Constants.ActionTypes.POST_DELETED, - post - }); -} - -async function handleTeamAddedEvent(msg) { - await TeamActions.getTeam(msg.data.team_id)(dispatch, getState); - await TeamActions.getMyTeamMembers()(dispatch, getState); - await TeamActions.getMyTeamUnreads()(dispatch, getState); -} - -function handleLeaveTeamEvent(msg) { - if (UserStore.getCurrentId() === msg.data.user_id) { - TeamStore.removeMyTeamMember(msg.data.team_id); - - // if they are on the team being removed redirect them to default team - if (TeamStore.getCurrentId() === msg.data.team_id) { - BrowserStore.removeGlobalItem('team'); - BrowserStore.removeGlobalItem(msg.data.team_id); - - if (!global.location.pathname.startsWith('/admin_console')) { - GlobalActions.redirectUserToDefaultTeam(); - } - } - - dispatch(batchActions([ - { - type: UserTypes.RECEIVED_PROFILE_NOT_IN_TEAM, - data: {user_id: msg.data.user_id}, - id: msg.data.team_id - }, - { - type: TeamTypes.REMOVE_MEMBER_FROM_TEAM, - data: {team_id: msg.data.team_id, user_id: msg.data.user_id} - } - ])); - } else { - UserStore.removeProfileFromTeam(msg.data.team_id, msg.data.user_id); - TeamStore.removeMemberInTeam(msg.data.team_id, msg.data.user_id); - } -} - -function handleUpdateTeamEvent(msg) { - TeamStore.updateTeam(msg.data.team); -} - -function handleUpdateMemberRoleEvent(msg) { - const member = JSON.parse(msg.data.member); - TeamStore.updateMyRoles(member); -} - -function handleDirectAddedEvent(msg) { - getChannelAndMyMember(msg.broadcast.channel_id)(dispatch, getState); - PreferenceStore.setPreference(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, msg.data.teammate_id, 'true'); - loadProfilesForSidebar(); -} - -function handleUserAddedEvent(msg) { - if (ChannelStore.getCurrentId() === msg.broadcast.channel_id) { - getChannelStats(ChannelStore.getCurrentId())(dispatch, getState); - } - - if (TeamStore.getCurrentId() === msg.data.team_id && UserStore.getCurrentId() === msg.data.user_id) { - getChannelAndMyMember(msg.broadcast.channel_id)(dispatch, getState); - } -} - -function handleUserRemovedEvent(msg) { - if (UserStore.getCurrentId() === msg.broadcast.user_id) { - loadChannelsForCurrentUser(); - - if (msg.data.remover_id !== msg.broadcast.user_id && - msg.data.channel_id === ChannelStore.getCurrentId() && - $('#removed_from_channel').length > 0) { - var sentState = {}; - sentState.channelName = ChannelStore.getCurrent().display_name; - sentState.remover = UserStore.getProfile(msg.data.remover_id).username; - - BrowserStore.setItem('channel-removed-state', sentState); - $('#removed_from_channel').modal('show'); - } - - GlobalActions.toggleSideBarAction(false); - - const townsquare = ChannelStore.getByName('town-square'); - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + townsquare.name); - - dispatch({ - type: ChannelTypes.LEAVE_CHANNEL, - data: {id: msg.data.channel_id, user_id: msg.broadcast.user_id} - }); - } else if (ChannelStore.getCurrentId() === msg.broadcast.channel_id) { - getChannelStats(ChannelStore.getCurrentId())(dispatch, getState); - } -} - -function handleUserUpdatedEvent(msg) { - const user = msg.data.user; - if (UserStore.getCurrentId() !== user.id) { - UserStore.saveProfile(user); - } -} - -function handleChannelCreatedEvent(msg) { - const channelId = msg.data.channel_id; - const teamId = msg.data.team_id; - - if (TeamStore.getCurrentId() === teamId && !ChannelStore.getChannelById(channelId)) { - getChannelAndMyMember(channelId)(dispatch, getState); - } -} - -function handleChannelDeletedEvent(msg) { - if (ChannelStore.getCurrentId() === msg.data.channel_id) { - const teamUrl = TeamStore.getCurrentTeamRelativeUrl(); - browserHistory.push(teamUrl + '/channels/' + Constants.DEFAULT_CHANNEL); - } - dispatch({type: ChannelTypes.RECEIVED_CHANNEL_DELETED, data: {id: msg.data.channel_id, team_id: msg.broadcast.team_id}}, getState); - loadChannelsForCurrentUser(); -} - -function handlePreferenceChangedEvent(msg) { - const preference = JSON.parse(msg.data.preference); - GlobalActions.emitPreferenceChangedEvent(preference); -} - -function handlePreferencesChangedEvent(msg) { - const preferences = JSON.parse(msg.data.preferences); - GlobalActions.emitPreferencesChangedEvent(preferences); -} - -function handlePreferencesDeletedEvent(msg) { - const preferences = JSON.parse(msg.data.preferences); - GlobalActions.emitPreferencesDeletedEvent(preferences); -} - -function handleUserTypingEvent(msg) { - GlobalActions.emitRemoteUserTypingEvent(msg.broadcast.channel_id, msg.data.user_id, msg.data.parent_id); - - if (msg.data.user_id !== UserStore.getCurrentId()) { - UserStore.setStatus(msg.data.user_id, UserStatuses.ONLINE); - } -} - -function handleStatusChangedEvent(msg) { - UserStore.setStatus(msg.data.user_id, msg.data.status); -} - -function handleHelloEvent(msg) { - setServerVersion(msg.data.server_version)(dispatch, getState); -} - -function handleWebrtc(msg) { - const data = msg.data; - return WebrtcActions.handle(data); -} - -function handleReactionAddedEvent(msg) { - const reaction = JSON.parse(msg.data.reaction); - - dispatch({ - type: PostTypes.RECEIVED_REACTION, - data: reaction - }); -} - -function handleAddEmoji(msg) { - const data = JSON.parse(msg.data.emoji); - - dispatch({ - type: EmojiTypes.RECEIVED_CUSTOM_EMOJI, - data - }); -} - -function handleReactionRemovedEvent(msg) { - const reaction = JSON.parse(msg.data.reaction); - - dispatch({ - type: PostTypes.REACTION_DELETED, - data: reaction - }); -} - -function handleChannelViewedEvent(msg) { -// Useful for when multiple devices have the app open to different channels - if (ChannelStore.getCurrentId() !== msg.data.channel_id && - UserStore.getCurrentId() === msg.broadcast.user_id) { - // Mark previous and next channel as read - ChannelStore.resetCounts([msg.data.channel_id]); - } -} diff --git a/webapp/client/web_websocket_client.jsx b/webapp/client/web_websocket_client.jsx deleted file mode 100644 index 775c0ff59..000000000 --- a/webapp/client/web_websocket_client.jsx +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import WebSocketClient from './websocket_client.jsx'; - -var WebClient = new WebSocketClient(); -export default WebClient; diff --git a/webapp/client/websocket_client.jsx b/webapp/client/websocket_client.jsx deleted file mode 100644 index eaa059197..000000000 --- a/webapp/client/websocket_client.jsx +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -const MAX_WEBSOCKET_FAILS = 7; -const MIN_WEBSOCKET_RETRY_TIME = 3000; // 3 sec -const MAX_WEBSOCKET_RETRY_TIME = 300000; // 5 mins - -export default class WebSocketClient { - constructor() { - this.conn = null; - this.connectionUrl = null; - this.sequence = 1; - this.eventSequence = 0; - this.connectFailCount = 0; - this.eventCallback = null; - this.responseCallbacks = {}; - this.firstConnectCallback = null; - this.reconnectCallback = null; - this.missedEventCallback = null; - this.errorCallback = null; - this.closeCallback = null; - } - - initialize(connectionUrl = this.connectionUrl, token) { - if (this.conn) { - return; - } - - if (connectionUrl == null) { - console.log('websocket must have connection url'); //eslint-disable-line no-console - return; - } - - if (this.connectFailCount === 0) { - console.log('websocket connecting to ' + connectionUrl); //eslint-disable-line no-console - } - - this.conn = new WebSocket(connectionUrl); - this.connectionUrl = connectionUrl; - - this.conn.onopen = () => { - this.eventSequence = 0; - - if (token) { - this.sendMessage('authentication_challenge', {token}); - } - - if (this.connectFailCount > 0) { - console.log('websocket re-established connection'); //eslint-disable-line no-console - if (this.reconnectCallback) { - this.reconnectCallback(); - } - } else if (this.firstConnectCallback) { - this.firstConnectCallback(); - } - - this.connectFailCount = 0; - }; - - this.conn.onclose = () => { - this.conn = null; - this.sequence = 1; - - if (this.connectFailCount === 0) { - console.log('websocket closed'); //eslint-disable-line no-console - } - - this.connectFailCount++; - - if (this.closeCallback) { - this.closeCallback(this.connectFailCount); - } - - let retryTime = MIN_WEBSOCKET_RETRY_TIME; - - // If we've failed a bunch of connections then start backing off - if (this.connectFailCount > MAX_WEBSOCKET_FAILS) { - retryTime = MIN_WEBSOCKET_RETRY_TIME * this.connectFailCount * this.connectFailCount; - if (retryTime > MAX_WEBSOCKET_RETRY_TIME) { - retryTime = MAX_WEBSOCKET_RETRY_TIME; - } - } - - setTimeout( - () => { - this.initialize(connectionUrl, token); - }, - retryTime - ); - }; - - this.conn.onerror = (evt) => { - if (this.connectFailCount <= 1) { - console.log('websocket error'); //eslint-disable-line no-console - console.log(evt); //eslint-disable-line no-console - } - - if (this.errorCallback) { - this.errorCallback(evt); - } - }; - - this.conn.onmessage = (evt) => { - const msg = JSON.parse(evt.data); - if (msg.seq_reply) { - if (msg.error) { - console.log(msg); //eslint-disable-line no-console - } - - if (this.responseCallbacks[msg.seq_reply]) { - this.responseCallbacks[msg.seq_reply](msg); - Reflect.deleteProperty(this.responseCallbacks, msg.seq_reply); - } - } else if (this.eventCallback) { - if (msg.seq !== this.eventSequence && this.missedEventCallback) { - console.log('missed websocket event, act_seq=' + msg.seq + ' exp_seq=' + this.eventSequence); //eslint-disable-line no-console - this.missedEventCallback(); - } - this.eventSequence = msg.seq + 1; - this.eventCallback(msg); - } - }; - } - - setEventCallback(callback) { - this.eventCallback = callback; - } - - setFirstConnectCallback(callback) { - this.firstConnectCallback = callback; - } - - setReconnectCallback(callback) { - this.reconnectCallback = callback; - } - - setMissedEventCallback(callback) { - this.missedEventCallback = callback; - } - - setErrorCallback(callback) { - this.errorCallback = callback; - } - - setCloseCallback(callback) { - this.closeCallback = callback; - } - - close() { - this.connectFailCount = 0; - this.sequence = 1; - if (this.conn && this.conn.readyState === WebSocket.OPEN) { - this.conn.onclose = () => {}; //eslint-disable-line no-empty-function - this.conn.close(); - this.conn = null; - console.log('websocket closed'); //eslint-disable-line no-console - } - } - - sendMessage(action, data, responseCallback) { - const msg = { - action, - seq: this.sequence++, - data - }; - - if (responseCallback) { - this.responseCallbacks[msg.seq] = responseCallback; - } - - if (this.conn && this.conn.readyState === WebSocket.OPEN) { - this.conn.send(JSON.stringify(msg)); - } else if (!this.conn || this.conn.readyState === WebSocket.CLOSED) { - this.conn = null; - this.initialize(); - } - } - - userTyping(channelId, parentId, callback) { - const data = {}; - data.channel_id = channelId; - data.parent_id = parentId; - - this.sendMessage('user_typing', data, callback); - } - - getStatuses(callback) { - this.sendMessage('get_statuses', null, callback); - } - - getStatusesByIds(userIds, callback) { - const data = {}; - data.user_ids = userIds; - this.sendMessage('get_statuses_by_ids', data, callback); - } -} diff --git a/webapp/components/about_build_modal.jsx b/webapp/components/about_build_modal.jsx deleted file mode 100644 index 4621cfc89..000000000 --- a/webapp/components/about_build_modal.jsx +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {Modal} from 'react-bootstrap'; - -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -import PropTypes from 'prop-types'; - -import React from 'react'; -import Constants from 'utils/constants.jsx'; - -export default class AboutBuildModal extends React.Component { - constructor(props) { - super(props); - this.doHide = this.doHide.bind(this); - } - - doHide() { - this.props.onModalDismissed(); - } - - render() { - const config = global.window.mm_config; - const license = global.window.mm_license; - const mattermostLogo = Constants.MATTERMOST_ICON_SVG; - - let title = ( - - ); - - let subTitle = ( - - ); - - let learnMore = ( -
- - - {'mattermost.org'} - -
- ); - - let licensee; - if (config.BuildEnterpriseReady === 'true') { - title = ( - - ); - - subTitle = ( - - ); - - learnMore = ( - - ); - - if (license.IsLicensed === 'true') { - title = ( - - ); - licensee = ( -
- -  {license.Company} -
- ); - } - } - - let version = '\u00a0' + config.Version; - if (config.BuildNumber !== config.Version) { - version += '\u00a0 (' + config.BuildNumber + ')'; - } - - return ( - - - - - - - -
-
- -
-
-

{'Mattermost'} {title}

-

{subTitle}

-
-
- - {version} -
-
- - {'\u00a0' + config.SQLDriverName} -
-
- {licensee} -
-
-
- {learnMore} -
- -
-
-
-

- -

-
-
-

- -  {config.BuildHash} -
- -  {config.BuildHashEnterprise} -

-

- -  {config.BuildDate} -

-
-
-
- ); - } -} - -AboutBuildModal.defaultProps = { - show: false -}; - -AboutBuildModal.propTypes = { - show: PropTypes.bool.isRequired, - onModalDismissed: PropTypes.func.isRequired -}; diff --git a/webapp/components/access_history_modal/access_history_modal.jsx b/webapp/components/access_history_modal/access_history_modal.jsx deleted file mode 100644 index fdd18669b..000000000 --- a/webapp/components/access_history_modal/access_history_modal.jsx +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; -import AuditTable from 'components/audit_table.jsx'; - -import UserStore from 'stores/user_store.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; - -import {Modal} from 'react-bootstrap'; -import {FormattedMessage} from 'react-intl'; - -export default class AccessHistoryModal extends React.Component { - static propTypes = { - onHide: PropTypes.func.isRequired, - actions: PropTypes.shape({ - getUserAudits: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.onAuditChange = this.onAuditChange.bind(this); - this.onShow = this.onShow.bind(this); - this.onHide = this.onHide.bind(this); - - const state = this.getStateFromStoresForAudits(); - state.moreInfo = []; - state.show = true; - - this.state = state; - } - - getStateFromStoresForAudits() { - return { - audits: UserStore.getAudits() - }; - } - - onShow() { - this.props.actions.getUserAudits(UserStore.getCurrentId(), 0, 200); - if (!Utils.isMobile()) { - $('.modal-body').perfectScrollbar(); - } - } - - onHide() { - this.setState({show: false}); - } - - componentDidMount() { - UserStore.addAuditsChangeListener(this.onAuditChange); - this.onShow(); - } - - componentWillUnmount() { - UserStore.removeAuditsChangeListener(this.onAuditChange); - } - - onAuditChange() { - const newState = this.getStateFromStoresForAudits(); - if (!Utils.areObjectsEqual(newState.audits, this.state.audits)) { - this.setState(newState); - } - } - - render() { - let content; - if (this.state.audits.length === 0) { - content = (); - } else { - content = ( - - ); - } - - return ( - - - - - - - - {content} - - - ); - } -} diff --git a/webapp/components/access_history_modal/index.js b/webapp/components/access_history_modal/index.js deleted file mode 100644 index 4842ca730..000000000 --- a/webapp/components/access_history_modal/index.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getUserAudits} from 'mattermost-redux/actions/users'; - -import AccessHistoryModal from './access_history_modal.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getUserAudits - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(AccessHistoryModal); diff --git a/webapp/components/activity_log_modal/activity_log_modal.jsx b/webapp/components/activity_log_modal/activity_log_modal.jsx deleted file mode 100644 index 854a2f0cf..000000000 --- a/webapp/components/activity_log_modal/activity_log_modal.jsx +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; - -import UserStore from 'stores/user_store.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; -import {Modal} from 'react-bootstrap'; -import {FormattedMessage, FormattedTime, FormattedDate} from 'react-intl'; -import {General} from 'mattermost-redux/constants'; - -export default class ActivityLogModal extends React.Component { - static propTypes = { - onHide: PropTypes.func.isRequired, - actions: PropTypes.shape({ - getSessions: PropTypes.func.isRequired, - revokeSession: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.submitRevoke = this.submitRevoke.bind(this); - this.onListenerChange = this.onListenerChange.bind(this); - this.handleMoreInfo = this.handleMoreInfo.bind(this); - this.onHide = this.onHide.bind(this); - this.onShow = this.onShow.bind(this); - - const state = this.getStateFromStores(); - state.moreInfo = []; - state.show = true; - - this.state = state; - } - - getStateFromStores() { - return { - sessions: UserStore.getSessions(), - clientError: null - }; - } - - submitRevoke(altId, e) { - e.preventDefault(); - var modalContent = $(e.target).closest('.modal-content'); - modalContent.addClass('animation--highlight'); - setTimeout(() => { - modalContent.removeClass('animation--highlight'); - }, 1500); - this.props.actions.revokeSession(UserStore.getCurrentId(), altId).then(() => { - this.props.actions.getSessions(UserStore.getCurrentId()); - }); - } - - onShow() { - this.props.actions.getSessions(UserStore.getCurrentId()); - if (!Utils.isMobile()) { - $('.modal-body').perfectScrollbar(); - } - } - - onHide() { - this.setState({show: false}); - } - - componentDidMount() { - UserStore.addSessionsChangeListener(this.onListenerChange); - this.onShow(); - } - - componentWillUnmount() { - UserStore.removeSessionsChangeListener(this.onListenerChange); - } - - onListenerChange() { - const newState = this.getStateFromStores(); - if (!Utils.areObjectsEqual(newState.sessions, this.state.sessions)) { - this.setState(newState); - } - } - - handleMoreInfo(index) { - const newMoreInfo = this.state.moreInfo; - newMoreInfo[index] = true; - this.setState({moreInfo: newMoreInfo}); - } - - isMobileSession = (session) => { - return session.device_id && (session.device_id.includes('apple') || session.device_id.includes('android')); - }; - - mobileSessionInfo = (session) => { - let deviceTypeId; - let deviceTypeMessage; - let devicePicture; - - if (session.device_id.includes('apple')) { - devicePicture = 'fa fa-apple'; - deviceTypeId = 'activity_log_modal.iphoneNativeClassicApp'; - deviceTypeMessage = 'iPhone Native Classic App'; - - if (session.device_id.includes(General.PUSH_NOTIFY_APPLE_REACT_NATIVE)) { - deviceTypeId = 'activity_log_modal.iphoneNativeApp'; - deviceTypeMessage = 'iPhone Native App'; - } - } else if (session.device_id.includes('android')) { - devicePicture = 'fa fa-android'; - deviceTypeId = 'activity_log_modal.androidNativeClassicApp'; - deviceTypeMessage = 'Android Native Classic App'; - - if (session.device_id.includes(General.PUSH_NOTIFY_ANDROID_REACT_NATIVE)) { - deviceTypeId = 'activity_log_modal.androidNativeApp'; - deviceTypeMessage = 'Android Native App'; - } - } - - return { - devicePicture, - devicePlatform: ( - - ) - }; - }; - - render() { - const activityList = []; - - for (let i = 0; i < this.state.sessions.length; i++) { - const currentSession = this.state.sessions[i]; - const lastAccessTime = new Date(currentSession.last_activity_at); - const firstAccessTime = new Date(currentSession.create_at); - let devicePlatform = currentSession.props.platform; - let devicePicture = ''; - - if (currentSession.props.type === 'UserAccessToken') { - continue; - } - - if (currentSession.props.platform === 'Windows') { - devicePicture = 'fa fa-windows'; - } else if (this.isMobileSession(currentSession)) { - const sessionInfo = this.mobileSessionInfo(currentSession); - - devicePicture = sessionInfo.devicePicture; - devicePlatform = sessionInfo.devicePlatform; - } else if (currentSession.props.platform === 'Macintosh' || - currentSession.props.platform === 'iPhone') { - devicePicture = 'fa fa-apple'; - } else if (currentSession.props.platform === 'Linux') { - if (currentSession.props.os.indexOf('Android') >= 0) { - devicePlatform = ( - - ); - devicePicture = 'fa fa-android'; - } else { - devicePicture = 'fa fa-linux'; - } - } else if (currentSession.props.os.indexOf('Linux') !== -1) { - devicePicture = 'fa fa-linux'; - } - - if (currentSession.props.browser.indexOf('Desktop App') !== -1) { - devicePlatform = ( - - ); - } - - let moreInfo; - if (this.state.moreInfo[i]) { - moreInfo = ( -
-
- - ), - time: ( - - ) - }} - /> -
-
- -
-
- -
-
- -
-
- ); - } else { - moreInfo = ( - - - - ); - } - - activityList[i] = ( -
-
-
{devicePlatform}
-
-
- - ), - time: ( - - ) - }} - /> -
- {moreInfo} -
-
-
- -
-
- ); - } - - let content; - if (this.state.sessions.loading) { - content = ; - } else { - content =
{activityList}
; - } - - return ( - - - - - - - -

- -

- {content} -
-
- ); - } -} diff --git a/webapp/components/activity_log_modal/index.js b/webapp/components/activity_log_modal/index.js deleted file mode 100644 index 1c4890c65..000000000 --- a/webapp/components/activity_log_modal/index.js +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {revokeSession, getSessions} from 'mattermost-redux/actions/users'; - -import ActivityLogModal from './activity_log_modal.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getSessions, - revokeSession - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(ActivityLogModal); diff --git a/webapp/components/add_users_to_team/add_users_to_team.jsx b/webapp/components/add_users_to_team/add_users_to_team.jsx deleted file mode 100644 index b86176c34..000000000 --- a/webapp/components/add_users_to_team/add_users_to_team.jsx +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import MultiSelect from 'components/multiselect/multiselect.jsx'; -import ProfilePicture from 'components/profile_picture.jsx'; - -import {addUsersToTeam} from 'actions/team_actions.jsx'; -import {searchUsersNotInTeam} from 'actions/user_actions.jsx'; - -import UserStore from 'stores/user_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; - -import Constants from 'utils/constants.jsx'; -import {displayEntireNameForUser} from 'utils/utils.jsx'; -import {Client4} from 'mattermost-redux/client'; - -import PropTypes from 'prop-types'; - -import React from 'react'; -import {Modal} from 'react-bootstrap'; -import {FormattedMessage} from 'react-intl'; -import {browserHistory} from 'react-router/es6'; - -import store from 'stores/redux_store.jsx'; -import {searchProfilesNotInCurrentTeam} from 'mattermost-redux/selectors/entities/users'; - -const USERS_PER_PAGE = 50; -const MAX_SELECTABLE_VALUES = 20; - -export default class AddUsersToTeam extends React.Component { - static propTypes = { - onModalDismissed: PropTypes.func, - actions: PropTypes.shape({ - getProfilesNotInTeam: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.handleHide = this.handleHide.bind(this); - this.handleExit = this.handleExit.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - this.handleDelete = this.handleDelete.bind(this); - this.onChange = this.onChange.bind(this); - this.search = this.search.bind(this); - this.addValue = this.addValue.bind(this); - this.handlePageChange = this.handlePageChange.bind(this); - - this.searchTimeoutId = 0; - - this.state = { - users: Object.assign([], UserStore.getProfileListNotInTeam(TeamStore.getCurrentId(), true)), - values: [], - show: true, - search: false - }; - } - - componentDidMount() { - UserStore.addChangeListener(this.onChange); - UserStore.addNotInTeamChangeListener(this.onChange); - UserStore.addStatusesChangeListener(this.onChange); - - this.props.actions.getProfilesNotInTeam(TeamStore.getCurrentId(), 0, USERS_PER_PAGE * 2); - } - - componentWillUnmount() { - UserStore.removeChangeListener(this.onChange); - UserStore.removeNotInTeamChangeListener(this.onChange); - UserStore.removeStatusesChangeListener(this.onChange); - } - - handleHide() { - this.setState({show: false}); - } - - handleExit() { - if (this.exitToChannel) { - browserHistory.push(this.exitToChannel); - } - - if (this.props.onModalDismissed) { - this.props.onModalDismissed(); - } - } - - handleSubmit(e) { - if (e) { - e.preventDefault(); - } - - const userIds = this.state.values.map((v) => v.id); - if (userIds.length === 0) { - return; - } - - addUsersToTeam(TeamStore.getCurrentId(), userIds); - - this.handleHide(); - } - - addValue(value) { - const values = Object.assign([], this.state.values); - if (values.indexOf(value) === -1) { - values.push(value); - } - - this.setState({values}); - } - - onChange() { - let users; - if (this.term) { - users = Object.assign([], searchProfilesNotInCurrentTeam(store.getState(), this.term, true)); - } else { - users = Object.assign([], UserStore.getProfileListNotInTeam(TeamStore.getCurrentId(), true)); - } - - for (let i = 0; i < users.length; i++) { - const user = Object.assign({}, users[i]); - user.value = user.id; - user.label = '@' + user.username; - users[i] = user; - } - - this.setState({ - users - }); - } - - handlePageChange(page, prevPage) { - if (page > prevPage) { - this.props.actions.getProfilesNotInTeam(TeamStore.getCurrentId(), page + 1, USERS_PER_PAGE); - } - } - - search(term) { - clearTimeout(this.searchTimeoutId); - this.term = term; - - if (term === '') { - this.onChange(); - return; - } - - this.searchTimeoutId = setTimeout( - () => { - searchUsersNotInTeam(term, TeamStore.getCurrentId(), {}); - }, - Constants.SEARCH_TIMEOUT_MILLISECONDS - ); - } - - handleDelete(values) { - this.setState({values}); - } - - renderOption(option, isSelected, onAdd) { - var rowSelected = ''; - if (isSelected) { - rowSelected = 'more-modal__row--selected'; - } - - return ( -
onAdd(option)} - > - -
-
- {displayEntireNameForUser(option)} -
-
- {option.email} -
-
-
-
- -
-
-
- ); - } - - renderValue(user) { - return user.username; - } - - render() { - const numRemainingText = ( - - ); - - const buttonSubmitText = ( - - ); - - let users = []; - if (this.state.users) { - users = this.state.users.filter((user) => user.delete_at === 0); - } - - return ( - - - - {TeamStore.getCurrent().display_name} - ) - }} - /> - - - - - - - ); - } -} diff --git a/webapp/components/add_users_to_team/index.js b/webapp/components/add_users_to_team/index.js deleted file mode 100644 index d38aeb4e5..000000000 --- a/webapp/components/add_users_to_team/index.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getProfilesNotInTeam} from 'mattermost-redux/actions/users'; - -import AddUsersToTeam from './add_users_to_team.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getProfilesNotInTeam - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(AddUsersToTeam); diff --git a/webapp/components/admin_console/admin_console.jsx b/webapp/components/admin_console/admin_console.jsx deleted file mode 100644 index 17670d6ab..000000000 --- a/webapp/components/admin_console/admin_console.jsx +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import 'bootstrap'; - -import AnnouncementBar from 'components/announcement_bar'; -import AdminSidebar from './admin_sidebar.jsx'; - -import {reloadIfServerVersionChanged} from 'actions/global_actions.jsx'; - -export default class AdminConsole extends React.Component { - static propTypes = { - - /* - * Children components to render - */ - children: PropTypes.node.isRequired, - - /* - * Object representing the config file - */ - config: PropTypes.object.isRequired, - - actions: PropTypes.shape({ - - /* - * Function to get the config file - */ - getConfig: PropTypes.func.isRequired - }).isRequired - } - - componentWillMount() { - this.props.actions.getConfig(); - reloadIfServerVersionChanged(); - } - - render() { - const config = this.props.config; - if (Object.keys(config).length === 0) { - return
; - } - if (config && Object.keys(config).length === 0 && config.constructor === 'Object') { - return ( -
- -
-
- ); - } - - // not every page in the system console will need the config, but the vast majority will - const children = React.cloneElement(this.props.children, { - config - }); - return ( -
- -
- - {children} -
-
- ); - } -} diff --git a/webapp/components/admin_console/admin_navbar_dropdown.jsx b/webapp/components/admin_console/admin_navbar_dropdown.jsx deleted file mode 100644 index 6ef4906f5..000000000 --- a/webapp/components/admin_console/admin_navbar_dropdown.jsx +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import ReactDOM from 'react-dom'; - -import TeamStore from 'stores/team_store.jsx'; -import Constants from 'utils/constants.jsx'; -import AboutBuildModal from 'components/about_build_modal.jsx'; -import {sortTeamsByDisplayName} from 'utils/team_utils.jsx'; -import * as GlobalActions from 'actions/global_actions.jsx'; - -import {FormattedMessage} from 'react-intl'; - -import {Link} from 'react-router/es6'; - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -export default class AdminNavbarDropdown extends React.Component { - constructor(props) { - super(props); - this.blockToggle = false; - this.onTeamChange = this.onTeamChange.bind(this); - this.handleAboutModal = this.handleAboutModal.bind(this); - this.aboutModalDismissed = this.aboutModalDismissed.bind(this); - - this.state = { - teams: TeamStore.getAll(), - teamMembers: TeamStore.getMyTeamMembers(), - showAboutModal: false - }; - } - - componentDidMount() { - $(ReactDOM.findDOMNode(this.refs.dropdown)).on('hide.bs.dropdown', () => { - this.blockToggle = true; - setTimeout(() => { - this.blockToggle = false; - }, 100); - }); - - TeamStore.addChangeListener(this.onTeamChange); - } - - componentWillUnmount() { - $(ReactDOM.findDOMNode(this.refs.dropdown)).off('hide.bs.dropdown'); - TeamStore.removeChangeListener(this.onTeamChange); - } - - handleAboutModal(e) { - e.preventDefault(); - - this.setState({showAboutModal: true}); - } - - aboutModalDismissed() { - this.setState({showAboutModal: false}); - } - - onTeamChange() { - this.setState({ - teams: TeamStore.getAll(), - teamMembers: TeamStore.getMyTeamMembers() - }); - } - - render() { - var teamsArray = []; // Array of team objects - var teams = []; // Array of team components - let switchTeams; - - if (this.state.teamMembers && this.state.teamMembers.length > 0) { - for (const index in this.state.teamMembers) { - if (this.state.teamMembers.hasOwnProperty(index)) { - const teamMember = this.state.teamMembers[index]; - const team = this.state.teams[teamMember.team_id]; - teamsArray.push(team); - } - } - - // Sort teams alphabetically with display_name - teamsArray = teamsArray.sort(sortTeamsByDisplayName); - - for (const team of teamsArray) { - teams.push( -
  • - - - {team.display_name} - -
  • - ); - } - - teams.push( -
  • - ); - } else { - switchTeams = ( -
  • - - - - -
  • - ); - } - - return ( - - ); - } -} diff --git a/webapp/components/admin_console/admin_settings.jsx b/webapp/components/admin_console/admin_settings.jsx deleted file mode 100644 index 2411fbdb8..000000000 --- a/webapp/components/admin_console/admin_settings.jsx +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; - -import FormError from 'components/form_error.jsx'; -import SaveButton from 'components/admin_console/save_button.jsx'; - -import {saveConfig} from 'actions/admin_actions.jsx'; - -export default class AdminSettings extends React.Component { - static propTypes = { - - /* - * Object representing the config file - */ - config: PropTypes.object - } - - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - this.doSubmit = this.doSubmit.bind(this); - - this.state = Object.assign(this.getStateFromConfig(props.config), { - saveNeeded: false, - saving: false, - serverError: null - }); - } - - handleChange(id, value) { - this.setState({ - saveNeeded: true, - [id]: value - }); - } - - handleSubmit(e) { - e.preventDefault(); - - this.doSubmit(); - } - - doSubmit(callback) { - this.setState({ - saving: true, - serverError: null - }); - - // clone config so that we aren't modifying data in the stores - let config = JSON.parse(JSON.stringify(this.props.config)); - config = this.getConfigFromState(config); - - saveConfig( - config, - (savedConfig) => { - this.setState(this.getStateFromConfig(savedConfig)); - - this.setState({ - saveNeeded: false, - saving: false - }); - - if (callback) { - callback(); - } - - if (this.handleSaved) { - this.handleSaved(config); - } - }, - (err) => { - this.setState({ - saving: false, - serverError: err.message - }); - - if (callback) { - callback(); - } - - if (this.handleSaved) { - this.handleSaved(config); - } - } - ); - } - - parseInt(str, defaultValue) { - const n = parseInt(str, 10); - - if (isNaN(n)) { - if (defaultValue) { - return defaultValue; - } - return 0; - } - - return n; - } - - parseIntNonZero(str, defaultValue) { - const n = parseInt(str, 10); - - if (isNaN(n) || n < 1) { - if (defaultValue) { - return defaultValue; - } - return 1; - } - - return n; - } - - render() { - return ( -
    -

    - {this.renderTitle()} -

    -
    - {this.renderSettings()} -
    - -
    -
    -
    - -
    -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/admin_sidebar.jsx b/webapp/components/admin_console/admin_sidebar.jsx deleted file mode 100644 index 4918cdac0..000000000 --- a/webapp/components/admin_console/admin_sidebar.jsx +++ /dev/null @@ -1,702 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; -import {FormattedMessage} from 'react-intl'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSidebarCategory from './admin_sidebar_category.jsx'; -import AdminSidebarHeader from './admin_sidebar_header.jsx'; -import AdminSidebarSection from './admin_sidebar_section.jsx'; - -export default class AdminSidebar extends React.Component { - static get contextTypes() { - return { - router: PropTypes.object.isRequired - }; - } - - constructor(props) { - super(props); - - this.updateTitle = this.updateTitle.bind(this); - } - - componentDidMount() { - this.updateTitle(); - - if (!Utils.isMobile()) { - $('.admin-sidebar .nav-pills__container').perfectScrollbar({ - suppressScrollX: true - }); - } - } - - componentDidUpdate() { - if (!Utils.isMobile()) { - $('.admin-sidebar .nav-pills__container').perfectScrollbar({ - suppressScrollX: true - }); - } - } - - updateTitle() { - let currentSiteName = ''; - if (global.window.mm_config.SiteName != null) { - currentSiteName = global.window.mm_config.SiteName; - } - - document.title = Utils.localizeMessage('sidebar_right_menu.console', 'System Console') + ' - ' + currentSiteName; - } - - render() { - let oauthSettings = null; - let ldapSettings = null; - let samlSettings = null; - let clusterSettings = null; - let metricsSettings = null; - let complianceSettings = null; - let mfaSettings = null; - let pluginSettings = null; - - let license = null; - let audits = null; - let policy = null; - - if (window.mm_config.BuildEnterpriseReady === 'true') { - license = ( - - } - /> - ); - } - - if (window.mm_license.IsLicensed === 'true') { - if (global.window.mm_license.LDAP === 'true') { - ldapSettings = ( - - } - /> - ); - } - - if (global.window.mm_license.Cluster === 'true') { - clusterSettings = ( - - } - /> - ); - } - - if (global.window.mm_license.Metrics === 'true') { - metricsSettings = ( - - } - /> - ); - } - - if (global.window.mm_license.SAML === 'true') { - samlSettings = ( - - } - /> - ); - } - - if (global.window.mm_license.Compliance === 'true') { - complianceSettings = ( - - } - /> - ); - } - - if (global.window.mm_license.MFA === 'true') { - mfaSettings = ( - - } - /> - ); - } - - oauthSettings = ( - - } - /> - ); - - policy = ( - - } - /> - ); - } else { - oauthSettings = ( - - } - /> - ); - } - - if (window.mm_license.IsLicensed === 'true') { - audits = ( - - } - /> - ); - } - - let customBranding = null; - - if (window.mm_license.IsLicensed === 'true') { - customBranding = ( - - } - /> - ); - } - - let otherCategory = null; - if (license || audits) { - otherCategory = ( - - } - > - {license} - {audits} - - ); - } - - const webrtcSettings = ( - - } - /> - ); - - let elasticSearchSettings = null; - if (window.mm_license.IsLicensed === 'true') { - elasticSearchSettings = ( - - } - /> - ); - } - - if (window.mm_config.PluginsEnabled === 'true' && window.mm_license.IsLicensed === 'true') { - pluginSettings = ( - - } - /> - ); - } - - const SHOW_CLIENT_VERSIONS = false; - let clientVersions = null; - if (SHOW_CLIENT_VERSIONS) { - clientVersions = ( - - } - /> - ); - } - - return ( -
    - -
    -
      - - } - > - - } - /> - - } - /> - - } - /> - - } - /> - - - } - > - - } - > - - } - /> - - } - /> - - } - /> - {policy} - - } - /> - {complianceSettings} - - } - /> - - - } - > - - } - /> - {oauthSettings} - {ldapSettings} - {samlSettings} - {mfaSettings} - - - } - > - - } - /> - - } - /> - - } - /> - - } - /> - - } - /> - {clientVersions} - - - } - > - - } - /> - - } - /> - - - } - > - - } - /> - - } - /> - {webrtcSettings} - - } - /> - {pluginSettings} - - - } - > - - } - /> - - - } - > - {customBranding} - - - } - /> - - - } - /> - - } - /> - - - } - /> - - - } - > - - } - /> - - } - /> - {elasticSearchSettings} - - } - /> - {clusterSettings} - {metricsSettings} - - - {otherCategory} -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/admin_sidebar_category.jsx b/webapp/components/admin_console/admin_sidebar_category.jsx deleted file mode 100644 index 5db68e876..000000000 --- a/webapp/components/admin_console/admin_sidebar_category.jsx +++ /dev/null @@ -1,86 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {Link} from 'react-router/es6'; - -export default class AdminSidebarCategory extends React.Component { - static get propTypes() { - return { - name: PropTypes.string, - title: PropTypes.node.isRequired, - icon: PropTypes.string.isRequired, - sectionClass: PropTypes.string, - parentLink: PropTypes.string, - children: PropTypes.node, - action: PropTypes.node - }; - } - - static get defaultProps() { - return { - parentLink: '' - }; - } - - static get contextTypes() { - return { - router: PropTypes.object.isRequired - }; - } - - render() { - let link = this.props.parentLink; - let title = ( -
    - - - {this.props.title} - - {this.props.action} -
    - ); - - if (this.props.name) { - link += '/' + name; - title = ( - - {title} - - ); - } - - let clonedChildren = null; - if (this.props.children && this.context.router.isActive(link)) { - clonedChildren = ( -
      - { - React.Children.map(this.props.children, (child) => { - if (child === null) { - return null; - } - - return React.cloneElement(child, { - parentLink: link - }); - }) - } -
    - ); - } - - return ( -
  • - {title} - {clonedChildren} -
  • - ); - } -} diff --git a/webapp/components/admin_console/admin_sidebar_header.jsx b/webapp/components/admin_console/admin_sidebar_header.jsx deleted file mode 100644 index 1c64eb6d1..000000000 --- a/webapp/components/admin_console/admin_sidebar_header.jsx +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import AdminNavbarDropdown from './admin_navbar_dropdown.jsx'; -import UserStore from 'stores/user_store.jsx'; -import {Client4} from 'mattermost-redux/client'; - -import {FormattedMessage} from 'react-intl'; - -import React from 'react'; - -export default class SidebarHeader extends React.Component { - constructor(props) { - super(props); - - this.state = {}; - } - - toggleDropdown = (e) => { - e.preventDefault(); - - if (this.refs.dropdown.blockToggle) { - this.refs.dropdown.blockToggle = false; - return; - } - - $('.team__header').find('.dropdown-toggle').dropdown('toggle'); - } - - render() { - var me = UserStore.getCurrentUser(); - var profilePicture = null; - - if (!me) { - return null; - } - - if (me.last_picture_update) { - profilePicture = ( - - ); - } - - return ( - - ); - } -} diff --git a/webapp/components/admin_console/admin_sidebar_section.jsx b/webapp/components/admin_console/admin_sidebar_section.jsx deleted file mode 100644 index 2a8ecab71..000000000 --- a/webapp/components/admin_console/admin_sidebar_section.jsx +++ /dev/null @@ -1,102 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {Link} from 'react-router/es6'; -import * as Utils from 'utils/utils.jsx'; - -export default class AdminSidebarSection extends React.Component { - static get propTypes() { - return { - name: PropTypes.string.isRequired, - title: PropTypes.node.isRequired, - type: PropTypes.string, - parentLink: PropTypes.string, - subsection: PropTypes.bool, - children: PropTypes.node, - action: PropTypes.node, - onlyActiveOnIndex: PropTypes.bool - }; - } - - static get defaultProps() { - return { - parentLink: '', - subsection: false, - children: [], - onlyActiveOnIndex: true - }; - } - - getLink() { - return this.props.parentLink + '/' + this.props.name; - } - - render() { - const link = this.getLink(); - - let clonedChildren = null; - if (this.props.children) { - clonedChildren = ( -
      - { - React.Children.map(this.props.children, (child) => { - if (child === null) { - return null; - } - - return React.cloneElement(child, { - parentLink: link, - subsection: true - }); - }) - } -
    - ); - } - - let className = 'sidebar-section'; - if (this.props.subsection) { - className += ' sidebar-subsection'; - } - - let sidebarItem = ( - - - {this.props.title} - - {this.props.action} - - ); - - if (this.props.type === 'text') { - sidebarItem = ( -
    - - {this.props.title} - - {this.props.action} -
    - ); - } - - return ( -
  • - {sidebarItem} - {clonedChildren} -
  • - ); - } -} diff --git a/webapp/components/admin_console/audits/audits.jsx b/webapp/components/admin_console/audits/audits.jsx deleted file mode 100644 index 0811c216f..000000000 --- a/webapp/components/admin_console/audits/audits.jsx +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; -import AuditTable from 'components/audit_table.jsx'; -import ComplianceReports from 'components/admin_console/compliance_reports'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -export default class Audits extends React.PureComponent { - static propTypes = { - - /* - * Array of audits to render - */ - audits: PropTypes.arrayOf(PropTypes.object).isRequired, - - actions: PropTypes.shape({ - - /* - * Function to fetch audits - */ - getAudits: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.state = { - loadingAudits: true - }; - } - - componentDidMount() { - this.props.actions.getAudits().then( - () => this.setState({loadingAudits: false}) - ); - } - - reload = () => { - this.setState({loadingAudits: true}); - this.props.actions.getAudits().then( - () => this.setState({loadingAudits: false}) - ); - } - - render() { - let content = null; - - if (global.window.mm_license.IsLicensed !== 'true') { - return
    ; - } - - if (this.state.loadingAudits) { - content = ; - } else { - content = ( -
    - -
    - ); - } - - return ( -
    - - -
    -

    - - -

    -
    - {content} -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/audits/index.js b/webapp/components/admin_console/audits/index.js deleted file mode 100644 index a48e33538..000000000 --- a/webapp/components/admin_console/audits/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getAudits} from 'mattermost-redux/actions/admin'; - -import * as Selectors from 'mattermost-redux/selectors/entities/admin'; - -import Audits from './audits.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - audits: Object.values(Selectors.getAudits(state)) - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getAudits - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(Audits); diff --git a/webapp/components/admin_console/banner.jsx b/webapp/components/admin_console/banner.jsx deleted file mode 100644 index 6395ef4a1..000000000 --- a/webapp/components/admin_console/banner.jsx +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -export default function Banner(props) { - let title = ( - - ); - - if (props.title) { - title = props.title; - } - - return ( -
    -
    -

    - {title} -

    -

    - {props.description} -

    -
    -
    - ); -} - -Banner.defaultProps = { -}; -Banner.propTypes = { - title: PropTypes.node, - description: PropTypes.node.isRequired -}; diff --git a/webapp/components/admin_console/boolean_setting.jsx b/webapp/components/admin_console/boolean_setting.jsx deleted file mode 100644 index 45c23c869..000000000 --- a/webapp/components/admin_console/boolean_setting.jsx +++ /dev/null @@ -1,99 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Setting from './setting.jsx'; - -import {FormattedMessage} from 'react-intl'; - -import * as Utils from 'utils/utils.jsx'; - -export default class BooleanSetting extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - } - - handleChange(e) { - this.props.onChange(this.props.id, e.target.value === 'true'); - } - - render() { - let helpText; - if (this.props.disabled && this.props.disabledText) { - helpText = ( -
    - - {this.props.disabledText} - - {this.props.helpText} -
    - ); - } else { - helpText = this.props.helpText; - } - - return ( - - - - - ); - } -} -BooleanSetting.defaultProps = { - trueText: ( - - ), - falseText: ( - - ), - disabled: false -}; - -BooleanSetting.propTypes = { - id: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - value: PropTypes.bool.isRequired, - onChange: PropTypes.func.isRequired, - trueText: PropTypes.node, - falseText: PropTypes.node, - disabled: PropTypes.bool.isRequired, - disabledText: PropTypes.node, - helpText: PropTypes.node.isRequired -}; diff --git a/webapp/components/admin_console/brand_image_setting.jsx b/webapp/components/admin_console/brand_image_setting.jsx deleted file mode 100644 index d2eae3f6e..000000000 --- a/webapp/components/admin_console/brand_image_setting.jsx +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; - -import {Client4} from 'mattermost-redux/client'; -import * as Utils from 'utils/utils.jsx'; -import {uploadBrandImage} from 'actions/admin_actions.jsx'; - -import FormError from 'components/form_error.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; - -const HTTP_STATUS_OK = 200; - -export default class BrandImageSetting extends React.PureComponent { - static propTypes = { - - /* - * Set to disable the setting - */ - disabled: PropTypes.bool.isRequired - } - - constructor(props) { - super(props); - - this.handleImageChange = this.handleImageChange.bind(this); - this.handleImageSubmit = this.handleImageSubmit.bind(this); - - this.state = { - brandImage: null, - brandImageExists: false, - brandImageTimestamp: Date.now(), - uploading: false, - uploadCompleted: false, - error: '' - }; - } - - componentWillMount() { - fetch(Client4.getBrandImageUrl(this.state.brandImageTimestamp)).then( - (resp) => { - if (resp.status === HTTP_STATUS_OK) { - this.setState({brandImageExists: true}); - } else { - this.setState({brandImageExists: false}); - } - } - ); - } - - componentDidUpdate() { - if (this.refs.image) { - const reader = new FileReader(); - - const img = this.refs.image; - reader.onload = (e) => { - $(img).attr('src', e.target.result); - }; - - reader.readAsDataURL(this.state.brandImage); - } - } - - handleImageChange() { - const element = $(this.refs.fileInput); - - if (element.prop('files').length > 0) { - this.setState({ - brandImage: element.prop('files')[0] - }); - } - } - - handleImageSubmit(e) { - e.preventDefault(); - - if (!this.state.brandImage) { - return; - } - - if (this.state.uploading) { - return; - } - - $(this.refs.upload).button('loading'); - - this.setState({ - uploading: true, - error: '' - }); - - uploadBrandImage( - this.state.brandImage, - () => { - $(this.refs.upload).button('complete'); - - this.setState({ - brandImageExists: true, - brandImage: null, - brandImageTimestamp: Date.now(), - uploading: false - }); - }, - (err) => { - $(this.refs.upload).button('reset'); - - this.setState({ - uploading: false, - error: err.message - }); - } - ); - } - - render() { - let btnPrimaryClass = 'btn'; - if (this.state.brandImage) { - btnPrimaryClass += ' btn-primary'; - } - - let letbtnDefaultClass = 'btn'; - if (!this.props.disabled) { - letbtnDefaultClass += ' btn-default'; - } - - let img = null; - if (this.state.brandImage) { - img = ( - - ); - } else if (this.state.brandImageExists) { - img = ( - - ); - } else { - img = ( -

    - -

    - ); - } - - return ( -
    - -
    - {img} -
    -
    -
    -
    - - -
    - -
    - -

    - -

    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/client_versions_settings.jsx b/webapp/components/admin_console/client_versions_settings.jsx deleted file mode 100644 index 0c9a5f58a..000000000 --- a/webapp/components/admin_console/client_versions_settings.jsx +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class ClientVersionsSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ClientRequirements.AndroidLatestVersion = this.state.androidLatestVersion; - config.ClientRequirements.AndroidMinVersion = this.state.androidMinVersion; - config.ClientRequirements.DesktopLatestVersion = this.state.desktopLatestVersion; - config.ClientRequirements.DesktopMinVersion = this.state.desktopMinVersion; - config.ClientRequirements.IosLatestVersion = this.state.iosLatestVersion; - config.ClientRequirements.IosMinVersion = this.state.iosMinVersion; - - return config; - } - - getStateFromConfig(config) { - return { - androidLatestVersion: config.ClientRequirements.AndroidLatestVersion, - androidMinVersion: config.ClientRequirements.AndroidMinVersion, - desktopLatestVersion: config.ClientRequirements.DesktopLatestVersion, - desktopMinVersion: config.ClientRequirements.DesktopMinVersion, - iosLatestVersion: config.ClientRequirements.IosLatestVersion, - iosMinVersion: config.ClientRequirements.IosMinVersion - }; - } - - renderTitle() { - return ( -

    - -

    - ); - } - - renderSettings() { - return ( - - - } - placeholder={Utils.localizeMessage('admin.client_versions.androidLatestVersion', 'X.X.X')} - helpText={ - - } - value={this.state.androidLatestVersion} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.client_versions.androidMinVersion', 'X.X.X')} - helpText={ - - } - value={this.state.androidMinVersion} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.client_versions.desktopLatestVersion', 'X.X.X')} - helpText={ - - } - value={this.state.desktopLatestVersion} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.client_versions.desktopMinVersion', 'X.X.X')} - helpText={ - - } - value={this.state.desktopMinVersion} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.client_versions.iosLatestVersion', 'X.X.X')} - helpText={ - - } - value={this.state.iosLatestVersion} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.client_versions.iosMinVersion', 'X.X.X')} - helpText={ - - } - value={this.state.iosMinVersion} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/cluster_settings.jsx b/webapp/components/admin_console/cluster_settings.jsx deleted file mode 100644 index 36f86f0ef..000000000 --- a/webapp/components/admin_console/cluster_settings.jsx +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import TextSetting from './text_setting.jsx'; - -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import ClusterTableContainer from './cluster_table_container.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import {Client4} from 'mattermost-redux/client'; - -export default class ClusterSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - this.renderSettings = this.renderSettings.bind(this); - this.overrideHandleChange = this.overrideHandleChange.bind(this); - } - - getConfigFromState(config) { - config.ClusterSettings.Enable = this.state.Enable; - config.ClusterSettings.ClusterName = this.state.ClusterName; - config.ClusterSettings.OverrideHostname = this.state.OverrideHostname; - config.ClusterSettings.UseIpAddress = this.state.UseIpAddress; - config.ClusterSettings.UseExperimentalGossip = this.state.UseExperimentalGossip; - config.ClusterSettings.ReadOnlyConfig = this.state.ReadOnlyConfig; - config.ClusterSettings.GossipPort = this.parseIntNonZero(this.state.GossipPort, 8074); - config.ClusterSettings.StreamingPort = this.parseIntNonZero(this.state.StreamingPort, 8075); - return config; - } - - getStateFromConfig(config) { - const settings = config.ClusterSettings; - - return { - Enable: settings.Enable, - ClusterName: settings.ClusterName, - OverrideHostname: settings.OverrideHostname, - UseIpAddress: settings.UseIpAddress, - UseExperimentalGossip: settings.UseExperimentalGossip, - ReadOnlyConfig: settings.ReadOnlyConfig, - GossipPort: settings.GossipPort, - StreamingPort: settings.StreamingPort, - showWarning: false - }; - } - - renderTitle() { - return ( - - ); - } - - overrideHandleChange(id, value) { - this.setState({ - showWarning: true - }); - - this.handleChange(id, value); - } - - renderSettings() { - const licenseEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.Cluster === 'true'; - if (!licenseEnabled) { - return null; - } - - var configLoadedFromCluster = null; - - if (Client4.clusterId) { - configLoadedFromCluster = ( -
    - - -
    - ); - } - - var warning = null; - if (this.state.showWarning) { - warning = ( -
    - - -
    - ); - } - - var clusterTableContainer = null; - if (this.state.Enable) { - clusterTableContainer = (); - } - - return ( - - {configLoadedFromCluster} - {clusterTableContainer} -
    - -
    - {warning} - - } - helpText={ - - } - value={this.state.Enable} - onChange={this.overrideHandleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.cluster.ClusterNameEx', 'Ex "Production" or "Staging"')} - helpText={ - - } - value={this.state.ClusterName} - onChange={this.overrideHandleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.cluster.OverrideHostnameEx', 'Ex "app-server-01"')} - helpText={ - - } - value={this.state.OverrideHostname} - onChange={this.overrideHandleChange} - /> - - } - helpText={ - - } - value={this.state.UseIpAddress} - onChange={this.overrideHandleChange} - /> - - } - helpText={ - - } - value={this.state.UseExperimentalGossip} - onChange={this.overrideHandleChange} - /> - - } - helpText={ - - } - value={this.state.ReadOnlyConfig} - onChange={this.overrideHandleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.cluster.GossipPortEx', 'Ex "8074"')} - helpText={ - - } - value={this.state.GossipPort} - onChange={this.overrideHandleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.cluster.StreamingPortEx', 'Ex "8075"')} - helpText={ - - } - value={this.state.StreamingPort} - onChange={this.overrideHandleChange} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/cluster_table.jsx b/webapp/components/admin_console/cluster_table.jsx deleted file mode 100644 index e7157635d..000000000 --- a/webapp/components/admin_console/cluster_table.jsx +++ /dev/null @@ -1,172 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {FormattedMessage} from 'react-intl'; -import * as Utils from 'utils/utils.jsx'; - -import statusGreen from 'images/status_green.png'; -import statusYellow from 'images/status_yellow.png'; - -export default class ClusterTable extends React.Component { - static propTypes = { - clusterInfos: PropTypes.array.isRequired, - reload: PropTypes.func.isRequired - } - - render() { - var versionMismatch = ( - - ); - - var configMismatch = ( - - ); - - var version = ''; - var configHash = ''; - var singleItem = false; - - if (this.props.clusterInfos.length) { - version = this.props.clusterInfos[0].version; - configHash = this.props.clusterInfos[0].config_hash; - singleItem = this.props.clusterInfos.length === 1; - } - - this.props.clusterInfos.map((clusterInfo) => { - if (clusterInfo.version !== version) { - versionMismatch = ( - - ); - } - - if (clusterInfo.config_hash !== configHash) { - configMismatch = ( - - ); - } - - return null; - }); - - var items = this.props.clusterInfos.map((clusterInfo) => { - var status = null; - - if (clusterInfo.hostname === '') { - clusterInfo.hostname = Utils.localizeMessage('admin.cluster.unknown', 'unknown'); - } - - if (clusterInfo.version === '') { - clusterInfo.version = Utils.localizeMessage('admin.cluster.unknown', 'unknown'); - } - - if (clusterInfo.config_hash === '') { - clusterInfo.config_hash = Utils.localizeMessage('admin.cluster.unknown', 'unknown'); - } - - if (singleItem) { - status = ( - - ); - } else { - status = ( - - ); - } - - return ( - - {status} - {clusterInfo.hostname} - {versionMismatch} {clusterInfo.version} -
    {configMismatch} {clusterInfo.config_hash}
    - {clusterInfo.ipaddress} - - ); - }); - - return ( -
    -
    - -
    - - - - - - - - - - - - {items} - -
    - - - - - - - - - -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/cluster_table_container.jsx b/webapp/components/admin_console/cluster_table_container.jsx deleted file mode 100644 index 7a67bb842..000000000 --- a/webapp/components/admin_console/cluster_table_container.jsx +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import ClusterTable from './cluster_table.jsx'; -import LoadingScreen from '../loading_screen.jsx'; - -import {getClusterStatus} from 'actions/admin_actions.jsx'; - -export default class ClusterTableContainer extends React.Component { - constructor(props) { - super(props); - - this.load = this.load.bind(this); - this.reload = this.reload.bind(this); - - this.interval = null; - - this.state = { - clusterInfos: null - }; - } - - load() { - getClusterStatus( - (data) => { - this.setState({ - clusterInfos: data - }); - }, - null - ); - } - - componentWillMount() { - this.load(); - - // reload the cluster status every 15 seconds - this.interval = setInterval(this.load, 15000); - } - - componentWillUnmount() { - if (this.interval) { - clearInterval(this.interval); - } - } - - reload(e) { - if (e) { - e.preventDefault(); - } - - this.setState({ - clusterInfos: null - }); - - this.load(); - } - - render() { - if (this.state.clusterInfos == null) { - return (); - } - - return ( - - ); - } -} diff --git a/webapp/components/admin_console/color_setting.jsx b/webapp/components/admin_console/color_setting.jsx deleted file mode 100644 index 483b585ee..000000000 --- a/webapp/components/admin_console/color_setting.jsx +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import Setting from './setting.jsx'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import {ChromePicker} from 'react-color'; - -export default class ColorSetting extends React.PureComponent { - static propTypes = { - - /* - * The unique identifer for the admin console setting - */ - id: PropTypes.string.isRequired, - - /* - * The text/jsx display name for the setting - */ - label: PropTypes.node.isRequired, - - /* - * The text/jsx help text to display underneath the setting - */ - helpText: PropTypes.node, - - /* - * The hex color value - */ - value: PropTypes.string.isRequired, - - /* - * Function called when the input changes - */ - onChange: PropTypes.func, - - /* - * Set to disable the setting - */ - disabled: PropTypes.bool - } - - constructor(props) { - super(props); - - this.state = { - showPicker: false - }; - } - - componentDidMount() { - document.addEventListener('click', this.closePicker); - } - - componentWillUnmount() { - document.removeEventListener('click', this.closePicker); - } - - handleChange = (color) => { - this.props.onChange(this.props.id, color.hex); - } - - togglePicker = () => { - if (this.props.disabled) { - this.setState({showPicker: false}); - } - this.setState({showPicker: !this.state.showPicker}); - } - - closePicker = (e) => { - if (!e.target.closest('.picker-' + this.props.id)) { - this.setState({showPicker: false}); - } - } - - onTextInput = (e) => { - this.props.onChange(this.props.id, e.target.value); - } - - render() { - let picker; - if (this.state.showPicker) { - picker = ( -
    - -
    - ); - } - - return ( - -
    - - - - - {picker} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/compliance_reports/compliance_reports.jsx b/webapp/components/admin_console/compliance_reports/compliance_reports.jsx deleted file mode 100644 index af361bace..000000000 --- a/webapp/components/admin_console/compliance_reports/compliance_reports.jsx +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; - -import * as Utils from 'utils/utils.jsx'; -import UserStore from 'stores/user_store.jsx'; -import {Client4} from 'mattermost-redux/client'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage, FormattedDate, FormattedTime} from 'react-intl'; - -export default class ComplianceReports extends React.PureComponent { - static propTypes = { - - /* - * Set if compliance reports are enabled in the config - */ - enabled: PropTypes.bool.isRequired, - - /* - * Array of reports to render - */ - reports: PropTypes.arrayOf(PropTypes.object).isRequired, - - /* - * Error message to display - */ - serverError: PropTypes.string, - - actions: PropTypes.shape({ - - /* - * Function to get compliance reports - */ - getComplianceReports: PropTypes.func.isRequired, - - /* - * Function to save compliance reports - */ - createComplianceReport: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.state = { - loadingReports: true - }; - } - - componentDidMount() { - if (global.window.mm_license.IsLicensed !== 'true' || !this.props.enabled) { - return; - } - - this.props.actions.getComplianceReports().then( - () => this.setState({loadingReports: false}) - ); - } - - reload = () => { - this.setState({loadingReports: true}); - - this.props.actions.getComplianceReports().then( - () => this.setState({loadingReports: false}) - ); - } - - runReport = (e) => { - e.preventDefault(); - - this.setState({runningReport: true}); - - const job = {}; - job.desc = this.refs.desc.value; - job.emails = this.refs.emails.value; - job.keywords = this.refs.keywords.value; - job.start_at = Date.parse(this.refs.from.value); - job.end_at = Date.parse(this.refs.to.value); - - this.props.actions.createComplianceReport(job).then( - (data) => { - if (data) { - this.refs.emails.value = ''; - this.refs.keywords.value = ''; - this.refs.desc.value = ''; - this.refs.from.value = ''; - this.refs.to.value = ''; - } - this.setState({runningReport: false}); - } - ); - } - - getDateTime(millis) { - const date = new Date(millis); - return ( - - - {' - '} - - - ); - } - - render() { - if (global.window.mm_license.IsLicensed !== 'true' || !this.props.enabled) { - return
    ; - } - - let content = null; - if (this.state.loadingReports) { - content = ; - } else { - var list = []; - - for (var i = 0; i < this.props.reports.length; i++) { - const report = this.props.reports[i]; - - let params = ''; - if (report.type === 'adhoc') { - params = ( - - {' '}{this.getDateTime(report.start_at)} -
    - {' '}{this.getDateTime(report.end_at)} -
    - {' '}{report.emails} -
    - {' '}{report.keywords} -
    ); - } - - let download = ''; - if (report.status === 'finished') { - download = ( - - - - ); - } - - let status = report.status; - if (report.status === 'finished') { - status = ( - {report.status} - ); - } - - if (report.status === 'failed') { - status = ( - {report.status} - ); - } - - let user = report.user_id; - const profile = UserStore.getProfile(report.user_id); - if (profile) { - user = profile.email; - } - - list[i] = ( - - {download} - {this.getDateTime(report.create_at)} - {status} - {report.count} - {report.type} - {report.desc} - {user} - {params} - - ); - } - - content = ( -
    - - - - - - - - - - - - - - {list} - -
    - - - - - - - - - - - - - - -
    -
    - ); - } - - let serverError = ''; - if (this.props.serverError) { - serverError = ( -
    - -
    - ); - } - - return ( -
    -

    - -

    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    -
    - - -
    -
    - - -
    -
    -
    - -
    - {serverError} -
    - -
    -
    - {content} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/compliance_reports/index.js b/webapp/components/admin_console/compliance_reports/index.js deleted file mode 100644 index 1cbf669e5..000000000 --- a/webapp/components/admin_console/compliance_reports/index.js +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getComplianceReports, createComplianceReport} from 'mattermost-redux/actions/admin'; - -import {getComplianceReports as selectComplianceReports, getConfig} from 'mattermost-redux/selectors/entities/admin'; - -import ComplianceReports from './compliance_reports.jsx'; - -function mapStateToProps(state, ownProps) { - let enabled = false; - const config = getConfig(state); - if (config && config.ComplianceSettings) { - enabled = config.ComplianceSettings.Enable; - } - - let serverError; - const error = state.requests.admin.createCompliance.error; - if (error) { - serverError = error.message; - } - - const reports = Object.values(selectComplianceReports(state)).sort((a, b) => { - return b.create_at - a.create_at; - }); - - return { - ...ownProps, - enabled, - reports, - serverError - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getComplianceReports, - createComplianceReport - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(ComplianceReports); diff --git a/webapp/components/admin_console/compliance_settings.jsx b/webapp/components/admin_console/compliance_settings.jsx deleted file mode 100644 index 5521c6e39..000000000 --- a/webapp/components/admin_console/compliance_settings.jsx +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class ComplianceSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ComplianceSettings.Enable = this.state.enable; - config.ComplianceSettings.Directory = this.state.directory; - config.ComplianceSettings.EnableDaily = this.state.enableDaily; - - return config; - } - - getStateFromConfig(config) { - return { - enable: config.ComplianceSettings.Enable, - directory: config.ComplianceSettings.Directory, - enableDaily: config.ComplianceSettings.EnableDaily - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const licenseEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.Compliance === 'true'; - - let bannerContent; - if (!licenseEnabled) { - bannerContent = ( -
    -
    - -
    -
    - ); - } - - return ( - - {bannerContent} - - } - helpText={ - - } - value={this.state.enable} - onChange={this.handleChange} - disabled={!licenseEnabled} - /> - - } - placeholder={Utils.localizeMessage('admin.sql.maxOpenExample', 'Ex "10"')} - helpText={ - - } - value={this.state.directory} - onChange={this.handleChange} - disabled={!licenseEnabled || !this.state.enable} - /> - - } - helpText={ - - } - value={this.state.enableDaily} - onChange={this.handleChange} - disabled={!licenseEnabled || !this.state.enable} - /> - - ); - } -} diff --git a/webapp/components/admin_console/configuration_settings.jsx b/webapp/components/admin_console/configuration_settings.jsx deleted file mode 100644 index 6ac68a3bb..000000000 --- a/webapp/components/admin_console/configuration_settings.jsx +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -import ErrorStore from 'stores/error_store.jsx'; - -import {ErrorBarTypes} from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import {invalidateAllCaches, reloadConfig} from 'actions/admin_actions.jsx'; -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {ConnectionSecurityDropdownSettingWebserver} from './connection_security_dropdown_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; -import RequestButton from './request_button/request_button'; -import TextSetting from './text_setting.jsx'; -import WebserverModeDropdownSetting from './webserver_mode_dropdown_setting.jsx'; - -export default class ConfigurationSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.handleSaved = this.handleSaved.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - componentWillReceiveProps(nextProps) { - // special case for this page since we don't update AdminSettings components when the - // stored config changes, but we want this page to update when you reload the config - this.setState(this.getStateFromConfig(nextProps.config)); - } - - getConfigFromState(config) { - config.ServiceSettings.SiteURL = this.state.siteURL; - config.ServiceSettings.ListenAddress = this.state.listenAddress; - config.ServiceSettings.WebserverMode = this.state.webserverMode; - config.ServiceSettings.ConnectionSecurity = this.state.connectionSecurity; - config.ServiceSettings.TLSCertFile = this.state.TLSCertFile; - config.ServiceSettings.TLSKeyFile = this.state.TLSKeyFile; - config.ServiceSettings.UseLetsEncrypt = this.state.useLetsEncrypt; - config.ServiceSettings.LetsEncryptCertificateCacheFile = this.state.letsEncryptCertificateCacheFile; - config.ServiceSettings.Forward80To443 = this.state.forward80To443; - config.ServiceSettings.ReadTimeout = this.parseIntNonZero(this.state.readTimeout); - config.ServiceSettings.WriteTimeout = this.parseIntNonZero(this.state.writeTimeout); - config.ServiceSettings.EnableAPIv3 = this.state.enableAPIv3; - - return config; - } - - getStateFromConfig(config) { - return { - siteURL: config.ServiceSettings.SiteURL, - listenAddress: config.ServiceSettings.ListenAddress, - webserverMode: config.ServiceSettings.WebserverMode, - connectionSecurity: config.ServiceSettings.ConnectionSecurity, - TLSCertFile: config.ServiceSettings.TLSCertFile, - TLSKeyFile: config.ServiceSettings.TLSKeyFile, - useLetsEncrypt: config.ServiceSettings.UseLetsEncrypt, - letsEncryptCertificateCacheFile: config.ServiceSettings.LetsEncryptCertificateCacheFile, - forward80To443: config.ServiceSettings.Forward80To443, - readTimeout: config.ServiceSettings.ReadTimeout, - writeTimeout: config.ServiceSettings.WriteTimeout, - enableAPIv3: config.ServiceSettings.EnableAPIv3 - }; - } - - handleSaved(newConfig) { - if (newConfig.ServiceSettings.SiteURL) { - ErrorStore.clearError(ErrorBarTypes.SITE_URL); - } - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const reloadConfigurationHelpText = ( - - - - ), - recycleDatabaseConnections: ( - - - - - - ) - }} - /> - ); - - let reloadConfigButton =
    ; - if (global.window.mm_license.IsLicensed === 'true') { - reloadConfigButton = ( - - } - showSuccessMessage={false} - errorMessage={{ - id: 'admin.reload.reloadFail', - defaultMessage: 'Reload unsuccessful: {error}' - }} - /> - ); - } - - return ( - -
    -
    - -
    -
    - - } - placeholder={Utils.localizeMessage('admin.service.siteURLExample', 'Ex "https://mattermost.example.com:1234"')} - helpText={ - - } - value={this.state.siteURL} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.service.listenExample', 'Ex ":8065"')} - helpText={ - - } - value={this.state.listenAddress} - onChange={this.handleChange} - /> - - - } - helpText={ - - } - disabled={this.state.useLetsEncrypt} - value={this.state.TLSCertFile} - onChange={this.handleChange} - /> - - } - helpText={ - - } - disabled={this.state.useLetsEncrypt} - value={this.state.TLSKeyFile} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.useLetsEncrypt} - onChange={this.handleChange} - /> - - } - helpText={ - - } - disabled={!this.state.useLetsEncrypt} - value={this.state.letsEncryptCertificateCacheFile} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.forward80To443} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.readTimeout} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.writeTimeout} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableAPIv3} - onChange={this.handleChange} - /> - - {reloadConfigButton} - - } - buttonText={ - - } - showSuccessMessage={false} - includeDetailedError={true} - errorMessage={{ - id: 'admin.purge.purgeFail', - defaultMessage: 'Purging unsuccessful: {error}' - }} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/connection_security_dropdown_setting.jsx b/webapp/components/admin_console/connection_security_dropdown_setting.jsx deleted file mode 100644 index b7b283be1..000000000 --- a/webapp/components/admin_console/connection_security_dropdown_setting.jsx +++ /dev/null @@ -1,191 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import * as Utils from 'utils/utils.jsx'; - -import DropdownSetting from './dropdown_setting.jsx'; -import {FormattedMessage} from 'react-intl'; - -const SECTION_NONE = ( - - - - - - - - -); - -const SECTION_TLS = ( - - - - - - - - -); - -const SECTION_STARTTLS = ( - - - - - - - - -); - -const CONNECTION_SECURITY_HELP_TEXT_EMAIL = ( - - - {SECTION_NONE} - {SECTION_TLS} - {SECTION_STARTTLS} - -
    -); - -const CONNECTION_SECURITY_HELP_TEXT_LDAP = ( - - - {SECTION_NONE} - {SECTION_TLS} - {SECTION_STARTTLS} - -
    -); - -const CONNECTION_SECURITY_HELP_TEXT_WEBSERVER = ( - - - {SECTION_NONE} - {SECTION_TLS} - -
    -); - -export function ConnectionSecurityDropdownSettingEmail(props) { - return ( - - } - value={props.value} - onChange={props.onChange} - disabled={props.disabled} - helpText={CONNECTION_SECURITY_HELP_TEXT_EMAIL} - /> - ); -} -ConnectionSecurityDropdownSettingEmail.defaultProps = { -}; - -ConnectionSecurityDropdownSettingEmail.propTypes = { - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool.isRequired -}; - -export function ConnectionSecurityDropdownSettingLdap(props) { - return ( - - } - value={props.value} - onChange={props.onChange} - disabled={props.disabled} - helpText={CONNECTION_SECURITY_HELP_TEXT_LDAP} - /> - ); -} -ConnectionSecurityDropdownSettingLdap.defaultProps = { -}; - -ConnectionSecurityDropdownSettingLdap.propTypes = { - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool.isRequired -}; - -export function ConnectionSecurityDropdownSettingWebserver(props) { - return ( - - } - value={props.value} - onChange={props.onChange} - disabled={props.disabled} - helpText={CONNECTION_SECURITY_HELP_TEXT_WEBSERVER} - /> - ); -} -ConnectionSecurityDropdownSettingWebserver.defaultProps = { -}; - -ConnectionSecurityDropdownSettingWebserver.propTypes = { - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool.isRequired -}; diff --git a/webapp/components/admin_console/connection_settings.jsx b/webapp/components/admin_console/connection_settings.jsx deleted file mode 100644 index 78a0b89ed..000000000 --- a/webapp/components/admin_console/connection_settings.jsx +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class ConnectionSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.AllowCorsFrom = this.state.allowCorsFrom; - config.ServiceSettings.EnableInsecureOutgoingConnections = this.state.enableInsecureOutgoingConnections; - - return config; - } - - getStateFromConfig(config) { - return { - allowCorsFrom: config.ServiceSettings.AllowCorsFrom, - enableInsecureOutgoingConnections: config.ServiceSettings.EnableInsecureOutgoingConnections - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - placeholder={Utils.localizeMessage('admin.service.corsEx', 'http://example.com')} - helpText={ - - } - value={this.state.allowCorsFrom} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableInsecureOutgoingConnections} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/custom_brand_settings.jsx b/webapp/components/admin_console/custom_brand_settings.jsx deleted file mode 100644 index 4ca3dee0c..000000000 --- a/webapp/components/admin_console/custom_brand_settings.jsx +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import BrandImageSetting from './brand_image_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; -import Constants from 'utils/constants.jsx'; - -export default class CustomBrandSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.TeamSettings.SiteName = this.state.siteName; - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.CustomBrand === 'true') { - config.TeamSettings.customDescriptionText = this.state.customDescriptionText; - config.TeamSettings.EnableCustomBrand = this.state.enableCustomBrand; - config.TeamSettings.CustomBrandText = this.state.customBrandText; - } - - return config; - } - - getStateFromConfig(config) { - return { - siteName: config.TeamSettings.SiteName, - enableCustomBrand: config.TeamSettings.EnableCustomBrand, - customBrandText: config.TeamSettings.CustomBrandText, - customDescriptionText: config.TeamSettings.CustomDescriptionText - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const enterpriseSettings = []; - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.CustomBrand === 'true') { - enterpriseSettings.push( - - } - helpText={ - - } - value={this.state.customDescriptionText} - placeholder={Utils.localizeMessage('web.root.signup_info', 'All team communication in one place, searchable and accessible anywhere')} - onChange={this.handleChange} - /> - ); - - enterpriseSettings.push( - - } - helpText={ - - } - value={this.state.enableCustomBrand} - onChange={this.handleChange} - /> - ); - - enterpriseSettings.push( - - ); - - enterpriseSettings.push( - - } - helpText={ - - } - value={this.state.customBrandText} - onChange={this.handleChange} - disabled={!this.state.enableCustomBrand} - /> - ); - } - - return ( - - - } - maxLength={Constants.MAX_SITENAME_LENGTH} - placeholder={Utils.localizeMessage('admin.team.siteNameExample', 'Ex "Mattermost"')} - helpText={ - - } - value={this.state.siteName} - onChange={this.handleChange} - /> - {enterpriseSettings} - - ); - } -} diff --git a/webapp/components/admin_console/custom_emoji_settings.jsx b/webapp/components/admin_console/custom_emoji_settings.jsx deleted file mode 100644 index 329900888..000000000 --- a/webapp/components/admin_console/custom_emoji_settings.jsx +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -export default class CustomEmojiSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.EnableCustomEmoji = this.state.enableCustomEmoji; - config.ServiceSettings.EnableEmojiPicker = this.state.enableEmojiPicker; - - if (global.window.mm_license.IsLicensed === 'true') { - config.ServiceSettings.RestrictCustomEmojiCreation = this.state.restrictCustomEmojiCreation; - } - - return config; - } - - getStateFromConfig(config) { - return { - enableCustomEmoji: config.ServiceSettings.EnableCustomEmoji, - enableEmojiPicker: config.ServiceSettings.EnableEmojiPicker, - restrictCustomEmojiCreation: config.ServiceSettings.RestrictCustomEmojiCreation - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - let restrictSetting = null; - if (global.window.mm_license.IsLicensed === 'true') { - restrictSetting = ( - - } - helpText={ - - } - value={this.state.restrictCustomEmojiCreation} - onChange={this.handleChange} - disabled={!this.state.enableCustomEmoji} - /> - ); - } - - return ( - - - } - helpText={ - - } - value={this.state.enableEmojiPicker} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableCustomEmoji} - onChange={this.handleChange} - /> - {restrictSetting} - - ); - } -} diff --git a/webapp/components/admin_console/custom_integrations_settings.jsx b/webapp/components/admin_console/custom_integrations_settings.jsx deleted file mode 100644 index e6bcb4b32..000000000 --- a/webapp/components/admin_console/custom_integrations_settings.jsx +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -export default class WebhookSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.EnableIncomingWebhooks = this.state.enableIncomingWebhooks; - config.ServiceSettings.EnableOutgoingWebhooks = this.state.enableOutgoingWebhooks; - config.ServiceSettings.EnableCommands = this.state.enableCommands; - config.ServiceSettings.EnableOnlyAdminIntegrations = this.state.enableOnlyAdminIntegrations; - config.ServiceSettings.EnablePostUsernameOverride = this.state.enablePostUsernameOverride; - config.ServiceSettings.EnablePostIconOverride = this.state.enablePostIconOverride; - config.ServiceSettings.EnableOAuthServiceProvider = this.state.enableOAuthServiceProvider; - config.ServiceSettings.EnableUserAccessTokens = this.state.enableUserAccessTokens; - - return config; - } - - getStateFromConfig(config) { - return { - enableIncomingWebhooks: config.ServiceSettings.EnableIncomingWebhooks, - enableOutgoingWebhooks: config.ServiceSettings.EnableOutgoingWebhooks, - enableCommands: config.ServiceSettings.EnableCommands, - enableOnlyAdminIntegrations: config.ServiceSettings.EnableOnlyAdminIntegrations, - enablePostUsernameOverride: config.ServiceSettings.EnablePostUsernameOverride, - enablePostIconOverride: config.ServiceSettings.EnablePostIconOverride, - enableOAuthServiceProvider: config.ServiceSettings.EnableOAuthServiceProvider, - enableUserAccessTokens: config.ServiceSettings.EnableUserAccessTokens - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.enableIncomingWebhooks} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableOutgoingWebhooks} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableCommands} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableOAuthServiceProvider} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableOnlyAdminIntegrations} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enablePostUsernameOverride} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enablePostIconOverride} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableUserAccessTokens} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/database_settings.jsx b/webapp/components/admin_console/database_settings.jsx deleted file mode 100644 index 9f008483c..000000000 --- a/webapp/components/admin_console/database_settings.jsx +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {recycleDatabaseConnection} from 'actions/admin_actions.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import GeneratedSetting from './generated_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; -import RequestButton from './request_button/request_button.jsx'; - -export default class DatabaseSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - // driverName and dataSource are read-only from the UI - - config.SqlSettings.MaxIdleConns = this.parseIntNonZero(this.state.maxIdleConns); - config.SqlSettings.MaxOpenConns = this.parseIntNonZero(this.state.maxOpenConns); - config.SqlSettings.AtRestEncryptKey = this.state.atRestEncryptKey; - config.SqlSettings.Trace = this.state.trace; - config.SqlSettings.QueryTimeout = this.parseIntNonZero(this.state.queryTimeout); - - return config; - } - - getStateFromConfig(config) { - return { - driverName: config.SqlSettings.DriverName, - dataSource: config.SqlSettings.DataSource, - maxIdleConns: config.SqlSettings.MaxIdleConns, - maxOpenConns: config.SqlSettings.MaxOpenConns, - atRestEncryptKey: config.SqlSettings.AtRestEncryptKey, - trace: config.SqlSettings.Trace, - queryTimeout: config.SqlSettings.QueryTimeout - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const dataSource = '**********' + this.state.dataSource.substring(this.state.dataSource.indexOf('@')); - - let recycleDbButton =
    ; - if (global.window.mm_license.IsLicensed === 'true') { - recycleDbButton = ( - - - - ), - reloadConfiguration: ( - - - - - - ) - }} - /> - } - buttonText={ - - } - showSuccessMessage={false} - errorMessage={{ - id: 'admin.recycle.reloadFail', - defaultMessage: 'Recycling unsuccessful: {error}' - }} - includeDetailedError={true} - /> - ); - } - - return ( - -
    - -
    -
    - -
    -

    {this.state.driverName}

    -
    -
    -
    - -
    -

    {dataSource}

    -
    -
    - - } - placeholder={Utils.localizeMessage('admin.sql.maxConnectionsExample', 'Ex "10"')} - helpText={ - - } - value={this.state.maxIdleConns} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.sql.maxOpenExample', 'Ex "10"')} - helpText={ - - } - value={this.state.maxOpenConns} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.sql.queryTimeoutExample', 'Ex "30"')} - helpText={ - - } - value={this.state.queryTimeout} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.sql.keyExample', 'Ex "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6"')} - helpText={ - - } - value={this.state.atRestEncryptKey} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.trace} - onChange={this.handleChange} - /> - {recycleDbButton} -
    - ); - } -} diff --git a/webapp/components/admin_console/developer_settings.jsx b/webapp/components/admin_console/developer_settings.jsx deleted file mode 100644 index 6a8f49dbd..000000000 --- a/webapp/components/admin_console/developer_settings.jsx +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class DeveloperSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.EnableTesting = this.state.enableTesting; - config.ServiceSettings.EnableDeveloper = this.state.enableDeveloper; - config.ServiceSettings.AllowedUntrustedInternalConnections = this.state.allowedUntrustedInternalConnections; - - return config; - } - - getStateFromConfig(config) { - return { - enableTesting: config.ServiceSettings.EnableTesting, - enableDeveloper: config.ServiceSettings.EnableDeveloper, - allowedUntrustedInternalConnections: config.ServiceSettings.AllowedUntrustedInternalConnections - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.enableTesting} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableDeveloper} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.service.internalConnectionsEx', 'webhooks.internal.example.com 127.0.0.1 10.0.16.0/28')} - helpText={ - - } - value={this.state.allowedUntrustedInternalConnections} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/dropdown_setting.jsx b/webapp/components/admin_console/dropdown_setting.jsx deleted file mode 100644 index 05179a4b9..000000000 --- a/webapp/components/admin_console/dropdown_setting.jsx +++ /dev/null @@ -1,66 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Setting from './setting.jsx'; - -export default class DropdownSetting extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - } - - handleChange(e) { - this.props.onChange(this.props.id, e.target.value); - } - - render() { - const options = []; - for (const {value, text} of this.props.values) { - options.push( - - ); - } - - return ( - - - - ); - } -} - -DropdownSetting.defaultProps = { - isDisabled: false -}; - -DropdownSetting.propTypes = { - id: PropTypes.string.isRequired, - values: PropTypes.array.isRequired, - label: PropTypes.node.isRequired, - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool, - helpText: PropTypes.node -}; diff --git a/webapp/components/admin_console/elasticsearch_settings.jsx b/webapp/components/admin_console/elasticsearch_settings.jsx deleted file mode 100644 index b739241ef..000000000 --- a/webapp/components/admin_console/elasticsearch_settings.jsx +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import {elasticsearchTest, elasticsearchPurgeIndexes} from 'actions/admin_actions.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; -import RequestButton from './request_button/request_button.jsx'; -import ElasticsearchStatus from './elasticsearch_status'; - -export default class ElasticsearchSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.doTestConfig = this.doTestConfig.bind(this); - this.handleChange = this.handleChange.bind(this); - this.handleSaved = this.handleSaved.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ElasticsearchSettings.ConnectionUrl = this.state.connectionUrl; - config.ElasticsearchSettings.Username = this.state.username; - config.ElasticsearchSettings.Password = this.state.password; - config.ElasticsearchSettings.Sniff = this.state.sniff; - config.ElasticsearchSettings.EnableIndexing = this.state.enableIndexing; - config.ElasticsearchSettings.EnableSearching = this.state.enableSearching; - - return config; - } - - getStateFromConfig(config) { - return { - connectionUrl: config.ElasticsearchSettings.ConnectionUrl, - username: config.ElasticsearchSettings.Username, - password: config.ElasticsearchSettings.Password, - sniff: config.ElasticsearchSettings.Sniff, - enableIndexing: config.ElasticsearchSettings.EnableIndexing, - enableSearching: config.ElasticsearchSettings.EnableSearching, - configTested: true, - canSave: true, - canPurgeAndIndex: config.ElasticsearchSettings.EnableIndexing - }; - } - - handleChange(id, value) { - if (id === 'enableIndexing') { - if (value === false) { - this.setState({ - enableSearching: false - }); - } else { - this.setState({ - canSave: false, - configTested: false - }); - } - } - - if (id === 'connectionUrl' || id === 'username' || id === 'password' || id === 'sniff') { - this.setState({ - configTested: false, - canSave: false - }); - } - - if (id !== 'enableSearching') { - this.setState({ - canPurgeAndIndex: false - }); - } - - super.handleChange(id, value); - } - - handleSaved() { - this.setState({ - canPurgeAndIndex: this.state.enableIndexing - }); - } - - canSave() { - return this.state.canSave; - } - - doTestConfig(success, error) { - const config = JSON.parse(JSON.stringify(this.props.config)); - this.getConfigFromState(config); - - elasticsearchTest( - config, - () => { - this.setState({ - configTested: true, - canSave: true - }); - success(); - this.doSubmit(); - }, - (err) => { - this.setState({ - configTested: false, - canSave: false - }); - error(err); - } - ); - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - -
    -
    - -
    -
    - - } - helpText={ - - - - ) - }} - /> - } - value={this.state.enableIndexing} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.elasticsearch.connectionUrlExample', 'E.g.: "https://elasticsearch.example.org:9200"')} - helpText={ - - - - ) - }} - /> - } - value={this.state.connectionUrl} - disabled={!this.state.enableIndexing} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.elasticsearch.usernameExample', 'E.g.: "elastic"')} - helpText={ - - } - value={this.state.username} - disabled={!this.state.enableIndexing} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.elasticsearch.password', 'E.g.: "yourpassword"')} - helpText={ - - } - value={this.state.password} - disabled={!this.state.enableIndexing} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.sniff} - disabled={!this.state.enableIndexing} - onChange={this.handleChange} - /> - - } - buttonText={ - - } - successMessage={{ - id: 'admin.elasticsearch.testConfigSuccess', - defaultMessage: 'Test successful. Configuration saved.' - }} - disabled={!this.state.enableIndexing} - /> - - - } - buttonText={ - - } - successMessage={{ - id: 'admin.elasticsearch.purgeIndexesButton.success', - defaultMessage: 'Indexes purged successfully.' - }} - errorMessage={{ - id: 'admin.elasticsearch.purgeIndexesButton.error', - defaultMessage: 'Failed to purge indexes: {error}' - }} - disabled={!this.state.canPurgeAndIndex} - label={( - - )} - /> - - } - helpText={ - - } - value={this.state.enableSearching} - disabled={!this.state.enableIndexing || !this.state.configTested} - onChange={this.handleChange} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/elasticsearch_status/index.js b/webapp/components/admin_console/elasticsearch_status/index.js deleted file mode 100644 index 6446195d2..000000000 --- a/webapp/components/admin_console/elasticsearch_status/index.js +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getJobsByType} from 'mattermost-redux/actions/jobs'; -import {JobTypes} from 'utils/constants.jsx'; - -import * as Selectors from 'mattermost-redux/selectors/entities/jobs'; - -import Status from './status.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - jobs: Selectors.makeGetJobsByType(JobTypes.ELASTICSEARCH_POST_INDEXING)(state) - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getJobsByType - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(Status); diff --git a/webapp/components/admin_console/elasticsearch_status/status.jsx b/webapp/components/admin_console/elasticsearch_status/status.jsx deleted file mode 100644 index 0a32d39c8..000000000 --- a/webapp/components/admin_console/elasticsearch_status/status.jsx +++ /dev/null @@ -1,361 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -import {createJob, cancelJob} from 'actions/job_actions.jsx'; -import {JobTypes, JobStatuses} from 'utils/constants.jsx'; -import RequestButton from '../request_button/request_button.jsx'; - -export default class Status extends React.PureComponent { - static propTypes = { - - /** - * Array of jobs - */ - jobs: PropTypes.arrayOf(PropTypes.object).isRequired, - - /** - * Whether Elasticsearch is properly configured. - */ - isConfigured: PropTypes.bool.isRequired, - - actions: PropTypes.shape({ - - /** - * Function to fetch jobs - */ - getJobsByType: PropTypes.func.isRequired - }).isRequired - }; - - constructor(props) { - super(props); - - this.interval = null; - - this.state = { - loading: true, - cancelInProgress: false - }; - } - - componentWillMount() { - // reload the cluster status every 15 seconds - this.interval = setInterval(this.reload, 15000); - } - - componentDidMount() { - this.props.actions.getJobsByType(JobTypes.ELASTICSEARCH_POST_INDEXING).then( - () => this.setState({loading: false}) - ); - } - - componentWillUnmount() { - if (this.interval) { - clearInterval(this.interval); - } - } - - reload = () => { - this.props.actions.getJobsByType(JobTypes.ELASTICSEARCH_POST_INDEXING).then( - () => { - this.setState({ - loading: false, - cancelInProgress: false - }); - } - ); - }; - - createIndexJob = (success, error) => { - const job = { - type: JobTypes.ELASTICSEARCH_POST_INDEXING - }; - - createJob( - job, - () => { - this.reload(); - success(); - }, - error - ); - }; - - cancelIndexJob = (e) => { - e.preventDefault(); - - const chosenJob = this.getChosenJob(); - if (!chosenJob) { - return; - } - - this.setState({ - cancelInProgress: true - }); - - cancelJob( - chosenJob.id, - () => { - this.reload(); - }, - () => { - this.reload(); - } - ); - }; - - getChosenJob = () => { - let chosenJob = null; - - if (this.props.jobs.length > 0) { - for (let i = 0; i < this.props.jobs.length; i++) { - const job = this.props.jobs[i]; - if (job.status === JobStatuses.CANCEL_REQUESTED || job.status === JobStatuses.IN_PROGRESS) { - chosenJob = job; - } else { - break; - } - } - - if (!chosenJob) { - for (let i = 0; i < this.props.jobs.length; i++) { - const job = this.props.jobs[i]; - if (job.status !== JobStatuses.PENDING && chosenJob) { - continue; - } else { - chosenJob = job; - break; - } - } - } - } - - return chosenJob; - }; - - render() { - const chosenJob = this.getChosenJob(); - - let indexButtonDisabled = !this.props.isConfigured; - let buttonText = ( - - ); - let cancelButton = null; - let indexButtonHelp = ( - - ); - - if (this.state.loading) { - indexButtonDisabled = true; - } else if (chosenJob) { - if (chosenJob.status === JobStatuses.PENDING || chosenJob.status === JobStatuses.IN_PROGRESS || chosenJob.status === JobStatuses.CANCEL_REQUESTED) { - indexButtonDisabled = true; - buttonText = ( - - - - - ); - } - - if (chosenJob.status === JobStatuses.PENDING || chosenJob.status === JobStatuses.IN_PROGRESS || chosenJob.status === JobStatuses.CANCEL_REQUESTED) { - indexButtonHelp = ( - - ); - } - - if (!this.state.cancelInProgress && (chosenJob.status === JobStatuses.PENDING || chosenJob.status === JobStatuses.IN_PROGRESS)) { - cancelButton = ( - - - - ); - } - } - - const indexButton = ( - - )} - /> - ); - - let status = null; - let statusHelp = null; - let statusClass = null; - if (!this.props.isConfigured) { - status = ( - - ); - } else if (this.state.loading) { - status = ( - - ); - statusClass = 'status-icon-unknown'; - } else if (chosenJob) { - if (chosenJob.status === JobStatuses.PENDING) { - status = ( - - ); - statusHelp = ( - - ); - statusClass = 'status-icon-warning'; - } else if (chosenJob.status === JobStatuses.IN_PROGRESS) { - status = ( - - ); - statusHelp = ( - - ); - statusClass = 'status-icon-warning'; - } else if (chosenJob.status === JobStatuses.SUCCESS) { - status = ( - - ); - statusHelp = ( - - ); - statusClass = 'status-icon-success'; - } else if (chosenJob.status === JobStatuses.ERROR) { - status = ( - - ); - statusHelp = ( - - ); - statusClass = 'status-icon-error'; - } else if (chosenJob.status === JobStatuses.CANCEL_REQUESTED) { - status = ( - - ); - statusClass = 'status-icon-warning'; - } else if (chosenJob.status === JobStatuses.CANCELED) { - status = ( - - ); - statusClass = 'status-icon-error'; - } - } else { - status = ( - - ); - statusClass = 'status-icon-unknown'; - } - - if (statusHelp !== null) { - statusHelp = ( -
    -
    - {statusHelp} -
    -
    - ); - } - - statusClass = 'fa fa-circle margin--right ' + statusClass; - - return ( -
    - {indexButton} -
    -
    -
    - - - {status} -
    -
    - {statusHelp} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/email_authentication_settings.jsx b/webapp/components/admin_console/email_authentication_settings.jsx deleted file mode 100644 index 9cc3ab3d7..000000000 --- a/webapp/components/admin_console/email_authentication_settings.jsx +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -export default class EmailAuthenticationSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.EmailSettings.EnableSignUpWithEmail = this.state.enableSignUpWithEmail; - config.EmailSettings.EnableSignInWithEmail = this.state.enableSignInWithEmail; - config.EmailSettings.EnableSignInWithUsername = this.state.enableSignInWithUsername; - - return config; - } - - getStateFromConfig(config) { - return { - enableSignUpWithEmail: config.EmailSettings.EnableSignUpWithEmail, - enableSignInWithEmail: config.EmailSettings.EnableSignInWithEmail, - enableSignInWithUsername: config.EmailSettings.EnableSignInWithUsername - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.enableSignUpWithEmail} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableSignInWithEmail} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableSignInWithUsername} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/email_connection_test.jsx b/webapp/components/admin_console/email_connection_test.jsx deleted file mode 100644 index 17edbf23e..000000000 --- a/webapp/components/admin_console/email_connection_test.jsx +++ /dev/null @@ -1,130 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import {FormattedMessage} from 'react-intl'; - -import {testEmail} from 'actions/admin_actions.jsx'; - -export default class EmailConnectionTestButton extends React.Component { - static get propTypes() { - return { - config: PropTypes.object.isRequired, - getConfigFromState: PropTypes.func.isRequired, - disabled: PropTypes.bool.isRequired - }; - } - - constructor(props) { - super(props); - - this.handleTestConnection = this.handleTestConnection.bind(this); - - this.state = { - testing: false, - success: false, - fail: null - }; - } - - handleTestConnection(e) { - e.preventDefault(); - - this.setState({ - testing: true, - success: false, - fail: null - }); - - const config = JSON.parse(JSON.stringify(this.props.config)); - this.props.getConfigFromState(config); - - testEmail( - config, - () => { - this.setState({ - testing: false, - success: true - }); - }, - (err) => { - let fail = err.message; - if (err.detailed_error) { - fail += ' - ' + err.detailed_error; - } - - this.setState({ - testing: false, - fail - }); - } - ); - } - - render() { - let testMessage = null; - if (this.state.success) { - testMessage = ( -
    - - -
    - ); - } else if (this.state.fail) { - testMessage = ( -
    - - -
    - ); - } - - let contents = null; - if (this.state.testing) { - contents = ( - - - {Utils.localizeMessage('admin.email.testing', 'Testing...')} - - ); - } else { - contents = ( - - ); - } - - return ( -
    -
    -
    - - {testMessage} -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/email_settings.jsx b/webapp/components/admin_console/email_settings.jsx deleted file mode 100644 index e630402bc..000000000 --- a/webapp/components/admin_console/email_settings.jsx +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import ErrorStore from 'stores/error_store.jsx'; - -import {ErrorBarTypes} from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {ConnectionSecurityDropdownSettingEmail} from './connection_security_dropdown_setting.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import EmailConnectionTest from './email_connection_test.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -const EMAIL_NOTIFICATION_CONTENTS_FULL = 'full'; -const EMAIL_NOTIFICATION_CONTENTS_GENERIC = 'generic'; - -export default class EmailSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - this.handleSaved = this.handleSaved.bind(this); - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.EmailSettings.SendEmailNotifications = this.state.sendEmailNotifications; - config.EmailSettings.FeedbackName = this.state.feedbackName; - config.EmailSettings.FeedbackEmail = this.state.feedbackEmail; - config.EmailSettings.FeedbackOrganization = this.state.feedbackOrganization; - config.EmailSettings.EnableSMTPAuth = this.state.enableSMTPAuth; - config.EmailSettings.SMTPUsername = this.state.smtpUsername; - config.EmailSettings.SMTPPassword = this.state.smtpPassword; - config.EmailSettings.SMTPServer = this.state.smtpServer; - config.EmailSettings.SMTPPort = this.state.smtpPort; - config.EmailSettings.ConnectionSecurity = this.state.connectionSecurity; - config.EmailSettings.EnableEmailBatching = this.state.enableEmailBatching; - config.ServiceSettings.EnableSecurityFixAlert = this.state.enableSecurityFixAlert; - config.EmailSettings.SkipServerCertificateVerification = this.state.skipServerCertificateVerification; - config.EmailSettings.EmailNotificationContentsType = this.state.emailNotificationContentsType; - - return config; - } - - handleSaved(newConfig) { - if (newConfig.EmailSettings.SendEmailNotifications) { - ErrorStore.clearError(ErrorBarTypes.PREVIEW_MODE); - } - } - - getStateFromConfig(config) { - return { - sendEmailNotifications: config.EmailSettings.SendEmailNotifications, - feedbackName: config.EmailSettings.FeedbackName, - feedbackEmail: config.EmailSettings.FeedbackEmail, - feedbackOrganization: config.EmailSettings.FeedbackOrganization, - enableSMTPAuth: config.EmailSettings.EnableSMTPAuth, - smtpUsername: config.EmailSettings.SMTPUsername, - smtpPassword: config.EmailSettings.SMTPPassword, - smtpServer: config.EmailSettings.SMTPServer, - smtpPort: config.EmailSettings.SMTPPort, - connectionSecurity: config.EmailSettings.ConnectionSecurity, - enableEmailBatching: config.EmailSettings.EnableEmailBatching, - skipServerCertificateVerification: config.EmailSettings.SkipServerCertificateVerification, - enableSecurityFixAlert: config.ServiceSettings.EnableSecurityFixAlert, - emailNotificationContentsType: config.EmailSettings.EmailNotificationContentsType - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - let enableEmailBatchingDisabledText = null; - - if (this.props.config.ClusterSettings.Enable) { - enableEmailBatchingDisabledText = ( - - - - ); - } else if (!this.props.config.ServiceSettings.SiteURL) { - enableEmailBatchingDisabledText = ( - - - - ); - } - - let emailNotificationContentsTypeDropdown = null; - let emailNotificationContentsHelpText = null; - if (window.mm_license.EmailNotificationContents === 'true') { - const emailNotificationContentsTypes = []; - emailNotificationContentsTypes.push({value: EMAIL_NOTIFICATION_CONTENTS_FULL, text: Utils.localizeMessage('admin.email.notification.contents.full', 'Send full message contents')}); - emailNotificationContentsTypes.push({value: EMAIL_NOTIFICATION_CONTENTS_GENERIC, text: Utils.localizeMessage('admin.email.notification.contents.generic', 'Send generic description with only sender name')}); - - if (this.state.emailNotificationContentsType === EMAIL_NOTIFICATION_CONTENTS_FULL) { - emailNotificationContentsHelpText = ( - - ); - } else if (this.state.emailNotificationContentsType === EMAIL_NOTIFICATION_CONTENTS_GENERIC) { - emailNotificationContentsHelpText = ( - - ); - } - - emailNotificationContentsTypeDropdown = ( - - } - value={this.state.emailNotificationContentsType} - onChange={this.handleChange} - helpText={emailNotificationContentsHelpText} - /> - ); - } - - return ( - - - } - helpText={ - - } - value={this.state.sendEmailNotifications} - onChange={this.handleChange} - /> - - } - helpText={[ - , - enableEmailBatchingDisabledText - ]} - value={this.state.enableEmailBatching && !this.props.config.ClusterSettings.Enable && Boolean(this.props.config.ServiceSettings.SiteURL)} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications || this.props.config.ClusterSettings.Enable || !this.props.config.ServiceSettings.SiteURL} - /> - {emailNotificationContentsTypeDropdown} - - } - placeholder={Utils.localizeMessage('admin.email.notificationDisplayExample', 'Ex: "Mattermost Notification", "System", "No-Reply"')} - helpText={ - - } - value={this.state.feedbackName} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - placeholder={Utils.localizeMessage('admin.email.notificationEmailExample', 'Ex: "mattermost@yourcompany.com", "admin@yourcompany.com"')} - helpText={ - - } - value={this.state.feedbackEmail} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - placeholder={Utils.localizeMessage('admin.email.notificationOrganizationExample', 'Ex: "© ABC Corporation, 565 Knight Way, Palo Alto, California, 94305, USA"')} - helpText={ - - } - value={this.state.feedbackOrganization} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - placeholder={Utils.localizeMessage('admin.email.smtpServerExample', 'Ex: "smtp.yourcompany.com", "email-smtp.us-east-1.amazonaws.com"')} - helpText={ - - } - value={this.state.smtpServer} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - placeholder={Utils.localizeMessage('admin.email.smtpPortExample', 'Ex: "25", "465", "587"')} - helpText={ - - } - value={this.state.smtpPort} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - helpText={[ - - ]} - value={this.state.enableSMTPAuth} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications} - /> - - } - placeholder={Utils.localizeMessage('admin.email.smtpUsernameExample', 'Ex: "admin@yourcompany.com", "AKIADTOVBGERKLCBV"')} - helpText={ - - } - value={this.state.smtpUsername} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications || !this.state.enableSMTPAuth} - /> - - } - placeholder={Utils.localizeMessage('admin.email.smtpPasswordExample', 'Ex: "yourpassword", "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.smtpPassword} - onChange={this.handleChange} - disabled={!this.state.sendEmailNotifications || !this.state.enableSMTPAuth} - /> - - - - } - helpText={ - - } - value={this.state.skipServerCertificateVerification} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableSecurityFixAlert} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/external_service_settings.jsx b/webapp/components/admin_console/external_service_settings.jsx deleted file mode 100644 index 6359470a8..000000000 --- a/webapp/components/admin_console/external_service_settings.jsx +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class ExternalServiceSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.GoogleDeveloperKey = this.state.googleDeveloperKey; - return config; - } - - getStateFromConfig(config) { - return { - googleDeveloperKey: config.ServiceSettings.GoogleDeveloperKey - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - placeholder={Utils.localizeMessage('admin.service.googleExample', 'Ex "7rAh6iwQCkV4cA1Gsg3fgGOXJAQ43QV"')} - helpText={ - - } - value={this.state.googleDeveloperKey} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/file_upload_setting.jsx b/webapp/components/admin_console/file_upload_setting.jsx deleted file mode 100644 index c2bc9869e..000000000 --- a/webapp/components/admin_console/file_upload_setting.jsx +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; -import {FormattedMessage} from 'react-intl'; - -import Setting from './setting.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -export default class FileUploadSetting extends Setting { - static get propTypes() { - return { - id: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - helpText: PropTypes.node, - uploadingText: PropTypes.node, - onSubmit: PropTypes.func.isRequired, - disabled: PropTypes.bool, - fileType: PropTypes.string.isRequired, - error: PropTypes.string - }; - } - - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - - this.state = { - fileName: null, - serverError: props.error - }; - } - - handleChange() { - const files = this.refs.fileInput.files; - if (files && files.length > 0) { - this.setState({fileSelected: true, fileName: files[0].name}); - } - } - - handleSubmit(e) { - e.preventDefault(); - - $(this.refs.upload_button).button('loading'); - this.props.onSubmit(this.props.id, this.refs.fileInput.files[0], (error) => { - $(this.refs.upload_button).button('reset'); - if (error) { - Utils.clearFileInput(this.refs.fileInput); - } - }); - } - - render() { - let serverError; - if (this.state.serverError) { - serverError =
    ; - } - - let btnClass = 'btn'; - if (this.state.fileSelected) { - btnClass = 'btn btn-primary'; - } - - let fileName; - if (this.state.fileName) { - fileName = this.state.fileName; - } else { - fileName = ( - - ); - } - - return ( - -
    -
    - - -
    - -
    - {fileName} -
    - {serverError} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/generated_setting.jsx b/webapp/components/admin_console/generated_setting.jsx deleted file mode 100644 index 2fed2f42f..000000000 --- a/webapp/components/admin_console/generated_setting.jsx +++ /dev/null @@ -1,106 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import crypto from 'crypto'; - -import {FormattedMessage} from 'react-intl'; - -export default class GeneratedSetting extends React.Component { - static get propTypes() { - return { - id: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - placeholder: PropTypes.string, - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool.isRequired, - disabledText: PropTypes.node, - helpText: PropTypes.node.isRequired, - regenerateText: PropTypes.node, - regenerateHelpText: PropTypes.node - }; - } - - static get defaultProps() { - return { - disabled: false, - regenerateText: ( - - ) - }; - } - - constructor(props) { - super(props); - - this.regenerate = this.regenerate.bind(this); - } - - regenerate(e) { - e.preventDefault(); - - this.props.onChange(this.props.id, crypto.randomBytes(256).toString('base64').substring(0, 32)); - } - - render() { - let disabledText = null; - if (this.props.disabled && this.props.disabledText) { - disabledText = ( -
    - {this.props.disabledText} -
    - ); - } - - let regenerateHelpText = null; - if (this.props.regenerateHelpText) { - regenerateHelpText = ( -
    - {this.props.regenerateHelpText} -
    - ); - } - - return ( -
    - -
    - - {disabledText} -
    - {this.props.helpText} -
    -
    - -
    - {regenerateHelpText} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/gitlab_settings.jsx b/webapp/components/admin_console/gitlab_settings.jsx deleted file mode 100644 index d08597b7d..000000000 --- a/webapp/components/admin_console/gitlab_settings.jsx +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class GitLabSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.GitLabSettings.Enable = this.state.enable; - config.GitLabSettings.Id = this.state.id; - config.GitLabSettings.Secret = this.state.secret; - config.GitLabSettings.UserApiEndpoint = this.state.userApiEndpoint; - config.GitLabSettings.AuthEndpoint = this.state.authEndpoint; - config.GitLabSettings.TokenEndpoint = this.state.tokenEndpoint; - - return config; - } - - getStateFromConfig(config) { - return { - enable: config.GitLabSettings.Enable, - id: config.GitLabSettings.Id, - secret: config.GitLabSettings.Secret, - userApiEndpoint: config.GitLabSettings.UserApiEndpoint, - authEndpoint: config.GitLabSettings.AuthEndpoint, - tokenEndpoint: config.GitLabSettings.TokenEndpoint - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ -
    - -
    - -
    - } - value={this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.clientIdExample', 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.id} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.clientSecretExample', 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.secret} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.userExample', 'Ex "https:///api/v3/user"')} - helpText={ - - } - value={this.state.userApiEndpoint} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.authExample', 'Ex "https:///oauth/authorize"')} - helpText={ - - } - value={this.state.authEndpoint} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.tokenExample', 'Ex "https:///oauth/token"')} - helpText={ - - } - value={this.state.tokenEndpoint} - onChange={this.handleChange} - disabled={!this.state.enable} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/index.js b/webapp/components/admin_console/index.js deleted file mode 100644 index 4b333e65c..000000000 --- a/webapp/components/admin_console/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getConfig} from 'mattermost-redux/actions/admin'; - -import * as Selectors from 'mattermost-redux/selectors/entities/admin'; - -import AdminConsole from './admin_console.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - config: Selectors.getConfig(state) - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getConfig - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(AdminConsole); diff --git a/webapp/components/admin_console/ldap_settings.jsx b/webapp/components/admin_console/ldap_settings.jsx deleted file mode 100644 index 9ffbe3b0e..000000000 --- a/webapp/components/admin_console/ldap_settings.jsx +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {ConnectionSecurityDropdownSettingLdap} from './connection_security_dropdown_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -import {ldapSyncNow, ldapTest} from 'actions/admin_actions.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import React from 'react'; -import {FormattedMessage} from 'react-intl'; -import RequestButton from './request_button/request_button.jsx'; - -export default class LdapSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.LdapSettings.Enable = this.state.enable; - config.LdapSettings.LdapServer = this.state.ldapServer; - config.LdapSettings.LdapPort = this.parseIntNonZero(this.state.ldapPort); - config.LdapSettings.ConnectionSecurity = this.state.connectionSecurity; - config.LdapSettings.BaseDN = this.state.baseDN; - config.LdapSettings.BindUsername = this.state.bindUsername; - config.LdapSettings.BindPassword = this.state.bindPassword; - config.LdapSettings.UserFilter = this.state.userFilter; - config.LdapSettings.FirstNameAttribute = this.state.firstNameAttribute; - config.LdapSettings.LastNameAttribute = this.state.lastNameAttribute; - config.LdapSettings.NicknameAttribute = this.state.nicknameAttribute; - config.LdapSettings.EmailAttribute = this.state.emailAttribute; - config.LdapSettings.UsernameAttribute = this.state.usernameAttribute; - config.LdapSettings.PositionAttribute = this.state.positionAttribute; - config.LdapSettings.IdAttribute = this.state.idAttribute; - config.LdapSettings.SyncIntervalMinutes = this.parseIntNonZero(this.state.syncIntervalMinutes); - config.LdapSettings.SkipCertificateVerification = this.state.skipCertificateVerification; - config.LdapSettings.QueryTimeout = this.parseIntNonZero(this.state.queryTimeout); - config.LdapSettings.MaxPageSize = this.parseInt(this.state.maxPageSize); - config.LdapSettings.LoginFieldName = this.state.loginFieldName; - - return config; - } - - getStateFromConfig(config) { - return { - enable: config.LdapSettings.Enable, - ldapServer: config.LdapSettings.LdapServer, - ldapPort: config.LdapSettings.LdapPort, - connectionSecurity: config.LdapSettings.ConnectionSecurity, - baseDN: config.LdapSettings.BaseDN, - bindUsername: config.LdapSettings.BindUsername, - bindPassword: config.LdapSettings.BindPassword, - userFilter: config.LdapSettings.UserFilter, - firstNameAttribute: config.LdapSettings.FirstNameAttribute, - lastNameAttribute: config.LdapSettings.LastNameAttribute, - nicknameAttribute: config.LdapSettings.NicknameAttribute, - emailAttribute: config.LdapSettings.EmailAttribute, - usernameAttribute: config.LdapSettings.UsernameAttribute, - positionAttribute: config.LdapSettings.PositionAttribute, - idAttribute: config.LdapSettings.IdAttribute, - syncIntervalMinutes: config.LdapSettings.SyncIntervalMinutes, - skipCertificateVerification: config.LdapSettings.SkipCertificateVerification, - queryTimeout: config.LdapSettings.QueryTimeout, - maxPageSize: config.LdapSettings.MaxPageSize, - loginFieldName: config.LdapSettings.LoginFieldName - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const licenseEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.LDAP === 'true'; - if (!licenseEnabled) { - return null; - } - - return ( - - - } - helpText={ - - } - value={this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.serverEx', 'Ex "10.0.0.23"')} - helpText={ - - } - value={this.state.ldapServer} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.portEx', 'Ex "389"')} - helpText={ - - } - value={this.state.ldapPort} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - - } - helpText={ - - } - value={this.state.skipCertificateVerification} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.baseEx', 'Ex "ou=Unit Name,dc=corp,dc=example,dc=com"')} - helpText={ - - } - value={this.state.baseDN} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - helpText={ - - } - value={this.state.bindUsername} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - helpText={ - - } - value={this.state.bindPassword} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.userFilterEx', 'Ex. "(objectClass=user)"')} - helpText={ - - } - value={this.state.userFilter} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.firstnameAttrEx', 'Ex "givenName"')} - helpText={ - - } - value={this.state.firstNameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.lastnameAttrEx', 'Ex "sn"')} - helpText={ - - } - value={this.state.lastNameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.nicknameAttrEx', 'Ex "nickname"')} - helpText={ - - } - value={this.state.nicknameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.positionAttrEx', 'E.g.: "title"')} - helpText={ - - } - value={this.state.positionAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.emailAttrEx', 'Ex "mail" or "userPrincipalName"')} - helpText={ - - } - value={this.state.emailAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.usernameAttrEx', 'Ex "sAMAccountName"')} - helpText={ - - } - value={this.state.usernameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.idAttrEx', 'Ex "sAMAccountName"')} - helpText={ - - } - value={this.state.idAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.loginNameEx', 'Ex "AD/LDAP Username"')} - helpText={ - - } - value={this.state.loginFieldName} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - helpText={ - - } - value={this.state.syncIntervalMinutes} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.maxPageSizeEx', 'Ex "2000"')} - helpText={ - - } - value={this.state.maxPageSize} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.ldap.queryEx', 'Ex "60"')} - helpText={ - - } - value={this.state.queryTimeout} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - buttonText={ - - } - disabled={!this.state.enable} - showSuccessMessage={false} - errorMessage={{ - id: 'admin.ldap.syncFailure', - defaultMessage: 'Sync Failure: {error}' - }} - includeDetailedError={true} - /> - - } - buttonText={ - - } - disabled={!this.state.enable} - saveNeeded={this.state.saveNeeded} - saveConfigAction={this.doSubmit} - errorMessage={{ - id: 'admin.ldap.testFailure', - defaultMessage: 'AD/LDAP Test Failure: {error}' - }} - successMessage={{ - id: 'admin.ldap.testSuccess', - defaultMessage: 'AD/LDAP Test Successful' - }} - /> - - ); - } -} diff --git a/webapp/components/admin_console/legal_and_support_settings.jsx b/webapp/components/admin_console/legal_and_support_settings.jsx deleted file mode 100644 index 6b64e0c07..000000000 --- a/webapp/components/admin_console/legal_and_support_settings.jsx +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class LegalAndSupportSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.SupportSettings.TermsOfServiceLink = this.state.termsOfServiceLink; - config.SupportSettings.PrivacyPolicyLink = this.state.privacyPolicyLink; - config.SupportSettings.AboutLink = this.state.aboutLink; - config.SupportSettings.HelpLink = this.state.helpLink; - config.SupportSettings.ReportAProblemLink = this.state.reportAProblemLink; - config.SupportSettings.SupportEmail = this.state.supportEmail; - - return config; - } - - getStateFromConfig(config) { - return { - termsOfServiceLink: config.SupportSettings.TermsOfServiceLink, - privacyPolicyLink: config.SupportSettings.PrivacyPolicyLink, - aboutLink: config.SupportSettings.AboutLink, - helpLink: config.SupportSettings.HelpLink, - reportAProblemLink: config.SupportSettings.ReportAProblemLink, - supportEmail: config.SupportSettings.SupportEmail - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.termsOfServiceLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.privacyPolicyLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.aboutLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.helpLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.reportAProblemLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.supportEmail} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/license_settings.jsx b/webapp/components/admin_console/license_settings.jsx deleted file mode 100644 index f04a0c351..000000000 --- a/webapp/components/admin_console/license_settings.jsx +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import ReactDOM from 'react-dom'; -import * as Utils from 'utils/utils.jsx'; - -import ErrorStore from 'stores/error_store.jsx'; -import {uploadLicenseFile, removeLicenseFile} from 'actions/admin_actions.jsx'; - -import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -const holders = defineMessages({ - removing: { - id: 'admin.license.removing', - defaultMessage: 'Removing License...' - }, - uploading: { - id: 'admin.license.uploading', - defaultMessage: 'Uploading License...' - } -}); - -import PropTypes from 'prop-types'; - -import React from 'react'; - -class LicenseSettings extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - this.handleRemove = this.handleRemove.bind(this); - - this.state = { - fileSelected: false, - fileName: null, - serverError: null - }; - } - - handleChange() { - const element = $(ReactDOM.findDOMNode(this.refs.fileInput)); - if (element.prop('files').length > 0) { - this.setState({fileSelected: true, fileName: element.prop('files')[0].name}); - } - } - - handleSubmit(e) { - e.preventDefault(); - - const element = $(ReactDOM.findDOMNode(this.refs.fileInput)); - if (element.prop('files').length === 0) { - return; - } - const file = element.prop('files')[0]; - - $('#upload-button').button('loading'); - - uploadLicenseFile( - file, - () => { - Utils.clearFileInput(element[0]); - $('#upload-button').button('reset'); - this.setState({fileSelected: false, fileName: null, serverError: null}); - window.location.reload(true); - }, - (error) => { - Utils.clearFileInput(element[0]); - $('#upload-button').button('reset'); - this.setState({fileSelected: false, fileName: null, serverError: error.message}); - } - ); - } - - handleRemove(e) { - e.preventDefault(); - - $('#remove-button').button('loading'); - - removeLicenseFile( - () => { - $('#remove-button').button('reset'); - this.setState({fileSelected: false, fileName: null, serverError: null}); - ErrorStore.clearLastError(true); - window.location.reload(true); - }, - (error) => { - $('#remove-button').button('reset'); - this.setState({fileSelected: false, fileName: null, serverError: error.message}); - } - ); - } - - render() { - var serverError = ''; - if (this.state.serverError) { - serverError =
    ; - } - - var btnClass = 'btn'; - if (this.state.fileSelected) { - btnClass = 'btn btn-primary'; - } - - let edition; - let licenseType; - let licenseKey; - - const issued = Utils.displayDate(parseInt(global.window.mm_license.IssuedAt, 10)) + ' ' + Utils.displayTime(parseInt(global.window.mm_license.IssuedAt, 10), true); - const startsAt = Utils.displayDate(parseInt(global.window.mm_license.StartsAt, 10)); - const expiresAt = Utils.displayDate(parseInt(global.window.mm_license.ExpiresAt, 10)); - - if (global.window.mm_license.IsLicensed === 'true') { - // Note: DO NOT LOCALISE THESE STRINGS. Legally we can not since the license is in English. - edition = 'Mattermost Enterprise Edition. Enterprise features on this server have been unlocked with a license key and a valid subscription.'; - licenseType = ( -
    -

    - {'This software is offered under a commercial license.\n\nSee ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.\n\nYour subscription details are as follows:'} -

    - {`Name: ${global.window.mm_license.Name}`}
    - {`Company or organization name: ${global.window.mm_license.Company}`}
    - {`Number of users: ${global.window.mm_license.Users}`}
    - {`License issued: ${issued}`}
    - {`Start date of license: ${startsAt}`}
    - {`Expiry date of license: ${expiresAt}`}
    -
    - {'See also '}{'Enterprise Edition Terms of Service'}{' and '}{'Privacy Policy.'} -
    - ); - - licenseKey = ( -
    - -
    -
    -

    - {'If you migrate servers you may need to remove your license key to install it elsewhere. You can remove the key here, which will revert functionality to that of Team Edition.'} -

    -
    - ); - } else { - // Note: DO NOT LOCALISE THESE STRINGS. Legally we can not since the license is in English. - edition = ( -

    - {'Mattermost Enterprise Edition. Unlock enterprise features in this software through the purchase of a subscription from '} - - {'https://mattermost.com/'} - -

    - ); - - licenseType = 'This software is offered under a commercial license.\n\nSee ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.'; - - let fileName; - if (this.state.fileName) { - fileName = this.state.fileName; - } else { - fileName = ( - - ); - } - - licenseKey = ( -
    -
    - - -
    - -
    - {fileName} -
    -
    - {serverError} -

    - -

    -
    - ); - } - - return ( -
    -

    - -

    -
    -
    - -
    - {edition} -
    -
    -
    - -
    - {licenseType} -
    -
    -
    - - {licenseKey} -
    -
    -
    - ); - } -} - -LicenseSettings.propTypes = { - intl: intlShape.isRequired, - config: PropTypes.object -}; - -export default injectIntl(LicenseSettings); diff --git a/webapp/components/admin_console/link_previews_settings.jsx b/webapp/components/admin_console/link_previews_settings.jsx deleted file mode 100644 index b120d75d2..000000000 --- a/webapp/components/admin_console/link_previews_settings.jsx +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -export default class LinkPreviewsSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.EnableLinkPreviews = this.state.enableLinkPreviews; - - return config; - } - - getStateFromConfig(config) { - return { - enableLinkPreviews: config.ServiceSettings.EnableLinkPreviews - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.enableLinkPreviews} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/localization_settings.jsx b/webapp/components/admin_console/localization_settings.jsx deleted file mode 100644 index 78b63b163..000000000 --- a/webapp/components/admin_console/localization_settings.jsx +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as I18n from 'i18n/i18n.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import MultiSelectSetting from './multiselect_settings.jsx'; - -export default class LocalizationSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - this.canSave = this.canSave.bind(this); - - const locales = I18n.getAllLanguages(); - - this.state = Object.assign(this.state, { - hasErrors: false, - languages: Object.keys(locales).map((l) => { - return {value: locales[l].value, text: locales[l].name, order: locales[l].order}; - }).sort((a, b) => a.order - b.order) - }); - } - - canSave() { - return this.state.availableLocales.join(',').indexOf(this.state.defaultClientLocale) !== -1 || this.state.availableLocales.length === 0; - } - - getConfigFromState(config) { - config.LocalizationSettings.DefaultServerLocale = this.state.defaultServerLocale; - config.LocalizationSettings.DefaultClientLocale = this.state.defaultClientLocale; - config.LocalizationSettings.AvailableLocales = this.state.availableLocales.join(','); - - return config; - } - - getStateFromConfig(config) { - return { - defaultServerLocale: config.LocalizationSettings.DefaultServerLocale, - defaultClientLocale: config.LocalizationSettings.DefaultClientLocale, - availableLocales: config.LocalizationSettings.AvailableLocales ? config.LocalizationSettings.AvailableLocales.split(',') : [] - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - value={this.state.defaultServerLocale} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.defaultClientLocale} - onChange={this.handleChange} - helpText={ - - } - /> - - } - selected={this.state.availableLocales} - onChange={this.handleChange} - helpText={ - - } - noResultText={ - - } - notPresent={ - - } - /> - - ); - } -} diff --git a/webapp/components/admin_console/log_settings.jsx b/webapp/components/admin_console/log_settings.jsx deleted file mode 100644 index 8e1e4891e..000000000 --- a/webapp/components/admin_console/log_settings.jsx +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class LogSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.LogSettings.EnableConsole = this.state.enableConsole; - config.LogSettings.ConsoleLevel = this.state.consoleLevel; - config.LogSettings.EnableFile = this.state.enableFile; - config.LogSettings.FileLevel = this.state.fileLevel; - config.LogSettings.FileLocation = this.state.fileLocation; - config.LogSettings.FileFormat = this.state.fileFormat; - config.LogSettings.EnableWebhookDebugging = this.state.enableWebhookDebugging; - config.LogSettings.EnableDiagnostics = this.state.enableDiagnostics; - - return config; - } - - getStateFromConfig(config) { - return { - enableConsole: config.LogSettings.EnableConsole, - consoleLevel: config.LogSettings.ConsoleLevel, - enableFile: config.LogSettings.EnableFile, - fileLevel: config.LogSettings.FileLevel, - fileLocation: config.LogSettings.FileLocation, - fileFormat: config.LogSettings.FileFormat, - enableWebhookDebugging: config.LogSettings.EnableWebhookDebugging, - enableDiagnostics: config.LogSettings.EnableDiagnostics - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const logLevels = [ - {value: 'DEBUG', text: 'DEBUG'}, - {value: 'INFO', text: 'INFO'}, - {value: 'ERROR', text: 'ERROR'} - ]; - - return ( - - - } - helpText={ - - } - value={this.state.enableConsole} - onChange={this.handleChange} - /> - - } - value={this.state.consoleLevel} - onChange={this.handleChange} - disabled={!this.state.enableConsole} - helpText={ - - } - /> - - } - helpText={ - - } - value={this.state.enableFile} - onChange={this.handleChange} - /> - - } - value={this.state.fileLevel} - onChange={this.handleChange} - disabled={!this.state.enableFile} - helpText={ - - } - /> - - } - placeholder={Utils.localizeMessage('admin.log.locationPlaceholder', 'Enter your file location')} - helpText={ - - } - value={this.state.fileLocation} - onChange={this.handleChange} - disabled={!this.state.enableFile} - /> - - } - placeholder={Utils.localizeMessage('admin.log.formatPlaceholder', 'Enter your file format')} - helpText={this.renderFileFormatHelpText()} - value={this.state.fileFormat} - onChange={this.handleChange} - disabled={!this.state.enableFile} - /> - - } - helpText={ - - } - value={this.state.enableWebhookDebugging} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.enableDiagnostics} - onChange={this.handleChange} - /> - - ); - } - - renderFileFormatHelpText() { - return ( -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {'%T'} - -
    {'%D'} - -
    {'%d'} - -
    {'%L'} - -
    {'%S'} - -
    {'%M'} - -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/manage_roles_modal/index.js b/webapp/components/admin_console/manage_roles_modal/index.js deleted file mode 100644 index 1ca243621..000000000 --- a/webapp/components/admin_console/manage_roles_modal/index.js +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {updateUserRoles} from 'mattermost-redux/actions/users'; - -import ManageRolesModal from './manage_roles_modal.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - userAccessTokensEnabled: state.entities.admin.config.ServiceSettings.EnableUserAccessTokens - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - updateUserRoles - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(ManageRolesModal); diff --git a/webapp/components/admin_console/manage_roles_modal/manage_roles_modal.jsx b/webapp/components/admin_console/manage_roles_modal/manage_roles_modal.jsx deleted file mode 100644 index 2358f0241..000000000 --- a/webapp/components/admin_console/manage_roles_modal/manage_roles_modal.jsx +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import * as UserUtils from 'mattermost-redux/utils/user_utils'; -import {Client4} from 'mattermost-redux/client'; -import {General} from 'mattermost-redux/constants'; - -import {trackEvent} from 'actions/diagnostics_actions.jsx'; - -import React from 'react'; -import {Modal} from 'react-bootstrap'; -import PropTypes from 'prop-types'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -function getStateFromProps(props) { - const roles = props.user && props.user.roles ? props.user.roles : ''; - - return { - error: null, - hasPostAllRole: UserUtils.hasPostAllRole(roles), - hasPostAllPublicRole: UserUtils.hasPostAllPublicRole(roles), - hasUserAccessTokenRole: UserUtils.hasUserAccessTokenRole(roles), - isSystemAdmin: UserUtils.isSystemAdmin(roles) - }; -} - -export default class ManageRolesModal extends React.PureComponent { - static propTypes = { - - /** - * Set to render the modal - */ - show: PropTypes.bool.isRequired, - - /** - * The user the roles are being managed for - */ - user: PropTypes.object, - - /** - * Set if user access tokens are enabled - */ - userAccessTokensEnabled: PropTypes.bool.isRequired, - - /** - * Function called when modal is dismissed - */ - onModalDismissed: PropTypes.func.isRequired, - - actions: PropTypes.shape({ - - /** - * Function to update a user's roles - */ - updateUserRoles: PropTypes.func.isRequired - }).isRequired - }; - - constructor(props) { - super(props); - this.state = getStateFromProps(props); - } - - componentWillReceiveProps(nextProps) { - const user = this.props.user || {}; - const nextUser = nextProps.user || {}; - if (user.id !== nextUser.id) { - this.setState(getStateFromProps(nextProps)); - } - } - - handleError = (error) => { - this.setState({ - error - }); - } - - handleSystemAdminChange = (e) => { - if (e.target.name === 'systemadmin') { - this.setState({isSystemAdmin: true}); - } else if (e.target.name === 'systemmember') { - this.setState({isSystemAdmin: false}); - } - }; - - handleUserAccessTokenChange = (e) => { - this.setState({ - hasUserAccessTokenRole: e.target.checked - }); - }; - - handlePostAllChange = (e) => { - this.setState({ - hasPostAllRole: e.target.checked - }); - }; - - handlePostAllPublicChange = (e) => { - this.setState({ - hasPostAllPublicRole: e.target.checked - }); - }; - - trackRoleChanges = (roles, oldRoles) => { - if (UserUtils.hasUserAccessTokenRole(roles) && !UserUtils.hasUserAccessTokenRole(oldRoles)) { - trackEvent('actions', 'add_roles', {role: General.SYSTEM_USER_ACCESS_TOKEN_ROLE}); - } else if (!UserUtils.hasUserAccessTokenRole(roles) && UserUtils.hasUserAccessTokenRole(oldRoles)) { - trackEvent('actions', 'remove_roles', {role: General.SYSTEM_USER_ACCESS_TOKEN_ROLE}); - } - - if (UserUtils.hasPostAllRole(roles) && !UserUtils.hasPostAllRole(oldRoles)) { - trackEvent('actions', 'add_roles', {role: General.SYSTEM_POST_ALL_ROLE}); - } else if (!UserUtils.hasPostAllRole(roles) && UserUtils.hasPostAllRole(oldRoles)) { - trackEvent('actions', 'remove_roles', {role: General.SYSTEM_POST_ALL_ROLE}); - } - - if (UserUtils.hasPostAllPublicRole(roles) && !UserUtils.hasPostAllPublicRole(oldRoles)) { - trackEvent('actions', 'add_roles', {role: General.SYSTEM_POST_ALL_PUBLIC_ROLE}); - } else if (!UserUtils.hasPostAllPublicRole(roles) && UserUtils.hasPostAllPublicRole(oldRoles)) { - trackEvent('actions', 'remove_roles', {role: General.SYSTEM_POST_ALL_PUBLIC_ROLE}); - } - } - - handleSave = async () => { - this.setState({error: null}); - - let roles = General.SYSTEM_USER_ROLE; - - if (this.state.isSystemAdmin) { - roles += ' ' + General.SYSTEM_ADMIN_ROLE; - } else if (this.state.hasUserAccessTokenRole) { - roles += ' ' + General.SYSTEM_USER_ACCESS_TOKEN_ROLE; - if (this.state.hasPostAllRole) { - roles += ' ' + General.SYSTEM_POST_ALL_ROLE; - } else if (this.state.hasPostAllPublicRole) { - roles += ' ' + General.SYSTEM_POST_ALL_PUBLIC_ROLE; - } - } - - const data = await this.props.actions.updateUserRoles(this.props.user.id, roles); - - this.trackRoleChanges(roles, this.props.user.roles); - - if (data) { - this.props.onModalDismissed(); - } else { - this.handleError( - - ); - } - } - - renderContents = () => { - const {user} = this.props; - - if (user == null) { - return
    ; - } - - let name = UserUtils.getFullName(user); - if (name) { - name += ` (@${user.username})`; - } else { - name = `@${user.username}`; - } - - let additionalRoles; - if (this.state.hasUserAccessTokenRole || this.state.isSystemAdmin) { - additionalRoles = ( -
    -

    - -

    -
    - -
    -
    - -
    -
    - ); - } - - let userAccessTokenContent; - if (this.props.userAccessTokensEnabled) { - userAccessTokenContent = ( -
    -
    - -
    -
    - {additionalRoles} -
    -
    - ); - } - - return ( -
    -
    - -
    -
    - {name} -
    -
    - {user.email} -
    -
    -
    -
    -
    -
    - -
    -
    - -
    -
    - {userAccessTokenContent} -
    -
    - ); - } - - render() { - return ( - - - - - - - - {this.renderContents()} - {this.state.error} - - - - - - - ); - } -} diff --git a/webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx b/webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx deleted file mode 100644 index 4ee3c11cd..000000000 --- a/webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx +++ /dev/null @@ -1,148 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import {Dropdown, MenuItem} from 'react-bootstrap'; -import {FormattedMessage} from 'react-intl'; - -import {updateTeamMemberRoles, removeUserFromTeam} from 'actions/team_actions.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -export default class ManageTeamsDropdown extends React.Component { - static propTypes = { - user: PropTypes.object.isRequired, - teamMember: PropTypes.object.isRequired, - onError: PropTypes.func.isRequired, - onMemberChange: PropTypes.func.isRequired, - onMemberRemove: PropTypes.func.isRequired - }; - - constructor(props) { - super(props); - - this.toggleDropdown = this.toggleDropdown.bind(this); - - this.makeTeamAdmin = this.makeTeamAdmin.bind(this); - this.makeMember = this.makeMember.bind(this); - this.removeFromTeam = this.removeFromTeam.bind(this); - - this.handleMemberChange = this.handleMemberChange.bind(this); - this.handleMemberRemove = this.handleMemberRemove.bind(this); - - this.state = { - show: false - }; - } - - toggleDropdown() { - this.setState((prevState) => { - return {show: !prevState.show}; - }); - } - - makeTeamAdmin() { - updateTeamMemberRoles( - this.props.teamMember.team_id, - this.props.user.id, - 'team_user team_admin', - this.handleMemberChange, - this.props.onError - ); - } - - makeMember() { - updateTeamMemberRoles( - this.props.teamMember.team_id, - this.props.user.id, - 'team_user', - this.handleMemberChange, - this.props.onError - ); - } - - removeFromTeam() { - removeUserFromTeam( - this.props.teamMember.team_id, - this.props.user.id, - this.handleMemberRemove, - this.props.onError - ); - } - - handleMemberChange() { - this.props.onMemberChange(this.props.teamMember.team_id); - } - - handleMemberRemove() { - this.props.onMemberRemove(this.props.teamMember.team_id); - } - - render() { - const isTeamAdmin = Utils.isAdmin(this.props.teamMember.roles); - - let title; - if (isTeamAdmin) { - title = Utils.localizeMessage('admin.user_item.teamAdmin', 'Team Admin'); - } else { - title = Utils.localizeMessage('admin.user_item.teamMember', 'Team Member'); - } - - let makeTeamAdmin = null; - if (!isTeamAdmin) { - makeTeamAdmin = ( - - - - ); - } - - let makeMember = null; - if (isTeamAdmin) { - makeMember = ( - - - - ); - } - - return ( - - - {title} - - - {makeTeamAdmin} - {makeMember} - - - - - - ); - } -} diff --git a/webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx b/webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx deleted file mode 100644 index 21f9d762d..000000000 --- a/webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import {Modal} from 'react-bootstrap'; -import {FormattedMessage} from 'react-intl'; -import PropTypes from 'prop-types'; - -import * as TeamActions from 'actions/team_actions.jsx'; - -import {Client4} from 'mattermost-redux/client'; - -import LoadingScreen from 'components/loading_screen.jsx'; - -import {sortTeamsByDisplayName} from 'utils/team_utils.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import ManageTeamsDropdown from './manage_teams_dropdown.jsx'; -import RemoveFromTeamButton from './remove_from_team_button.jsx'; - -export default class ManageTeamsModal extends React.Component { - static propTypes = { - onModalDismissed: PropTypes.func.isRequired, - show: PropTypes.bool.isRequired, - user: PropTypes.object - }; - - constructor(props) { - super(props); - - this.state = { - error: null, - teams: null, - teamMembers: null - }; - } - - componentDidMount() { - if (this.props.user) { - this.loadTeamsAndTeamMembers(); - } - } - - componentWillReceiveProps(nextProps) { - const userId = this.props.user ? this.props.user.id : ''; - const nextUserId = nextProps.user ? nextProps.user.id : ''; - - if (userId !== nextUserId) { - this.setState({ - teams: null, - teamMembers: null - }); - - if (nextProps.user) { - this.loadTeamsAndTeamMembers(nextProps.user); - } - } - } - - loadTeamsAndTeamMembers = (user = this.props.user) => { - TeamActions.getTeamsForUser(user.id, (teams) => { - this.setState({ - teams: teams.sort(sortTeamsByDisplayName) - }); - }); - - TeamActions.getTeamMembersForUser(user.id, (teamMembers) => { - this.setState({ - teamMembers - }); - }); - } - - handleError = (error) => { - this.setState({ - error - }); - } - - handleMemberChange = () => { - TeamActions.getTeamMembersForUser(this.props.user.id, (teamMembers) => { - this.setState({ - teamMembers - }); - }); - } - - handleMemberRemove = (teamId) => { - this.setState({ - teams: this.state.teams.filter((team) => team.id !== teamId), - teamMembers: this.state.teamMembers.filter((teamMember) => teamMember.team_id !== teamId) - }); - } - - renderContents = () => { - const {user} = this.props; - const {teams, teamMembers} = this.state; - - if (!user) { - return ; - } - - const isSystemAdmin = Utils.isAdmin(user.roles); - - let name = Utils.getFullName(user); - if (name) { - name += ` (@${user.username})`; - } else { - name = `@${user.username}`; - } - - let teamList; - if (teams && teamMembers) { - teamList = teams.map((team) => { - const teamMember = teamMembers.find((member) => member.team_id === team.id); - if (!teamMember) { - return null; - } - - let action; - if (isSystemAdmin) { - action = ( - - ); - } else { - action = ( - - ); - } - - return ( -
    -
    - {team.display_name} -
    -
    - {action} -
    -
    - ); - }); - } else { - teamList = ; - } - - let systemAdminIndicator = null; - if (isSystemAdmin) { - systemAdminIndicator = ( -
    - -
    - ); - } - - return ( -
    -
    - -
    -
    - {name} -
    -
    - {user.email} -
    -
    - {systemAdminIndicator} -
    -
    - {teamList} -
    -
    - ); - } - - render() { - return ( - - - - - - - - {this.renderContents()} - - - ); - } -} diff --git a/webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx b/webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx deleted file mode 100644 index 69579d46f..000000000 --- a/webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import {FormattedMessage} from 'react-intl'; - -import {removeUserFromTeam} from 'actions/team_actions.jsx'; - -export default class RemoveFromTeamButton extends React.PureComponent { - static propTypes = { - onError: PropTypes.func.isRequired, - onMemberRemove: PropTypes.func.isRequired, - team: PropTypes.object.isRequired, - user: PropTypes.object.isRequired - }; - - constructor(props) { - super(props); - - this.handleClick = this.handleClick.bind(this); - this.handleMemberRemove = this.handleMemberRemove.bind(this); - } - - handleClick(e) { - e.preventDefault(); - - removeUserFromTeam( - this.props.team.id, - this.props.user.id, - this.handleMemberRemove, - this.props.onError - ); - } - - handleMemberRemove() { - this.props.onMemberRemove(this.props.team.id); - } - - render() { - return ( - - ); - } -} diff --git a/webapp/components/admin_console/manage_tokens_modal/index.js b/webapp/components/admin_console/manage_tokens_modal/index.js deleted file mode 100644 index 9f7a31141..000000000 --- a/webapp/components/admin_console/manage_tokens_modal/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getUserAccessTokensForUser} from 'mattermost-redux/actions/users'; - -import ManageTokensModal from './manage_tokens_modal.jsx'; - -function mapStateToProps(state, ownProps) { - const userId = ownProps.user ? ownProps.user.id : ''; - - return { - ...ownProps, - userAccessTokens: state.entities.admin.userAccessTokens[userId] - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getUserAccessTokensForUser - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(ManageTokensModal); diff --git a/webapp/components/admin_console/manage_tokens_modal/manage_tokens_modal.jsx b/webapp/components/admin_console/manage_tokens_modal/manage_tokens_modal.jsx deleted file mode 100644 index fdef870e5..000000000 --- a/webapp/components/admin_console/manage_tokens_modal/manage_tokens_modal.jsx +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; -import RevokeTokenButton from 'components/admin_console/revoke_token_button'; - -import {Client4} from 'mattermost-redux/client'; -import * as UserUtils from 'mattermost-redux/utils/user_utils'; - -import React from 'react'; -import {Modal} from 'react-bootstrap'; -import PropTypes from 'prop-types'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -export default class ManageTokensModal extends React.PureComponent { - static propTypes = { - - /** - * Set to render the modal - */ - show: PropTypes.bool.isRequired, - - /** - * The user the roles are being managed for - */ - user: PropTypes.object, - - /** - * The personal access tokens for a user, object with token ids as keys - */ - userAccessTokens: PropTypes.object, - - /** - * Function called when modal is dismissed - */ - onModalDismissed: PropTypes.func.isRequired, - - actions: PropTypes.shape({ - - /** - * Function to get a user's access tokens - */ - getUserAccessTokensForUser: PropTypes.func.isRequired - }).isRequired - }; - - constructor(props) { - super(props); - this.state = {error: null}; - } - - componentWillReceiveProps(nextProps) { - const userId = this.props.user ? this.props.user.id : null; - const nextUserId = nextProps.user ? nextProps.user.id : null; - if (nextUserId && nextUserId !== userId) { - this.props.actions.getUserAccessTokensForUser(nextUserId, 0, 200); - } - } - - handleError = (error) => { - this.setState({ - error - }); - } - - renderContents = () => { - const {user, userAccessTokens} = this.props; - - if (!user) { - return ; - } - - let name = UserUtils.getFullName(user); - if (name) { - name += ` (@${user.username})`; - } else { - name = `@${user.username}`; - } - - let tokenList; - if (userAccessTokens) { - const userAccessTokensList = Object.values(userAccessTokens); - - if (userAccessTokensList.length === 0) { - tokenList = ( -
    - -
    - ); - } else { - tokenList = userAccessTokensList.map((token) => { - return ( -
    -
    -
    - - {token.description} -
    -
    - - {token.id} -
    -
    -
    - -
    -
    - ); - }); - } - } else { - tokenList = ; - } - - return ( -
    -
    - -
    -
    - {name} -
    -
    - {user.email} -
    -
    -
    -
    - -
    -
    - {tokenList} -
    -
    - ); - } - - render() { - return ( - - - - - - - - {this.renderContents()} - {this.state.error} - - - ); - } -} diff --git a/webapp/components/admin_console/metrics_settings.jsx b/webapp/components/admin_console/metrics_settings.jsx deleted file mode 100644 index 9eab4073b..000000000 --- a/webapp/components/admin_console/metrics_settings.jsx +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import TextSetting from './text_setting.jsx'; - -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -export default class MetricsSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.MetricsSettings.Enable = this.state.enable; - config.MetricsSettings.ListenAddress = this.state.listenAddress; - - return config; - } - - getStateFromConfig(config) { - const settings = config.MetricsSettings; - - return { - enable: settings.Enable, - listenAddress: settings.ListenAddress - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const licenseEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.Metrics === 'true'; - if (!licenseEnabled) { - return null; - } - - return ( - - - } - helpText={ - - } - value={this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.metrics.listenAddressEx', 'Ex ":8067"')} - helpText={ - - } - value={this.state.listenAddress} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/mfa_settings.jsx b/webapp/components/admin_console/mfa_settings.jsx deleted file mode 100644 index 9d7a64d05..000000000 --- a/webapp/components/admin_console/mfa_settings.jsx +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import AdminSettings from './admin_settings.jsx'; -import SettingsGroup from './settings_group.jsx'; -import BooleanSetting from './boolean_setting.jsx'; - -import React from 'react'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -export default class MfaSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - - this.state = Object.assign(this.state, { - enableMultifactorAuthentication: props.config.ServiceSettings.EnableMultifactorAuthentication, - enforceMultifactorAuthentication: props.config.ServiceSettings.EnforceMultifactorAuthentication - }); - } - - getConfigFromState(config) { - config.ServiceSettings.EnableMultifactorAuthentication = this.state.enableMultifactorAuthentication; - config.ServiceSettings.EnforceMultifactorAuthentication = this.state.enableMultifactorAuthentication && this.state.enforceMultifactorAuthentication; - - return config; - } - - getStateFromConfig(config) { - return { - enableMultifactorAuthentication: config.ServiceSettings.EnableMultifactorAuthentication, - enforceMultifactorAuthentication: config.ServiceSettings.EnableMultifactorAuthentication && config.ServiceSettings.EnforceMultifactorAuthentication - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - -
    -
    - -
    -
    - - } - helpText={ - - } - value={this.state.enableMultifactorAuthentication} - onChange={this.handleChange} - /> - - } - helpText={ - - } - disabled={!this.state.enableMultifactorAuthentication} - value={this.state.enforceMultifactorAuthentication} - onChange={this.handleChange} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/multiselect_settings.jsx b/webapp/components/admin_console/multiselect_settings.jsx deleted file mode 100644 index 8ae8e1349..000000000 --- a/webapp/components/admin_console/multiselect_settings.jsx +++ /dev/null @@ -1,81 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. -import React from 'react'; -import ReactSelect from 'react-select'; - -import Setting from './setting.jsx'; -import FormError from 'components/form_error.jsx'; - -export default class MultiSelectSetting extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - this.state = {error: false}; - } - - handleChange(newValue) { - const values = newValue.map((n) => { - return n.value; - }); - - if (this.props.selected.length > 0 && this.props.mustBePresent && values.join(',').indexOf(this.props.mustBePresent) === -1) { - this.setState({error: this.props.notPresent}); - } else { - this.props.onChange(this.props.id, values); - this.setState({error: false}); - } - } - - componentWillReceiveProps(newProps) { - if (newProps.selected.length > 0 && newProps.mustBePresent && newProps.selected.join(',').indexOf(newProps.mustBePresent) === -1) { - this.setState({error: this.props.notPresent}); - } else { - this.setState({error: false}); - } - } - - render() { - return ( - - - - - ); - } -} - -MultiSelectSetting.defaultProps = { - disabled: false -}; - -MultiSelectSetting.propTypes = { - id: PropTypes.string.isRequired, - values: PropTypes.array.isRequired, - label: PropTypes.node.isRequired, - selected: PropTypes.array.isRequired, - mustBePresent: PropTypes.string, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool, - helpText: PropTypes.node, - noResultText: PropTypes.node, - errorText: PropTypes.node, - notPresent: PropTypes.node -}; diff --git a/webapp/components/admin_console/native_app_link_settings.jsx b/webapp/components/admin_console/native_app_link_settings.jsx deleted file mode 100644 index 88c078476..000000000 --- a/webapp/components/admin_console/native_app_link_settings.jsx +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class NativeAppLinkSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.NativeAppSettings.AppDownloadLink = this.state.appDownloadLink; - config.NativeAppSettings.AndroidAppDownloadLink = this.state.androidAppDownloadLink; - config.NativeAppSettings.IosAppDownloadLink = this.state.iosAppDownloadLink; - - return config; - } - - getStateFromConfig(config) { - return { - appDownloadLink: config.NativeAppSettings.AppDownloadLink, - androidAppDownloadLink: config.NativeAppSettings.AndroidAppDownloadLink, - iosAppDownloadLink: config.NativeAppSettings.IosAppDownloadLink - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.appDownloadLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.androidAppDownloadLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.iosAppDownloadLink} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/oauth_settings.jsx b/webapp/components/admin_console/oauth_settings.jsx deleted file mode 100644 index abb4dc762..000000000 --- a/webapp/components/admin_console/oauth_settings.jsx +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import * as Utils from 'utils/utils.jsx'; -import Constants from 'utils/constants.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -import React from 'react'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; - -export default class OAuthSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - this.getStateFromConfig = this.getStateFromConfig.bind(this); - this.renderSettings = this.renderSettings.bind(this); - this.renderOffice365 = this.renderOffice365.bind(this); - this.renderGoogle = this.renderGoogle.bind(this); - this.renderGitLab = this.renderGitLab.bind(this); - this.changeType = this.changeType.bind(this); - } - - getConfigFromState(config) { - config.GitLabSettings.Enable = false; - config.GoogleSettings.Enable = false; - config.Office365Settings.Enable = false; - - if (this.state.oauthType === Constants.GITLAB_SERVICE) { - config.GitLabSettings.Enable = true; - config.GitLabSettings.Id = this.state.id; - config.GitLabSettings.Secret = this.state.secret; - config.GitLabSettings.UserApiEndpoint = this.state.userApiEndpoint; - config.GitLabSettings.AuthEndpoint = this.state.authEndpoint; - config.GitLabSettings.TokenEndpoint = this.state.tokenEndpoint; - } - - if (this.state.oauthType === Constants.GOOGLE_SERVICE) { - config.GoogleSettings.Enable = true; - config.GoogleSettings.Id = this.state.id; - config.GoogleSettings.Secret = this.state.secret; - config.GoogleSettings.UserApiEndpoint = 'https://www.googleapis.com/plus/v1/people/me'; - config.GoogleSettings.AuthEndpoint = 'https://accounts.google.com/o/oauth2/v2/auth'; - config.GoogleSettings.TokenEndpoint = 'https://www.googleapis.com/oauth2/v4/token'; - config.GoogleSettings.Scope = 'profile email'; - } - - if (this.state.oauthType === Constants.OFFICE365_SERVICE) { - config.Office365Settings.Enable = true; - config.Office365Settings.Id = this.state.id; - config.Office365Settings.Secret = this.state.secret; - config.Office365Settings.UserApiEndpoint = 'https://graph.microsoft.com/v1.0/me'; - config.Office365Settings.AuthEndpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize'; - config.Office365Settings.TokenEndpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/token'; - config.Office365Settings.Scope = 'User.Read'; - } - - return config; - } - - getStateFromConfig(config) { - this.config = config; - - let oauthType = 'off'; - let settings = {}; - if (config.GitLabSettings.Enable) { - oauthType = Constants.GITLAB_SERVICE; - settings = config.GitLabSettings; - } else if (config.GoogleSettings.Enable) { - oauthType = Constants.GOOGLE_SERVICE; - settings = config.GoogleSettings; - } else if (config.Office365Settings.Enable) { - oauthType = Constants.OFFICE365_SERVICE; - settings = config.Office365Settings; - } - - return { - oauthType, - id: settings.Id, - secret: settings.Secret, - userApiEndpoint: settings.UserApiEndpoint, - authEndpoint: settings.AuthEndpoint, - tokenEndpoint: settings.TokenEndpoint - }; - } - - changeType(id, value) { - let settings = {}; - if (value === Constants.GITLAB_SERVICE) { - settings = this.config.GitLabSettings; - } else if (value === Constants.GOOGLE_SERVICE) { - settings = this.config.GoogleSettings; - } else if (value === Constants.OFFICE365_SERVICE) { - settings = this.config.Office365Settings; - } - - this.setState({ - id: settings.Id, - secret: settings.Secret, - userApiEndpoint: settings.UserApiEndpoint, - authEndpoint: settings.AuthEndpoint, - tokenEndpoint: settings.TokenEndpoint - }); - - this.handleChange(id, value); - } - - renderTitle() { - return ( - - ); - } - - renderGoogle() { - return ( -
    - - } - placeholder={Utils.localizeMessage('admin.google.clientIdExample', 'Ex "7602141235235-url0fhs1mayfasbmop5qlfns8dh4.apps.googleusercontent.com"')} - helpText={ - - } - value={this.state.id} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.google.clientSecretExample', 'Ex "H8sz0Az-dDs2p15-7QzD231"')} - helpText={ - - } - value={this.state.secret} - onChange={this.handleChange} - /> - - } - value='https://www.googleapis.com/plus/v1/people/me' - disabled={true} - /> - - } - value='https://accounts.google.com/o/oauth2/v2/auth' - disabled={true} - /> - - } - value='https://www.googleapis.com/oauth2/v4/token' - disabled={true} - /> -
    - ); - } - - renderOffice365() { - return ( -
    - - } - placeholder={Utils.localizeMessage('admin.office365.clientIdExample', 'Ex "adf3sfa2-ag3f-sn4n-ids0-sh1hdax192qq"')} - helpText={ - - } - value={this.state.id} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.office365.clientSecretExample', 'Ex "shAieM47sNBfgl20f8ci294"')} - helpText={ - - } - value={this.state.secret} - onChange={this.handleChange} - /> - - } - value='https://graph.microsoft.com/v1.0/me' - disabled={true} - /> - - } - value='https://login.microsoftonline.com/common/oauth2/v2.0/authorize' - disabled={true} - /> - - } - value='https://login.microsoftonline.com/common/oauth2/v2.0/token' - disabled={true} - /> -
    - ); - } - - renderGitLab() { - return ( -
    - - } - placeholder={Utils.localizeMessage('admin.gitlab.clientIdExample', 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.id} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.clientSecretExample', 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.secret} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.userExample', 'Ex "https:///api/v3/user"')} - helpText={ - - } - value={this.state.userApiEndpoint} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.authExample', 'Ex "https:///oauth/authorize"')} - helpText={ - - } - value={this.state.authEndpoint} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.gitlab.tokenExample', 'Ex "https:///oauth/token"')} - helpText={ - - } - value={this.state.tokenEndpoint} - onChange={this.handleChange} - /> -
    - ); - } - - renderSettings() { - let contents; - let helpText; - if (this.state.oauthType === Constants.GITLAB_SERVICE) { - contents = this.renderGitLab(); - helpText = ( - - ); - } else if (this.state.oauthType === Constants.GOOGLE_SERVICE) { - contents = this.renderGoogle(); - helpText = ( - - ); - } else if (this.state.oauthType === Constants.OFFICE365_SERVICE) { - contents = this.renderOffice365(); - helpText = ( - - ); - } - - const oauthTypes = []; - oauthTypes.push({value: 'off', text: Utils.localizeMessage('admin.oauth.off', 'Do not allow sign-in via an OAuth 2.0 provider.')}); - oauthTypes.push({value: Constants.GITLAB_SERVICE, text: Utils.localizeMessage('admin.oauth.gitlab', 'GitLab')}); - if (global.window.mm_license.IsLicensed === 'true') { - if (global.window.mm_license.GoogleOAuth === 'true') { - oauthTypes.push({value: Constants.GOOGLE_SERVICE, text: Utils.localizeMessage('admin.oauth.google', 'Google Apps')}); - } - if (global.window.mm_license.Office365OAuth === 'true') { - oauthTypes.push({value: Constants.OFFICE365_SERVICE, text: Utils.localizeMessage('admin.oauth.office365', 'Office 365 (Beta)')}); - } - } - - return ( - - - } - helpText={helpText} - value={this.state.oauthType} - onChange={this.changeType} - /> - {contents} - - ); - } -} diff --git a/webapp/components/admin_console/password_settings.jsx b/webapp/components/admin_console/password_settings.jsx deleted file mode 100644 index 6f39269c0..000000000 --- a/webapp/components/admin_console/password_settings.jsx +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; -import Setting from './setting.jsx'; -import * as Utils from 'utils/utils.jsx'; -import Constants from 'utils/constants.jsx'; - -export default class PasswordSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - - this.getSampleErrorMsg = this.getSampleErrorMsg.bind(this); - - this.handlePasswordLengthChange = this.handlePasswordLengthChange.bind(this); - this.handleCheckboxChange = this.handleCheckboxChange.bind(this); - - this.state = Object.assign(this.state, { - passwordMinimumLength: props.config.PasswordSettings.MinimumLength, - passwordLowercase: props.config.PasswordSettings.Lowercase, - passwordNumber: props.config.PasswordSettings.Number, - passwordUppercase: props.config.PasswordSettings.Uppercase, - passwordSymbol: props.config.PasswordSettings.Symbol, - maximumLoginAttempts: props.config.ServiceSettings.MaximumLoginAttempts - }); - - // Update sample message from config settings - this.sampleErrorMsg = null; - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.PasswordRequirements === 'true') { - let sampleErrorMsgId = 'user.settings.security.passwordError'; - if (props.config.PasswordSettings.Lowercase) { - sampleErrorMsgId += 'Lowercase'; - } - if (props.config.PasswordSettings.Uppercase) { - sampleErrorMsgId += 'Uppercase'; - } - if (props.config.PasswordSettings.Number) { - sampleErrorMsgId += 'Number'; - } - if (props.config.PasswordSettings.Symbol) { - sampleErrorMsgId += 'Symbol'; - } - this.sampleErrorMsg = ( - - ); - } - } - - getConfigFromState(config) { - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.PasswordRequirements === 'true') { - config.PasswordSettings.MinimumLength = this.parseIntNonZero(this.state.passwordMinimumLength, Constants.MIN_PASSWORD_LENGTH); - config.PasswordSettings.Lowercase = this.refs.lowercase.checked; - config.PasswordSettings.Uppercase = this.refs.uppercase.checked; - config.PasswordSettings.Number = this.refs.number.checked; - config.PasswordSettings.Symbol = this.refs.symbol.checked; - } - - config.ServiceSettings.MaximumLoginAttempts = this.parseIntNonZero(this.state.maximumLoginAttempts); - - return config; - } - - getStateFromConfig(config) { - return { - passwordMinimumLength: config.PasswordSettings.MinimumLength, - passwordLowercase: config.PasswordSettings.Lowercase, - passwordNumber: config.PasswordSettings.Number, - passwordUppercase: config.PasswordSettings.Uppercase, - passwordSymbol: config.PasswordSettings.Symbol, - maximumLoginAttempts: config.ServiceSettings.MaximumLoginAttempts - }; - } - - getSampleErrorMsg(minLength) { - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.PasswordRequirements === 'true') { - if (this.props.config.PasswordSettings.MinimumLength > Constants.MAX_PASSWORD_LENGTH || this.props.config.PasswordSettings.MinimumLength < Constants.MIN_PASSWORD_LENGTH) { - return ( - - ); - } - let sampleErrorMsgId = 'user.settings.security.passwordError'; - if (this.refs.lowercase.checked) { - sampleErrorMsgId += 'Lowercase'; - } - if (this.refs.uppercase.checked) { - sampleErrorMsgId += 'Uppercase'; - } - if (this.refs.number.checked) { - sampleErrorMsgId += 'Number'; - } - if (this.refs.symbol.checked) { - sampleErrorMsgId += 'Symbol'; - } - return ( - - ); - } - - return null; - } - - handlePasswordLengthChange(id, value) { - this.sampleErrorMsg = this.getSampleErrorMsg(value); - this.handleChange(id, value); - } - - handleCheckboxChange(id, value) { - this.sampleErrorMsg = this.getSampleErrorMsg(this.state.passwordMinimumLength); - this.handleChange(id, value); - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - let passwordSettings = null; - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.PasswordRequirements === 'true') { - passwordSettings = ( -
    - - } - placeholder={Utils.localizeMessage('admin.password.minimumLengthExample', 'Ex "5"')} - helpText={ - - } - value={this.state.passwordMinimumLength} - onChange={this.handlePasswordLengthChange} - /> - - } - > -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    - -
    - {this.sampleErrorMsg} -
    -
    -
    - ); - } - - return ( - - {passwordSettings} - - } - placeholder={Utils.localizeMessage('admin.service.attemptExample', 'Ex "10"')} - helpText={ - - } - value={this.state.maximumLoginAttempts} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/plugin_settings/index.js b/webapp/components/admin_console/plugin_settings/index.js deleted file mode 100644 index 469d4ee2e..000000000 --- a/webapp/components/admin_console/plugin_settings/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {uploadPlugin, removePlugin, getPlugins} from 'mattermost-redux/actions/admin'; - -import PluginSettings from './plugin_settings.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - plugins: state.entities.admin.plugins - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - uploadPlugin, - removePlugin, - getPlugins - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(PluginSettings); diff --git a/webapp/components/admin_console/plugin_settings/plugin_settings.jsx b/webapp/components/admin_console/plugin_settings/plugin_settings.jsx deleted file mode 100644 index 286e05c06..000000000 --- a/webapp/components/admin_console/plugin_settings/plugin_settings.jsx +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; -import Banner from 'components/admin_console/banner.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -export default class PluginSettings extends React.Component { - static propTypes = { - - /* - * The config - */ - config: PropTypes.object.isRequired, - - /* - * Plugins object with ids as keys and manifests as values - */ - plugins: PropTypes.object.isRequired, - - actions: PropTypes.shape({ - - /* - * Function to upload a plugin - */ - uploadPlugin: PropTypes.func.isRequired, - - /* - * Function to remove a plugin - */ - removePlugin: PropTypes.func.isRequired, - - /* - * Function to get installed plugins - */ - getPlugins: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.state = { - loading: true, - fileSelected: false, - fileName: null, - serverError: null - }; - } - - componentDidMount() { - this.props.actions.getPlugins().then( - () => this.setState({loading: false}) - ); - } - - handleChange = () => { - const element = this.refs.fileInput; - if (element.files.length > 0) { - this.setState({fileSelected: true, fileName: element.files[0].name}); - } - } - - handleSubmit = async (e) => { - e.preventDefault(); - - const element = this.refs.fileInput; - if (element.files.length === 0) { - return; - } - const file = element.files[0]; - - this.setState({uploading: true}); - - const {error} = await this.props.actions.uploadPlugin(file); - this.setState({fileSelected: false, fileName: null, uploading: false}); - Utils.clearFileInput(element); - - if (error) { - if (error.server_error_id === 'app.plugin.activate.app_error') { - this.setState({serverError: Utils.localizeMessage('admin.plugin.error.activate', 'Unable to upload the plugin. It may conflict with another plugin on your server.')}); - } else if (error.server_error_id === 'app.plugin.extract.app_error') { - this.setState({serverError: Utils.localizeMessage('admin.plugin.error.extract', 'Encountered an error when extracting the plugin. Review your plugin file content and try again.')}); - } else { - this.setState({serverError: error.message}); - } - } - } - - handleRemove = async (pluginId) => { - this.setState({removing: pluginId}); - - const {error} = await this.props.actions.removePlugin(pluginId); - this.setState({removing: null}); - - if (error) { - this.setState({serverError: error.message}); - } - } - - render() { - let serverError = ''; - if (this.state.serverError) { - serverError =
    ; - } - - let btnClass = 'btn'; - if (this.state.fileSelected) { - btnClass = 'btn btn-primary'; - } - - let fileName; - if (this.state.fileName) { - fileName = this.state.fileName; - } - - let uploadButtonText; - if (this.state.uploading) { - uploadButtonText = ( - - ); - } else { - uploadButtonText = ( - - ); - } - - let activePluginsList; - let activePluginsContainer; - const plugins = Object.values(this.props.plugins); - if (this.state.loading) { - activePluginsList = ; - } else if (plugins.length === 0) { - activePluginsContainer = ( - - ); - } else { - activePluginsList = plugins.map( - (p) => { - let removeButtonText; - if (this.state.removing === p.id) { - removeButtonText = ( - - ); - } else { - removeButtonText = ( - - ); - } - - return ( -
    -
    - - - - {' ' + p.id} -
    -
    - - - - {' ' + p.description} -
    - -
    -
    - ); - } - ); - - activePluginsContainer = ( -
    - {activePluginsList} -
    - ); - } - - return ( -
    -

    - -

    - } - description={ - - } - /> -
    -
    - -
    -
    - - -
    - -
    - {fileName} -
    - {serverError} -

    - -

    -
    -
    -
    - -
    - {activePluginsContainer} -
    -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/policy_settings.jsx b/webapp/components/admin_console/policy_settings.jsx deleted file mode 100644 index f689efd82..000000000 --- a/webapp/components/admin_console/policy_settings.jsx +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import SettingsGroup from './settings_group.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import RadioSetting from './radio_setting.jsx'; -import PostEditSetting from './post_edit_setting.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import TextSetting from './text_setting.jsx'; -import ColorSetting from './color_setting.jsx'; - -import Constants from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -export default class PolicySettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.RestrictPostDelete = this.state.restrictPostDelete; - config.ServiceSettings.AllowEditPost = this.state.allowEditPost; - config.ServiceSettings.PostEditTimeLimit = this.parseIntNonZero(this.state.postEditTimeLimit, Constants.DEFAULT_POST_EDIT_TIME_LIMIT); - config.TeamSettings.RestrictTeamInvite = this.state.restrictTeamInvite; - config.TeamSettings.RestrictPublicChannelCreation = this.state.restrictPublicChannelCreation; - config.TeamSettings.RestrictPrivateChannelCreation = this.state.restrictPrivateChannelCreation; - config.TeamSettings.RestrictPublicChannelManagement = this.state.restrictPublicChannelManagement; - config.TeamSettings.RestrictPrivateChannelManagement = this.state.restrictPrivateChannelManagement; - config.TeamSettings.RestrictPublicChannelDeletion = this.state.restrictPublicChannelDeletion; - config.TeamSettings.RestrictPrivateChannelDeletion = this.state.restrictPrivateChannelDeletion; - config.TeamSettings.RestrictPrivateChannelManageMembers = this.state.restrictPrivateChannelManageMembers; - config.AnnouncementSettings.EnableBanner = this.state.enableBanner; - config.AnnouncementSettings.BannerText = this.state.bannerText; - config.AnnouncementSettings.BannerColor = this.state.bannerColor; - config.AnnouncementSettings.BannerTextColor = this.state.bannerTextColor; - config.AnnouncementSettings.AllowBannerDismissal = this.state.allowBannerDismissal; - - return config; - } - - getStateFromConfig(config) { - return { - restrictPostDelete: config.ServiceSettings.RestrictPostDelete, - allowEditPost: config.ServiceSettings.AllowEditPost, - postEditTimeLimit: config.ServiceSettings.PostEditTimeLimit, - restrictTeamInvite: config.TeamSettings.RestrictTeamInvite, - restrictPublicChannelCreation: config.TeamSettings.RestrictPublicChannelCreation, - restrictPrivateChannelCreation: config.TeamSettings.RestrictPrivateChannelCreation, - restrictPublicChannelManagement: config.TeamSettings.RestrictPublicChannelManagement, - restrictPrivateChannelManagement: config.TeamSettings.RestrictPrivateChannelManagement, - restrictPublicChannelDeletion: config.TeamSettings.RestrictPublicChannelDeletion, - restrictPrivateChannelDeletion: config.TeamSettings.RestrictPrivateChannelDeletion, - restrictPrivateChannelManageMembers: config.TeamSettings.RestrictPrivateChannelManageMembers, - enableBanner: config.AnnouncementSettings.EnableBanner, - bannerText: config.AnnouncementSettings.BannerText, - bannerColor: config.AnnouncementSettings.BannerColor, - bannerTextColor: config.AnnouncementSettings.BannerTextColor, - allowBannerDismissal: config.AnnouncementSettings.AllowBannerDismissal - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - value={this.state.restrictTeamInvite} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPublicChannelCreation} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPublicChannelManagement} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPublicChannelDeletion} - onChange={this.handleChange} - helpText={ - - - - ) - }} - /> - } - /> - - } - value={this.state.restrictPrivateChannelCreation} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPrivateChannelManagement} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPrivateChannelManageMembers} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.restrictPrivateChannelDeletion} - onChange={this.handleChange} - helpText={ - - - - ) - }} - /> - } - /> - - } - value={this.state.restrictPostDelete} - onChange={this.handleChange} - helpText={ - - } - /> - - } - value={this.state.allowEditPost} - timeLimitValue={this.state.postEditTimeLimit} - onChange={this.handleChange} - helpText={ - - } - /> - - } - helpText={ - - } - value={this.state.enableBanner} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.bannerText} - onChange={this.handleChange} - disabled={!this.state.enableBanner} - /> - - } - value={this.state.bannerColor} - onChange={this.handleChange} - disabled={!this.state.enableBanner} - /> - - } - value={this.state.bannerTextColor} - onChange={this.handleChange} - disabled={!this.state.enableBanner} - /> - - } - helpText={ - - } - value={this.state.allowBannerDismissal} - onChange={this.handleChange} - disabled={!this.state.enableBanner} - /> - - ); - } -} diff --git a/webapp/components/admin_console/post_edit_setting.jsx b/webapp/components/admin_console/post_edit_setting.jsx deleted file mode 100644 index 08fafc14b..000000000 --- a/webapp/components/admin_console/post_edit_setting.jsx +++ /dev/null @@ -1,101 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Setting from './setting.jsx'; - -import Constants from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -export default class PostEditSetting extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - this.handleTimeLimitChange = this.handleTimeLimitChange.bind(this); - } - - handleChange(e) { - this.props.onChange(this.props.id, e.target.value); - } - - handleTimeLimitChange(e) { - this.props.onChange(this.props.timeLimitId, e.target.value); - } - - render() { - return ( - -
    - -
    -
    - -
    -
    - -
    -
    - ); - } -} - -PostEditSetting.defaultProps = { - isDisabled: false -}; - -PostEditSetting.propTypes = { - id: PropTypes.string.isRequired, - timeLimitId: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - value: PropTypes.string.isRequired, - timeLimitValue: PropTypes.number.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool, - helpText: PropTypes.node -}; diff --git a/webapp/components/admin_console/privacy_settings.jsx b/webapp/components/admin_console/privacy_settings.jsx deleted file mode 100644 index 92fcb3e88..000000000 --- a/webapp/components/admin_console/privacy_settings.jsx +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -export default class PrivacySettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.PrivacySettings.ShowEmailAddress = this.state.showEmailAddress; - config.PrivacySettings.ShowFullName = this.state.showFullName; - - return config; - } - - getStateFromConfig(config) { - return { - showEmailAddress: config.PrivacySettings.ShowEmailAddress, - showFullName: config.PrivacySettings.ShowFullName - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.showEmailAddress} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.showFullName} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/public_link_settings.jsx b/webapp/components/admin_console/public_link_settings.jsx deleted file mode 100644 index a10574353..000000000 --- a/webapp/components/admin_console/public_link_settings.jsx +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import GeneratedSetting from './generated_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; - -export default class PublicLinkSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.FileSettings.EnablePublicLink = this.state.enablePublicLink; - config.FileSettings.PublicLinkSalt = this.state.publicLinkSalt; - - return config; - } - - getStateFromConfig(config) { - return { - enablePublicLink: config.FileSettings.EnablePublicLink, - publicLinkSalt: config.FileSettings.PublicLinkSalt - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.enablePublicLink} - onChange={this.handleChange} - /> - - } - helpText={ - - } - value={this.state.publicLinkSalt} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/push_settings.jsx b/webapp/components/admin_console/push_settings.jsx deleted file mode 100644 index b5f788c86..000000000 --- a/webapp/components/admin_console/push_settings.jsx +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Constants from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -const PUSH_NOTIFICATIONS_OFF = 'off'; -const PUSH_NOTIFICATIONS_MHPNS = 'mhpns'; -const PUSH_NOTIFICATIONS_MTPNS = 'mtpns'; -const PUSH_NOTIFICATIONS_CUSTOM = 'custom'; - -export default class PushSettings extends AdminSettings { - constructor(props) { - super(props); - - this.canSave = this.canSave.bind(this); - - this.handleAgreeChange = this.handleAgreeChange.bind(this); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - canSave() { - return this.state.pushNotificationServerType !== PUSH_NOTIFICATIONS_MHPNS || this.state.agree; - } - - handleAgreeChange(e) { - this.setState({ - agree: e.target.checked - }); - } - - handleChange(id, value) { - if (id === 'pushNotificationServerType') { - this.setState({ - agree: false - }); - - if (value === PUSH_NOTIFICATIONS_MHPNS) { - this.setState({ - pushNotificationServer: Constants.MHPNS - }); - } else if (value === PUSH_NOTIFICATIONS_MTPNS) { - this.setState({ - pushNotificationServer: Constants.MTPNS - }); - } - } - - super.handleChange(id, value); - } - - getConfigFromState(config) { - config.EmailSettings.SendPushNotifications = this.state.pushNotificationServerType !== PUSH_NOTIFICATIONS_OFF; - config.EmailSettings.PushNotificationServer = this.state.pushNotificationServer.trim(); - config.EmailSettings.PushNotificationContents = this.state.pushNotificationContents; - - return config; - } - - getStateFromConfig(config) { - let pushNotificationServerType = PUSH_NOTIFICATIONS_CUSTOM; - let agree = false; - if (!config.EmailSettings.SendPushNotifications) { - pushNotificationServerType = PUSH_NOTIFICATIONS_OFF; - } else if (config.EmailSettings.PushNotificationServer === Constants.MHPNS && - global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MHPNS === 'true') { - pushNotificationServerType = PUSH_NOTIFICATIONS_MHPNS; - agree = true; - } else if (config.EmailSettings.PushNotificationServer === Constants.MTPNS) { - pushNotificationServerType = PUSH_NOTIFICATIONS_MTPNS; - } - - let pushNotificationServer = config.EmailSettings.PushNotificationServer; - if (pushNotificationServerType === PUSH_NOTIFICATIONS_MTPNS) { - pushNotificationServer = Constants.MTPNS; - } else if (pushNotificationServerType === PUSH_NOTIFICATIONS_MHPNS) { - pushNotificationServer = Constants.MHPNS; - } - - return { - pushNotificationServerType, - pushNotificationServer, - pushNotificationContents: config.EmailSettings.PushNotificationContents, - agree - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const pushNotificationServerTypes = []; - pushNotificationServerTypes.push({value: PUSH_NOTIFICATIONS_OFF, text: Utils.localizeMessage('admin.email.pushOff', 'Do not send push notifications')}); - if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MHPNS === 'true') { - pushNotificationServerTypes.push({value: PUSH_NOTIFICATIONS_MHPNS, text: Utils.localizeMessage('admin.email.mhpns', 'Use encrypted, production-quality HPNS connection to iOS and Android apps')}); - } - pushNotificationServerTypes.push({value: PUSH_NOTIFICATIONS_MTPNS, text: Utils.localizeMessage('admin.email.mtpns', 'Use iOS and Android apps on iTunes and Google Play with TPNS')}); - pushNotificationServerTypes.push({value: PUSH_NOTIFICATIONS_CUSTOM, text: Utils.localizeMessage('admin.email.selfPush', 'Manually enter Push Notification Service location')}); - - let sendHelpText = null; - let pushServerHelpText = null; - if (this.state.pushNotificationServerType === PUSH_NOTIFICATIONS_OFF) { - sendHelpText = ( - - ); - } else if (this.state.pushNotificationServerType === PUSH_NOTIFICATIONS_MHPNS) { - pushServerHelpText = ( - - ); - } else if (this.state.pushNotificationServerType === PUSH_NOTIFICATIONS_MTPNS) { - pushServerHelpText = ( - - ); - } else { - pushServerHelpText = ( - - ); - } - - let tosCheckbox; - if (this.state.pushNotificationServerType === PUSH_NOTIFICATIONS_MHPNS) { - tosCheckbox = ( -
    -
    -
    - - -
    -
    - ); - } - - return ( - - } - > - - } - value={this.state.pushNotificationServerType} - onChange={this.handleChange} - helpText={sendHelpText} - /> - {tosCheckbox} - - } - placeholder={Utils.localizeMessage('admin.email.pushServerEx', 'E.g.: "http://push-test.mattermost.com"')} - helpText={pushServerHelpText} - value={this.state.pushNotificationServer} - onChange={this.handleChange} - disabled={this.state.pushNotificationServerType !== PUSH_NOTIFICATIONS_CUSTOM} - /> - - } - value={this.state.pushNotificationContents} - onChange={this.handleChange} - disabled={this.state.pushNotificationServerType === PUSH_NOTIFICATIONS_OFF} - helpText={ - - } - /> - - ); - } -} diff --git a/webapp/components/admin_console/radio_setting.jsx b/webapp/components/admin_console/radio_setting.jsx deleted file mode 100644 index 7a6c2e459..000000000 --- a/webapp/components/admin_console/radio_setting.jsx +++ /dev/null @@ -1,65 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Setting from './setting.jsx'; - -export default class RadioSetting extends React.Component { - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - } - - handleChange(e) { - this.props.onChange(this.props.id, e.target.value); - } - - render() { - const options = []; - for (const {value, text} of this.props.values) { - options.push( -
    - -
    - ); - } - - return ( - - {options} - - ); - } -} - -RadioSetting.defaultProps = { - isDisabled: false -}; - -RadioSetting.propTypes = { - id: PropTypes.string.isRequired, - values: PropTypes.array.isRequired, - label: PropTypes.node.isRequired, - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - disabled: PropTypes.bool, - helpText: PropTypes.node -}; diff --git a/webapp/components/admin_console/rate_settings.jsx b/webapp/components/admin_console/rate_settings.jsx deleted file mode 100644 index a0cf14f75..000000000 --- a/webapp/components/admin_console/rate_settings.jsx +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class RateSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.RateLimitSettings.Enable = this.state.enable; - config.RateLimitSettings.PerSec = this.parseIntNonZero(this.state.perSec); - config.RateLimitSettings.MaxBurst = this.parseIntNonZero(this.state.maxBurst); - config.RateLimitSettings.MemoryStoreSize = this.parseIntNonZero(this.state.memoryStoreSize); - config.RateLimitSettings.VaryByRemoteAddr = this.state.varyByRemoteAddr; - config.RateLimitSettings.VaryByHeader = this.state.varyByHeader; - - return config; - } - - getStateFromConfig(config) { - return { - enable: config.RateLimitSettings.Enable, - perSec: config.RateLimitSettings.PerSec, - maxBurst: config.RateLimitSettings.MaxBurst, - memoryStoreSize: config.RateLimitSettings.MemoryStoreSize, - varyByRemoteAddr: config.RateLimitSettings.VaryByRemoteAddr, - varyByHeader: config.RateLimitSettings.VaryByHeader - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - -
    -
    - -
    -
    - - } - helpText={ - - } - value={this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.rate.queriesExample', 'Ex "10"')} - helpText={ - - } - value={this.state.perSec} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.rate.maxBurstExample', 'Ex "100"')} - helpText={ - - } - value={this.state.maxBurst} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.rate.memoryExample', 'Ex "10000"')} - helpText={ - - } - value={this.state.memoryStoreSize} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - helpText={ - - } - value={this.state.varyByRemoteAddr} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.rate.httpHeaderExample', 'Ex "X-Real-IP", "X-Forwarded-For"')} - helpText={ - - } - value={this.state.varyByHeader} - onChange={this.handleChange} - disabled={!this.state.enable || this.state.varyByRemoteAddr} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/remove_file_setting.jsx b/webapp/components/admin_console/remove_file_setting.jsx deleted file mode 100644 index ff453d9fc..000000000 --- a/webapp/components/admin_console/remove_file_setting.jsx +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import $ from 'jquery'; -import PropTypes from 'prop-types'; -import React from 'react'; - -import Setting from './setting.jsx'; - -export default class RemoveFileSetting extends Setting { - static get propTypes() { - return { - id: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - helpText: PropTypes.node, - removeButtonText: PropTypes.node.isRequired, - removingText: PropTypes.node, - fileName: PropTypes.string.isRequired, - onSubmit: PropTypes.func.isRequired, - disabled: PropTypes.bool - }; - } - - constructor(props) { - super(props); - this.handleRemove = this.handleRemove.bind(this); - } - - handleRemove(e) { - e.preventDefault(); - - $(this.refs.remove_button).button('loading'); - this.props.onSubmit(this.props.id, () => { - $(this.refs.remove_button).button('reset'); - }); - } - - render() { - return ( - -
    -
    - {this.props.fileName} -
    - -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/request_button/request_button.jsx b/webapp/components/admin_console/request_button/request_button.jsx deleted file mode 100644 index e78d0443d..000000000 --- a/webapp/components/admin_console/request_button/request_button.jsx +++ /dev/null @@ -1,262 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {FormattedMessage} from 'react-intl'; -import PropTypes from 'prop-types'; - -import * as Utils from 'utils/utils.jsx'; - -/** - * A button which, when clicked, performs an action and displays - * its outcome as either success, or failure accompanied by the - * `message` property of the `err` object. - */ -export default class RequestButton extends React.Component { - static propTypes = { - - /** - * The action to be called to carry out the request. - */ - requestAction: PropTypes.func.isRequired, - - /** - * A component that displays help text for the request button. - * - * Typically, this will be a . - */ - helpText: PropTypes.element.isRequired, - - /** - * A component to be displayed on the button. - * - * Typically, this will be a - */ - buttonText: PropTypes.element.isRequired, - - /** - * The element to display as the field label. - * - * Typically, this will be a - */ - label: PropTypes.element, - - /** - * True if the button form control should be disabled, otherwise false. - */ - disabled: PropTypes.bool, - - /** - * True if the config needs to be saved before running the request, otherwise false. - * - * If set to true, the action provided in the `saveConfigAction` property will be - * called before the action provided in the `requestAction` property, with the later - * only being called if the former is successful. - */ - saveNeeded: PropTypes.bool, - - /** - * Action to be called to save the config, if saveNeeded is set to true. - */ - saveConfigAction: PropTypes.func, - - /** - * True if the success message should be show when the request completes successfully, - * otherwise false. - */ - showSuccessMessage: PropTypes.bool, - - /** - * The message to show when the request completes successfully. - */ - successMessage: PropTypes.shape({ - - /** - * The i18n string ID for the success message. - */ - id: PropTypes.string.isRequired, - - /** - * The i18n default value for the success message. - */ - defaultMessage: PropTypes.string.isRequired - }), - - /** - * The message to show when the request returns an error. - */ - errorMessage: PropTypes.shape({ - - /** - * The i18n string ID for the error message. - */ - id: PropTypes.string.isRequired, - - /** - * The i18n default value for the error message. - * - * The placeholder {error} may be used to include the error message returned - * by the server in response to the failed request. - */ - defaultMessage: PropTypes.string.isRequired - }), - - /** - * True if the {error} placeholder for the `errorMessage` property should include both - * the `message` and `detailed_error` properties of the error returned from the server, - * otherwise false to include only the `message` property. - */ - includeDetailedError: PropTypes.bool, - - /** - * An element to display adjacent to the request button. - */ - alternativeActionElement: PropTypes.element - } - - static defaultProps = { - disabled: false, - saveNeeded: false, - showSuccessMessage: true, - includeDetailedError: false, - successMessage: { - id: 'admin.requestButton.requestSuccess', - defaultMessage: 'Test Successful' - }, - errorMessage: { - id: 'admin.requestButton.requestFailure', - defaultMessage: 'Test Failure: {error}' - } - } - - constructor(props) { - super(props); - - this.handleRequest = this.handleRequest.bind(this); - - this.state = { - busy: false, - fail: null, - success: false - }; - } - - handleRequest(e) { - e.preventDefault(); - - this.setState({ - busy: true, - fail: null, - success: false - }); - - const doRequest = () => { //eslint-disable-line func-style - this.props.requestAction( - () => { - this.setState({ - busy: false, - success: true - }); - }, - (err) => { - let errMsg = err.message; - if (this.props.includeDetailedError) { - errMsg += ' - ' + err.detailed_error; - } - - this.setState({ - busy: false, - fail: errMsg - }); - } - ); - }; - - if (this.props.saveNeeded) { - this.props.saveConfigAction(doRequest); - } else { - doRequest(); - } - } - - render() { - let message = null; - if (this.state.fail) { - message = ( -
    -
    - - -
    -
    - ); - } else if (this.state.success && this.props.showSuccessMessage) { - message = ( -
    -
    - - -
    -
    - ); - } - - let contents = null; - if (this.state.busy) { - contents = ( - - - {Utils.localizeMessage('admin.requestButton.loading', ' Loading...')} - - ); - } else { - contents = this.props.buttonText; - } - - let widgetClassNames = 'col-sm-8'; - let label = null; - if (this.props.label) { - label = ( - - ); - } else { - widgetClassNames = 'col-sm-offset-4 ' + widgetClassNames; - } - - return ( -
    - {label} -
    -
    - - {this.props.alternativeActionElement} - {message} -
    -
    - {this.props.helpText} -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/reset_password_modal.jsx b/webapp/components/admin_console/reset_password_modal.jsx deleted file mode 100644 index 0a38adda1..000000000 --- a/webapp/components/admin_console/reset_password_modal.jsx +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import * as Utils from 'utils/utils.jsx'; -import {Modal} from 'react-bootstrap'; - -import {FormattedMessage} from 'react-intl'; - -import {adminResetPassword} from 'actions/admin_actions.jsx'; - -import PropTypes from 'prop-types'; - -import React from 'react'; - -export default class ResetPasswordModal extends React.Component { - static propTypes = { - user: PropTypes.object, - show: PropTypes.bool.isRequired, - onModalSubmit: PropTypes.func, - onModalDismissed: PropTypes.func - }; - - static defaultProps = { - show: false - }; - - constructor(props) { - super(props); - - this.doSubmit = this.doSubmit.bind(this); - this.doCancel = this.doCancel.bind(this); - - this.state = { - serverError: null - }; - } - - doSubmit(e) { - e.preventDefault(); - const password = this.refs.password.value; - - const passwordErr = Utils.isValidPassword(password); - if (passwordErr) { - this.setState({serverError: passwordErr}); - return; - } - this.setState({serverError: null}); - - adminResetPassword( - this.props.user.id, - password, - () => { - this.props.onModalSubmit(this.props.user); - }, - (err) => { - this.setState({serverError: err.message}); - } - ); - } - - doCancel() { - this.setState({serverError: null}); - this.props.onModalDismissed(); - } - - render() { - const user = this.props.user; - if (user == null) { - return
    ; - } - - let urlClass = 'input-group input-group--limit'; - let serverError = null; - - if (this.state.serverError) { - urlClass += ' has-error'; - serverError =

    {this.state.serverError}

    ; - } - - let title; - if (user.auth_service) { - title = ( - - ); - } else { - title = ( - - ); - } - - return ( - - - - {title} - - -
    - -
    -
    -
    - - - - -
    - {serverError} -
    -
    -
    - - - - -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/revoke_token_button/index.js b/webapp/components/admin_console/revoke_token_button/index.js deleted file mode 100644 index 6fada1bcc..000000000 --- a/webapp/components/admin_console/revoke_token_button/index.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {revokeUserAccessToken} from 'mattermost-redux/actions/users'; - -import RevokeTokenButton from './revoke_token_button.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - revokeUserAccessToken - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(RevokeTokenButton); diff --git a/webapp/components/admin_console/revoke_token_button/revoke_token_button.jsx b/webapp/components/admin_console/revoke_token_button/revoke_token_button.jsx deleted file mode 100644 index 4829a0cde..000000000 --- a/webapp/components/admin_console/revoke_token_button/revoke_token_button.jsx +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -import {trackEvent} from 'actions/diagnostics_actions.jsx'; - -export default class RevokeTokenButton extends React.PureComponent { - static propTypes = { - - /* - * Token id to revoke - */ - tokenId: PropTypes.string.isRequired, - - /* - * Function to call on error - */ - onError: PropTypes.func.isRequired, - - actions: PropTypes.shape({ - - /** - * Function to revoke a user access token - */ - revokeUserAccessToken: PropTypes.func.isRequired - }).isRequired - }; - - handleClick = async (e) => { - e.preventDefault(); - - const {error} = await this.props.actions.revokeUserAccessToken(this.props.tokenId); - trackEvent('system_console', 'revoke_user_access_token'); - - if (error) { - this.props.onError(error.message); - } - } - - render() { - return ( - - ); - } -} diff --git a/webapp/components/admin_console/saml_settings.jsx b/webapp/components/admin_console/saml_settings.jsx deleted file mode 100644 index 98c02e571..000000000 --- a/webapp/components/admin_console/saml_settings.jsx +++ /dev/null @@ -1,584 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import TextSetting from './text_setting.jsx'; -import FileUploadSetting from './file_upload_setting.jsx'; -import RemoveFileSetting from './remove_file_setting.jsx'; - -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; - -import * as Utils from 'utils/utils.jsx'; - -import * as AdminActions from 'actions/admin_actions.jsx'; - -export default class SamlSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - this.uploadCertificate = this.uploadCertificate.bind(this); - this.removeCertificate = this.removeCertificate.bind(this); - } - - getConfigFromState(config) { - config.SamlSettings.Enable = this.state.enable; - config.SamlSettings.Verify = this.state.verify; - config.SamlSettings.Encrypt = this.state.encrypt; - config.SamlSettings.IdpUrl = this.state.idpUrl; - config.SamlSettings.IdpDescriptorUrl = this.state.idpDescriptorUrl; - config.SamlSettings.AssertionConsumerServiceURL = this.state.assertionConsumerServiceURL; - config.SamlSettings.IdpCertificateFile = this.state.idpCertificateFile; - config.SamlSettings.PublicCertificateFile = this.state.publicCertificateFile; - config.SamlSettings.PrivateKeyFile = this.state.privateKeyFile; - config.SamlSettings.FirstNameAttribute = this.state.firstNameAttribute; - config.SamlSettings.LastNameAttribute = this.state.lastNameAttribute; - config.SamlSettings.EmailAttribute = this.state.emailAttribute; - config.SamlSettings.UsernameAttribute = this.state.usernameAttribute; - config.SamlSettings.NicknameAttribute = this.state.nicknameAttribute; - config.SamlSettings.PositionAttribute = this.state.positionAttribute; - config.SamlSettings.LocaleAttribute = this.state.localeAttribute; - config.SamlSettings.LoginButtonText = this.state.loginButtonText; - - return config; - } - - getStateFromConfig(config) { - const settings = config.SamlSettings; - - return { - enable: settings.Enable, - verify: settings.Verify, - encrypt: settings.Encrypt, - idpUrl: settings.IdpUrl, - idpDescriptorUrl: settings.IdpDescriptorUrl, - assertionConsumerServiceURL: settings.AssertionConsumerServiceURL, - idpCertificateFile: settings.IdpCertificateFile, - publicCertificateFile: settings.PublicCertificateFile, - privateKeyFile: settings.PrivateKeyFile, - firstNameAttribute: settings.FirstNameAttribute, - lastNameAttribute: settings.LastNameAttribute, - emailAttribute: settings.EmailAttribute, - usernameAttribute: settings.UsernameAttribute, - nicknameAttribute: settings.NicknameAttribute, - positionAttribute: settings.PositionAttribute, - localeAttribute: settings.LocaleAttribute, - loginButtonText: settings.LoginButtonText - }; - } - - componentWillMount() { - AdminActions.samlCertificateStatus( - (data) => { - const files = {}; - if (!data.idp_certificate_file) { - files.idpCertificateFile = ''; - } - - if (!data.public_certificate_file) { - files.publicCertificateFile = ''; - } - - if (!data.private_key_file) { - files.privateKeyFile = ''; - } - this.setState(files); - } - ); - } - - uploadCertificate(id, file, callback) { - const complete = () => { - const fileName = file.name; - this.handleChange(id, fileName); - this.setState({[id]: fileName, [`${id}Error`]: null}); - if (callback && typeof callback === 'function') { - callback(); - } - }; - - function fail(error) { - if (callback && typeof callback === 'function') { - callback(error.message); - } - } - - if (id === 'idpCertificateFile') { - AdminActions.uploadIdpSamlCertificate(file, complete, fail); - } else if (id === 'publicCertificateFile') { - AdminActions.uploadPublicSamlCertificate(file, complete, fail); - } else if (id === 'privateKeyFile') { - AdminActions.uploadPrivateSamlCertificate(file, complete, fail); - } - } - - removeCertificate(id, callback) { - const complete = () => { - this.handleChange(id, ''); - this.setState({[id]: null, [`${id}Error`]: null}); - }; - - const fail = (error) => { - if (callback && typeof callback === 'function') { - callback(); - } - this.setState({[id]: null, [`${id}Error`]: error.message}); - }; - - if (id === 'idpCertificateFile') { - AdminActions.removeIdpSamlCertificate(complete, fail); - } else if (id === 'publicCertificateFile') { - AdminActions.removePublicSamlCertificate(complete, fail); - } else if (id === 'privateKeyFile') { - AdminActions.removePrivateSamlCertificate(complete, fail); - } - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - const licenseEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.SAML === 'true'; - if (!licenseEnabled) { - return null; - } - - let idpCert; - let privKey; - let pubCert; - - if (this.state.idpCertificateFile) { - idpCert = ( - - } - helpText={ - - } - removeButtonText={Utils.localizeMessage('admin.saml.remove.idp_certificate', 'Remove Identity Provider Certificate')} - removingText={Utils.localizeMessage('admin.saml.removing.certificate', 'Removing Certificate...')} - fileName={this.state.idpCertificateFile} - onSubmit={this.removeCertificate} - disabled={!this.state.enable} - /> - ); - } else { - idpCert = ( - - } - helpText={ - - } - uploadingText={Utils.localizeMessage('admin.saml.uploading.certificate', 'Uploading Certificate...')} - disabled={!this.state.enable} - fileType='.crt,.cer' - onSubmit={this.uploadCertificate} - error={this.state.idpCertificateFileError} - /> - ); - } - - if (this.state.privateKeyFile) { - privKey = ( - - } - helpText={ - - } - removeButtonText={Utils.localizeMessage('admin.saml.remove.privKey', 'Remove Service Provider Private Key')} - removingText={Utils.localizeMessage('admin.saml.removing.privKey', 'Removing Private Key...')} - fileName={this.state.privateKeyFile} - onSubmit={this.removeCertificate} - disabled={!this.state.enable || !this.state.encrypt} - /> - ); - } else { - privKey = ( - - } - helpText={ - - } - uploadingText={Utils.localizeMessage('admin.saml.uploading.privateKey', 'Uploading Private Key...')} - disabled={!this.state.enable || !this.state.encrypt} - fileType='.key' - onSubmit={this.uploadCertificate} - error={this.state.privateKeyFileError} - /> - ); - } - - if (this.state.publicCertificateFile) { - pubCert = ( - - } - helpText={ - - } - removeButtonText={Utils.localizeMessage('admin.saml.remove.sp_certificate', 'Remove Service Provider Certificate')} - removingText={Utils.localizeMessage('admin.saml.removing.certificate', 'Removing Certificate...')} - fileName={this.state.publicCertificateFile} - onSubmit={this.removeCertificate} - disabled={!this.state.enable || !this.state.encrypt} - /> - ); - } else { - pubCert = ( - - } - helpText={ - - } - uploadingText={Utils.localizeMessage('admin.saml.uploading.certificate', 'Uploading Certificate...')} - disabled={!this.state.enable || !this.state.encrypt} - fileType='.crt,.cer' - onSubmit={this.uploadCertificate} - error={this.state.publicCertificateFileError} - /> - ); - } - - return ( - -
    -
    - -
    -
    - - } - helpText={ - - } - value={this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.idpUrlEx', 'Ex "https://idp.example.org/SAML2/SSO/Login"')} - helpText={ - - } - value={this.state.idpUrl} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.idpDescriptorUrlEx', 'Ex "https://idp.example.org/SAML2/issuer"')} - helpText={ - - } - value={this.state.idpDescriptorUrl} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - {idpCert} - - } - helpText={ - - } - value={this.state.verify} - disabled={!this.state.enable} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.assertionConsumerServiceURLEx', 'Ex "https:///login/sso/saml"')} - helpText={ - - } - value={this.state.assertionConsumerServiceURL} - onChange={this.handleChange} - disabled={!this.state.enable || !this.state.verify} - /> - - } - helpText={ - - } - value={this.state.encrypt} - disabled={!this.state.enable} - onChange={this.handleChange} - /> - {privKey} - {pubCert} - - } - placeholder={Utils.localizeMessage('admin.saml.emailAttrEx', 'Ex "Email" or "PrimaryEmail"')} - helpText={ - - } - value={this.state.emailAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.usernameAttrEx', 'Ex "Username"')} - helpText={ - - } - value={this.state.usernameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.firstnameAttrEx', 'Ex "FirstName"')} - helpText={ - - } - value={this.state.firstNameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.lastnameAttrEx', 'Ex "LastName"')} - helpText={ - - } - value={this.state.lastNameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.nicknameAttrEx', 'Ex "Nickname"')} - helpText={ - - } - value={this.state.nicknameAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.positionAttrEx', 'E.g.: "Role"')} - helpText={ - - } - value={this.state.positionAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.localeAttrEx', 'Ex "Locale" or "PrimaryLanguage"')} - helpText={ - - } - value={this.state.localeAttribute} - onChange={this.handleChange} - disabled={!this.state.enable} - /> - - } - placeholder={Utils.localizeMessage('admin.saml.loginButtonTextEx', 'Ex "With OKTA"')} - helpText={ - - } - value={this.state.loginButtonText} - onChange={this.handleChange} - disabled={!this.state.enable} - /> -
    - ); - } -} diff --git a/webapp/components/admin_console/save_button.jsx b/webapp/components/admin_console/save_button.jsx deleted file mode 100644 index 4d2b562da..000000000 --- a/webapp/components/admin_console/save_button.jsx +++ /dev/null @@ -1,64 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {FormattedMessage} from 'react-intl'; - -export default class SaveButton extends React.Component { - static get propTypes() { - return { - saving: PropTypes.bool.isRequired, - disabled: PropTypes.bool - }; - } - - static get defaultProps() { - return { - disabled: false - }; - } - - render() { - const {saving, disabled, ...props} = this.props; // eslint-disable-line no-use-before-define - - let contents; - if (saving) { - contents = ( - - - - - ); - } else { - contents = ( - - ); - } - - let className = 'save-button btn'; - if (!disabled) { - className += ' btn-primary'; - } - - return ( - - ); - } -} diff --git a/webapp/components/admin_console/server_logs/index.js b/webapp/components/admin_console/server_logs/index.js deleted file mode 100644 index 3adacaf1a..000000000 --- a/webapp/components/admin_console/server_logs/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getLogs} from 'mattermost-redux/actions/admin'; - -import * as Selectors from 'mattermost-redux/selectors/entities/admin'; - -import Logs from './logs.jsx'; - -function mapStateToProps(state, ownProps) { - return { - ...ownProps, - logs: Selectors.getLogs(state) - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getLogs - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(Logs); diff --git a/webapp/components/admin_console/server_logs/logs.jsx b/webapp/components/admin_console/server_logs/logs.jsx deleted file mode 100644 index b0d8b38ac..000000000 --- a/webapp/components/admin_console/server_logs/logs.jsx +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import LoadingScreen from 'components/loading_screen.jsx'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -export default class Logs extends React.PureComponent { - static propTypes = { - - /* - * Array of logs to render - */ - logs: PropTypes.arrayOf(PropTypes.string).isRequired, - - actions: PropTypes.shape({ - - /* - * Function to fetch logs - */ - getLogs: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.state = { - loadingLogs: true - }; - } - - componentDidMount() { - this.refs.logPanel.focus(); - - this.props.actions.getLogs().then( - () => this.setState({loadingLogs: false}) - ); - } - - componentDidUpdate() { - // Scroll Down to get the latest logs - var node = this.refs.logPanel; - node.scrollTop = node.scrollHeight; - node.focus(); - } - - reload = () => { - this.setState({loadingLogs: true}); - this.props.actions.getLogs().then( - () => this.setState({loadingLogs: false}) - ); - } - - render() { - let content = null; - - if (this.state.loadingLogs) { - content = ; - } else { - content = []; - - for (let i = 0; i < this.props.logs.length; i++) { - const style = { - whiteSpace: 'nowrap', - fontFamily: 'monospace' - }; - - if (this.props.logs[i].indexOf('[EROR]') > 0) { - style.color = 'red'; - } - - content.push(
    ); - content.push( - - {this.props.logs[i]} - - ); - } - } - - return ( -
    -

    - -

    -
    -
    - -
    -
    - -
    - {content} -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/session_settings.jsx b/webapp/components/admin_console/session_settings.jsx deleted file mode 100644 index a36126789..000000000 --- a/webapp/components/admin_console/session_settings.jsx +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import {FormattedMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; - -export default class SessionSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.ServiceSettings.SessionLengthWebInDays = this.parseIntNonZero(this.state.sessionLengthWebInDays); - config.ServiceSettings.SessionLengthMobileInDays = this.parseIntNonZero(this.state.sessionLengthMobileInDays); - config.ServiceSettings.SessionLengthSSOInDays = this.parseIntNonZero(this.state.sessionLengthSSOInDays); - config.ServiceSettings.SessionCacheInMinutes = this.parseIntNonZero(this.state.sessionCacheInMinutes); - - return config; - } - - getStateFromConfig(config) { - return { - sessionLengthWebInDays: config.ServiceSettings.SessionLengthWebInDays, - sessionLengthMobileInDays: config.ServiceSettings.SessionLengthMobileInDays, - sessionLengthSSOInDays: config.ServiceSettings.SessionLengthSSOInDays, - sessionCacheInMinutes: config.ServiceSettings.SessionCacheInMinutes - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - placeholder={Utils.localizeMessage('admin.service.sessionDaysEx', 'Ex "30"')} - helpText={ - - } - value={this.state.sessionLengthWebInDays} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.service.sessionDaysEx', 'Ex "30"')} - helpText={ - - } - value={this.state.sessionLengthMobileInDays} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.service.sessionDaysEx', 'Ex "30"')} - helpText={ - - } - value={this.state.sessionLengthSSOInDays} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.service.sessionDaysEx', 'Ex "30"')} - helpText={ - - } - value={this.state.sessionCacheInMinutes} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/setting.jsx b/webapp/components/admin_console/setting.jsx deleted file mode 100644 index 9ef6554ac..000000000 --- a/webapp/components/admin_console/setting.jsx +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React, {PureComponent} from 'react'; -import PropTypes from 'prop-types'; - -export default class Settings extends PureComponent { - static propTypes = { - inputId: PropTypes.string, - label: PropTypes.node.isRequired, - children: PropTypes.node.isRequired, - helpText: PropTypes.node - }; - - render() { - const {children, helpText, inputId, label} = this.props; - - return ( -
    - -
    - {children} -
    - {helpText} -
    -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/settings_group.jsx b/webapp/components/admin_console/settings_group.jsx deleted file mode 100644 index 79f8dac97..000000000 --- a/webapp/components/admin_console/settings_group.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -export default class SettingsGroup extends React.Component { - static get propTypes() { - return { - show: PropTypes.bool.isRequired, - header: PropTypes.node, - children: PropTypes.node - }; - } - - static get defaultProps() { - return { - show: true - }; - } - - render() { - if (!this.props.show) { - return null; - } - - let header = null; - if (this.props.header) { - header = ( -

    - {this.props.header} -

    - ); - } - - return ( -
    - {header} - {this.props.children} -
    - ); - } -} diff --git a/webapp/components/admin_console/signup_settings.jsx b/webapp/components/admin_console/signup_settings.jsx deleted file mode 100644 index b3ae6fe60..000000000 --- a/webapp/components/admin_console/signup_settings.jsx +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import AdminSettings from './admin_settings.jsx'; -import BooleanSetting from './boolean_setting.jsx'; -import {FormattedMessage} from 'react-intl'; -import GeneratedSetting from './generated_setting.jsx'; -import SettingsGroup from './settings_group.jsx'; - -export default class SignupSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.EmailSettings.RequireEmailVerification = this.state.requireEmailVerification; - config.EmailSettings.InviteSalt = this.state.inviteSalt; - config.TeamSettings.EnableOpenServer = this.state.enableOpenServer; - - return config; - } - - getStateFromConfig(config) { - return { - requireEmailVerification: config.EmailSettings.RequireEmailVerification, - inviteSalt: config.EmailSettings.InviteSalt, - enableOpenServer: config.TeamSettings.EnableOpenServer - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - return ( - - - } - helpText={ - - } - value={this.state.requireEmailVerification} - onChange={this.handleChange} - disabled={this.state.sendEmailNotifications} - disabledText={ - - } - /> - - } - helpText={ - - } - value={this.state.inviteSalt} - onChange={this.handleChange} - disabled={this.state.sendEmailNotifications} - disabledText={ - - } - /> - - } - helpText={ - - } - value={this.state.enableOpenServer} - onChange={this.handleChange} - /> - - ); - } -} diff --git a/webapp/components/admin_console/storage_settings.jsx b/webapp/components/admin_console/storage_settings.jsx deleted file mode 100644 index 4b20a8b93..000000000 --- a/webapp/components/admin_console/storage_settings.jsx +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import * as Utils from 'utils/utils.jsx'; - -import AdminSettings from './admin_settings.jsx'; -import DropdownSetting from './dropdown_setting.jsx'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import SettingsGroup from './settings_group.jsx'; -import TextSetting from './text_setting.jsx'; -import BooleanSetting from './boolean_setting.jsx'; - -const DRIVER_LOCAL = 'local'; -const DRIVER_S3 = 'amazons3'; - -export default class StorageSettings extends AdminSettings { - constructor(props) { - super(props); - - this.getConfigFromState = this.getConfigFromState.bind(this); - - this.renderSettings = this.renderSettings.bind(this); - } - - getConfigFromState(config) { - config.FileSettings.EnableFileAttachments = this.state.enableFileAttachments; - config.FileSettings.EnableMobileUpload = this.state.enableMobileUpload; - config.FileSettings.EnableMobileDownload = this.state.enableMobileDownload; - config.FileSettings.MaxFileSize = this.parseInt(this.state.maxFileSize) * 1024 * 1024; - config.FileSettings.DriverName = this.state.driverName; - config.FileSettings.Directory = this.state.directory; - config.FileSettings.AmazonS3AccessKeyId = this.state.amazonS3AccessKeyId; - config.FileSettings.AmazonS3SecretAccessKey = this.state.amazonS3SecretAccessKey; - config.FileSettings.AmazonS3Bucket = this.state.amazonS3Bucket; - config.FileSettings.AmazonS3Endpoint = this.state.amazonS3Endpoint; - config.FileSettings.AmazonS3SSL = this.state.amazonS3SSL; - config.FileSettings.AmazonS3SSE = this.state.amazonS3SSE; - config.FileSettings.AmazonS3Trace = this.state.amazonS3Trace; - - return config; - } - - getStateFromConfig(config) { - return { - enableFileAttachments: config.FileSettings.EnableFileAttachments, - enableMobileUpload: config.FileSettings.EnableMobileUpload, - enableMobileDownload: config.FileSettings.EnableMobileDownload, - maxFileSize: config.FileSettings.MaxFileSize / 1024 / 1024, - driverName: config.FileSettings.DriverName, - directory: config.FileSettings.Directory, - amazonS3AccessKeyId: config.FileSettings.AmazonS3AccessKeyId, - amazonS3SecretAccessKey: config.FileSettings.AmazonS3SecretAccessKey, - amazonS3Bucket: config.FileSettings.AmazonS3Bucket, - amazonS3Endpoint: config.FileSettings.AmazonS3Endpoint, - amazonS3SSL: config.FileSettings.AmazonS3SSL, - amazonS3SSE: config.FileSettings.AmazonS3SSE, - amazonS3Trace: config.FileSettings.AmazonS3Trace - }; - } - - renderTitle() { - return ( - - ); - } - - renderSettings() { - let amazonSSEComp; - const mobileUploadDownloadSettings = []; - if (window.mm_license.IsLicensed === 'true' && window.mm_license.Compliance === 'true') { - mobileUploadDownloadSettings.push( - - } - helpText={ - - } - value={this.state.enableMobileUpload} - onChange={this.handleChange} - disabled={!this.state.enableFileAttachments} - /> - ); - - mobileUploadDownloadSettings.push( - - } - helpText={ - - } - value={this.state.enableMobileDownload} - onChange={this.handleChange} - disabled={!this.state.enableFileAttachments} - /> - ); - - amazonSSEComp = - ( - - } - helpText={ - - } - value={this.state.amazonS3SSE} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - ); - } - - return ( - - - } - helpText={ - - } - value={this.state.driverName} - onChange={this.handleChange} - /> - - } - placeholder={Utils.localizeMessage('admin.image.localExample', 'Ex "./data/"')} - helpText={ - - } - value={this.state.directory} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_LOCAL} - /> - - } - placeholder={Utils.localizeMessage('admin.image.amazonS3IdExample', 'Ex "AKIADTOVBGERKLCBV"')} - helpText={ - - } - value={this.state.amazonS3AccessKeyId} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - - } - placeholder={Utils.localizeMessage('admin.image.amazonS3SecretExample', 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"')} - helpText={ - - } - value={this.state.amazonS3SecretAccessKey} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - - } - placeholder={Utils.localizeMessage('admin.image.amazonS3BucketExample', 'Ex "mattermost-media"')} - helpText={ - - } - value={this.state.amazonS3Bucket} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - - } - placeholder={Utils.localizeMessage('admin.image.amazonS3EndpointExample', 'Ex "s3.amazonaws.com"')} - helpText={ - - } - value={this.state.amazonS3Endpoint} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - - } - helpText={ - - } - value={this.state.amazonS3SSL} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - {amazonSSEComp} - - } - helpText={ - - } - value={this.state.amazonS3Trace} - onChange={this.handleChange} - disabled={this.state.driverName !== DRIVER_S3} - /> - - } - helpText={ - - } - value={this.state.enableFileAttachments} - onChange={this.handleChange} - /> - {mobileUploadDownloadSettings} - - } - placeholder={Utils.localizeMessage('admin.image.maxFileSizeExample', '50')} - helpText={ - - } - value={this.state.maxFileSize} - onChange={this.handleChange} - disabled={!this.state.enableFileAttachments} - /> - - ); - } -} diff --git a/webapp/components/admin_console/system_users/index.js b/webapp/components/admin_console/system_users/index.js deleted file mode 100644 index 261a11d7e..000000000 --- a/webapp/components/admin_console/system_users/index.js +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -import {getTeams, getTeamStats} from 'mattermost-redux/actions/teams'; -import {getUser, getUserAccessToken} from 'mattermost-redux/actions/users'; - -import {getTeamsList} from 'mattermost-redux/selectors/entities/teams'; - -import SystemUsers from './system_users.jsx'; - -function mapStateToProps(state, ownProps) { - return { - teams: getTeamsList(state), - ...ownProps - }; -} - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - getTeams, - getTeamStats, - getUser, - getUserAccessToken - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(SystemUsers); diff --git a/webapp/components/admin_console/system_users/system_users.jsx b/webapp/components/admin_console/system_users/system_users.jsx deleted file mode 100644 index db8400217..000000000 --- a/webapp/components/admin_console/system_users/system_users.jsx +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage} from 'react-intl'; - -import { - loadProfiles, - loadProfilesAndTeamMembers, - loadProfilesWithoutTeam, - searchUsers -} from 'actions/user_actions.jsx'; - -import AnalyticsStore from 'stores/analytics_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; -import UserStore from 'stores/user_store.jsx'; - -import {reloadIfServerVersionChanged} from 'actions/global_actions.jsx'; -import {getStandardAnalytics} from 'actions/admin_actions.jsx'; -import {Constants, StatTypes, UserSearchOptions} from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import SystemUsersList from './system_users_list.jsx'; - -import store from 'stores/redux_store.jsx'; -import {searchProfiles, searchProfilesInTeam} from 'mattermost-redux/selectors/entities/users'; - -const ALL_USERS = ''; -const NO_TEAM = 'no_team'; - -const USER_ID_LENGTH = 26; -const USERS_PER_PAGE = 50; - -export default class SystemUsers extends React.Component { - static propTypes = { - - /* - * Array of team objects - */ - teams: PropTypes.arrayOf(PropTypes.object).isRequired, - - actions: PropTypes.shape({ - - /* - * Function to get teams - */ - getTeams: PropTypes.func.isRequired, - - /* - * Function to get statistics for a team - */ - getTeamStats: PropTypes.func.isRequired, - - /* - * Function to get a user - */ - getUser: PropTypes.func.isRequired, - - /* - * Function to get a user access token - */ - getUserAccessToken: PropTypes.func.isRequired - }).isRequired - } - - constructor(props) { - super(props); - - this.updateTotalUsersFromStore = this.updateTotalUsersFromStore.bind(this); - this.updateUsersFromStore = this.updateUsersFromStore.bind(this); - - this.loadDataForTeam = this.loadDataForTeam.bind(this); - this.loadComplete = this.loadComplete.bind(this); - - this.handleTeamChange = this.handleTeamChange.bind(this); - this.handleTermChange = this.handleTermChange.bind(this); - this.nextPage = this.nextPage.bind(this); - - this.doSearch = this.doSearch.bind(this); - this.search = this.search.bind(this); - this.getUserById = this.getUserById.bind(this); - - this.renderFilterRow = this.renderFilterRow.bind(this); - - this.state = { - totalUsers: AnalyticsStore.getAllSystem()[StatTypes.TOTAL_USERS], - users: UserStore.getProfileList(), - - teamId: ALL_USERS, - term: '', - loading: true, - searching: false - }; - } - - componentDidMount() { - AnalyticsStore.addChangeListener(this.updateTotalUsersFromStore); - TeamStore.addStatsChangeListener(this.updateTotalUsersFromStore); - - UserStore.addChangeListener(this.updateUsersFromStore); - UserStore.addInTeamChangeListener(this.updateUsersFromStore); - UserStore.addWithoutTeamChangeListener(this.updateUsersFromStore); - - this.loadDataForTeam(this.state.teamId); - this.props.actions.getTeams(0, 1000).then(reloadIfServerVersionChanged); - } - - componentWillUpdate(nextProps, nextState) { - const nextTeamId = nextState.teamId; - - if (this.state.teamId !== nextTeamId) { - this.updateTotalUsersFromStore(nextTeamId); - this.updateUsersFromStore(nextTeamId, nextState.term); - - this.loadDataForTeam(nextTeamId); - } - } - - componentWillUnmount() { - AnalyticsStore.removeChangeListener(this.updateTotalUsersFromStore); - TeamStore.removeStatsChangeListener(this.updateTotalUsersFromStore); - - UserStore.removeChangeListener(this.updateUsersFromStore); - UserStore.removeInTeamChangeListener(this.updateUsersFromStore); - UserStore.removeWithoutTeamChangeListener(this.updateUsersFromStore); - } - - updateTotalUsersFromStore(teamId = this.state.teamId) { - if (teamId === ALL_USERS) { - this.setState({ - totalUsers: AnalyticsStore.getAllSystem()[StatTypes.TOTAL_USERS] - }); - } else if (teamId === NO_TEAM) { - this.setState({ - totalUsers: 0 - }); - } else { - this.setState({ - totalUsers: TeamStore.getStats(teamId).total_member_count - }); - } - } - - updateUsersFromStore(teamId = this.state.teamId, term = this.state.term) { - if (term) { - let users; - if (teamId) { - users = searchProfilesInTeam(store.getState(), teamId, term); - } else { - users = searchProfiles(store.getState(), term); - } - - if (users.length === 0 && UserStore.hasProfile(term)) { - users = [UserStore.getProfile(term)]; - } - - this.setState({users}); - return; - } - - if (teamId === ALL_USERS) { - this.setState({users: UserStore.getProfileList(false, true)}); - } else if (teamId === NO_TEAM) { - this.setState({users: UserStore.getProfileListWithoutTeam()}); - } else { - this.setState({users: UserStore.getProfileListInTeam(this.state.teamId)}); - } - } - - loadDataForTeam(teamId) { - if (this.state.term) { - this.search(this.state.term, teamId); - return; - } - - if (teamId === ALL_USERS) { - loadProfiles(0, Constants.PROFILE_CHUNK_SIZE, this.loadComplete); - getStandardAnalytics(); - } else if (teamId === NO_TEAM) { - loadProfilesWithoutTeam(0, Constants.PROFILE_CHUNK_SIZE, this.loadComplete); - } else { - loadProfilesAndTeamMembers(0, Constants.PROFILE_CHUNK_SIZE, teamId, this.loadComplete); - this.props.actions.getTeamStats(teamId); - } - } - - loadComplete() { - this.setState({loading: false}); - } - - handleTeamChange(e) { - this.setState({teamId: e.target.value}); - } - - handleTermChange(term) { - this.setState({term}); - } - - nextPage(page) { - // Paging isn't supported while searching - - if (this.state.teamId === ALL_USERS) { - loadProfiles(page, USERS_PER_PAGE, this.loadComplete); - } else if (this.state.teamId === NO_TEAM) { - loadProfilesWithoutTeam(page + 1, USERS_PER_PAGE, this.loadComplete); - } else { - loadProfilesAndTeamMembers(page + 1, USERS_PER_PAGE, this.state.teamId, this.loadComplete); - } - } - - search(term, teamId = this.state.teamId) { - if (term === '') { - this.updateUsersFromStore(teamId, term); - - this.setState({ - loading: false - }); - - this.searchTimeoutId = ''; - return; - } - - this.doSearch(teamId, term); - } - - doSearch(teamId, term, now = false) { - clearTimeout(this.searchTimeoutId); - this.term = term; - - this.setState({loading: true}); - - const options = { - [UserSearchOptions.ALLOW_INACTIVE]: true - }; - if (teamId === NO_TEAM) { - options[UserSearchOptions.WITHOUT_TEAM] = true; - } - - this.searchTimeoutId = setTimeout( - () => { - searchUsers( - term, - teamId, - options, - (users) => { - if (users.length === 0 && term.length === USER_ID_LENGTH) { - // This term didn't match any users name, but it does look like it might be a user's ID - this.getUserByTokenOrId(term); - } else { - this.setState({loading: false}); - } - }, - () => { - this.setState({loading: false}); - } - ); - }, - now ? 0 : Constants.SEARCH_TIMEOUT_MILLISECONDS - ); - } - - getUserById(id) { - if (UserStore.hasProfile(id)) { - this.setState({loading: false}); - return; - } - - this.props.actions.getUser(id).then( - () => { - this.setState({ - loading: false - }); - } - ); - } - - getUserByTokenOrId = async (id) => { - if (global.window.mm_config.EnableUserAccessTokens === 'true') { - const {data} = await this.props.actions.getUserAccessToken(id); - - if (data) { - this.term = data.user_id; - this.setState({term: data.user_id}); - this.updateUsersFromStore(this.state.teamId, data.user_id); - this.getUserById(data.user_id); - return; - } - } - - this.getUserById(id); - } - - renderFilterRow(doSearch) { - const teams = this.props.teams.map((team) => { - return ( - - ); - }); - - return ( -
    -
    - -
    - -
    - ); - } - - render() { - let users = null; - if (!this.state.loading) { - users = this.state.users; - } - - return ( -
    -

    - -

    -
    - -
    -
    - ); - } -} diff --git a/webapp/components/admin_console/system_users/system_users_dropdown.jsx b/webapp/components/admin_console/system_users/system_users_dropdown.jsx deleted file mode 100644 index 79ccc8b31..000000000 --- a/webapp/components/admin_console/system_users/system_users_dropdown.jsx +++ /dev/null @@ -1,529 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import ConfirmModal from 'components/confirm_modal.jsx'; - -import TeamStore from 'stores/team_store.jsx'; -import UserStore from 'stores/user_store.jsx'; - -import Constants from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; -import {updateActive} from 'actions/user_actions.jsx'; -import {adminResetMfa} from 'actions/admin_actions.jsx'; -import * as UserUtils from 'mattermost-redux/utils/user_utils'; - -import {FormattedMessage} from 'react-intl'; - -import PropTypes from 'prop-types'; - -import React from 'react'; - -export default class SystemUsersDropdown extends React.Component { - static propTypes = { - - /* - * User to manage with dropdown - */ - user: PropTypes.object.isRequired, - - /* - * Function to open password reset, takes user as an argument - */ - doPasswordReset: PropTypes.func.isRequired, - - /* - * Function to open manage teams, takes user as an argument - */ - doManageTeams: PropTypes.func.isRequired, - - /* - * Function to open manage roles, takes user as an argument - */ - doManageRoles: PropTypes.func.isRequired, - - /* - * Function to open manage tokens, takes user as an argument - */ - doManageTokens: PropTypes.func.isRequired - }; - - constructor(props) { - super(props); - - this.state = { - serverError: null, - showDemoteModal: false, - showDeactivateMemberModal: false, - user: null, - role: null - }; - } - - handleMakeActive = (e) => { - e.preventDefault(); - updateActive(this.props.user.id, true, null, - (err) => { - this.setState({serverError: err.message}); - } - ); - } - - handleManageTeams = (e) => { - e.preventDefault(); - - this.props.doManageTeams(this.props.user); - } - - handleManageRoles = (e) => { - e.preventDefault(); - - this.props.doManageRoles(this.props.user); - } - - handleManageTokens = (e) => { - e.preventDefault(); - - this.props.doManageTokens(this.props.user); - } - - handleResetPassword = (e) => { - e.preventDefault(); - this.props.doPasswordReset(this.props.user); - } - - handleResetMfa = (e) => { - e.preventDefault(); - - adminResetMfa(this.props.user.id, - null, - (err) => { - this.setState({serverError: err.message}); - } - ); - } - - handleDemoteSystemAdmin = (user, role) => { - this.setState({ - serverError: this.state.serverError, - showDemoteModal: true, - user, - role - }); - } - - handleDemoteCancel = () => { - this.setState({ - serverError: null, - showDemoteModal: false, - user: null, - role: null - }); - } - - handleDemoteSubmit = () => { - if (this.state.role === 'member') { - this.doMakeMember(); - } - - const teamUrl = TeamStore.getCurrentTeamUrl(); - if (teamUrl) { - // the channel is added to the URL cause endless loading not being fully fixed - window.location.href = teamUrl + '/channels/town-square'; - } else { - window.location.href = '/'; - } - } - - handleShowDeactivateMemberModal = (e) => { - e.preventDefault(); - - this.setState({showDeactivateMemberModal: true}); - } - - handleDeactivateMember = () => { - updateActive(this.props.user.id, false, null, - (err) => { - this.setState({serverError: err.message}); - } - ); - - this.setState({showDeactivateMemberModal: false}); - } - - handleDeactivateCancel = () => { - this.setState({showDeactivateMemberModal: false}); - } - - renderDeactivateMemberModal = () => { - const title = ( - - ); - - const message = ( - - ); - - const confirmButtonClass = 'btn btn-danger'; - const deactivateMemberButton = ( - - ); - - return ( - - ); - } - - renderAccessToken = () => { - const userAccessTokensEnabled = global.window.mm_config.EnableUserAccessTokens === 'true'; - if (!userAccessTokensEnabled) { - return null; - } - - const user = this.props.user; - const hasPostAllRole = UserUtils.hasPostAllRole(user.roles); - const hasPostAllPublicRole = UserUtils.hasPostAllPublicRole(user.roles); - const hasUserAccessTokenRole = UserUtils.hasUserAccessTokenRole(user.roles); - const isSystemAdmin = UserUtils.isSystemAdmin(user.roles); - - let messageId = ''; - if (hasUserAccessTokenRole || isSystemAdmin) { - if (hasPostAllRole) { - messageId = 'admin.user_item.userAccessTokenPostAll'; - } else if (hasPostAllPublicRole) { - messageId = 'admin.user_item.userAccessTokenPostAllPublic'; - } else { - messageId = 'admin.user_item.userAccessTokenYes'; - } - } - - if (!messageId) { - return null; - } - - return ( -
    - -
    - ); - } - - render() { - let serverError = null; - if (this.state.serverError) { - serverError = ( -
    - -
    - ); - } - - const user = this.props.user; - if (!user) { - return
    ; - } - let currentRoles = ( - - ); - - if (user.roles.length > 0 && Utils.isSystemAdmin(user.roles)) { - currentRoles = ( - - ); - } - - const me = UserStore.getCurrentUser(); - let showMakeActive = false; - let showMakeNotActive = !Utils.isSystemAdmin(user.roles); - let showManageTeams = true; - const mfaEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MFA === 'true' && global.window.mm_config.EnableMultifactorAuthentication === 'true'; - const showMfaReset = mfaEnabled && user.mfa_active; - - if (user.delete_at > 0) { - currentRoles = ( - - ); - showMakeActive = true; - showMakeNotActive = false; - showManageTeams = false; - } - - let disableActivationToggle = false; - if (user.auth_service === Constants.LDAP_SERVICE) { - disableActivationToggle = true; - } - - let menuClass = ''; - if (disableActivationToggle) { - menuClass = 'disabled'; - } - - let makeActive = null; - if (showMakeActive) { - makeActive = ( -
  • - - - -
  • - ); - } - - let makeNotActive = null; - if (showMakeNotActive) { - makeNotActive = ( -
  • - - - -
  • - ); - } - - let manageTeams = null; - if (showManageTeams) { - manageTeams = ( -
  • - - - -
  • - ); - } - - let mfaReset = null; - if (showMfaReset) { - mfaReset = ( -
  • - - - -
  • - ); - } - - let passwordReset; - if (user.auth_service) { - passwordReset = ( -
  • - - - -
  • - ); - } else { - passwordReset = ( -
  • - - - -
  • - ); - } - - let manageTokens; - if (global.window.mm_config.EnableUserAccessTokens === 'true') { - manageTokens = ( -
  • - - - -
  • - ); - } - - let makeDemoteModal = null; - if (this.props.user.id === me.id) { - const title = ( - - ); - - const message = ( -
    - -
    -
    - - {serverError} -
    - ); - - const confirmButton = ( - - ); - - makeDemoteModal = ( - - ); - } - - const deactivateMemberModal = this.renderDeactivateMemberModal(); - - let displayedName = Utils.getDisplayName(user); - if (displayedName !== user.username) { - displayedName += ' (@' + user.username + ')'; - } - - return ( -
    - - {currentRoles} - - - {this.renderAccessToken()} -
      - {makeActive} - {makeNotActive} -
    • - - - -
    • - {manageTeams} - {manageTokens} - {mfaReset} - {passwordReset} -
    - {makeDemoteModal} - {deactivateMemberModal} - {serverError} -
    - ); - } -} diff --git a/webapp/components/admin_console/system_users/system_users_list.jsx b/webapp/components/admin_console/system_users/system_users_list.jsx deleted file mode 100644 index 8a7f30e1b..000000000 --- a/webapp/components/admin_console/system_users/system_users_list.jsx +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import PropTypes from 'prop-types'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; - -import ManageTeamsModal from 'components/admin_console/manage_teams_modal/manage_teams_modal.jsx'; -import ManageRolesModal from 'components/admin_console/manage_roles_modal'; -import ManageTokensModal from 'components/admin_console/manage_tokens_modal'; -import ResetPasswordModal from 'components/admin_console/reset_password_modal.jsx'; -import SearchableUserList from 'components/searchable_user_list/searchable_user_list.jsx'; - -import store from 'stores/redux_store.jsx'; -const dispatch = store.dispatch; -const getState = store.getState; - -import {getUser} from 'mattermost-redux/actions/users'; -import {Constants} from 'utils/constants.jsx'; -import * as Utils from 'utils/utils.jsx'; - -import SystemUsersDropdown from './system_users_dropdown.jsx'; - -export default class SystemUsersList extends React.Component { - static propTypes = { - users: PropTypes.arrayOf(PropTypes.object), - usersPerPage: PropTypes.number, - total: PropTypes.number, - nextPage: PropTypes.func, - search: PropTypes.func.isRequired, - focusOnMount: PropTypes.bool, - renderFilterRow: PropTypes.func, - - teamId: PropTypes.string.isRequired, - term: PropTypes.string.isRequired, - onTermChange: PropTypes.func.isRequired - }; - - constructor(props) { - super(props); - - this.state = { - page: 0, - - showManageTeamsModal: false, - showManageRolesModal: false, - showManageTokensModal: false, - showPasswordModal: false, - user: null - }; - } - - componentWillReceiveProps(nextProps) { - if (nextProps.teamId !== this.props.teamId) { - this.setState({page: 0}); - } - } - - nextPage = () => { - this.setState({page: this.state.page + 1}); - - this.props.nextPage(this.state.page + 1); - } - - previousPage = () => { - this.setState({page: this.state.page - 1}); - } - - search = (term) => { - this.props.search(term); - - if (term !== '') { - this.setState({page: 0}); - } - } - - doManageTeams = (user) => { - this.setState({ - showManageTeamsModal: true, - user - }); - } - - doManageRoles = (user) => { - this.setState({ - showManageRolesModal: true, - user - }); - } - - doManageTokens = (user) => { - this.setState({ - showManageTokensModal: true, - user - }); - } - - doManageTeamsDismiss = () => { - this.setState({ - showManageTeamsModal: false, - user: null - }); - } - - doManageRolesDismiss = () => { - this.setState({ - showManageRolesModal: false, - user: null - }); - } - - doManageTokensDismiss = () => { - this.setState({ - showManageTokensModal: false, - user: null - }); - } - - doPasswordReset = (user) => { - this.setState({ - showPasswordModal: true, - user - }); - } - - doPasswordResetDismiss = () => { - this.setState({ - showPasswordModal: false, - user: null - }); - } - - doPasswordResetSubmit = (user) => { - getUser(user.id)(dispatch, getState); - - this.setState({ - showPasswordModal: false, - user: null - }); - } - - getInfoForUser(user) { - const info = []; - - if (user.auth_service) { - let service; - if (user.auth_service === Constants.LDAP_SERVICE || user.auth_service === Constants.SAML_SERVICE) { - service = user.auth_service.toUpperCase(); - } else { - service = Utils.toTitleCase(user.auth_service); - } - - info.push( - - ); - } else { - info.push( - - ); - } - - const mfaEnabled = global.window.mm_license.IsLicensed === 'true' && - global.window.mm_license.MFA === 'true' && - global.window.mm_config.EnableMultifactorAuthentication === 'true'; - if (mfaEnabled) { - info.push(', '); - - if (user.mfa_active) { - info.push( - - ); - } else { - info.push( - - ); - } - } - - return info; - } - - renderCount(count, total, startCount, endCount, isSearch) { - if (total) { - if (isSearch) { - return ( - - ); - } else if (startCount !== 0 || endCount !== total) { - return ( - - ); - } - - return ( - - ); - } - - return null; - } - - render() { - const extraInfo = {}; - if (this.props.users) { - for (const user of this.props.users) { - extraInfo[user.id] = this.getInfoForUser(user); - } - } - - return ( -
    - - - - - -
    - ); - } -} diff --git a/webapp/components/admin_console/text_setting.jsx b/webapp/components/admin_console/text_setting.jsx deleted file mode 100644 index 5830828d2..000000000 --- a/webapp/components/admin_console/text_setting.jsx +++ /dev/null @@ -1,88 +0,0 @@ -import PropTypes from 'prop-types'; - -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import Setting from './setting.jsx'; - -export default class TextSetting extends React.Component { - static get propTypes() { - return { - id: PropTypes.string.isRequired, - label: PropTypes.node.isRequired, - placeholder: PropTypes.string, - helpText: PropTypes.node, - value: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number - ]).isRequired, - maxLength: PropTypes.number, - onChange: PropTypes.func, - disabled: PropTypes.bool, - type: PropTypes.oneOf([ - 'input', - 'textarea' - ]) - }; - } - - static get defaultProps() { - return { - type: 'input', - maxLength: null - }; - } - - constructor(props) { - super(props); - - this.handleChange = this.handleChange.bind(this); - } - - handleChange(e) { - this.props.onChange(this.props.id, e.target.value); - } - - render() { - let input = null; - if (this.props.type === 'input') { - input = ( - - ); - } else if (this.props.type === 'textarea') { - input = ( -