summaryrefslogtreecommitdiff
path: root/app/assets/javascripts
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/abuse_reports.js (renamed from app/assets/javascripts/abuse_reports.js.es6)0
-rw-r--r--app/assets/javascripts/activities.js (renamed from app/assets/javascripts/activities.js.es6)0
-rw-r--r--app/assets/javascripts/awards_handler.js876
-rw-r--r--app/assets/javascripts/behaviors/bind_in_out.js47
-rw-r--r--app/assets/javascripts/behaviors/gl_emoji.js217
-rw-r--r--app/assets/javascripts/behaviors/gl_emoji/spread_string.js50
-rw-r--r--app/assets/javascripts/behaviors/gl_emoji/unicode_support_map.js154
-rw-r--r--app/assets/javascripts/behaviors/toggler_behavior.js3
-rw-r--r--app/assets/javascripts/blob/blob_ci_yaml.js (renamed from app/assets/javascripts/blob/blob_ci_yaml.js.es6)0
-rw-r--r--app/assets/javascripts/blob/blob_dockerfile_selector.js (renamed from app/assets/javascripts/blob/blob_dockerfile_selector.js.es6)0
-rw-r--r--app/assets/javascripts/blob/blob_dockerfile_selectors.js (renamed from app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6)0
-rw-r--r--app/assets/javascripts/blob/blob_license_selectors.js (renamed from app/assets/javascripts/blob/blob_license_selectors.js.es6)0
-rw-r--r--app/assets/javascripts/blob/template_selector.js (renamed from app/assets/javascripts/blob/template_selector.js.es6)0
-rw-r--r--app/assets/javascripts/boards/boards_bundle.js (renamed from app/assets/javascripts/boards/boards_bundle.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/board.js (renamed from app/assets/javascripts/boards/components/board.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/board_blank_state.js (renamed from app/assets/javascripts/boards/components/board_blank_state.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/board_delete.js (renamed from app/assets/javascripts/boards/components/board_delete.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/board_list.js (renamed from app/assets/javascripts/boards/components/board_list.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/board_sidebar.js (renamed from app/assets/javascripts/boards/components/board_sidebar.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.js (renamed from app/assets/javascripts/boards/components/issue_card_inner.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/modal/empty_state.js (renamed from app/assets/javascripts/boards/components/modal/empty_state.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/modal/filters.js (renamed from app/assets/javascripts/boards/components/modal/filters.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/modal/filters/label.js (renamed from app/assets/javascripts/boards/components/modal/filters/label.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/modal/filters/milestone.js (renamed from app/assets/javascripts/boards/components/modal/filters/milestone.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/modal/filters/user.js (renamed from app/assets/javascripts/boards/components/modal/filters/user.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/modal/footer.js (renamed from app/assets/javascripts/boards/components/modal/footer.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/modal/header.js (renamed from app/assets/javascripts/boards/components/modal/header.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/modal/index.js (renamed from app/assets/javascripts/boards/components/modal/index.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/modal/list.js (renamed from app/assets/javascripts/boards/components/modal/list.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/modal/lists_dropdown.js (renamed from app/assets/javascripts/boards/components/modal/lists_dropdown.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/modal/tabs.js (renamed from app/assets/javascripts/boards/components/modal/tabs.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/new_list_dropdown.js (renamed from app/assets/javascripts/boards/components/new_list_dropdown.js.es6)0
-rw-r--r--app/assets/javascripts/boards/components/sidebar/remove_issue.js (renamed from app/assets/javascripts/boards/components/sidebar/remove_issue.js.es6)0
-rw-r--r--app/assets/javascripts/boards/filters/due_date_filters.js (renamed from app/assets/javascripts/boards/filters/due_date_filters.js.es6)0
-rw-r--r--app/assets/javascripts/boards/mixins/modal_mixins.js (renamed from app/assets/javascripts/boards/mixins/modal_mixins.js.es6)0
-rw-r--r--app/assets/javascripts/boards/mixins/sortable_default_options.js (renamed from app/assets/javascripts/boards/mixins/sortable_default_options.js.es6)0
-rw-r--r--app/assets/javascripts/boards/models/issue.js (renamed from app/assets/javascripts/boards/models/issue.js.es6)0
-rw-r--r--app/assets/javascripts/boards/models/label.js (renamed from app/assets/javascripts/boards/models/label.js.es6)0
-rw-r--r--app/assets/javascripts/boards/models/list.js (renamed from app/assets/javascripts/boards/models/list.js.es6)0
-rw-r--r--app/assets/javascripts/boards/models/milestone.js (renamed from app/assets/javascripts/boards/models/milestone.js.es6)0
-rw-r--r--app/assets/javascripts/boards/models/user.js (renamed from app/assets/javascripts/boards/models/user.js.es6)0
-rw-r--r--app/assets/javascripts/boards/services/board_service.js (renamed from app/assets/javascripts/boards/services/board_service.js.es6)0
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js (renamed from app/assets/javascripts/boards/stores/boards_store.js.es6)0
-rw-r--r--app/assets/javascripts/boards/stores/modal_store.js (renamed from app/assets/javascripts/boards/stores/modal_store.js.es6)0
-rw-r--r--app/assets/javascripts/build_variables.js (renamed from app/assets/javascripts/build_variables.js.es6)0
-rw-r--r--app/assets/javascripts/ci_lint_editor.js (renamed from app/assets/javascripts/ci_lint_editor.js.es6)0
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_bundle.js (renamed from app/assets/javascripts/commit/pipelines/pipelines_bundle.js.es6)0
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_service.js (renamed from app/assets/javascripts/commit/pipelines/pipelines_service.js.es6)0
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_store.js (renamed from app/assets/javascripts/commit/pipelines/pipelines_store.js.es6)0
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.js (renamed from app/assets/javascripts/commit/pipelines/pipelines_table.js.es6)10
-rw-r--r--app/assets/javascripts/commons/bootstrap.js10
-rw-r--r--app/assets/javascripts/commons/index.js2
-rw-r--r--app/assets/javascripts/commons/jquery.js11
-rw-r--r--app/assets/javascripts/compare_autocomplete.js (renamed from app/assets/javascripts/compare_autocomplete.js.es6)0
-rw-r--r--app/assets/javascripts/copy_as_gfm.js (renamed from app/assets/javascripts/copy_as_gfm.js.es6)5
-rw-r--r--app/assets/javascripts/create_label.js (renamed from app/assets/javascripts/create_label.js.es6)0
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_code_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_code_component.js.es6)0
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_issue_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_issue_component.js.es6)0
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_plan_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_plan_component.js.es6)10
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_production_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_production_component.js.es6)0
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_review_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_review_component.js.es6)0
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_staging_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_staging_component.js.es6)8
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_test_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_test_component.js.es6)11
-rw-r--r--app/assets/javascripts/cycle_analytics/components/total_time_component.js (renamed from app/assets/javascripts/cycle_analytics/components/total_time_component.js.es6)0
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js (renamed from app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js.es6)3
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_service.js (renamed from app/assets/javascripts/cycle_analytics/cycle_analytics_service.js.es6)0
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_store.js (renamed from app/assets/javascripts/cycle_analytics/cycle_analytics_store.js.es6)0
-rw-r--r--app/assets/javascripts/cycle_analytics/default_event_objects.js (renamed from app/assets/javascripts/cycle_analytics/default_event_objects.js.es6)0
-rw-r--r--app/assets/javascripts/cycle_analytics/svg/icon_branch.js.es67
-rw-r--r--app/assets/javascripts/cycle_analytics/svg/icon_branch.svg1
-rw-r--r--app/assets/javascripts/cycle_analytics/svg/icon_build_status.js.es67
-rw-r--r--app/assets/javascripts/cycle_analytics/svg/icon_build_status.svg1
-rw-r--r--app/assets/javascripts/cycle_analytics/svg/icon_commit.js.es67
-rw-r--r--app/assets/javascripts/cycle_analytics/svg/icon_commit.svg1
-rw-r--r--app/assets/javascripts/diff.js (renamed from app/assets/javascripts/diff.js.es6)10
-rw-r--r--app/assets/javascripts/diff_notes/components/comment_resolve_btn.js (renamed from app/assets/javascripts/diff_notes/components/comment_resolve_btn.js.es6)0
-rw-r--r--app/assets/javascripts/diff_notes/components/jump_to_discussion.js (renamed from app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6)0
-rw-r--r--app/assets/javascripts/diff_notes/components/resolve_btn.js (renamed from app/assets/javascripts/diff_notes/components/resolve_btn.js.es6)0
-rw-r--r--app/assets/javascripts/diff_notes/components/resolve_count.js (renamed from app/assets/javascripts/diff_notes/components/resolve_count.js.es6)0
-rw-r--r--app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js (renamed from app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6)0
-rw-r--r--app/assets/javascripts/diff_notes/diff_notes_bundle.js (renamed from app/assets/javascripts/diff_notes/diff_notes_bundle.js.es6)0
-rw-r--r--app/assets/javascripts/diff_notes/mixins/discussion.js (renamed from app/assets/javascripts/diff_notes/mixins/discussion.js.es6)0
-rw-r--r--app/assets/javascripts/diff_notes/models/discussion.js (renamed from app/assets/javascripts/diff_notes/models/discussion.js.es6)0
-rw-r--r--app/assets/javascripts/diff_notes/models/note.js (renamed from app/assets/javascripts/diff_notes/models/note.js.es6)0
-rw-r--r--app/assets/javascripts/diff_notes/services/resolve.js (renamed from app/assets/javascripts/diff_notes/services/resolve.js.es6)0
-rw-r--r--app/assets/javascripts/diff_notes/stores/comments.js (renamed from app/assets/javascripts/diff_notes/stores/comments.js.es6)0
-rw-r--r--app/assets/javascripts/dispatcher.js (renamed from app/assets/javascripts/dispatcher.js.es6)21
-rw-r--r--app/assets/javascripts/due_date_select.js (renamed from app/assets/javascripts/due_date_select.js.es6)0
-rw-r--r--app/assets/javascripts/environments/components/environment.js (renamed from app/assets/javascripts/environments/components/environment.js.es6)11
-rw-r--r--app/assets/javascripts/environments/components/environment_actions.js (renamed from app/assets/javascripts/environments/components/environment_actions.js.es6)12
-rw-r--r--app/assets/javascripts/environments/components/environment_external_url.js (renamed from app/assets/javascripts/environments/components/environment_external_url.js.es6)0
-rw-r--r--app/assets/javascripts/environments/components/environment_item.js (renamed from app/assets/javascripts/environments/components/environment_item.js.es6)36
-rw-r--r--app/assets/javascripts/environments/components/environment_rollback.js (renamed from app/assets/javascripts/environments/components/environment_rollback.js.es6)0
-rw-r--r--app/assets/javascripts/environments/components/environment_stop.js (renamed from app/assets/javascripts/environments/components/environment_stop.js.es6)0
-rw-r--r--app/assets/javascripts/environments/components/environment_terminal_button.js (renamed from app/assets/javascripts/environments/components/environment_terminal_button.js.es6)11
-rw-r--r--app/assets/javascripts/environments/components/environments_table.js (renamed from app/assets/javascripts/environments/components/environments_table.js.es6)20
-rw-r--r--app/assets/javascripts/environments/environments_bundle.js (renamed from app/assets/javascripts/environments/environments_bundle.js.es6)0
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_bundle.js (renamed from app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6)0
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_view.js (renamed from app/assets/javascripts/environments/folder/environments_folder_view.js.es6)2
-rw-r--r--app/assets/javascripts/environments/services/environments_service.js (renamed from app/assets/javascripts/environments/services/environments_service.js.es6)2
-rw-r--r--app/assets/javascripts/environments/stores/environments_store.js (renamed from app/assets/javascripts/environments/stores/environments_store.js.es6)0
-rw-r--r--app/assets/javascripts/extensions/array.js (renamed from app/assets/javascripts/extensions/array.js.es6)0
-rw-r--r--app/assets/javascripts/extensions/custom_event.js (renamed from app/assets/javascripts/extensions/custom_event.js.es6)0
-rw-r--r--app/assets/javascripts/extensions/element.js (renamed from app/assets/javascripts/extensions/element.js.es6)0
-rw-r--r--app/assets/javascripts/extensions/object.js (renamed from app/assets/javascripts/extensions/object.js.es6)0
-rw-r--r--app/assets/javascripts/extensions/string.js2
-rw-r--r--app/assets/javascripts/filterable_list.js45
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_hint.js (renamed from app/assets/javascripts/filtered_search/dropdown_hint.js.es6)0
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_non_user.js (renamed from app/assets/javascripts/filtered_search/dropdown_non_user.js.es6)0
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_user.js (renamed from app/assets/javascripts/filtered_search/dropdown_user.js.es6)0
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_utils.js (renamed from app/assets/javascripts/filtered_search/dropdown_utils.js.es6)0
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown.js (renamed from app/assets/javascripts/filtered_search/filtered_search_dropdown.js.es6)0
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js (renamed from app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6)0
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js (renamed from app/assets/javascripts/filtered_search/filtered_search_manager.js.es6)0
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_token_keys.js (renamed from app/assets/javascripts/filtered_search/filtered_search_token_keys.js.es6)0
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_tokenizer.js (renamed from app/assets/javascripts/filtered_search/filtered_search_tokenizer.js.es6)0
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js (renamed from app/assets/javascripts/gfm_auto_complete.js.es6)17
-rw-r--r--app/assets/javascripts/gl_field_error.js (renamed from app/assets/javascripts/gl_field_error.js.es6)0
-rw-r--r--app/assets/javascripts/gl_field_errors.js (renamed from app/assets/javascripts/gl_field_errors.js.es6)0
-rw-r--r--app/assets/javascripts/gl_form.js (renamed from app/assets/javascripts/gl_form.js.es6)0
-rw-r--r--app/assets/javascripts/graphs/graphs_bundle.js2
-rw-r--r--app/assets/javascripts/group_label_subscription.js (renamed from app/assets/javascripts/group_label_subscription.js.es6)0
-rw-r--r--app/assets/javascripts/groups_list.js45
-rw-r--r--app/assets/javascripts/issuable.js (renamed from app/assets/javascripts/issuable.js.es6)0
-rw-r--r--app/assets/javascripts/issuable/issuable_bundle.js (renamed from app/assets/javascripts/issuable/issuable_bundle.js.es6)0
-rw-r--r--app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js (renamed from app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js.es6)5
-rw-r--r--app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js (renamed from app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js.es6)0
-rw-r--r--app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js (renamed from app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js.es6)0
-rw-r--r--app/assets/javascripts/issuable/time_tracking/components/help_state.js (renamed from app/assets/javascripts/issuable/time_tracking/components/help_state.js.es6)0
-rw-r--r--app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js (renamed from app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js.es6)0
-rw-r--r--app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js (renamed from app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js.es6)0
-rw-r--r--app/assets/javascripts/issuable/time_tracking/components/time_tracker.js (renamed from app/assets/javascripts/issuable/time_tracking/components/time_tracker.js.es6)4
-rw-r--r--app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js (renamed from app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js.es6)2
-rw-r--r--app/assets/javascripts/issues_bulk_assignment.js (renamed from app/assets/javascripts/issues_bulk_assignment.js.es6)0
-rw-r--r--app/assets/javascripts/label_manager.js (renamed from app/assets/javascripts/label_manager.js.es6)0
-rw-r--r--app/assets/javascripts/lib/chart.js3
-rw-r--r--app/assets/javascripts/lib/cropper.js7
-rw-r--r--app/assets/javascripts/lib/d3.js3
-rw-r--r--app/assets/javascripts/lib/raphael.js9
-rw-r--r--app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js (renamed from app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js.es6)0
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js (renamed from app/assets/javascripts/lib/utils/common_utils.js.es6)11
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js (renamed from app/assets/javascripts/lib/utils/datetime_utility.js.es6)0
-rw-r--r--app/assets/javascripts/lib/utils/pretty_time.js (renamed from app/assets/javascripts/lib/utils/pretty_time.js.es6)0
-rw-r--r--app/assets/javascripts/lib/utils/text_utility.js18
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js (renamed from app/assets/javascripts/lib/utils/url_utility.js.es6)0
-rw-r--r--app/assets/javascripts/lib/vue_resource.js.es62
-rw-r--r--app/assets/javascripts/main.js (renamed from app/assets/javascripts/application.js)73
-rw-r--r--app/assets/javascripts/member_expiration_date.js (renamed from app/assets/javascripts/member_expiration_date.js.es6)0
-rw-r--r--app/assets/javascripts/members.js (renamed from app/assets/javascripts/members.js.es6)0
-rw-r--r--app/assets/javascripts/merge_conflicts/components/diff_file_editor.js (renamed from app/assets/javascripts/merge_conflicts/components/diff_file_editor.js.es6)0
-rw-r--r--app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js (renamed from app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js.es6)0
-rw-r--r--app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js (renamed from app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js.es6)0
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflict_service.js (renamed from app/assets/javascripts/merge_conflicts/merge_conflict_service.js.es6)0
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflict_store.js (renamed from app/assets/javascripts/merge_conflicts/merge_conflict_store.js.es6)0
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js (renamed from app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js.es6)0
-rw-r--r--app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js (renamed from app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js.es6)0
-rw-r--r--app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js (renamed from app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js.es6)0
-rw-r--r--app/assets/javascripts/merge_request_tabs.js (renamed from app/assets/javascripts/merge_request_tabs.js.es6)0
-rw-r--r--app/assets/javascripts/merge_request_widget.js (renamed from app/assets/javascripts/merge_request_widget.js.es6)46
-rw-r--r--app/assets/javascripts/merge_request_widget/ci_bundle.js (renamed from app/assets/javascripts/merge_request_widget/ci_bundle.js.es6)10
-rw-r--r--app/assets/javascripts/mini_pipeline_graph_dropdown.js (renamed from app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6)0
-rw-r--r--app/assets/javascripts/network/branch_graph.js703
-rw-r--r--app/assets/javascripts/network/network.js33
-rw-r--r--app/assets/javascripts/network/network_bundle.js26
-rw-r--r--app/assets/javascripts/network/raphael.js74
-rw-r--r--app/assets/javascripts/notes.js2
-rw-r--r--app/assets/javascripts/pager.js (renamed from app/assets/javascripts/pager.js.es6)0
-rw-r--r--app/assets/javascripts/pipelines.js (renamed from app/assets/javascripts/pipelines.js.es6)0
-rw-r--r--app/assets/javascripts/profile/gl_crop.js (renamed from app/assets/javascripts/profile/gl_crop.js.es6)2
-rw-r--r--app/assets/javascripts/profile/profile.js (renamed from app/assets/javascripts/profile/profile.js.es6)0
-rw-r--r--app/assets/javascripts/project_label_subscription.js (renamed from app/assets/javascripts/project_label_subscription.js.es6)0
-rw-r--r--app/assets/javascripts/project_variables.js (renamed from app/assets/javascripts/project_variables.js.es6)0
-rw-r--r--app/assets/javascripts/projects_list.js64
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js (renamed from app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js.es6)0
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_create.js (renamed from app/assets/javascripts/protected_branches/protected_branch_create.js.es6)0
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_dropdown.js (renamed from app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6)0
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_edit.js (renamed from app/assets/javascripts/protected_branches/protected_branch_edit.js.es6)0
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_edit_list.js (renamed from app/assets/javascripts/protected_branches/protected_branch_edit_list.js.es6)0
-rw-r--r--app/assets/javascripts/search_autocomplete.js (renamed from app/assets/javascripts/search_autocomplete.js.es6)0
-rw-r--r--app/assets/javascripts/shortcuts_blob.js (renamed from app/assets/javascripts/shortcuts_blob.js.es6)0
-rw-r--r--app/assets/javascripts/shortcuts_navigation.js2
-rw-r--r--app/assets/javascripts/signin_tabs_memoizer.js (renamed from app/assets/javascripts/signin_tabs_memoizer.js.es6)0
-rw-r--r--app/assets/javascripts/smart_interval.js (renamed from app/assets/javascripts/smart_interval.js.es6)0
-rw-r--r--app/assets/javascripts/snippets_list.js (renamed from app/assets/javascripts/snippets_list.js.es6)0
-rw-r--r--app/assets/javascripts/subbable_resource.js (renamed from app/assets/javascripts/subbable_resource.js.es6)0
-rw-r--r--app/assets/javascripts/subscription.js (renamed from app/assets/javascripts/subscription.js.es6)0
-rw-r--r--app/assets/javascripts/templates/issuable_template_selector.js (renamed from app/assets/javascripts/templates/issuable_template_selector.js.es6)0
-rw-r--r--app/assets/javascripts/templates/issuable_template_selectors.js (renamed from app/assets/javascripts/templates/issuable_template_selectors.js.es6)0
-rw-r--r--app/assets/javascripts/terminal/terminal.js (renamed from app/assets/javascripts/terminal/terminal.js.es6)0
-rw-r--r--app/assets/javascripts/terminal/terminal_bundle.js (renamed from app/assets/javascripts/terminal/terminal_bundle.js.es6)0
-rw-r--r--app/assets/javascripts/todos.js (renamed from app/assets/javascripts/todos.js.es6)0
-rw-r--r--app/assets/javascripts/u2f/authenticate.js (renamed from app/assets/javascripts/u2f/authenticate.js.es6)0
-rw-r--r--app/assets/javascripts/user.js (renamed from app/assets/javascripts/user.js.es6)0
-rw-r--r--app/assets/javascripts/user_callout.js4
-rw-r--r--app/assets/javascripts/user_tabs.js (renamed from app/assets/javascripts/user_tabs.js.es6)0
-rw-r--r--app/assets/javascripts/username_validator.js (renamed from app/assets/javascripts/username_validator.js.es6)0
-rw-r--r--app/assets/javascripts/users/calendar.js3
-rw-r--r--app/assets/javascripts/users_select.js23
-rw-r--r--app/assets/javascripts/version_check_image.js (renamed from app/assets/javascripts/version_check_image.js.es6)0
-rw-r--r--app/assets/javascripts/visibility_select.js (renamed from app/assets/javascripts/visibility_select.js.es6)0
-rw-r--r--app/assets/javascripts/vue_pipelines_index/index.js (renamed from app/assets/javascripts/vue_pipelines_index/index.js.es6)11
-rw-r--r--app/assets/javascripts/vue_pipelines_index/pipeline_actions.js (renamed from app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6)16
-rw-r--r--app/assets/javascripts/vue_pipelines_index/pipeline_url.js (renamed from app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6)0
-rw-r--r--app/assets/javascripts/vue_pipelines_index/pipelines.js (renamed from app/assets/javascripts/vue_pipelines_index/pipelines.js.es6)7
-rw-r--r--app/assets/javascripts/vue_pipelines_index/stage.js (renamed from app/assets/javascripts/vue_pipelines_index/stage.js.es6)42
-rw-r--r--app/assets/javascripts/vue_pipelines_index/status.js64
-rw-r--r--app/assets/javascripts/vue_pipelines_index/status.js.es634
-rw-r--r--app/assets/javascripts/vue_pipelines_index/store.js (renamed from app/assets/javascripts/vue_pipelines_index/store.js.es6)0
-rw-r--r--app/assets/javascripts/vue_pipelines_index/time_ago.js (renamed from app/assets/javascripts/vue_pipelines_index/time_ago.js.es6)7
-rw-r--r--app/assets/javascripts/vue_realtime_listener/index.js (renamed from app/assets/javascripts/vue_realtime_listener/index.js.es6)0
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.js (renamed from app/assets/javascripts/vue_shared/components/commit.js.es6)10
-rw-r--r--app/assets/javascripts/vue_shared/components/pipelines_table.js (renamed from app/assets/javascripts/vue_shared/components/pipelines_table.js.es6)11
-rw-r--r--app/assets/javascripts/vue_shared/components/pipelines_table_row.js (renamed from app/assets/javascripts/vue_shared/components/pipelines_table_row.js.es6)45
-rw-r--r--app/assets/javascripts/vue_shared/components/table_pagination.js (renamed from app/assets/javascripts/vue_shared/components/table_pagination.js.es6)1
-rw-r--r--app/assets/javascripts/vue_shared/vue_resource_interceptor.js (renamed from app/assets/javascripts/vue_shared/vue_resource_interceptor.js.es6)0
-rw-r--r--app/assets/javascripts/wikis.js (renamed from app/assets/javascripts/wikis.js.es6)0
216 files changed, 1813 insertions, 1241 deletions
diff --git a/app/assets/javascripts/abuse_reports.js.es6 b/app/assets/javascripts/abuse_reports.js
index 8a260aae1b1..8a260aae1b1 100644
--- a/app/assets/javascripts/abuse_reports.js.es6
+++ b/app/assets/javascripts/abuse_reports.js
diff --git a/app/assets/javascripts/activities.js.es6 b/app/assets/javascripts/activities.js
index 648cb4d5d85..648cb4d5d85 100644
--- a/app/assets/javascripts/activities.js.es6
+++ b/app/assets/javascripts/activities.js
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js
index a4ccb30e447..4667980a960 100644
--- a/app/assets/javascripts/awards_handler.js
+++ b/app/assets/javascripts/awards_handler.js
@@ -1,380 +1,518 @@
-/* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, no-var, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, no-unused-vars, no-else-return, prefer-template, quotes, comma-dangle, no-param-reassign, no-void, brace-style, no-underscore-dangle, no-return-assign, camelcase */
/* global Cookies */
-var emojiAliases = require('emoji-aliases');
-
-(function() {
- this.AwardsHandler = (function() {
- var FROM_SENTENCE_REGEX = /(?:, and | and |, )/; // For separating lists produced by ruby's Array#toSentence
- function AwardsHandler() {
- this.aliases = emojiAliases;
- $(document).off('click', '.js-add-award').on('click', '.js-add-award', (function(_this) {
- return function(e) {
- e.stopPropagation();
- e.preventDefault();
- return _this.showEmojiMenu($(e.currentTarget));
- };
- })(this));
- $('html').on('click', function(e) {
- var $target;
- $target = $(e.target);
- if (!$target.closest('.emoji-menu-content').length) {
- $('.js-awards-block.current').removeClass('current');
- }
- if (!$target.closest('.emoji-menu').length) {
- if ($('.emoji-menu').is(':visible')) {
- $('.js-add-award.is-active').removeClass('is-active');
- return $('.emoji-menu').removeClass('is-visible');
- }
- }
- });
- $(document).off('click', '.js-emoji-btn').on('click', '.js-emoji-btn', (function(_this) {
- return function(e) {
- var $target, emoji;
- e.preventDefault();
- $target = $(e.currentTarget);
- emoji = $target.find('.icon').data('emoji');
- $target.closest('.js-awards-block').addClass('current');
- return _this.addAward(_this.getVotesBlock(), _this.getAwardUrl(), emoji);
- };
- })(this));
+const emojiMap = require('emoji-map');
+const emojiAliases = require('emoji-aliases');
+const glEmoji = require('./behaviors/gl_emoji');
+
+const glEmojiTag = glEmoji.glEmojiTag;
+
+const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd';
+const requestAnimationFrame = window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.setTimeout;
+
+const FROM_SENTENCE_REGEX = /(?:, and | and |, )/; // For separating lists produced by ruby's Array#toSentence
+
+let categoryMap = null;
+
+const categoryLabelMap = {
+ activity: 'Activity',
+ people: 'People',
+ nature: 'Nature',
+ food: 'Food',
+ travel: 'Travel',
+ objects: 'Objects',
+ symbols: 'Symbols',
+ flags: 'Flags',
+};
+
+function buildCategoryMap() {
+ return Object.keys(emojiMap).reduce((currentCategoryMap, emojiNameKey) => {
+ const emojiInfo = emojiMap[emojiNameKey];
+ if (currentCategoryMap[emojiInfo.category]) {
+ currentCategoryMap[emojiInfo.category].push(emojiNameKey);
}
- AwardsHandler.prototype.showEmojiMenu = function($addBtn) {
- var $holder, $menu, url;
- $menu = $('.emoji-menu');
- if ($addBtn.hasClass('js-note-emoji')) {
- $addBtn.closest('.note').find('.js-awards-block').addClass('current');
- } else {
- $addBtn.closest('.js-awards-block').addClass('current');
- }
- if ($menu.length) {
- $holder = $addBtn.closest('.js-award-holder');
- if ($menu.is('.is-visible')) {
- $addBtn.removeClass('is-active');
- $menu.removeClass('is-visible');
- return $('#emoji_search').blur();
- } else {
- $addBtn.addClass('is-active');
- this.positionMenu($menu, $addBtn);
- $menu.addClass('is-visible');
- return $('#emoji_search').focus();
- }
- } else {
- $addBtn.addClass('is-loading is-active');
- url = this.getAwardMenuUrl();
- return this.createEmojiMenu(url, (function(_this) {
- return function() {
- $addBtn.removeClass('is-loading');
- $menu = $('.emoji-menu');
- _this.positionMenu($menu, $addBtn);
- if (!_this.frequentEmojiBlockRendered) {
- _this.renderFrequentlyUsedBlock();
- }
- return setTimeout(function() {
- $menu.addClass('is-visible');
- $('#emoji_search').focus();
- return _this.setupSearch();
- }, 200);
- };
- })(this));
- }
- };
-
- AwardsHandler.prototype.createEmojiMenu = function(awardMenuUrl, callback) {
- return $.get(awardMenuUrl, function(response) {
- $('body').append(response);
- return callback();
+ return currentCategoryMap;
+ }, {
+ activity: [],
+ people: [],
+ nature: [],
+ food: [],
+ travel: [],
+ objects: [],
+ symbols: [],
+ flags: [],
+ });
+}
+
+function renderCategory(name, emojiList) {
+ return `
+ <h5 class="emoji-menu-title">
+ ${name}
+ </h5>
+ <ul class="clearfix emoji-menu-list">
+ ${emojiList.map(emojiName => `
+ <li class="emoji-menu-list-item">
+ <button class="emoji-menu-btn text-center js-emoji-btn" type="button">
+ ${glEmojiTag(emojiName, {
+ sprite: true,
+ })}
+ </button>
+ </li>
+ `).join('\n')}
+ </ul>
+ `;
+}
+
+function AwardsHandler() {
+ this.eventListeners = [];
+ this.aliases = emojiAliases;
+ // If the user shows intent let's pre-build the menu
+ this.registerEventListener('one', $(document), 'mouseenter focus', '.js-add-award', 'mouseenter focus', () => {
+ const $menu = $('.emoji-menu');
+ if ($menu.length === 0) {
+ requestAnimationFrame(() => {
+ this.createEmojiMenu();
});
- };
-
- AwardsHandler.prototype.positionMenu = function($menu, $addBtn) {
- var css, position;
- position = $addBtn.data('position');
- // The menu could potentially be off-screen or in a hidden overflow element
- // So we position the element absolute in the body
- css = {
- top: ($addBtn.offset().top + $addBtn.outerHeight()) + "px"
- };
- if (position === 'right') {
- css.left = (($addBtn.offset().left - $menu.outerWidth()) + 20) + "px";
- $menu.addClass('is-aligned-right');
- } else {
- css.left = ($addBtn.offset().left) + "px";
- $menu.removeClass('is-aligned-right');
- }
- return $menu.css(css);
- };
-
- AwardsHandler.prototype.addAward = function(votesBlock, awardUrl, emoji, checkMutuality, callback) {
- if (checkMutuality == null) {
- checkMutuality = true;
- }
- emoji = this.normilizeEmojiName(emoji);
- this.postEmoji(awardUrl, emoji, (function(_this) {
- return function() {
- _this.addAwardToEmojiBar(votesBlock, emoji, checkMutuality);
- return typeof callback === "function" ? callback() : void 0;
- };
- })(this));
- return $('.emoji-menu').removeClass('is-visible');
- };
-
- AwardsHandler.prototype.addAwardToEmojiBar = function(votesBlock, emoji, checkForMutuality) {
- var $emojiButton, counter;
- if (checkForMutuality == null) {
- checkForMutuality = true;
- }
- if (checkForMutuality) {
- this.checkMutuality(votesBlock, emoji);
- }
- this.addEmojiToFrequentlyUsedList(emoji);
- emoji = this.normilizeEmojiName(emoji);
- $emojiButton = this.findEmojiIcon(votesBlock, emoji).parent();
- if ($emojiButton.length > 0) {
- if (this.isActive($emojiButton)) {
- return this.decrementCounter($emojiButton, emoji);
- } else {
- counter = $emojiButton.find('.js-counter');
- counter.text(parseInt(counter.text(), 10) + 1);
- $emojiButton.addClass('active');
- this.addYouToUserList(votesBlock, emoji);
- return this.animateEmoji($emojiButton);
- }
- } else {
- votesBlock.removeClass('hidden');
- return this.createEmoji(votesBlock, emoji);
- }
- };
-
- AwardsHandler.prototype.getVotesBlock = function() {
- var currentBlock;
- currentBlock = $('.js-awards-block.current');
- if (currentBlock.length) {
- return currentBlock;
- } else {
- return $('.js-awards-block').eq(0);
- }
- };
-
- AwardsHandler.prototype.getAwardUrl = function() {
- return this.getVotesBlock().data('award-url');
- };
-
- AwardsHandler.prototype.checkMutuality = function(votesBlock, emoji) {
- var $emojiButton, awardUrl, isAlreadyVoted, mutualVote;
- awardUrl = this.getAwardUrl();
- if (emoji === 'thumbsup' || emoji === 'thumbsdown') {
- mutualVote = emoji === 'thumbsup' ? 'thumbsdown' : 'thumbsup';
- $emojiButton = votesBlock.find("[data-emoji=" + mutualVote + "]").parent();
- isAlreadyVoted = $emojiButton.hasClass('active');
- if (isAlreadyVoted) {
- this.addAward(votesBlock, awardUrl, mutualVote, false);
- }
- }
- };
-
- AwardsHandler.prototype.isActive = function($emojiButton) {
- return $emojiButton.hasClass('active');
- };
-
- AwardsHandler.prototype.decrementCounter = function($emojiButton, emoji) {
- var counter, counterNumber;
- counter = $('.js-counter', $emojiButton);
- counterNumber = parseInt(counter.text(), 10);
- if (counterNumber > 1) {
- counter.text(counterNumber - 1);
- this.removeYouFromUserList($emojiButton, emoji);
- } else if (emoji === 'thumbsup' || emoji === 'thumbsdown') {
- $emojiButton.tooltip('destroy');
- counter.text('0');
- this.removeYouFromUserList($emojiButton, emoji);
- if ($emojiButton.parents('.note').length) {
- this.removeEmoji($emojiButton);
- }
- } else {
- this.removeEmoji($emojiButton);
- }
- return $emojiButton.removeClass('active');
- };
-
- AwardsHandler.prototype.removeEmoji = function($emojiButton) {
- var $votesBlock;
- $emojiButton.tooltip('destroy');
- $emojiButton.remove();
- $votesBlock = this.getVotesBlock();
- if ($votesBlock.find('.js-emoji-btn').length === 0) {
- return $votesBlock.addClass('hidden');
- }
- };
-
- AwardsHandler.prototype.getAwardTooltip = function($awardBlock) {
- return $awardBlock.attr('data-original-title') || $awardBlock.attr('data-title') || '';
- };
-
- AwardsHandler.prototype.toSentence = function(list) {
- if (list.length <= 2) {
- return list.join(' and ');
+ }
+ // Prebuild the categoryMap
+ categoryMap = categoryMap || buildCategoryMap();
+ });
+ this.registerEventListener('on', $(document), 'click', '.js-add-award', (e) => {
+ e.stopPropagation();
+ e.preventDefault();
+ this.showEmojiMenu($(e.currentTarget));
+ });
+
+ this.registerEventListener('on', $('html'), 'click', (e) => {
+ const $target = $(e.target);
+ if (!$target.closest('.emoji-menu-content').length) {
+ $('.js-awards-block.current').removeClass('current');
+ }
+ if (!$target.closest('.emoji-menu').length) {
+ if ($('.emoji-menu').is(':visible')) {
+ $('.js-add-award.is-active').removeClass('is-active');
+ $('.emoji-menu').removeClass('is-visible');
}
- else {
- return list.slice(0, -1).join(', ') + ', and ' + list[list.length - 1];
+ }
+ });
+ this.registerEventListener('on', $(document), 'click', '.js-emoji-btn', (e) => {
+ e.preventDefault();
+ const $target = $(e.currentTarget);
+ const $glEmojiElement = $target.find('gl-emoji');
+ const $spriteIconElement = $target.find('.icon');
+ const emoji = ($glEmojiElement.length ? $glEmojiElement : $spriteIconElement).data('name');
+ $target.closest('.js-awards-block').addClass('current');
+ return this.addAward(this.getVotesBlock(), this.getAwardUrl(), emoji);
+ });
+}
+
+AwardsHandler.prototype.registerEventListener = function registerEventListener(method = 'on', element, ...args) {
+ element[method].call(element, ...args);
+ this.eventListeners.push({
+ element,
+ args,
+ });
+};
+
+AwardsHandler.prototype.showEmojiMenu = function showEmojiMenu($addBtn) {
+ if ($addBtn.hasClass('js-note-emoji')) {
+ $addBtn.closest('.note').find('.js-awards-block').addClass('current');
+ } else {
+ $addBtn.closest('.js-awards-block').addClass('current');
+ }
+
+ const $menu = $('.emoji-menu');
+ if ($menu.length) {
+ if ($menu.is('.is-visible')) {
+ $addBtn.removeClass('is-active');
+ $menu.removeClass('is-visible');
+ $('#emoji_search').blur();
+ } else {
+ $addBtn.addClass('is-active');
+ this.positionMenu($menu, $addBtn);
+ $menu.addClass('is-visible');
+ $('#emoji_search').focus();
+ }
+ } else {
+ $addBtn.addClass('is-loading is-active');
+ this.createEmojiMenu(() => {
+ const $createdMenu = $('.emoji-menu');
+ $addBtn.removeClass('is-loading');
+ this.positionMenu($createdMenu, $addBtn);
+ if (!this.frequentEmojiBlockRendered) {
+ this.renderFrequentlyUsedBlock();
}
- };
-
- AwardsHandler.prototype.removeYouFromUserList = function($emojiButton, emoji) {
- var authors, awardBlock, newAuthors, originalTitle;
- awardBlock = $emojiButton;
- originalTitle = this.getAwardTooltip(awardBlock);
- authors = originalTitle.split(FROM_SENTENCE_REGEX);
- authors.splice(authors.indexOf('You'), 1);
- return awardBlock
- .closest('.js-emoji-btn')
- .removeData('title')
- .removeAttr('data-title')
- .removeAttr('data-original-title')
- .attr('title', this.toSentence(authors))
- .tooltip('fixTitle');
- };
-
- AwardsHandler.prototype.addYouToUserList = function(votesBlock, emoji) {
- var awardBlock, origTitle, users;
- awardBlock = this.findEmojiIcon(votesBlock, emoji).parent();
- origTitle = this.getAwardTooltip(awardBlock);
- users = [];
- if (origTitle) {
- users = origTitle.trim().split(FROM_SENTENCE_REGEX);
+ return setTimeout(() => {
+ $createdMenu.addClass('is-visible');
+ $('#emoji_search').focus();
+ }, 200);
+ });
+ }
+};
+
+// Create the emoji menu with the first category of emojis.
+// Then render the remaining categories of emojis one by one to avoid jank.
+AwardsHandler.prototype.createEmojiMenu = function createEmojiMenu(callback) {
+ if (this.isCreatingEmojiMenu) {
+ return;
+ }
+ this.isCreatingEmojiMenu = true;
+
+ // Render the first category
+ categoryMap = categoryMap || buildCategoryMap();
+ const categoryNameKey = Object.keys(categoryMap)[0];
+ const emojisInCategory = categoryMap[categoryNameKey];
+ const firstCategory = renderCategory(categoryLabelMap[categoryNameKey], emojisInCategory);
+
+ const emojiMenuMarkup = `
+ <div class="emoji-menu">
+ <input type="text" name="emoji_search" id="emoji_search" value="" class="emoji-search search-input form-control" placeholder="Search emoji" />
+
+ <div class="emoji-menu-content">
+ ${firstCategory}
+ </div>
+ </div>
+ `;
+
+ document.body.insertAdjacentHTML('beforeend', emojiMenuMarkup);
+
+ this.addRemainingEmojiMenuCategories();
+ this.setupSearch();
+ if (callback) {
+ callback();
+ }
+};
+
+AwardsHandler
+ .prototype
+ .addRemainingEmojiMenuCategories = function addRemainingEmojiMenuCategories() {
+ if (this.isAddingRemainingEmojiMenuCategories) {
+ return;
+ }
+ this.isAddingRemainingEmojiMenuCategories = true;
+
+ categoryMap = categoryMap || buildCategoryMap();
+
+ // Avoid the jank and render the remaining categories separately
+ // This will take more time, but makes UI more responsive
+ const menu = document.querySelector('.emoji-menu');
+ const emojiContentElement = menu.querySelector('.emoji-menu-content');
+ const remainingCategories = Object.keys(categoryMap).slice(1);
+ const allCategoriesAddedPromise = remainingCategories.reduce(
+ (promiseChain, categoryNameKey) =>
+ promiseChain.then(() =>
+ new Promise((resolve) => {
+ const emojisInCategory = categoryMap[categoryNameKey];
+ const categoryMarkup = renderCategory(
+ categoryLabelMap[categoryNameKey],
+ emojisInCategory,
+ );
+ requestAnimationFrame(() => {
+ emojiContentElement.insertAdjacentHTML('beforeend', categoryMarkup);
+ resolve();
+ });
+ }),
+ ),
+ Promise.resolve(),
+ );
+
+ allCategoriesAddedPromise.then(() => {
+ // Used for tests
+ // We check for the menu in case it was destroyed in the meantime
+ if (menu) {
+ menu.dispatchEvent(new CustomEvent('build-emoji-menu-finish'));
}
- users.unshift('You');
- return awardBlock
- .attr('title', this.toSentence(users))
- .tooltip('fixTitle');
- };
-
- AwardsHandler.prototype.createEmoji_ = function(votesBlock, emoji) {
- var $emojiButton, buttonHtml, emojiCssClass;
- emojiCssClass = this.resolveNameToCssClass(emoji);
- buttonHtml = "<button class='btn award-control js-emoji-btn has-tooltip active' title='You' data-placement='bottom'> <div class='icon emoji-icon " + emojiCssClass + "' data-emoji='" + emoji + "'></div> <span class='award-control-text js-counter'>1</span> </button>";
- $emojiButton = $(buttonHtml);
- $emojiButton.insertBefore(votesBlock.find('.js-award-holder')).find('.emoji-icon').data('emoji', emoji);
+ });
+ };
+
+AwardsHandler.prototype.positionMenu = function positionMenu($menu, $addBtn) {
+ const position = $addBtn.data('position');
+ // The menu could potentially be off-screen or in a hidden overflow element
+ // So we position the element absolute in the body
+ const css = {
+ top: `${$addBtn.offset().top + $addBtn.outerHeight()}px`,
+ };
+ if (position === 'right') {
+ css.left = `${($addBtn.offset().left - $menu.outerWidth()) + 20}px`;
+ $menu.addClass('is-aligned-right');
+ } else {
+ css.left = `${$addBtn.offset().left}px`;
+ $menu.removeClass('is-aligned-right');
+ }
+ return $menu.css(css);
+};
+
+AwardsHandler.prototype.addAward = function addAward(
+ votesBlock,
+ awardUrl,
+ emoji,
+ checkMutuality,
+ callback,
+) {
+ const normalizedEmoji = this.normalizeEmojiName(emoji);
+ this.postEmoji(awardUrl, normalizedEmoji, () => {
+ this.addAwardToEmojiBar(votesBlock, normalizedEmoji, checkMutuality);
+ return typeof callback === 'function' ? callback() : undefined;
+ });
+ return $('.emoji-menu').removeClass('is-visible');
+};
+
+AwardsHandler.prototype.addAwardToEmojiBar = function addAwardToEmojiBar(
+ votesBlock,
+ emoji,
+ checkForMutuality,
+) {
+ if (checkForMutuality || checkForMutuality === null) {
+ this.checkMutuality(votesBlock, emoji);
+ }
+ this.addEmojiToFrequentlyUsedList(emoji);
+ const normalizedEmoji = this.normalizeEmojiName(emoji);
+ const $emojiButton = this.findEmojiIcon(votesBlock, normalizedEmoji).parent();
+ if ($emojiButton.length > 0) {
+ if (this.isActive($emojiButton)) {
+ this.decrementCounter($emojiButton, normalizedEmoji);
+ } else {
+ const counter = $emojiButton.find('.js-counter');
+ counter.text(parseInt(counter.text(), 10) + 1);
+ $emojiButton.addClass('active');
+ this.addYouToUserList(votesBlock, normalizedEmoji);
this.animateEmoji($emojiButton);
- $('.award-control').tooltip();
- return votesBlock.removeClass('current');
- };
-
- AwardsHandler.prototype.animateEmoji = function($emoji) {
- var className = 'pulse animated once short';
- $emoji.addClass(className);
+ }
+ } else {
+ votesBlock.removeClass('hidden');
+ this.createEmoji(votesBlock, normalizedEmoji);
+ }
+};
+
+AwardsHandler.prototype.getVotesBlock = function getVotesBlock() {
+ const currentBlock = $('.js-awards-block.current');
+ let resultantVotesBlock = currentBlock;
+ if (currentBlock.length === 0) {
+ resultantVotesBlock = $('.js-awards-block').eq(0);
+ }
+
+ return resultantVotesBlock;
+};
+
+AwardsHandler.prototype.getAwardUrl = function getAwardUrl() {
+ return this.getVotesBlock().data('award-url');
+};
+
+AwardsHandler.prototype.checkMutuality = function checkMutuality(votesBlock, emoji) {
+ const awardUrl = this.getAwardUrl();
+ if (emoji === 'thumbsup' || emoji === 'thumbsdown') {
+ const mutualVote = emoji === 'thumbsup' ? 'thumbsdown' : 'thumbsup';
+ const $emojiButton = votesBlock.find(`[data-name="${mutualVote}"]`).parent();
+ const isAlreadyVoted = $emojiButton.hasClass('active');
+ if (isAlreadyVoted) {
+ this.addAward(votesBlock, awardUrl, mutualVote, false);
+ }
+ }
+};
+
+AwardsHandler.prototype.isActive = function isActive($emojiButton) {
+ return $emojiButton.hasClass('active');
+};
+
+AwardsHandler.prototype.decrementCounter = function decrementCounter($emojiButton, emoji) {
+ const counter = $('.js-counter', $emojiButton);
+ const counterNumber = parseInt(counter.text(), 10);
+ if (counterNumber > 1) {
+ counter.text(counterNumber - 1);
+ this.removeYouFromUserList($emojiButton);
+ } else if (emoji === 'thumbsup' || emoji === 'thumbsdown') {
+ $emojiButton.tooltip('destroy');
+ counter.text('0');
+ this.removeYouFromUserList($emojiButton);
+ if ($emojiButton.parents('.note').length) {
+ this.removeEmoji($emojiButton);
+ }
+ } else {
+ this.removeEmoji($emojiButton);
+ }
+ return $emojiButton.removeClass('active');
+};
+
+AwardsHandler.prototype.removeEmoji = function removeEmoji($emojiButton) {
+ $emojiButton.tooltip('destroy');
+ $emojiButton.remove();
+ const $votesBlock = this.getVotesBlock();
+ if ($votesBlock.find('.js-emoji-btn').length === 0) {
+ $votesBlock.addClass('hidden');
+ }
+};
+
+AwardsHandler.prototype.getAwardTooltip = function getAwardTooltip($awardBlock) {
+ return $awardBlock.attr('data-original-title') || $awardBlock.attr('data-title') || '';
+};
+
+AwardsHandler.prototype.toSentence = function toSentence(list) {
+ let sentence;
+ if (list.length <= 2) {
+ sentence = list.join(' and ');
+ } else {
+ sentence = `${list.slice(0, -1).join(', ')}, and ${list[list.length - 1]}`;
+ }
+
+ return sentence;
+};
+
+AwardsHandler.prototype.removeYouFromUserList = function removeYouFromUserList($emojiButton) {
+ const awardBlock = $emojiButton;
+ const originalTitle = this.getAwardTooltip(awardBlock);
+ const authors = originalTitle.split(FROM_SENTENCE_REGEX);
+ authors.splice(authors.indexOf('You'), 1);
+ return awardBlock
+ .closest('.js-emoji-btn')
+ .removeData('title')
+ .removeAttr('data-title')
+ .removeAttr('data-original-title')
+ .attr('title', this.toSentence(authors))
+ .tooltip('fixTitle');
+};
+
+AwardsHandler.prototype.addYouToUserList = function addYouToUserList(votesBlock, emoji) {
+ const awardBlock = this.findEmojiIcon(votesBlock, emoji).parent();
+ const origTitle = this.getAwardTooltip(awardBlock);
+ let users = [];
+ if (origTitle) {
+ users = origTitle.trim().split(FROM_SENTENCE_REGEX);
+ }
+ users.unshift('You');
+ return awardBlock
+ .attr('title', this.toSentence(users))
+ .tooltip('fixTitle');
+};
+
+AwardsHandler
+ .prototype
+ .createAwardButtonForVotesBlock = function createAwardButtonForVotesBlock(votesBlock, emojiName) {
+ const buttonHtml = `
+ <button class="btn award-control js-emoji-btn has-tooltip active" title="You" data-placement="bottom">
+ ${glEmojiTag(emojiName)}
+ <span class="award-control-text js-counter">1</span>
+ </button>
+ `;
+ const $emojiButton = $(buttonHtml);
+ $emojiButton.insertBefore(votesBlock.find('.js-award-holder')).find('.emoji-icon').data('name', emojiName);
+ this.animateEmoji($emojiButton);
+ $('.award-control').tooltip();
+ votesBlock.removeClass('current');
+ };
+
+AwardsHandler.prototype.animateEmoji = function animateEmoji($emoji) {
+ const className = 'pulse animated once short';
+ $emoji.addClass(className);
+
+ this.registerEventListener('on', $emoji, animationEndEventString, (e) => {
+ $(e.currentTarget).removeClass(className);
+ });
+};
+
+AwardsHandler.prototype.createEmoji = function createEmoji(votesBlock, emoji) {
+ if ($('.emoji-menu').length) {
+ this.createAwardButtonForVotesBlock(votesBlock, emoji);
+ }
+ this.createEmojiMenu(() => {
+ this.createAwardButtonForVotesBlock(votesBlock, emoji);
+ });
+};
+
+AwardsHandler.prototype.postEmoji = function postEmoji(awardUrl, emoji, callback) {
+ return $.post(awardUrl, {
+ name: emoji,
+ }, (data) => {
+ if (data.ok) {
+ callback();
+ }
+ });
+};
+
+AwardsHandler.prototype.findEmojiIcon = function findEmojiIcon(votesBlock, emoji) {
+ return votesBlock.find(`.js-emoji-btn [data-name="${emoji}"]`);
+};
+
+AwardsHandler.prototype.scrollToAwards = function scrollToAwards() {
+ const options = {
+ scrollTop: $('.awards').offset().top - 110,
+ };
+ return $('body, html').animate(options, 200);
+};
+
+AwardsHandler.prototype.normalizeEmojiName = function normalizeEmojiName(emoji) {
+ return Object.prototype.hasOwnProperty.call(this.aliases, emoji) ? this.aliases[emoji] : emoji;
+};
+
+AwardsHandler
+ .prototype
+ .addEmojiToFrequentlyUsedList = function addEmojiToFrequentlyUsedList(emoji) {
+ const frequentlyUsedEmojis = this.getFrequentlyUsedEmojis();
+ frequentlyUsedEmojis.push(emoji);
+ Cookies.set('frequently_used_emojis', frequentlyUsedEmojis.join(','), { expires: 365 });
+ };
+
+AwardsHandler.prototype.getFrequentlyUsedEmojis = function getFrequentlyUsedEmojis() {
+ const frequentlyUsedEmojis = (Cookies.get('frequently_used_emojis') || '').split(',');
+ return _.compact(_.uniq(frequentlyUsedEmojis));
+};
+
+AwardsHandler.prototype.renderFrequentlyUsedBlock = function renderFrequentlyUsedBlock() {
+ if (Cookies.get('frequently_used_emojis')) {
+ const frequentlyUsedEmojis = this.getFrequentlyUsedEmojis();
+ const ul = $('<ul class="clearfix emoji-menu-list frequent-emojis">');
+ for (let i = 0, len = frequentlyUsedEmojis.length; i < len; i += 1) {
+ const emoji = frequentlyUsedEmojis[i];
+ $(`.emoji-menu-content [data-name="${emoji}"]`).closest('li').clone().appendTo(ul);
+ }
+ $('.emoji-menu-content').prepend(ul).prepend($('<h5>').text('Frequently used'));
+ }
+ this.frequentEmojiBlockRendered = true;
+};
+
+AwardsHandler.prototype.setupSearch = function setupSearch() {
+ this.registerEventListener('on', $('input.emoji-search'), 'input', (e) => {
+ const term = $(e.target).val().trim();
+ // Clean previous search results
+ $('ul.emoji-menu-search, h5.emoji-search').remove();
+ if (term.length > 0) {
+ // Generate a search result block
+ const h5 = $('<h5 class="emoji-search" />').text('Search results');
+ const foundEmojis = this.searchEmojis(term).show();
+ const ul = $('<ul>').addClass('emoji-menu-list emoji-menu-search').append(foundEmojis);
+ $('.emoji-menu-content ul, .emoji-menu-content h5').hide();
+ $('.emoji-menu-content').append(h5).append(ul);
+ } else {
+ $('.emoji-menu-content').children().show();
+ }
+ });
+};
- $emoji.on('webkitAnimationEnd animationEnd', function() {
- $(this).removeClass(className);
- });
- };
+AwardsHandler.prototype.searchEmojis = function searchEmojis(term) {
+ const safeTerm = term.toLowerCase();
- AwardsHandler.prototype.createEmoji = function(votesBlock, emoji) {
- if ($('.emoji-menu').length) {
- return this.createEmoji_(votesBlock, emoji);
- }
- return this.createEmojiMenu(this.getAwardMenuUrl(), (function(_this) {
- return function() {
- return _this.createEmoji_(votesBlock, emoji);
- };
- })(this));
- };
-
- AwardsHandler.prototype.getAwardMenuUrl = function() {
- return gon.award_menu_url;
- };
-
- AwardsHandler.prototype.resolveNameToCssClass = function(emoji) {
- var emojiIcon, unicodeName;
- emojiIcon = $(".emoji-menu-content [data-emoji='" + emoji + "']");
- if (emojiIcon.length > 0) {
- unicodeName = emojiIcon.data('unicode-name');
- } else {
- // Find by alias
- unicodeName = $(".emoji-menu-content [data-aliases*=':" + emoji + ":']").data('unicode-name');
- }
- return "emoji-" + unicodeName;
- };
-
- AwardsHandler.prototype.postEmoji = function(awardUrl, emoji, callback) {
- return $.post(awardUrl, {
- name: emoji
- }, function(data) {
- if (data.ok) {
- return callback();
- }
- });
- };
-
- AwardsHandler.prototype.findEmojiIcon = function(votesBlock, emoji) {
- return votesBlock.find(".js-emoji-btn [data-emoji='" + emoji + "']");
- };
-
- AwardsHandler.prototype.scrollToAwards = function() {
- var options;
- options = {
- scrollTop: $('.awards').offset().top - 110
- };
- return $('body, html').animate(options, 200);
- };
-
- AwardsHandler.prototype.normilizeEmojiName = function(emoji) {
- return this.aliases[emoji] || emoji;
- };
-
- AwardsHandler.prototype.addEmojiToFrequentlyUsedList = function(emoji) {
- var frequentlyUsedEmojis;
- frequentlyUsedEmojis = this.getFrequentlyUsedEmojis();
- frequentlyUsedEmojis.push(emoji);
- Cookies.set('frequently_used_emojis', frequentlyUsedEmojis.join(','), { expires: 365 });
- };
-
- AwardsHandler.prototype.getFrequentlyUsedEmojis = function() {
- var frequentlyUsedEmojis;
- frequentlyUsedEmojis = (Cookies.get('frequently_used_emojis') || '').split(',');
- return _.compact(_.uniq(frequentlyUsedEmojis));
- };
-
- AwardsHandler.prototype.renderFrequentlyUsedBlock = function() {
- var emoji, frequentlyUsedEmojis, i, len, ul;
- if (Cookies.get('frequently_used_emojis')) {
- frequentlyUsedEmojis = this.getFrequentlyUsedEmojis();
- ul = $("<ul class='clearfix emoji-menu-list frequent-emojis'>");
- for (i = 0, len = frequentlyUsedEmojis.length; i < len; i += 1) {
- emoji = frequentlyUsedEmojis[i];
- $(".emoji-menu-content [data-emoji='" + emoji + "']").closest('li').clone().appendTo(ul);
- }
- $('.emoji-menu-content').prepend(ul).prepend($('<h5>').text('Frequently used'));
- }
- return this.frequentEmojiBlockRendered = true;
- };
-
- AwardsHandler.prototype.setupSearch = function() {
- return $('input.emoji-search').on('keyup', (function(_this) {
- return function(ev) {
- var found_emojis, h5, term, ul;
- term = $(ev.target).val();
- // Clean previous search results
- $('ul.emoji-menu-search, h5.emoji-search').remove();
- if (term) {
- // Generate a search result block
- h5 = $('<h5 class="emoji-search" />').text('Search results');
- found_emojis = _this.searchEmojis(term).show();
- ul = $('<ul>').addClass('emoji-menu-list emoji-menu-search').append(found_emojis);
- $('.emoji-menu-content ul, .emoji-menu-content h5').hide();
- return $('.emoji-menu-content').append(h5).append(ul);
- } else {
- return $('.emoji-menu-content').children().show();
- }
- };
- })(this));
- };
-
- AwardsHandler.prototype.searchEmojis = function(term) {
- return $(".emoji-menu-list:not(.frequent-emojis) [data-emoji*='" + term + "']").closest('li').clone();
- };
-
- return AwardsHandler;
- })();
-}).call(window);
+ const namesMatchingAlias = [];
+ Object.keys(emojiAliases).forEach((alias) => {
+ if (alias.indexOf(safeTerm) >= 0) {
+ namesMatchingAlias.push(emojiAliases[alias]);
+ }
+ });
+ const $matchingElements = namesMatchingAlias.concat(safeTerm)
+ .reduce(
+ ($result, searchTerm) =>
+ $result.add($(`.emoji-menu-list:not(.frequent-emojis) [data-name*="${searchTerm}"]`)),
+ $([]),
+ );
+ return $matchingElements.closest('li').clone();
+};
+
+AwardsHandler.prototype.destroy = function destroy() {
+ this.eventListeners.forEach((entry) => {
+ entry.element.off.call(entry.element, ...entry.args);
+ });
+ $('.emoji-menu').remove();
+};
+
+module.exports = AwardsHandler;
diff --git a/app/assets/javascripts/behaviors/bind_in_out.js b/app/assets/javascripts/behaviors/bind_in_out.js
new file mode 100644
index 00000000000..886f127b06b
--- /dev/null
+++ b/app/assets/javascripts/behaviors/bind_in_out.js
@@ -0,0 +1,47 @@
+class BindInOut {
+ constructor(bindIn, bindOut) {
+ this.in = bindIn;
+ this.out = bindOut;
+
+ this.eventWrapper = {};
+ this.eventType = /(INPUT|TEXTAREA)/.test(bindIn.tagName) ? 'keyup' : 'change';
+ }
+
+ addEvents() {
+ this.eventWrapper.updateOut = this.updateOut.bind(this);
+
+ this.in.addEventListener(this.eventType, this.eventWrapper.updateOut);
+
+ return this;
+ }
+
+ updateOut() {
+ this.out.textContent = this.in.value;
+
+ return this;
+ }
+
+ removeEvents() {
+ this.in.removeEventListener(this.eventType, this.eventWrapper.updateOut);
+
+ return this;
+ }
+
+ static initAll() {
+ const ins = document.querySelectorAll('*[data-bind-in]');
+
+ return [].map.call(ins, anIn => BindInOut.init(anIn));
+ }
+
+ static init(anIn, anOut) {
+ const out = anOut || document.querySelector(`*[data-bind-out="${anIn.dataset.bindIn}"]`);
+
+ if (!out) return null;
+
+ const bindInOut = new BindInOut(anIn, out);
+
+ return bindInOut.addEvents().updateOut();
+ }
+}
+
+export default BindInOut;
diff --git a/app/assets/javascripts/behaviors/gl_emoji.js b/app/assets/javascripts/behaviors/gl_emoji.js
new file mode 100644
index 00000000000..d1d98c3919f
--- /dev/null
+++ b/app/assets/javascripts/behaviors/gl_emoji.js
@@ -0,0 +1,217 @@
+const installCustomElements = require('document-register-element');
+const emojiMap = require('emoji-map');
+const emojiAliases = require('emoji-aliases');
+const generatedUnicodeSupportMap = require('./gl_emoji/unicode_support_map');
+const spreadString = require('./gl_emoji/spread_string');
+
+installCustomElements(window);
+
+function emojiImageTag(name, src) {
+ return `<img class="emoji" title=":${name}:" alt=":${name}:" src="${src}" width="20" height="20" align="absmiddle" />`;
+}
+
+function assembleFallbackImageSrc(inputName) {
+ const name = Object.prototype.hasOwnProperty.call(emojiAliases, inputName) ?
+ emojiAliases[inputName] : inputName;
+ const emojiInfo = emojiMap[name];
+ const fallbackImageSrc = `${gon.asset_host || ''}${gon.relative_url_root || ''}/assets/emoji/${name}-${emojiInfo.digest}.png`;
+
+ return fallbackImageSrc;
+}
+const glEmojiTagDefaults = {
+ sprite: false,
+ forceFallback: false,
+};
+function glEmojiTag(inputName, options) {
+ const opts = Object.assign({}, glEmojiTagDefaults, options);
+ const name = Object.prototype.hasOwnProperty.call(emojiAliases, inputName) ?
+ emojiAliases[inputName] : inputName;
+ const emojiInfo = emojiMap[name];
+ const fallbackImageSrc = assembleFallbackImageSrc(name);
+ const fallbackSpriteClass = `emoji-${name}`;
+
+ const classList = [];
+ if (opts.forceFallback && opts.sprite) {
+ classList.push('emoji-icon');
+ classList.push(fallbackSpriteClass);
+ }
+ const classAttribute = classList.length > 0 ? `class="${classList.join(' ')}"` : '';
+ const fallbackSpriteAttribute = opts.sprite ? `data-fallback-sprite-class="${fallbackSpriteClass}"` : '';
+ let contents = emojiInfo.moji;
+ if (opts.forceFallback && !opts.sprite) {
+ contents = emojiImageTag(name, fallbackImageSrc);
+ }
+
+ return `
+ <gl-emoji
+ ${classAttribute}
+ data-name="${name}"
+ data-fallback-src="${fallbackImageSrc}"
+ ${fallbackSpriteAttribute}
+ data-unicode-version="${emojiInfo.unicodeVersion}"
+ >
+ ${contents}
+ </gl-emoji>
+ `;
+}
+
+// On Windows, flags render as two-letter country codes, see http://emojipedia.org/flags/
+const flagACodePoint = 127462; // parseInt('1F1E6', 16)
+const flagZCodePoint = 127487; // parseInt('1F1FF', 16)
+function isFlagEmoji(emojiUnicode) {
+ const cp = emojiUnicode.codePointAt(0);
+ // Length 4 because flags are made of 2 characters which are surrogate pairs
+ return emojiUnicode.length === 4 && cp >= flagACodePoint && cp <= flagZCodePoint;
+}
+
+// Chrome <57 renders keycaps oddly
+// See https://bugs.chromium.org/p/chromium/issues/detail?id=632294
+// Same issue on Windows also fixed in Chrome 57, http://i.imgur.com/rQF7woO.png
+function isKeycapEmoji(emojiUnicode) {
+ return emojiUnicode.length === 3 && emojiUnicode[2] === '\u20E3';
+}
+
+// Check for a skin tone variation emoji which aren't always supported
+const tone1 = 127995;// parseInt('1F3FB', 16)
+const tone5 = 127999;// parseInt('1F3FF', 16)
+function isSkinToneComboEmoji(emojiUnicode) {
+ return emojiUnicode.length > 2 && spreadString(emojiUnicode).some((char) => {
+ const cp = char.codePointAt(0);
+ return cp >= tone1 && cp <= tone5;
+ });
+}
+
+// macOS supports most skin tone emoji's but
+// doesn't support the skin tone versions of horse racing
+const horseRacingCodePoint = 127943;// parseInt('1F3C7', 16)
+function isHorceRacingSkinToneComboEmoji(emojiUnicode) {
+ return spreadString(emojiUnicode)[0].codePointAt(0) === horseRacingCodePoint &&
+ isSkinToneComboEmoji(emojiUnicode);
+}
+
+// Check for `family_*`, `kiss_*`, `couple_*`
+// For ex. Windows 8.1 Firefox 51.0.1, doesn't support these
+const zwj = 8205; // parseInt('200D', 16)
+const personStartCodePoint = 128102; // parseInt('1F466', 16)
+const personEndCodePoint = 128105; // parseInt('1F469', 16)
+function isPersonZwjEmoji(emojiUnicode) {
+ let hasPersonEmoji = false;
+ let hasZwj = false;
+ spreadString(emojiUnicode).forEach((character) => {
+ const cp = character.codePointAt(0);
+ if (cp === zwj) {
+ hasZwj = true;
+ } else if (cp >= personStartCodePoint && cp <= personEndCodePoint) {
+ hasPersonEmoji = true;
+ }
+ });
+
+ return hasPersonEmoji && hasZwj;
+}
+
+// Helper so we don't have to run `isFlagEmoji` twice
+// in `isEmojiUnicodeSupported` logic
+function checkFlagEmojiSupport(unicodeSupportMap, emojiUnicode) {
+ const isFlagResult = isFlagEmoji(emojiUnicode);
+ return (
+ (unicodeSupportMap.flag && isFlagResult) ||
+ !isFlagResult
+ );
+}
+
+// Helper so we don't have to run `isSkinToneComboEmoji` twice
+// in `isEmojiUnicodeSupported` logic
+function checkSkinToneModifierSupport(unicodeSupportMap, emojiUnicode) {
+ const isSkinToneResult = isSkinToneComboEmoji(emojiUnicode);
+ return (
+ (unicodeSupportMap.skinToneModifier && isSkinToneResult) ||
+ !isSkinToneResult
+ );
+}
+
+// Helper func so we don't have to run `isHorceRacingSkinToneComboEmoji` twice
+// in `isEmojiUnicodeSupported` logic
+function checkHorseRacingSkinToneComboEmojiSupport(unicodeSupportMap, emojiUnicode) {
+ const isHorseRacingSkinToneResult = isHorceRacingSkinToneComboEmoji(emojiUnicode);
+ return (
+ (unicodeSupportMap.horseRacing && isHorseRacingSkinToneResult) ||
+ !isHorseRacingSkinToneResult
+ );
+}
+
+// Helper so we don't have to run `isPersonZwjEmoji` twice
+// in `isEmojiUnicodeSupported` logic
+function checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode) {
+ const isPersonZwjResult = isPersonZwjEmoji(emojiUnicode);
+ return (
+ (unicodeSupportMap.personZwj && isPersonZwjResult) ||
+ !isPersonZwjResult
+ );
+}
+
+// Takes in a support map and determines whether
+// the given unicode emoji is supported on the platform.
+//
+// Combines all the edge case tests into a one-stop shop method
+function isEmojiUnicodeSupported(unicodeSupportMap = {}, emojiUnicode, unicodeVersion) {
+ const isOlderThanChrome57 = unicodeSupportMap.meta && unicodeSupportMap.meta.isChrome &&
+ unicodeSupportMap.meta.chromeVersion < 57;
+
+ // For comments about each scenario, see the comments above each individual respective function
+ return unicodeSupportMap[unicodeVersion] &&
+ !(isOlderThanChrome57 && isKeycapEmoji(emojiUnicode)) &&
+ checkFlagEmojiSupport(unicodeSupportMap, emojiUnicode) &&
+ checkSkinToneModifierSupport(unicodeSupportMap, emojiUnicode) &&
+ checkHorseRacingSkinToneComboEmojiSupport(unicodeSupportMap, emojiUnicode) &&
+ checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode);
+}
+
+const GlEmojiElementProto = Object.create(HTMLElement.prototype);
+GlEmojiElementProto.createdCallback = function createdCallback() {
+ const emojiUnicode = this.textContent.trim();
+ const {
+ name,
+ unicodeVersion,
+ fallbackSrc,
+ fallbackSpriteClass,
+ } = this.dataset;
+
+ const isEmojiUnicode = this.childNodes && Array.prototype.every.call(
+ this.childNodes,
+ childNode => childNode.nodeType === 3,
+ );
+ const hasImageFallback = fallbackSrc && fallbackSrc.length > 0;
+ const hasCssSpriteFalback = fallbackSpriteClass && fallbackSpriteClass.length > 0;
+
+ if (
+ isEmojiUnicode &&
+ !isEmojiUnicodeSupported(generatedUnicodeSupportMap, emojiUnicode, unicodeVersion)
+ ) {
+ // CSS sprite fallback takes precedence over image fallback
+ if (hasCssSpriteFalback) {
+ // IE 11 doesn't like adding multiple at once :(
+ this.classList.add('emoji-icon');
+ this.classList.add(fallbackSpriteClass);
+ } else if (hasImageFallback) {
+ this.innerHTML = emojiImageTag(name, fallbackSrc);
+ } else {
+ const src = assembleFallbackImageSrc(name);
+ this.innerHTML = emojiImageTag(name, src);
+ }
+ }
+};
+
+document.registerElement('gl-emoji', {
+ prototype: GlEmojiElementProto,
+});
+
+module.exports = {
+ emojiImageTag,
+ glEmojiTag,
+ isEmojiUnicodeSupported,
+ isFlagEmoji,
+ isKeycapEmoji,
+ isSkinToneComboEmoji,
+ isHorceRacingSkinToneComboEmoji,
+ isPersonZwjEmoji,
+};
diff --git a/app/assets/javascripts/behaviors/gl_emoji/spread_string.js b/app/assets/javascripts/behaviors/gl_emoji/spread_string.js
new file mode 100644
index 00000000000..2380349c4fa
--- /dev/null
+++ b/app/assets/javascripts/behaviors/gl_emoji/spread_string.js
@@ -0,0 +1,50 @@
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt#Fixing_charCodeAt()_to_handle_non-Basic-Multilingual-Plane_characters_if_their_presence_earlier_in_the_string_is_known
+function knownCharCodeAt(givenString, index) {
+ const str = `${givenString}`;
+ const end = str.length;
+
+ const surrogatePairs = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
+ let idx = index;
+ while ((surrogatePairs.exec(str)) != null) {
+ const li = surrogatePairs.lastIndex;
+ if (li - 2 < idx) {
+ idx += 1;
+ } else {
+ break;
+ }
+ }
+
+ if (idx >= end || idx < 0) {
+ return NaN;
+ }
+
+ const code = str.charCodeAt(idx);
+
+ let high;
+ let low;
+ if (code >= 0xD800 && code <= 0xDBFF) {
+ high = code;
+ low = str.charCodeAt(idx + 1);
+ // Go one further, since one of the "characters" is part of a surrogate pair
+ return ((high - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
+ }
+ return code;
+}
+
+// See http://stackoverflow.com/a/38901550/796832
+// ES5/PhantomJS compatible version of spreading a string
+//
+// [...'foo'] -> ['f', 'o', 'o']
+// [...'🖐🏿'] -> ['🖐', '🏿']
+function spreadString(str) {
+ const arr = [];
+ let i = 0;
+ while (!isNaN(knownCharCodeAt(str, i))) {
+ const codePoint = knownCharCodeAt(str, i);
+ arr.push(String.fromCodePoint(codePoint));
+ i += 1;
+ }
+ return arr;
+}
+
+module.exports = spreadString;
diff --git a/app/assets/javascripts/behaviors/gl_emoji/unicode_support_map.js b/app/assets/javascripts/behaviors/gl_emoji/unicode_support_map.js
new file mode 100644
index 00000000000..f31716d4c07
--- /dev/null
+++ b/app/assets/javascripts/behaviors/gl_emoji/unicode_support_map.js
@@ -0,0 +1,154 @@
+const unicodeSupportTestMap = {
+ // man, student (emojione does not have any of these yet), http://emojipedia.org/emoji-zwj-sequences/
+ // occupationZwj: '\u{1F468}\u{200D}\u{1F393}',
+ // woman, biking (emojione does not have any of these yet), http://emojipedia.org/emoji-zwj-sequences/
+ // sexZwj: '\u{1F6B4}\u{200D}\u{2640}',
+ // family_mwgb
+ // Windows 8.1, Firefox 51.0.1 does not support `family_`, `kiss_`, `couple_`
+ personZwj: '\u{1F468}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}',
+ // horse_racing_tone5
+ // Special case that is not supported on macOS 10.12 even though `skinToneModifier` succeeds
+ horseRacing: '\u{1F3C7}\u{1F3FF}',
+ // US flag, http://emojipedia.org/flags/
+ flag: '\u{1F1FA}\u{1F1F8}',
+ // http://emojipedia.org/modifiers/
+ skinToneModifier: [
+ // spy_tone5
+ '\u{1F575}\u{1F3FF}',
+ // person_with_ball_tone5
+ '\u{26F9}\u{1F3FF}',
+ // angel_tone5
+ '\u{1F47C}\u{1F3FF}',
+ ],
+ // rofl, http://emojipedia.org/unicode-9.0/
+ '9.0': '\u{1F923}',
+ // metal, http://emojipedia.org/unicode-8.0/
+ '8.0': '\u{1F918}',
+ // spy, http://emojipedia.org/unicode-7.0/
+ '7.0': '\u{1F575}',
+ // expressionless, http://emojipedia.org/unicode-6.1/
+ 6.1: '\u{1F611}',
+ // japanese_goblin, http://emojipedia.org/unicode-6.0/
+ '6.0': '\u{1F47A}',
+ // sailboat, http://emojipedia.org/unicode-5.2/
+ 5.2: '\u{26F5}',
+ // mahjong, http://emojipedia.org/unicode-5.1/
+ 5.1: '\u{1F004}',
+ // gear, http://emojipedia.org/unicode-4.1/
+ 4.1: '\u{2699}',
+ // zap, http://emojipedia.org/unicode-4.0/
+ '4.0': '\u{26A1}',
+ // recycle, http://emojipedia.org/unicode-3.2/
+ 3.2: '\u{267B}',
+ // information_source, http://emojipedia.org/unicode-3.0/
+ '3.0': '\u{2139}',
+ // heart, http://emojipedia.org/unicode-1.1/
+ 1.1: '\u{2764}',
+};
+
+function checkPixelInImageDataArray(pixelOffset, imageDataArray) {
+ // `4 *` because RGBA
+ const indexOffset = 4 * pixelOffset;
+ const hasColor = imageDataArray[indexOffset + 0] ||
+ imageDataArray[indexOffset + 1] ||
+ imageDataArray[indexOffset + 2];
+ const isVisible = imageDataArray[indexOffset + 3];
+ // Check for some sort of color other than black
+ if (hasColor && isVisible) {
+ return true;
+ }
+ return false;
+}
+
+const chromeMatches = navigator.userAgent.match(/Chrom(?:e|ium)\/([0-9]+)\./);
+const isChrome = chromeMatches && chromeMatches.length > 0;
+const chromeVersion = chromeMatches && chromeMatches[1] && parseInt(chromeMatches[1], 10);
+
+// We use 16px because mobile Safari (iOS 9.3) doesn't properly scale emojis :/
+// See 32px, https://i.imgur.com/htY6Zym.png
+// See 16px, https://i.imgur.com/FPPsIF8.png
+const fontSize = 16;
+function testUnicodeSupportMap(testMap) {
+ const testMapKeys = Object.keys(testMap);
+ const numTestEntries = testMapKeys
+ .reduce((list, testKey) => list.concat(testMap[testKey]), []).length;
+
+ const canvas = document.createElement('canvas');
+ (window.gl || window).testEmojiUnicodeSupportMapCanvas = canvas;
+ const ctx = canvas.getContext('2d');
+ canvas.width = (2 * fontSize);
+ canvas.height = (numTestEntries * fontSize);
+ ctx.fillStyle = '#000000';
+ ctx.textBaseline = 'middle';
+ ctx.font = `${fontSize}px "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"`;
+ // Write each emoji to the canvas vertically
+ let writeIndex = 0;
+ testMapKeys.forEach((testKey) => {
+ const testEntry = testMap[testKey];
+ [].concat(testEntry).forEach((emojiUnicode) => {
+ ctx.fillText(emojiUnicode, 0, (writeIndex * fontSize) + (fontSize / 2));
+ writeIndex += 1;
+ });
+ });
+
+ // Read from the canvas
+ const resultMap = {};
+ let readIndex = 0;
+ testMapKeys.forEach((testKey) => {
+ const testEntry = testMap[testKey];
+ // This needs to be a `reduce` instead of `every` because we need to
+ // keep the `readIndex` in sync from the writes by running all entries
+ const isTestSatisfied = [].concat(testEntry).reduce((isSatisfied) => {
+ // Sample along the vertical-middle for a couple of characters
+ const imageData = ctx.getImageData(
+ 0,
+ (readIndex * fontSize) + (fontSize / 2),
+ 2 * fontSize,
+ 1,
+ ).data;
+
+ let isValidEmoji = false;
+ for (let currentPixel = 0; currentPixel < 64; currentPixel += 1) {
+ const isLookingAtFirstChar = currentPixel < fontSize;
+ const isLookingAtSecondChar = currentPixel >= (fontSize + (fontSize / 2));
+ // Check for the emoji somewhere along the row
+ if (isLookingAtFirstChar && checkPixelInImageDataArray(currentPixel, imageData)) {
+ isValidEmoji = true;
+
+ // Check to see that nothing is rendered next to the first character
+ // to ensure that the ZWJ sequence rendered as one piece
+ } else if (isLookingAtSecondChar && checkPixelInImageDataArray(currentPixel, imageData)) {
+ isValidEmoji = false;
+ break;
+ }
+ }
+
+ readIndex += 1;
+ return isSatisfied && isValidEmoji;
+ }, true);
+
+ resultMap[testKey] = isTestSatisfied;
+ });
+
+ resultMap.meta = {
+ isChrome,
+ chromeVersion,
+ };
+
+ return resultMap;
+}
+
+let unicodeSupportMap;
+const userAgentFromCache = window.localStorage.getItem('gl-emoji-user-agent');
+try {
+ unicodeSupportMap = JSON.parse(window.localStorage.getItem('gl-emoji-unicode-support-map'));
+} catch (err) {
+ // swallow
+}
+if (!unicodeSupportMap || userAgentFromCache !== navigator.userAgent) {
+ unicodeSupportMap = testUnicodeSupportMap(unicodeSupportTestMap);
+ window.localStorage.setItem('gl-emoji-user-agent', navigator.userAgent);
+ window.localStorage.setItem('gl-emoji-unicode-support-map', JSON.stringify(unicodeSupportMap));
+}
+
+module.exports = unicodeSupportMap;
diff --git a/app/assets/javascripts/behaviors/toggler_behavior.js b/app/assets/javascripts/behaviors/toggler_behavior.js
index a7181904ac9..0726c6c9636 100644
--- a/app/assets/javascripts/behaviors/toggler_behavior.js
+++ b/app/assets/javascripts/behaviors/toggler_behavior.js
@@ -21,8 +21,7 @@
// %a.js-toggle-button
// %div.js-toggle-content
//
- $('body').on('click', '.js-toggle-button', function(e) {
- e.preventDefault();
+ $('body').on('click', '.js-toggle-button', function() {
toggleContainer($(this).closest('.js-toggle-container'));
});
diff --git a/app/assets/javascripts/blob/blob_ci_yaml.js.es6 b/app/assets/javascripts/blob/blob_ci_yaml.js
index ec1c018424d..ec1c018424d 100644
--- a/app/assets/javascripts/blob/blob_ci_yaml.js.es6
+++ b/app/assets/javascripts/blob/blob_ci_yaml.js
diff --git a/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6 b/app/assets/javascripts/blob/blob_dockerfile_selector.js
index d4f60cc6ecd..d4f60cc6ecd 100644
--- a/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6
+++ b/app/assets/javascripts/blob/blob_dockerfile_selector.js
diff --git a/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6 b/app/assets/javascripts/blob/blob_dockerfile_selectors.js
index 9cee79fa5d5..9cee79fa5d5 100644
--- a/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6
+++ b/app/assets/javascripts/blob/blob_dockerfile_selectors.js
diff --git a/app/assets/javascripts/blob/blob_license_selectors.js.es6 b/app/assets/javascripts/blob/blob_license_selectors.js
index c5067b0feae..c5067b0feae 100644
--- a/app/assets/javascripts/blob/blob_license_selectors.js.es6
+++ b/app/assets/javascripts/blob/blob_license_selectors.js
diff --git a/app/assets/javascripts/blob/template_selector.js.es6 b/app/assets/javascripts/blob/template_selector.js
index 7e03ec3b391..7e03ec3b391 100644
--- a/app/assets/javascripts/blob/template_selector.js.es6
+++ b/app/assets/javascripts/blob/template_selector.js
diff --git a/app/assets/javascripts/boards/boards_bundle.js.es6 b/app/assets/javascripts/boards/boards_bundle.js
index 55d13be6e5f..55d13be6e5f 100644
--- a/app/assets/javascripts/boards/boards_bundle.js.es6
+++ b/app/assets/javascripts/boards/boards_bundle.js
diff --git a/app/assets/javascripts/boards/components/board.js.es6 b/app/assets/javascripts/boards/components/board.js
index 18324de18b3..18324de18b3 100644
--- a/app/assets/javascripts/boards/components/board.js.es6
+++ b/app/assets/javascripts/boards/components/board.js
diff --git a/app/assets/javascripts/boards/components/board_blank_state.js.es6 b/app/assets/javascripts/boards/components/board_blank_state.js
index d76314c1892..d76314c1892 100644
--- a/app/assets/javascripts/boards/components/board_blank_state.js.es6
+++ b/app/assets/javascripts/boards/components/board_blank_state.js
diff --git a/app/assets/javascripts/boards/components/board_delete.js.es6 b/app/assets/javascripts/boards/components/board_delete.js
index 861600424a5..861600424a5 100644
--- a/app/assets/javascripts/boards/components/board_delete.js.es6
+++ b/app/assets/javascripts/boards/components/board_delete.js
diff --git a/app/assets/javascripts/boards/components/board_list.js.es6 b/app/assets/javascripts/boards/components/board_list.js
index 2d52e96e7fb..2d52e96e7fb 100644
--- a/app/assets/javascripts/boards/components/board_list.js.es6
+++ b/app/assets/javascripts/boards/components/board_list.js
diff --git a/app/assets/javascripts/boards/components/board_sidebar.js.es6 b/app/assets/javascripts/boards/components/board_sidebar.js
index dfc6eed785c..dfc6eed785c 100644
--- a/app/assets/javascripts/boards/components/board_sidebar.js.es6
+++ b/app/assets/javascripts/boards/components/board_sidebar.js
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.js.es6 b/app/assets/javascripts/boards/components/issue_card_inner.js
index 22a8b971ff8..22a8b971ff8 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.js.es6
+++ b/app/assets/javascripts/boards/components/issue_card_inner.js
diff --git a/app/assets/javascripts/boards/components/modal/empty_state.js.es6 b/app/assets/javascripts/boards/components/modal/empty_state.js
index 9538f5b69e9..9538f5b69e9 100644
--- a/app/assets/javascripts/boards/components/modal/empty_state.js.es6
+++ b/app/assets/javascripts/boards/components/modal/empty_state.js
diff --git a/app/assets/javascripts/boards/components/modal/filters.js.es6 b/app/assets/javascripts/boards/components/modal/filters.js
index 6de06811d94..6de06811d94 100644
--- a/app/assets/javascripts/boards/components/modal/filters.js.es6
+++ b/app/assets/javascripts/boards/components/modal/filters.js
diff --git a/app/assets/javascripts/boards/components/modal/filters/label.js.es6 b/app/assets/javascripts/boards/components/modal/filters/label.js
index 4fc8f72a145..4fc8f72a145 100644
--- a/app/assets/javascripts/boards/components/modal/filters/label.js.es6
+++ b/app/assets/javascripts/boards/components/modal/filters/label.js
diff --git a/app/assets/javascripts/boards/components/modal/filters/milestone.js.es6 b/app/assets/javascripts/boards/components/modal/filters/milestone.js
index d555599d300..d555599d300 100644
--- a/app/assets/javascripts/boards/components/modal/filters/milestone.js.es6
+++ b/app/assets/javascripts/boards/components/modal/filters/milestone.js
diff --git a/app/assets/javascripts/boards/components/modal/filters/user.js.es6 b/app/assets/javascripts/boards/components/modal/filters/user.js
index 8523028c29c..8523028c29c 100644
--- a/app/assets/javascripts/boards/components/modal/filters/user.js.es6
+++ b/app/assets/javascripts/boards/components/modal/filters/user.js
diff --git a/app/assets/javascripts/boards/components/modal/footer.js.es6 b/app/assets/javascripts/boards/components/modal/footer.js
index 1cbc422c961..1cbc422c961 100644
--- a/app/assets/javascripts/boards/components/modal/footer.js.es6
+++ b/app/assets/javascripts/boards/components/modal/footer.js
diff --git a/app/assets/javascripts/boards/components/modal/header.js.es6 b/app/assets/javascripts/boards/components/modal/header.js
index 70c088f9054..70c088f9054 100644
--- a/app/assets/javascripts/boards/components/modal/header.js.es6
+++ b/app/assets/javascripts/boards/components/modal/header.js
diff --git a/app/assets/javascripts/boards/components/modal/index.js.es6 b/app/assets/javascripts/boards/components/modal/index.js
index f290cd13763..f290cd13763 100644
--- a/app/assets/javascripts/boards/components/modal/index.js.es6
+++ b/app/assets/javascripts/boards/components/modal/index.js
diff --git a/app/assets/javascripts/boards/components/modal/list.js.es6 b/app/assets/javascripts/boards/components/modal/list.js
index 3730c1ecaeb..3730c1ecaeb 100644
--- a/app/assets/javascripts/boards/components/modal/list.js.es6
+++ b/app/assets/javascripts/boards/components/modal/list.js
diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.js.es6 b/app/assets/javascripts/boards/components/modal/lists_dropdown.js
index 3c05120a2da..3c05120a2da 100644
--- a/app/assets/javascripts/boards/components/modal/lists_dropdown.js.es6
+++ b/app/assets/javascripts/boards/components/modal/lists_dropdown.js
diff --git a/app/assets/javascripts/boards/components/modal/tabs.js.es6 b/app/assets/javascripts/boards/components/modal/tabs.js
index e8cb43f3503..e8cb43f3503 100644
--- a/app/assets/javascripts/boards/components/modal/tabs.js.es6
+++ b/app/assets/javascripts/boards/components/modal/tabs.js
diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 b/app/assets/javascripts/boards/components/new_list_dropdown.js
index 556826a9148..556826a9148 100644
--- a/app/assets/javascripts/boards/components/new_list_dropdown.js.es6
+++ b/app/assets/javascripts/boards/components/new_list_dropdown.js
diff --git a/app/assets/javascripts/boards/components/sidebar/remove_issue.js.es6 b/app/assets/javascripts/boards/components/sidebar/remove_issue.js
index e74935e1cb0..e74935e1cb0 100644
--- a/app/assets/javascripts/boards/components/sidebar/remove_issue.js.es6
+++ b/app/assets/javascripts/boards/components/sidebar/remove_issue.js
diff --git a/app/assets/javascripts/boards/filters/due_date_filters.js.es6 b/app/assets/javascripts/boards/filters/due_date_filters.js
index 03425bb145b..03425bb145b 100644
--- a/app/assets/javascripts/boards/filters/due_date_filters.js.es6
+++ b/app/assets/javascripts/boards/filters/due_date_filters.js
diff --git a/app/assets/javascripts/boards/mixins/modal_mixins.js.es6 b/app/assets/javascripts/boards/mixins/modal_mixins.js
index d378b7d4baf..d378b7d4baf 100644
--- a/app/assets/javascripts/boards/mixins/modal_mixins.js.es6
+++ b/app/assets/javascripts/boards/mixins/modal_mixins.js
diff --git a/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6 b/app/assets/javascripts/boards/mixins/sortable_default_options.js
index b6c6d17274f..b6c6d17274f 100644
--- a/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6
+++ b/app/assets/javascripts/boards/mixins/sortable_default_options.js
diff --git a/app/assets/javascripts/boards/models/issue.js.es6 b/app/assets/javascripts/boards/models/issue.js
index 2d0a295ae4d..2d0a295ae4d 100644
--- a/app/assets/javascripts/boards/models/issue.js.es6
+++ b/app/assets/javascripts/boards/models/issue.js
diff --git a/app/assets/javascripts/boards/models/label.js.es6 b/app/assets/javascripts/boards/models/label.js
index 9af88d167d6..9af88d167d6 100644
--- a/app/assets/javascripts/boards/models/label.js.es6
+++ b/app/assets/javascripts/boards/models/label.js
diff --git a/app/assets/javascripts/boards/models/list.js.es6 b/app/assets/javascripts/boards/models/list.js
index 8158ed4ec2c..8158ed4ec2c 100644
--- a/app/assets/javascripts/boards/models/list.js.es6
+++ b/app/assets/javascripts/boards/models/list.js
diff --git a/app/assets/javascripts/boards/models/milestone.js.es6 b/app/assets/javascripts/boards/models/milestone.js
index c867b06d320..c867b06d320 100644
--- a/app/assets/javascripts/boards/models/milestone.js.es6
+++ b/app/assets/javascripts/boards/models/milestone.js
diff --git a/app/assets/javascripts/boards/models/user.js.es6 b/app/assets/javascripts/boards/models/user.js
index 8e9de4d4cbb..8e9de4d4cbb 100644
--- a/app/assets/javascripts/boards/models/user.js.es6
+++ b/app/assets/javascripts/boards/models/user.js
diff --git a/app/assets/javascripts/boards/services/board_service.js.es6 b/app/assets/javascripts/boards/services/board_service.js
index 065e90518df..065e90518df 100644
--- a/app/assets/javascripts/boards/services/board_service.js.es6
+++ b/app/assets/javascripts/boards/services/board_service.js
diff --git a/app/assets/javascripts/boards/stores/boards_store.js.es6 b/app/assets/javascripts/boards/stores/boards_store.js
index 56436c8fdc7..56436c8fdc7 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js.es6
+++ b/app/assets/javascripts/boards/stores/boards_store.js
diff --git a/app/assets/javascripts/boards/stores/modal_store.js.es6 b/app/assets/javascripts/boards/stores/modal_store.js
index 15fc6c79e8d..15fc6c79e8d 100644
--- a/app/assets/javascripts/boards/stores/modal_store.js.es6
+++ b/app/assets/javascripts/boards/stores/modal_store.js
diff --git a/app/assets/javascripts/build_variables.js.es6 b/app/assets/javascripts/build_variables.js
index 99082b412e2..99082b412e2 100644
--- a/app/assets/javascripts/build_variables.js.es6
+++ b/app/assets/javascripts/build_variables.js
diff --git a/app/assets/javascripts/ci_lint_editor.js.es6 b/app/assets/javascripts/ci_lint_editor.js
index 56ffaa765a8..56ffaa765a8 100644
--- a/app/assets/javascripts/ci_lint_editor.js.es6
+++ b/app/assets/javascripts/ci_lint_editor.js
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js.es6 b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
index b5a988df897..b5a988df897 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js.es6
+++ b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_service.js.es6 b/app/assets/javascripts/commit/pipelines/pipelines_service.js
index 8ae98f9bf97..8ae98f9bf97 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_service.js.es6
+++ b/app/assets/javascripts/commit/pipelines/pipelines_service.js
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_store.js.es6 b/app/assets/javascripts/commit/pipelines/pipelines_store.js
index f1b80e45444..f1b80e45444 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_store.js.es6
+++ b/app/assets/javascripts/commit/pipelines/pipelines_store.js
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.js.es6 b/app/assets/javascripts/commit/pipelines/pipelines_table.js
index cd2bd883d32..631ed34851c 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.js.es6
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.js
@@ -39,15 +39,10 @@ const PipelineStore = require('./pipelines_store');
*/
data() {
const pipelinesTableData = document.querySelector('#commit-pipeline-table-view').dataset;
- const svgsData = document.querySelector('.pipeline-svgs').dataset;
const store = new PipelineStore();
- // Transform svgs DOMStringMap to a plain Object.
- const svgsObject = gl.utils.DOMStringMapToObject(svgsData);
-
return {
endpoint: pipelinesTableData.endpoint,
- svgs: svgsObject,
store,
state: store.state,
isLoading: false,
@@ -101,10 +96,7 @@ const PipelineStore = require('./pipelines_store');
<div class="table-holder pipelines"
v-if="!isLoading && state.pipelines.length > 0">
- <pipelines-table-component
- :pipelines="state.pipelines"
- :svgs="svgs">
- </pipelines-table-component>
+ <pipelines-table-component :pipelines="state.pipelines"/>
</div>
</div>
`,
diff --git a/app/assets/javascripts/commons/bootstrap.js b/app/assets/javascripts/commons/bootstrap.js
new file mode 100644
index 00000000000..db0cbfd87c3
--- /dev/null
+++ b/app/assets/javascripts/commons/bootstrap.js
@@ -0,0 +1,10 @@
+import 'jquery';
+
+// bootstrap jQuery plugins
+import 'bootstrap-sass/assets/javascripts/bootstrap/affix';
+import 'bootstrap-sass/assets/javascripts/bootstrap/alert';
+import 'bootstrap-sass/assets/javascripts/bootstrap/dropdown';
+import 'bootstrap-sass/assets/javascripts/bootstrap/modal';
+import 'bootstrap-sass/assets/javascripts/bootstrap/tab';
+import 'bootstrap-sass/assets/javascripts/bootstrap/transition';
+import 'bootstrap-sass/assets/javascripts/bootstrap/tooltip';
diff --git a/app/assets/javascripts/commons/index.js b/app/assets/javascripts/commons/index.js
new file mode 100644
index 00000000000..72ede1d621a
--- /dev/null
+++ b/app/assets/javascripts/commons/index.js
@@ -0,0 +1,2 @@
+import './jquery';
+import './bootstrap';
diff --git a/app/assets/javascripts/commons/jquery.js b/app/assets/javascripts/commons/jquery.js
new file mode 100644
index 00000000000..b53f6284afc
--- /dev/null
+++ b/app/assets/javascripts/commons/jquery.js
@@ -0,0 +1,11 @@
+import 'jquery';
+
+// common jQuery plugins
+import 'jquery-ujs';
+import 'vendor/jquery.endless-scroll';
+import 'vendor/jquery.caret';
+import 'vendor/jquery.atwho';
+import 'vendor/jquery.scrollTo';
+import 'vendor/jquery.nicescroll';
+import 'vendor/jquery.waitforimages';
+import 'select2/select2';
diff --git a/app/assets/javascripts/compare_autocomplete.js.es6 b/app/assets/javascripts/compare_autocomplete.js
index 1eca973e069..1eca973e069 100644
--- a/app/assets/javascripts/compare_autocomplete.js.es6
+++ b/app/assets/javascripts/compare_autocomplete.js
diff --git a/app/assets/javascripts/copy_as_gfm.js.es6 b/app/assets/javascripts/copy_as_gfm.js
index 2bc3d85fba4..8883c339335 100644
--- a/app/assets/javascripts/copy_as_gfm.js.es6
+++ b/app/assets/javascripts/copy_as_gfm.js
@@ -49,6 +49,9 @@ require('./lib/utils/common_utils');
'img.emoji'(el, text) {
return el.getAttribute('alt');
},
+ 'gl-emoji'(el, text) {
+ return `:${el.getAttribute('data-name')}:`;
+ },
},
ImageLinkFilter: {
'a.no-attachment-icon'(el, text) {
@@ -110,7 +113,7 @@ require('./lib/utils/common_utils');
return `<dl>\n${lines.join('\n')}\n</dl>`;
},
- 'sub, dt, dd, kbd, q, samp, var, ruby, rt, rp, abbr'(el, text) {
+ 'sub, dt, dd, kbd, q, samp, var, ruby, rt, rp, abbr, summary, details'(el, text) {
const tag = el.nodeName.toLowerCase();
return `<${tag}>${text}</${tag}>`;
},
diff --git a/app/assets/javascripts/create_label.js.es6 b/app/assets/javascripts/create_label.js
index 85384d98126..85384d98126 100644
--- a/app/assets/javascripts/create_label.js.es6
+++ b/app/assets/javascripts/create_label.js
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_code_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_code_component.js
index b83a4c63fad..b83a4c63fad 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_code_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_code_component.js
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js
index cb1687dcc7a..cb1687dcc7a 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js
index 8652479e7bf..42e1bbce744 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js
@@ -1,5 +1,6 @@
/* eslint-disable no-param-reassign */
-/* global Vue */
+import Vue from 'vue';
+import iconCommit from '../svg/icon_commit.svg';
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
@@ -9,6 +10,11 @@
items: Array,
stage: Object,
},
+
+ data() {
+ return { iconCommit };
+ },
+
template: `
<div>
<div class="events-description">
@@ -31,7 +37,7 @@
</h5>
<span>
First
- <span class="commit-icon">${global.cycleAnalytics.svgs.iconCommit}</span>
+ <span class="commit-icon">${iconCommit}</span>
<a :href="commit.commitUrl" class="commit-hash-link monospace">{{ commit.shortSha }}</a>
pushed by
<a :href="commit.author.webUrl" class="commit-author-link">
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_production_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_production_component.js
index 73f4205b578..73f4205b578 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_production_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_production_component.js
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_review_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_review_component.js
index 501ffb1fac9..501ffb1fac9 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_review_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_review_component.js
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js
index 82622232f64..8fa63734cf1 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js
@@ -1,5 +1,6 @@
/* eslint-disable no-param-reassign */
-/* global Vue */
+import Vue from 'vue';
+import iconBranch from '../svg/icon_branch.svg';
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
@@ -9,6 +10,9 @@
items: Array,
stage: Object,
},
+ data() {
+ return { iconBranch };
+ },
template: `
<div>
<div class="events-description">
@@ -22,7 +26,7 @@
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
<i class="fa fa-code-fork"></i>
<a :href="build.branch.url" class="branch-name monospace">{{ build.branch.name }}</a>
- <span class="icon-branch">${global.cycleAnalytics.svgs.iconBranch}</span>
+ <span class="icon-branch">${iconBranch}</span>
<a :href="build.commitUrl" class="short-sha monospace">{{ build.shortSha }}</a>
</h5>
<span>
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_test_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_test_component.js
index 4bfd363a1f1..0015249cfaa 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_test_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_test_component.js
@@ -1,5 +1,7 @@
/* eslint-disable no-param-reassign */
-/* global Vue */
+import Vue from 'vue';
+import iconBuildStatus from '../svg/icon_build_status.svg';
+import iconBranch from '../svg/icon_branch.svg';
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
@@ -9,6 +11,9 @@
items: Array,
stage: Object,
},
+ data() {
+ return { iconBuildStatus, iconBranch };
+ },
template: `
<div>
<div class="events-description">
@@ -18,13 +23,13 @@
<li v-for="build in items" class="stage-event-item item-build-component">
<div class="item-details">
<h5 class="item-title">
- <span class="icon-build-status">${global.cycleAnalytics.svgs.iconBuildStatus}</span>
+ <span class="icon-build-status">${iconBuildStatus}</span>
<a :href="build.url" class="item-build-name">{{ build.name }}</a>
&middot;
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
<i class="fa fa-code-fork"></i>
<a :href="build.branch.url" class="branch-name monospace">{{ build.branch.name }}</a>
- <span class="icon-branch">${global.cycleAnalytics.svgs.iconBranch}</span>
+ <span class="icon-branch">${iconBranch}</span>
<a :href="build.commitUrl" class="short-sha monospace">{{ build.shortSha }}</a>
</h5>
<span>
diff --git a/app/assets/javascripts/cycle_analytics/components/total_time_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/total_time_component.js
index 0d85e1a4678..0d85e1a4678 100644
--- a/app/assets/javascripts/cycle_analytics/components/total_time_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/total_time_component.js
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js.es6 b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
index 411ac7b24b2..beff293b587 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js.es6
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
@@ -4,9 +4,6 @@
window.Vue = require('vue');
window.Cookies = require('js-cookie');
-require('./svg/icon_branch');
-require('./svg/icon_build_status');
-require('./svg/icon_commit');
require('./components/stage_code_component');
require('./components/stage_issue_component');
require('./components/stage_plan_component');
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js.es6 b/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js
index 9f74b14c4b9..9f74b14c4b9 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js.es6
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js.es6 b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
index 7ae9de7297c..7ae9de7297c 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js.es6
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
diff --git a/app/assets/javascripts/cycle_analytics/default_event_objects.js.es6 b/app/assets/javascripts/cycle_analytics/default_event_objects.js
index cfaf9835bf8..cfaf9835bf8 100644
--- a/app/assets/javascripts/cycle_analytics/default_event_objects.js.es6
+++ b/app/assets/javascripts/cycle_analytics/default_event_objects.js
diff --git a/app/assets/javascripts/cycle_analytics/svg/icon_branch.js.es6 b/app/assets/javascripts/cycle_analytics/svg/icon_branch.js.es6
deleted file mode 100644
index 5d486bcaf66..00000000000
--- a/app/assets/javascripts/cycle_analytics/svg/icon_branch.js.es6
+++ /dev/null
@@ -1,7 +0,0 @@
-/* eslint-disable no-param-reassign */
-((global) => {
- global.cycleAnalytics = global.cycleAnalytics || {};
- global.cycleAnalytics.svgs = global.cycleAnalytics.svgs || {};
-
- global.cycleAnalytics.svgs.iconBranch = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14"><path fill="#8C8C8C" fill-rule="evenodd" d="M9.678 6.722C9.353 5.167 8.053 4 6.5 4S3.647 5.167 3.322 6.722h-2.6c-.397 0-.722.35-.722.778 0 .428.325.778.722.778h2.6C3.647 9.833 4.947 11 6.5 11s2.853-1.167 3.178-2.722h2.6c.397 0 .722-.35.722-.778 0-.428-.325-.778-.722-.778h-2.6zM4.694 7.5c0-1.09.795-1.944 1.806-1.944 1.01 0 1.806.855 1.806 1.944 0 1.09-.795 1.944-1.806 1.944-1.01 0-1.806-.855-1.806-1.944z"/></svg>';
-})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/cycle_analytics/svg/icon_branch.svg b/app/assets/javascripts/cycle_analytics/svg/icon_branch.svg
new file mode 100644
index 00000000000..9f547d3d744
--- /dev/null
+++ b/app/assets/javascripts/cycle_analytics/svg/icon_branch.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14"><path fill="#8C8C8C" fill-rule="evenodd" d="M9.678 6.722C9.353 5.167 8.053 4 6.5 4S3.647 5.167 3.322 6.722h-2.6c-.397 0-.722.35-.722.778 0 .428.325.778.722.778h2.6C3.647 9.833 4.947 11 6.5 11s2.853-1.167 3.178-2.722h2.6c.397 0 .722-.35.722-.778 0-.428-.325-.778-.722-.778h-2.6zM4.694 7.5c0-1.09.795-1.944 1.806-1.944 1.01 0 1.806.855 1.806 1.944 0 1.09-.795 1.944-1.806 1.944-1.01 0-1.806-.855-1.806-1.944z"/></svg>
diff --git a/app/assets/javascripts/cycle_analytics/svg/icon_build_status.js.es6 b/app/assets/javascripts/cycle_analytics/svg/icon_build_status.js.es6
deleted file mode 100644
index 661bf9e9f1c..00000000000
--- a/app/assets/javascripts/cycle_analytics/svg/icon_build_status.js.es6
+++ /dev/null
@@ -1,7 +0,0 @@
-/* eslint-disable no-param-reassign */
-((global) => {
- global.cycleAnalytics = global.cycleAnalytics || {};
- global.cycleAnalytics.svgs = global.cycleAnalytics.svgs || {};
-
- global.cycleAnalytics.svgs.iconBuildStatus = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14"><g fill="#31AF64" fill-rule="evenodd"><path d="M12.5 7c0-3.038-2.462-5.5-5.5-5.5S1.5 3.962 1.5 7s2.462 5.5 5.5 5.5 5.5-2.462 5.5-5.5zM0 7c0-3.866 3.134-7 7-7s7 3.134 7 7-3.134 7-7 7-7-3.134-7-7z"/><path d="M6.28 7.697L5.045 6.464c-.117-.117-.305-.117-.42-.002l-.614.614c-.11.113-.11.303.007.42l1.91 1.91c.19.19.51.197.703.004l.264-.265L9.997 6.04c.108-.107.107-.293-.01-.408l-.612-.614c-.114-.113-.298-.12-.41-.01L6.28 7.7z"/></g></svg>';
-})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/cycle_analytics/svg/icon_build_status.svg b/app/assets/javascripts/cycle_analytics/svg/icon_build_status.svg
new file mode 100644
index 00000000000..b932d90618a
--- /dev/null
+++ b/app/assets/javascripts/cycle_analytics/svg/icon_build_status.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14"><g fill="#31AF64" fill-rule="evenodd"><path d="M12.5 7c0-3.038-2.462-5.5-5.5-5.5S1.5 3.962 1.5 7s2.462 5.5 5.5 5.5 5.5-2.462 5.5-5.5zM0 7c0-3.866 3.134-7 7-7s7 3.134 7 7-3.134 7-7 7-7-3.134-7-7z"/><path d="M6.28 7.697L5.045 6.464c-.117-.117-.305-.117-.42-.002l-.614.614c-.11.113-.11.303.007.42l1.91 1.91c.19.19.51.197.703.004l.264-.265L9.997 6.04c.108-.107.107-.293-.01-.408l-.612-.614c-.114-.113-.298-.12-.41-.01L6.28 7.7z"/></g></svg>
diff --git a/app/assets/javascripts/cycle_analytics/svg/icon_commit.js.es6 b/app/assets/javascripts/cycle_analytics/svg/icon_commit.js.es6
deleted file mode 100644
index 2208c27a619..00000000000
--- a/app/assets/javascripts/cycle_analytics/svg/icon_commit.js.es6
+++ /dev/null
@@ -1,7 +0,0 @@
-/* eslint-disable no-param-reassign */
-((global) => {
- global.cycleAnalytics = global.cycleAnalytics || {};
- global.cycleAnalytics.svgs = global.cycleAnalytics.svgs || {};
-
- global.cycleAnalytics.svgs.iconCommit = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><path fill="#8F8F8F" fill-rule="evenodd" d="M28.777 18c-.91-4.008-4.494-7-8.777-7-4.283 0-7.868 2.992-8.777 7H4.01C2.9 18 2 18.895 2 20c0 1.112.9 2 2.01 2h7.213c.91 4.008 4.494 7 8.777 7 4.283 0 7.868-2.992 8.777-7h7.214C37.1 22 38 21.105 38 20c0-1.112-.9-2-2.01-2h-7.213zM20 25c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5z"/></svg>';
-})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/cycle_analytics/svg/icon_commit.svg b/app/assets/javascripts/cycle_analytics/svg/icon_commit.svg
new file mode 100644
index 00000000000..6a517756058
--- /dev/null
+++ b/app/assets/javascripts/cycle_analytics/svg/icon_commit.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><path fill="#8F8F8F" fill-rule="evenodd" d="M28.777 18c-.91-4.008-4.494-7-8.777-7-4.283 0-7.868 2.992-8.777 7H4.01C2.9 18 2 18.895 2 20c0 1.112.9 2 2.01 2h7.213c.91 4.008 4.494 7 8.777 7 4.283 0 7.868-2.992 8.777-7h7.214C37.1 22 38 21.105 38 20c0-1.112-.9-2-2.01-2h-7.213zM20 25c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5z"/></svg>
diff --git a/app/assets/javascripts/diff.js.es6 b/app/assets/javascripts/diff.js
index ccccd0a36ff..6829e8aeaea 100644
--- a/app/assets/javascripts/diff.js.es6
+++ b/app/assets/javascripts/diff.js
@@ -25,6 +25,10 @@ require('./lib/utils/url_utility');
isBound = true;
}
+ if (gl.utils.getLocationHash()) {
+ this.highlightSelectedLine();
+ }
+
this.openAnchoredDiff();
}
@@ -78,7 +82,7 @@ require('./lib/utils/url_utility');
if (nothingHereBlock.length) {
const clickTarget = $('.js-file-title, .click-to-expand', diffFile);
diffFile.data('singleFileDiff').toggleDiff(clickTarget, () => {
- this.highlighSelectedLine();
+ this.highlightSelectedLine();
if (cb) cb();
});
} else if (cb) {
@@ -94,7 +98,7 @@ require('./lib/utils/url_utility');
} else {
window.location.hash = hash;
}
- this.highlighSelectedLine();
+ this.highlightSelectedLine();
}
diffViewType() {
@@ -108,7 +112,7 @@ require('./lib/utils/url_utility');
return line.find('.diff-line-num').map((i, elm) => parseInt($(elm).data('linenumber'), 10));
}
- highlighSelectedLine() {
+ highlightSelectedLine() {
const hash = gl.utils.getLocationHash();
const $diffFiles = $('.diff-file');
$diffFiles.find('.hll').removeClass('hll');
diff --git a/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js.es6 b/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js
index d948dff58ec..d948dff58ec 100644
--- a/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js.es6
+++ b/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js
diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6 b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
index 283dc330cad..283dc330cad 100644
--- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6
+++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
diff --git a/app/assets/javascripts/diff_notes/components/resolve_btn.js.es6 b/app/assets/javascripts/diff_notes/components/resolve_btn.js
index d1873d6c7a2..d1873d6c7a2 100644
--- a/app/assets/javascripts/diff_notes/components/resolve_btn.js.es6
+++ b/app/assets/javascripts/diff_notes/components/resolve_btn.js
diff --git a/app/assets/javascripts/diff_notes/components/resolve_count.js.es6 b/app/assets/javascripts/diff_notes/components/resolve_count.js
index de9367f2136..de9367f2136 100644
--- a/app/assets/javascripts/diff_notes/components/resolve_count.js.es6
+++ b/app/assets/javascripts/diff_notes/components/resolve_count.js
diff --git a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6 b/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js
index 7c5fcd04d2d..7c5fcd04d2d 100644
--- a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6
+++ b/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js
diff --git a/app/assets/javascripts/diff_notes/diff_notes_bundle.js.es6 b/app/assets/javascripts/diff_notes/diff_notes_bundle.js
index cadf8b96b87..cadf8b96b87 100644
--- a/app/assets/javascripts/diff_notes/diff_notes_bundle.js.es6
+++ b/app/assets/javascripts/diff_notes/diff_notes_bundle.js
diff --git a/app/assets/javascripts/diff_notes/mixins/discussion.js.es6 b/app/assets/javascripts/diff_notes/mixins/discussion.js
index 3c08c222f46..3c08c222f46 100644
--- a/app/assets/javascripts/diff_notes/mixins/discussion.js.es6
+++ b/app/assets/javascripts/diff_notes/mixins/discussion.js
diff --git a/app/assets/javascripts/diff_notes/models/discussion.js.es6 b/app/assets/javascripts/diff_notes/models/discussion.js
index fa518ba4d33..fa518ba4d33 100644
--- a/app/assets/javascripts/diff_notes/models/discussion.js.es6
+++ b/app/assets/javascripts/diff_notes/models/discussion.js
diff --git a/app/assets/javascripts/diff_notes/models/note.js.es6 b/app/assets/javascripts/diff_notes/models/note.js
index f3a7cba5ef6..f3a7cba5ef6 100644
--- a/app/assets/javascripts/diff_notes/models/note.js.es6
+++ b/app/assets/javascripts/diff_notes/models/note.js
diff --git a/app/assets/javascripts/diff_notes/services/resolve.js.es6 b/app/assets/javascripts/diff_notes/services/resolve.js
index 090c454e9e4..090c454e9e4 100644
--- a/app/assets/javascripts/diff_notes/services/resolve.js.es6
+++ b/app/assets/javascripts/diff_notes/services/resolve.js
diff --git a/app/assets/javascripts/diff_notes/stores/comments.js.es6 b/app/assets/javascripts/diff_notes/stores/comments.js
index c80d979b977..c80d979b977 100644
--- a/app/assets/javascripts/diff_notes/stores/comments.js.es6
+++ b/app/assets/javascripts/diff_notes/stores/comments.js
diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js
index fc25122aedc..31f10f89245 100644
--- a/app/assets/javascripts/dispatcher.js.es6
+++ b/app/assets/javascripts/dispatcher.js
@@ -35,7 +35,9 @@
/* global Labels */
/* global Shortcuts */
+import BindInOut from './behaviors/bind_in_out';
import GroupsList from './groups_list';
+import ProjectsList from './projects_list';
const ShortcutsBlob = require('./shortcuts_blob');
const UserCallout = require('./user_callout');
@@ -98,6 +100,14 @@ const UserCallout = require('./user_callout');
case 'dashboard:todos:index':
new gl.Todos();
break;
+ case 'dashboard:projects:index':
+ case 'dashboard:projects:starred':
+ case 'explore:projects:index':
+ case 'explore:projects:trending':
+ case 'explore:projects:starred':
+ case 'admin:projects:index':
+ new ProjectsList();
+ break;
case 'dashboard:groups:index':
case 'explore:groups:index':
new GroupsList();
@@ -163,9 +173,6 @@ const UserCallout = require('./user_callout');
case 'dashboard:activity':
new gl.Activities();
break;
- case 'dashboard:projects:starred':
- new gl.Activities();
- break;
case 'projects:commit:show':
new Commit();
new gl.Diff();
@@ -208,6 +215,7 @@ const UserCallout = require('./user_callout');
shortcut_handler = new ShortcutsNavigation();
new NotificationsForm();
new NotificationsDropdown();
+ new ProjectsList();
break;
case 'groups:group_members:index':
new gl.MemberExpirationDate();
@@ -222,9 +230,14 @@ const UserCallout = require('./user_callout');
new UsersSelect();
break;
case 'groups:new':
+ case 'admin:groups:new':
+ case 'groups:create':
+ case 'admin:groups:create':
+ BindInOut.initAll();
+ case 'groups:new':
+ case 'admin:groups:new':
case 'groups:edit':
case 'admin:groups:edit':
- case 'admin:groups:new':
new GroupAvatar();
break;
case 'projects:tree:show':
diff --git a/app/assets/javascripts/due_date_select.js.es6 b/app/assets/javascripts/due_date_select.js
index 9169fcd7328..9169fcd7328 100644
--- a/app/assets/javascripts/due_date_select.js.es6
+++ b/app/assets/javascripts/due_date_select.js
diff --git a/app/assets/javascripts/environments/components/environment.js.es6 b/app/assets/javascripts/environments/components/environment.js
index 5869323d1e2..2cb48dde628 100644
--- a/app/assets/javascripts/environments/components/environment.js.es6
+++ b/app/assets/javascripts/environments/components/environment.js
@@ -35,9 +35,6 @@ module.exports = Vue.component('environment-component', {
projectStoppedEnvironmentsPath: environmentsData.projectStoppedEnvironmentsPath,
newEnvironmentPath: environmentsData.newEnvironmentPath,
helpPagePath: environmentsData.helpPagePath,
- commitIconSvg: environmentsData.commitIconSvg,
- playIconSvg: environmentsData.playIconSvg,
- terminalIconSvg: environmentsData.terminalIconSvg,
// Pagination Properties,
paginationInformation: {},
@@ -78,7 +75,7 @@ module.exports = Vue.component('environment-component', {
this.isLoading = true;
- return service.all()
+ return service.get()
.then(resp => ({
headers: resp.headers,
body: resp.json(),
@@ -176,11 +173,7 @@ module.exports = Vue.component('environment-component', {
<environment-table
:environments="state.environments"
:can-create-deployment="canCreateDeploymentParsed"
- :can-read-environment="canReadEnvironmentParsed"
- :play-icon-svg="playIconSvg"
- :terminal-icon-svg="terminalIconSvg"
- :commit-icon-svg="commitIconSvg">
- </environment-table>
+ :can-read-environment="canReadEnvironmentParsed"/>
</div>
<table-pagination v-if="state.paginationInformation && state.paginationInformation.totalPages > 1"
diff --git a/app/assets/javascripts/environments/components/environment_actions.js.es6 b/app/assets/javascripts/environments/components/environment_actions.js
index 978d4dd8b6b..15e3f8823d2 100644
--- a/app/assets/javascripts/environments/components/environment_actions.js.es6
+++ b/app/assets/javascripts/environments/components/environment_actions.js
@@ -1,4 +1,5 @@
const Vue = require('vue');
+const playIconSvg = require('icons/_icon_play.svg');
module.exports = Vue.component('actions-component', {
props: {
@@ -7,11 +8,10 @@ module.exports = Vue.component('actions-component', {
required: false,
default: () => [],
},
+ },
- playIconSvg: {
- type: String,
- required: false,
- },
+ data() {
+ return { playIconSvg };
},
template: `
@@ -28,9 +28,7 @@ module.exports = Vue.component('actions-component', {
data-method="post"
rel="nofollow"
class="js-manual-action-link">
-
- <span class="js-action-play-icon-container" v-html="playIconSvg"></span>
-
+ ${playIconSvg}
<span>
{{action.name}}
</span>
diff --git a/app/assets/javascripts/environments/components/environment_external_url.js.es6 b/app/assets/javascripts/environments/components/environment_external_url.js
index 2599bba3c59..2599bba3c59 100644
--- a/app/assets/javascripts/environments/components/environment_external_url.js.es6
+++ b/app/assets/javascripts/environments/components/environment_external_url.js
diff --git a/app/assets/javascripts/environments/components/environment_item.js.es6 b/app/assets/javascripts/environments/components/environment_item.js
index 3f782742c56..7f4e070b229 100644
--- a/app/assets/javascripts/environments/components/environment_item.js.es6
+++ b/app/assets/javascripts/environments/components/environment_item.js
@@ -46,21 +46,6 @@ module.exports = Vue.component('environment-item', {
required: false,
default: false,
},
-
- commitIconSvg: {
- type: String,
- required: false,
- },
-
- playIconSvg: {
- type: String,
- required: false,
- },
-
- terminalIconSvg: {
- type: String,
- required: false,
- },
},
computed: {
@@ -487,9 +472,7 @@ module.exports = Vue.component('environment-item', {
:commit-url="commitUrl"
:short-sha="commitShortSha"
:title="commitTitle"
- :author="commitAuthor"
- :commit-icon-svg="commitIconSvg">
- </commit-component>
+ :author="commitAuthor"/>
</div>
<p v-if="!model.isFolder && !hasLastDeploymentKey" class="commit-title">
No deployments yet
@@ -506,27 +489,20 @@ module.exports = Vue.component('environment-item', {
<td class="environments-actions">
<div v-if="!model.isFolder" class="btn-group pull-right" role="group">
<actions-component v-if="hasManualActions && canCreateDeployment"
- :play-icon-svg="playIconSvg"
- :actions="manualActions">
- </actions-component>
+ :actions="manualActions"/>
<external-url-component v-if="externalURL && canReadEnvironment"
- :external-url="externalURL">
- </external-url-component>
+ :external-url="externalURL"/>
<stop-component v-if="hasStopAction && canCreateDeployment"
- :stop-url="model.stop_path">
- </stop-component>
+ :stop-url="model.stop_path"/>
<terminal-button-component v-if="model && model.terminal_path"
- :terminal-icon-svg="terminalIconSvg"
- :terminal-path="model.terminal_path">
- </terminal-button-component>
+ :terminal-path="model.terminal_path"/>
<rollback-component v-if="canRetry && canCreateDeployment"
:is-last-deployment="isLastDeployment"
- :retry-url="retryUrl">
- </rollback-component>
+ :retry-url="retryUrl"/>
</div>
</td>
</tr>
diff --git a/app/assets/javascripts/environments/components/environment_rollback.js.es6 b/app/assets/javascripts/environments/components/environment_rollback.js
index daf126eb4e8..daf126eb4e8 100644
--- a/app/assets/javascripts/environments/components/environment_rollback.js.es6
+++ b/app/assets/javascripts/environments/components/environment_rollback.js
diff --git a/app/assets/javascripts/environments/components/environment_stop.js.es6 b/app/assets/javascripts/environments/components/environment_stop.js
index 96983a19568..96983a19568 100644
--- a/app/assets/javascripts/environments/components/environment_stop.js.es6
+++ b/app/assets/javascripts/environments/components/environment_stop.js
diff --git a/app/assets/javascripts/environments/components/environment_terminal_button.js.es6 b/app/assets/javascripts/environments/components/environment_terminal_button.js
index 481e0d15e7a..e86607e78f4 100644
--- a/app/assets/javascripts/environments/components/environment_terminal_button.js.es6
+++ b/app/assets/javascripts/environments/components/environment_terminal_button.js
@@ -3,6 +3,7 @@
* Used in environments table.
*/
const Vue = require('vue');
+const terminalIconSvg = require('icons/_icon_terminal.svg');
module.exports = Vue.component('terminal-button-component', {
props: {
@@ -10,16 +11,16 @@ module.exports = Vue.component('terminal-button-component', {
type: String,
default: '',
},
- terminalIconSvg: {
- type: String,
- default: '',
- },
+ },
+
+ data() {
+ return { terminalIconSvg };
},
template: `
<a class="btn terminal-button"
:href="terminalPath">
- <span class="js-terminal-icon-container" v-html="terminalIconSvg"></span>
+ ${terminalIconSvg}
</a>
`,
});
diff --git a/app/assets/javascripts/environments/components/environments_table.js.es6 b/app/assets/javascripts/environments/components/environments_table.js
index 33ebca19f5d..4088d63be80 100644
--- a/app/assets/javascripts/environments/components/environments_table.js.es6
+++ b/app/assets/javascripts/environments/components/environments_table.js
@@ -28,21 +28,6 @@ module.exports = Vue.component('environment-table-component', {
required: false,
default: false,
},
-
- commitIconSvg: {
- type: String,
- required: false,
- },
-
- playIconSvg: {
- type: String,
- required: false,
- },
-
- terminalIconSvg: {
- type: String,
- required: false,
- },
},
template: `
@@ -63,10 +48,7 @@ module.exports = Vue.component('environment-table-component', {
<tr is="environment-item"
:model="model"
:can-create-deployment="canCreateDeployment"
- :can-read-environment="canReadEnvironment"
- :play-icon-svg="playIconSvg"
- :terminal-icon-svg="terminalIconSvg"
- :commit-icon-svg="commitIconSvg"></tr>
+ :can-read-environment="canReadEnvironment"></tr>
</template>
</tbody>
</table>
diff --git a/app/assets/javascripts/environments/environments_bundle.js.es6 b/app/assets/javascripts/environments/environments_bundle.js
index 7bbba91bc10..7bbba91bc10 100644
--- a/app/assets/javascripts/environments/environments_bundle.js.es6
+++ b/app/assets/javascripts/environments/environments_bundle.js
diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6 b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
index d2ca465351a..d2ca465351a 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6
+++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.js.es6 b/app/assets/javascripts/environments/folder/environments_folder_view.js
index 53d52965758..2a9d0492d7a 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_view.js.es6
+++ b/app/assets/javascripts/environments/folder/environments_folder_view.js
@@ -92,7 +92,7 @@ module.exports = Vue.component('environment-folder-view', {
this.isLoading = true;
- return service.all()
+ return service.get()
.then(resp => ({
headers: resp.headers,
body: resp.json(),
diff --git a/app/assets/javascripts/environments/services/environments_service.js.es6 b/app/assets/javascripts/environments/services/environments_service.js
index 9cef335868e..effc6c4c838 100644
--- a/app/assets/javascripts/environments/services/environments_service.js.es6
+++ b/app/assets/javascripts/environments/services/environments_service.js
@@ -5,7 +5,7 @@ class EnvironmentsService {
this.environments = Vue.resource(endpoint);
}
- all() {
+ get() {
return this.environments.get();
}
}
diff --git a/app/assets/javascripts/environments/stores/environments_store.js.es6 b/app/assets/javascripts/environments/stores/environments_store.js
index 15cd9bde08e..15cd9bde08e 100644
--- a/app/assets/javascripts/environments/stores/environments_store.js.es6
+++ b/app/assets/javascripts/environments/stores/environments_store.js
diff --git a/app/assets/javascripts/extensions/array.js.es6 b/app/assets/javascripts/extensions/array.js
index f8256a8d26d..f8256a8d26d 100644
--- a/app/assets/javascripts/extensions/array.js.es6
+++ b/app/assets/javascripts/extensions/array.js
diff --git a/app/assets/javascripts/extensions/custom_event.js.es6 b/app/assets/javascripts/extensions/custom_event.js
index abedae4c1c7..abedae4c1c7 100644
--- a/app/assets/javascripts/extensions/custom_event.js.es6
+++ b/app/assets/javascripts/extensions/custom_event.js
diff --git a/app/assets/javascripts/extensions/element.js.es6 b/app/assets/javascripts/extensions/element.js
index 90ab79305a7..90ab79305a7 100644
--- a/app/assets/javascripts/extensions/element.js.es6
+++ b/app/assets/javascripts/extensions/element.js
diff --git a/app/assets/javascripts/extensions/object.js.es6 b/app/assets/javascripts/extensions/object.js
index 70a2d765abd..70a2d765abd 100644
--- a/app/assets/javascripts/extensions/object.js.es6
+++ b/app/assets/javascripts/extensions/object.js
diff --git a/app/assets/javascripts/extensions/string.js b/app/assets/javascripts/extensions/string.js
new file mode 100644
index 00000000000..fe23be0bbc1
--- /dev/null
+++ b/app/assets/javascripts/extensions/string.js
@@ -0,0 +1,2 @@
+require('string.prototype.codepointat');
+require('string.fromcodepoint');
diff --git a/app/assets/javascripts/filterable_list.js b/app/assets/javascripts/filterable_list.js
new file mode 100644
index 00000000000..47a40e28461
--- /dev/null
+++ b/app/assets/javascripts/filterable_list.js
@@ -0,0 +1,45 @@
+/**
+ * Makes search request for content when user types a value in the search input.
+ * Updates the html content of the page with the received one.
+ */
+export default class FilterableList {
+ constructor(form, filter, holder) {
+ this.filterForm = form;
+ this.listFilterElement = filter;
+ this.listHolderElement = holder;
+ }
+
+ initSearch() {
+ this.debounceFilter = _.debounce(this.filterResults.bind(this), 500);
+
+ this.listFilterElement.removeEventListener('input', this.debounceFilter);
+ this.listFilterElement.addEventListener('input', this.debounceFilter);
+ }
+
+ filterResults() {
+ const form = this.filterForm;
+ const filterUrl = `${form.getAttribute('action')}?${$(form).serialize()}`;
+
+ $(this.listHolderElement).fadeTo(250, 0.5);
+
+ return $.ajax({
+ url: form.getAttribute('action'),
+ data: $(form).serialize(),
+ type: 'GET',
+ dataType: 'json',
+ context: this,
+ complete() {
+ $(this.listHolderElement).fadeTo(250, 1);
+ },
+ success(data) {
+ this.listHolderElement.innerHTML = data.html;
+
+ // Change url so if user reload a page - search results are saved
+ return window.history.replaceState({
+ page: filterUrl,
+
+ }, document.title, filterUrl);
+ },
+ });
+ }
+}
diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js.es6 b/app/assets/javascripts/filtered_search/dropdown_hint.js
index 9e92d544bef..9e92d544bef 100644
--- a/app/assets/javascripts/filtered_search/dropdown_hint.js.es6
+++ b/app/assets/javascripts/filtered_search/dropdown_hint.js
diff --git a/app/assets/javascripts/filtered_search/dropdown_non_user.js.es6 b/app/assets/javascripts/filtered_search/dropdown_non_user.js
index b3dc3e502c5..b3dc3e502c5 100644
--- a/app/assets/javascripts/filtered_search/dropdown_non_user.js.es6
+++ b/app/assets/javascripts/filtered_search/dropdown_non_user.js
diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js.es6 b/app/assets/javascripts/filtered_search/dropdown_user.js
index 7e9c6f74aa5..7e9c6f74aa5 100644
--- a/app/assets/javascripts/filtered_search/dropdown_user.js.es6
+++ b/app/assets/javascripts/filtered_search/dropdown_user.js
diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js.es6 b/app/assets/javascripts/filtered_search/dropdown_utils.js
index de3fa116717..de3fa116717 100644
--- a/app/assets/javascripts/filtered_search/dropdown_utils.js.es6
+++ b/app/assets/javascripts/filtered_search/dropdown_utils.js
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
index dd565da507e..dd565da507e 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
index cecd3518ce3..cecd3518ce3 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index bbafead0305..bbafead0305 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
diff --git a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
index e6b53cd4b55..e6b53cd4b55 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
diff --git a/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js
index 9bf1b1ced88..9bf1b1ced88 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js
diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js
index 60d6658dc16..1bc04a5ad96 100644
--- a/app/assets/javascripts/gfm_auto_complete.js.es6
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -1,5 +1,11 @@
/* eslint-disable func-names, space-before-function-paren, no-template-curly-in-string, comma-dangle, object-shorthand, quotes, dot-notation, no-else-return, one-var, no-var, no-underscore-dangle, one-var-declaration-per-line, no-param-reassign, no-useless-escape, prefer-template, consistent-return, wrap-iife, prefer-arrow-callback, camelcase, no-unused-vars, no-useless-return, vars-on-top, max-len */
+const emojiMap = require('emoji-map');
+const emojiAliases = require('emoji-aliases');
+const glEmoji = require('./behaviors/gl_emoji');
+
+const glEmojiTag = glEmoji.glEmojiTag;
+
// Creates the variables for setting up GFM auto-completion
(function() {
if (window.gl == null) {
@@ -26,7 +32,12 @@
},
// Emoji
Emoji: {
- template: '<li>${name} <img alt="${name}" height="20" src="${path}" width="20" /></li>'
+ templateFunction: function(name) {
+ return `<li>
+ ${name} ${glEmojiTag(name)}
+ </li>
+ `;
+ }
},
// Team Members
Members: {
@@ -113,7 +124,7 @@
$input.atwho({
at: ':',
displayTpl: function(value) {
- return value.path != null ? this.Emoji.template : this.Loading.template;
+ return value && value.name ? this.Emoji.templateFunction(value.name) : this.Loading.template;
}.bind(this),
insertTpl: ':${name}:',
skipSpecialCharacterTest: true,
@@ -355,6 +366,8 @@
this.isLoadingData[at] = true;
if (this.cachedData[at]) {
this.loadData($input, at, this.cachedData[at]);
+ } else if (this.atTypeMap[at] === 'emojis') {
+ this.loadData($input, at, Object.keys(emojiMap).concat(Object.keys(emojiAliases)));
} else {
$.getJSON(this.dataSources[this.atTypeMap[at]], (data) => {
this.loadData($input, at, data);
diff --git a/app/assets/javascripts/gl_field_error.js.es6 b/app/assets/javascripts/gl_field_error.js
index f7cbecc0385..f7cbecc0385 100644
--- a/app/assets/javascripts/gl_field_error.js.es6
+++ b/app/assets/javascripts/gl_field_error.js
diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js
index e9add115429..e9add115429 100644
--- a/app/assets/javascripts/gl_field_errors.js.es6
+++ b/app/assets/javascripts/gl_field_errors.js
diff --git a/app/assets/javascripts/gl_form.js.es6 b/app/assets/javascripts/gl_form.js
index 0b446ff364a..0b446ff364a 100644
--- a/app/assets/javascripts/gl_form.js.es6
+++ b/app/assets/javascripts/gl_form.js
diff --git a/app/assets/javascripts/graphs/graphs_bundle.js b/app/assets/javascripts/graphs/graphs_bundle.js
index ea5afbd9d29..a433c7ba8f0 100644
--- a/app/assets/javascripts/graphs/graphs_bundle.js
+++ b/app/assets/javascripts/graphs/graphs_bundle.js
@@ -1,4 +1,6 @@
+import Chart from 'vendor/Chart';
import ContributorsStatGraph from './stat_graph_contributors';
// export to global scope
+window.Chart = Chart;
window.ContributorsStatGraph = ContributorsStatGraph;
diff --git a/app/assets/javascripts/group_label_subscription.js.es6 b/app/assets/javascripts/group_label_subscription.js
index 15e695e81cf..15e695e81cf 100644
--- a/app/assets/javascripts/group_label_subscription.js.es6
+++ b/app/assets/javascripts/group_label_subscription.js
diff --git a/app/assets/javascripts/groups_list.js b/app/assets/javascripts/groups_list.js
index 0ef81e49444..56a8cbf6d03 100644
--- a/app/assets/javascripts/groups_list.js
+++ b/app/assets/javascripts/groups_list.js
@@ -1,47 +1,18 @@
+import FilterableList from './filterable_list';
+
/**
- * Based on project list search.
* Makes search request for groups when user types a value in the search input.
* Updates the html content of the page with the received one.
*/
export default class GroupsList {
constructor() {
- this.groupsListFilterElement = document.querySelector('.js-groups-list-filter');
- this.groupsListHolderElement = document.querySelector('.js-groups-list-holder');
-
- this.initSearch();
- }
-
- initSearch() {
- this.debounceFilter = _.debounce(this.filterResults.bind(this), 500);
-
- this.groupsListFilterElement.removeEventListener('input', this.debounceFilter);
- this.groupsListFilterElement.addEventListener('input', this.debounceFilter);
- }
-
- filterResults() {
const form = document.querySelector('form#group-filter-form');
- const groupFilterUrl = `${form.getAttribute('action')}?${$(form).serialize()}`;
-
- $(this.groupsListHolderElement).fadeTo(250, 0.5);
-
- return $.ajax({
- url: form.getAttribute('action'),
- data: $(form).serialize(),
- type: 'GET',
- dataType: 'json',
- context: this,
- complete() {
- $(this.groupsListHolderElement).fadeTo(250, 1);
- },
- success(data) {
- this.groupsListHolderElement.innerHTML = data.html;
-
- // Change url so if user reload a page - search results are saved
- return window.history.replaceState({
- page: groupFilterUrl,
+ const filter = document.querySelector('.js-groups-list-filter');
+ const holder = document.querySelector('.js-groups-list-holder');
- }, document.title, groupFilterUrl);
- },
- });
+ if (form && filter && holder) {
+ const list = new FilterableList(form, filter, holder);
+ list.initSearch();
+ }
}
}
diff --git a/app/assets/javascripts/issuable.js.es6 b/app/assets/javascripts/issuable.js
index 3bfce32768a..3bfce32768a 100644
--- a/app/assets/javascripts/issuable.js.es6
+++ b/app/assets/javascripts/issuable.js
diff --git a/app/assets/javascripts/issuable/issuable_bundle.js.es6 b/app/assets/javascripts/issuable/issuable_bundle.js
index e927cc0077c..e927cc0077c 100644
--- a/app/assets/javascripts/issuable/issuable_bundle.js.es6
+++ b/app/assets/javascripts/issuable/issuable_bundle.js
diff --git a/app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js
index bf27fbac5d7..357b3487ca9 100644
--- a/app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js.es6
+++ b/app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js
@@ -1,4 +1,6 @@
/* global Vue */
+import stopwatchSvg from 'icons/_icon_stopwatch.svg';
+
require('../../../lib/utils/pretty_time');
(() => {
@@ -11,7 +13,6 @@ require('../../../lib/utils/pretty_time');
'showNoTimeTrackingState',
'timeSpentHumanReadable',
'timeEstimateHumanReadable',
- 'stopwatchSvg',
],
methods: {
abbreviateTime(timeStr) {
@@ -20,7 +21,7 @@ require('../../../lib/utils/pretty_time');
},
template: `
<div class='sidebar-collapsed-icon'>
- <div v-html='stopwatchSvg'></div>
+ ${stopwatchSvg}
<div class='time-tracking-collapsed-summary'>
<div class='compare' v-if='showComparisonState'>
<span>{{ abbreviateTime(timeSpentHumanReadable) }} / {{ abbreviateTime(timeEstimateHumanReadable) }}</span>
diff --git a/app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js
index 750468c679b..750468c679b 100644
--- a/app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js.es6
+++ b/app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js
diff --git a/app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js
index 309e9f2f9ef..309e9f2f9ef 100644
--- a/app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js.es6
+++ b/app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js
diff --git a/app/assets/javascripts/issuable/time_tracking/components/help_state.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/help_state.js
index d7ced6d7151..d7ced6d7151 100644
--- a/app/assets/javascripts/issuable/time_tracking/components/help_state.js.es6
+++ b/app/assets/javascripts/issuable/time_tracking/components/help_state.js
diff --git a/app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js
index 1d2ca643b5b..1d2ca643b5b 100644
--- a/app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js.es6
+++ b/app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js
diff --git a/app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js
index ed283fec3c3..ed283fec3c3 100644
--- a/app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js.es6
+++ b/app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js
diff --git a/app/assets/javascripts/issuable/time_tracking/components/time_tracker.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/time_tracker.js
index b271ea83330..1fae2d62b14 100644
--- a/app/assets/javascripts/issuable/time_tracking/components/time_tracker.js.es6
+++ b/app/assets/javascripts/issuable/time_tracking/components/time_tracker.js
@@ -15,7 +15,6 @@ require('./comparison_pane');
'time_spent',
'human_time_estimate',
'human_time_spent',
- 'stopwatchSvg',
'docsUrl',
],
data() {
@@ -71,8 +70,7 @@ require('./comparison_pane');
:show-spent-only-state='showSpentOnlyState'
:show-estimate-only-state='showEstimateOnlyState'
:time-spent-human-readable='timeSpentHumanReadable'
- :time-estimate-human-readable='timeEstimateHumanReadable'
- :stopwatch-svg='stopwatchSvg'>
+ :time-estimate-human-readable='timeEstimateHumanReadable'>
</time-tracking-collapsed-state>
<div class='title hide-collapsed'>
Time tracking
diff --git a/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js.es6 b/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js
index 958a0cc6d50..0134b7cb6f3 100644
--- a/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js.es6
+++ b/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js
@@ -1,5 +1,7 @@
/* global Vue */
+window.Vue = require('vue');
+window.Vue.use(require('vue-resource'));
require('./components/time_tracker');
require('../../smart_interval');
require('../../subbable_resource');
diff --git a/app/assets/javascripts/issues_bulk_assignment.js.es6 b/app/assets/javascripts/issues_bulk_assignment.js
index e0ebd36a65c..e0ebd36a65c 100644
--- a/app/assets/javascripts/issues_bulk_assignment.js.es6
+++ b/app/assets/javascripts/issues_bulk_assignment.js
diff --git a/app/assets/javascripts/label_manager.js.es6 b/app/assets/javascripts/label_manager.js
index 38b2eb9ff14..38b2eb9ff14 100644
--- a/app/assets/javascripts/label_manager.js.es6
+++ b/app/assets/javascripts/label_manager.js
diff --git a/app/assets/javascripts/lib/chart.js b/app/assets/javascripts/lib/chart.js
deleted file mode 100644
index 9b011d89e93..00000000000
--- a/app/assets/javascripts/lib/chart.js
+++ /dev/null
@@ -1,3 +0,0 @@
-/* eslint-disable func-names, space-before-function-paren */
-
-window.Chart = require('vendor/Chart');
diff --git a/app/assets/javascripts/lib/cropper.js b/app/assets/javascripts/lib/cropper.js
deleted file mode 100644
index 7862c6797c3..00000000000
--- a/app/assets/javascripts/lib/cropper.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/* eslint-disable func-names, space-before-function-paren */
-
-/*= require cropper */
-
-(function() {
-
-}).call(window);
diff --git a/app/assets/javascripts/lib/d3.js b/app/assets/javascripts/lib/d3.js
deleted file mode 100644
index a9dd32edbed..00000000000
--- a/app/assets/javascripts/lib/d3.js
+++ /dev/null
@@ -1,3 +0,0 @@
-/* eslint-disable func-names, space-before-function-paren */
-
-window.d3 = require('d3');
diff --git a/app/assets/javascripts/lib/raphael.js b/app/assets/javascripts/lib/raphael.js
deleted file mode 100644
index ebe1e2ae98d..00000000000
--- a/app/assets/javascripts/lib/raphael.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/* eslint-disable func-names, space-before-function-paren */
-
-/*= require raphael */
-/*= require g.raphael */
-/*= require g.bar */
-
-(function() {
-
-}).call(window);
diff --git a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js.es6 b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
index 2955bda1a36..2955bda1a36 100644
--- a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js.es6
+++ b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
diff --git a/app/assets/javascripts/lib/utils/common_utils.js.es6 b/app/assets/javascripts/lib/utils/common_utils.js
index 0242350f718..a1423b6fda5 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js.es6
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -247,17 +247,6 @@
});
/**
- * Transforms a DOMStringMap into a plain object.
- *
- * @param {DOMStringMap} DOMStringMapObject
- * @returns {Object}
- */
- w.gl.utils.DOMStringMapToObject = DOMStringMapObject => Object.keys(DOMStringMapObject).reduce((acc, element) => {
- acc[element] = DOMStringMapObject[element];
- return acc;
- }, {});
-
- /**
* Updates the search parameter of a URL given the parameter and values provided.
*
* If no search params are present we'll add it.
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js.es6 b/app/assets/javascripts/lib/utils/datetime_utility.js
index 82dcbdc26c8..82dcbdc26c8 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js.es6
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
diff --git a/app/assets/javascripts/lib/utils/pretty_time.js.es6 b/app/assets/javascripts/lib/utils/pretty_time.js
index ae397212e55..ae397212e55 100644
--- a/app/assets/javascripts/lib/utils/pretty_time.js.es6
+++ b/app/assets/javascripts/lib/utils/pretty_time.js
diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js
index 579d322e3fb..2e5f8a09fc1 100644
--- a/app/assets/javascripts/lib/utils/text_utility.js
+++ b/app/assets/javascripts/lib/utils/text_utility.js
@@ -65,9 +65,10 @@ require('vendor/latinise');
}
};
gl.text.insertText = function(textArea, text, tag, blockTag, selected, wrap) {
- var insertText, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine;
+ var insertText, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine, currentLineEmpty, lastNewLine;
removedLastNewLine = false;
removedFirstNewLine = false;
+ currentLineEmpty = false;
// Remove the first newline
if (selected.indexOf('\n') === 0) {
@@ -82,7 +83,17 @@ require('vendor/latinise');
}
selectedSplit = selected.split('\n');
- startChar = !wrap && textArea.selectionStart > 0 ? '\n' : '';
+
+ if (!wrap) {
+ lastNewLine = textArea.value.substr(0, textArea.selectionStart).lastIndexOf('\n');
+
+ // Check whether the current line is empty or consists only of spaces(=handle as empty)
+ if (/^\s*$/.test(textArea.value.substring(lastNewLine, textArea.selectionStart))) {
+ currentLineEmpty = true;
+ }
+ }
+
+ startChar = !wrap && !currentLineEmpty && textArea.selectionStart > 0 ? '\n' : '';
if (selectedSplit.length > 1 && (!wrap || (blockTag != null))) {
if (blockTag != null) {
@@ -142,9 +153,8 @@ require('vendor/latinise');
}
};
gl.text.updateText = function(textArea, tag, blockTag, wrap) {
- var $textArea, oldVal, selected, text;
+ var $textArea, selected, text;
$textArea = $(textArea);
- oldVal = $textArea.val();
textArea = $textArea.get(0);
text = $textArea.val();
selected = this.selectedText(text, textArea);
diff --git a/app/assets/javascripts/lib/utils/url_utility.js.es6 b/app/assets/javascripts/lib/utils/url_utility.js
index 1bc81d2e4a4..1bc81d2e4a4 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js.es6
+++ b/app/assets/javascripts/lib/utils/url_utility.js
diff --git a/app/assets/javascripts/lib/vue_resource.js.es6 b/app/assets/javascripts/lib/vue_resource.js.es6
deleted file mode 100644
index 49babdea2e1..00000000000
--- a/app/assets/javascripts/lib/vue_resource.js.es6
+++ /dev/null
@@ -1,2 +0,0 @@
-window.Vue = require('vue');
-window.Vue.use(require('vue-resource'));
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/main.js
index c51860d1604..ae4dd64424c 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/main.js
@@ -3,43 +3,45 @@
/* global Cookies */
/* global Flash */
/* global ConfirmDangerModal */
-/* global AwardsHandler */
/* global Aside */
-window.$ = window.jQuery = require('jquery');
-require('jquery-ujs');
-require('vendor/jquery.endless-scroll');
-require('vendor/jquery.highlight');
-require('vendor/jquery.waitforimages');
-require('vendor/jquery.caret');
-require('vendor/jquery.atwho');
-require('vendor/jquery.scrollTo');
-window.Cookies = require('js-cookie');
-require('./autosave');
-require('bootstrap/js/affix');
-require('bootstrap/js/alert');
-require('bootstrap/js/button');
-require('bootstrap/js/collapse');
-require('bootstrap/js/dropdown');
-require('bootstrap/js/modal');
-require('bootstrap/js/scrollspy');
-require('bootstrap/js/tab');
-require('bootstrap/js/transition');
-require('bootstrap/js/tooltip');
-require('bootstrap/js/popover');
-require('select2/select2.js');
-window.Pikaday = require('pikaday');
-window._ = require('underscore');
-window.Dropzone = require('dropzone');
-window.Sortable = require('vendor/Sortable');
+import jQuery from 'jquery';
+import _ from 'underscore';
+import Cookies from 'js-cookie';
+import Pikaday from 'pikaday';
+import Dropzone from 'dropzone';
+import Sortable from 'vendor/Sortable';
+
+// libraries with import side-effects
require('mousetrap');
require('mousetrap/plugins/pause/mousetrap-pause');
+require('vendor/fuzzaldrin-plus');
+require('es6-promise').polyfill();
+
+// extensions
+require('./extensions/string');
+require('./extensions/array');
+require('./extensions/custom_event');
+require('./extensions/element');
+require('./extensions/jquery');
+require('./extensions/object');
+require('es6-promise').polyfill();
+
+// expose common libraries as globals (TODO: remove these)
+window.jQuery = jQuery;
+window.$ = jQuery;
+window._ = _;
+window.Cookies = Cookies;
+window.Pikaday = Pikaday;
+window.Dropzone = Dropzone;
+window.Sortable = Sortable;
+
+// shortcuts
require('./shortcuts');
require('./shortcuts_navigation');
require('./shortcuts_dashboard_navigation');
require('./shortcuts_issuable');
require('./shortcuts_network');
-require('vendor/jquery.nicescroll');
// behaviors
require('./behaviors/autosize');
@@ -47,6 +49,7 @@ require('./behaviors/details_behavior');
require('./behaviors/quick_submit');
require('./behaviors/requires_input');
require('./behaviors/toggler_behavior');
+require('./behaviors/bind_in_out');
// blob
require('./blob/blob_ci_yaml');
@@ -67,13 +70,6 @@ require('./templates/issuable_template_selectors');
require('./commit/file.js');
require('./commit/image_file.js');
-// extensions
-require('./extensions/array');
-require('./extensions/custom_event');
-require('./extensions/element');
-require('./extensions/jquery');
-require('./extensions/object');
-
// lib/utils
require('./lib/utils/animate');
require('./lib/utils/bootstrap_linked_tabs');
@@ -105,7 +101,7 @@ require('./ajax_loading_spinner');
require('./api');
require('./aside');
require('./autosave');
-require('./awards_handler');
+const AwardsHandler = require('./awards_handler');
require('./breakpoints');
require('./broadcast_message');
require('./build');
@@ -210,9 +206,6 @@ require('./visibility_select');
require('./wikis');
require('./zen_mode');
-require('vendor/fuzzaldrin-plus');
-require('es6-promise').polyfill();
-
(function () {
document.addEventListener('beforeunload', function () {
// Unbind scroll events
@@ -290,7 +283,7 @@ require('es6-promise').polyfill();
$.fn.tooltip.Constructor.DEFAULTS.trigger = 'hover';
$body.tooltip({
selector: '.has-tooltip, [data-toggle="tooltip"]',
- placement: function (_, el) {
+ placement: function (tip, el) {
return $(el).data('placement') || 'bottom';
}
});
diff --git a/app/assets/javascripts/member_expiration_date.js.es6 b/app/assets/javascripts/member_expiration_date.js
index 129d2dc5f0a..129d2dc5f0a 100644
--- a/app/assets/javascripts/member_expiration_date.js.es6
+++ b/app/assets/javascripts/member_expiration_date.js
diff --git a/app/assets/javascripts/members.js.es6 b/app/assets/javascripts/members.js
index e3f367a11eb..e3f367a11eb 100644
--- a/app/assets/javascripts/members.js.es6
+++ b/app/assets/javascripts/members.js
diff --git a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js.es6 b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
index c7e78fed8fe..c7e78fed8fe 100644
--- a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js.es6
+++ b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
diff --git a/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js.es6 b/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js
index 240c8f98932..240c8f98932 100644
--- a/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js.es6
+++ b/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js
diff --git a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js.es6 b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js
index 97753c50b60..97753c50b60 100644
--- a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js.es6
+++ b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_service.js.es6 b/app/assets/javascripts/merge_conflicts/merge_conflict_service.js
index c012b77e0bf..c012b77e0bf 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflict_service.js.es6
+++ b/app/assets/javascripts/merge_conflicts/merge_conflict_service.js
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js.es6 b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
index 74587df22c5..74587df22c5 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js.es6
+++ b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js.es6 b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
index 653e52fb6bf..653e52fb6bf 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js.es6
+++ b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
diff --git a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js.es6 b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js
index 53e000d7e9e..53e000d7e9e 100644
--- a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js.es6
+++ b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js
diff --git a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js.es6 b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js
index 0f475f62ee6..0f475f62ee6 100644
--- a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js.es6
+++ b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js
diff --git a/app/assets/javascripts/merge_request_tabs.js.es6 b/app/assets/javascripts/merge_request_tabs.js
index 190336dbd20..190336dbd20 100644
--- a/app/assets/javascripts/merge_request_tabs.js.es6
+++ b/app/assets/javascripts/merge_request_tabs.js
diff --git a/app/assets/javascripts/merge_request_widget.js.es6 b/app/assets/javascripts/merge_request_widget.js
index 00c6c050612..5f1bd474a0c 100644
--- a/app/assets/javascripts/merge_request_widget.js.es6
+++ b/app/assets/javascripts/merge_request_widget.js
@@ -129,8 +129,9 @@ require('./smart_interval');
};
MergeRequestWidget.prototype.getMergeStatus = function() {
- return $.get(this.opts.merge_check_url, function(data) {
+ return $.get(this.opts.merge_check_url, (data) => {
var $html = $(data);
+ this.updateMergeButton(this.status, this.hasCi, $html);
$('.mr-widget-body').replaceWith($html.find('.mr-widget-body'));
$('.mr-widget-footer').replaceWith($html.find('.mr-widget-footer'));
});
@@ -154,9 +155,9 @@ require('./smart_interval');
return $.getJSON(this.opts.ci_status_url, (function(_this) {
return function(data) {
var message, status, title;
- if (!data.status) {
- return;
- }
+ _this.status = data.status;
+ _this.hasCi = data.has_ci;
+ _this.updateMergeButton(_this.status, _this.hasCi);
if (data.environments && data.environments.length) _this.renderEnvironments(data.environments);
if (data.status !== _this.opts.ci_status ||
data.sha !== _this.opts.ci_sha ||
@@ -232,36 +233,45 @@ require('./smart_interval');
return;
}
$('.ci_widget').hide();
- allowed_states = ["failed", "canceled", "running", "pending", "success", "success_with_warnings", "skipped", "not_found"];
- if (indexOf.call(allowed_states, state) !== -1) {
- $('.ci_widget.ci-' + state).show();
+ $('.ci_widget.ci-' + state).show();
+
+ this.initMiniPipelineGraph();
+ };
+
+ MergeRequestWidget.prototype.showCICoverage = function(coverage) {
+ var text = `Coverage ${coverage}%`;
+ return $('.ci_widget:visible .ci-coverage').text(text);
+ };
+
+ MergeRequestWidget.prototype.updateMergeButton = function(state, hasCi, $html) {
+ const allowed_states = ["failed", "canceled", "running", "pending", "success", "success_with_warnings", "skipped", "not_found"];
+ let stateClass = 'btn-danger';
+ if (!hasCi) {
+ stateClass = 'btn-create';
+ } else if (indexOf.call(allowed_states, state) !== -1) {
switch (state) {
case "failed":
case "canceled":
case "not_found":
- this.setMergeButtonClass('btn-danger');
+ stateClass = 'btn-danger';
break;
case "running":
- this.setMergeButtonClass('btn-info');
+ stateClass = 'btn-info';
break;
case "success":
case "success_with_warnings":
- this.setMergeButtonClass('btn-create');
+ stateClass = 'btn-create';
}
} else {
$('.ci_widget.ci-error').show();
- this.setMergeButtonClass('btn-danger');
+ stateClass = 'btn-danger';
}
- };
- MergeRequestWidget.prototype.showCICoverage = function(coverage) {
- var text;
- text = 'Coverage ' + coverage + '%';
- return $('.ci_widget:visible .ci-coverage').text(text);
+ this.setMergeButtonClass(stateClass, $html);
};
- MergeRequestWidget.prototype.setMergeButtonClass = function(css_class) {
- return $('.js-merge-button,.accept-action .dropdown-toggle').removeClass('btn-danger btn-info btn-create').addClass(css_class);
+ MergeRequestWidget.prototype.setMergeButtonClass = function(css_class, $html = $('.mr-state-widget')) {
+ return $html.find('.js-merge-button').removeClass('btn-danger btn-info btn-create').addClass(css_class);
};
MergeRequestWidget.prototype.updatePipelineUrls = function(id) {
diff --git a/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 b/app/assets/javascripts/merge_request_widget/ci_bundle.js
index 547dfa9e677..21d7c3e168e 100644
--- a/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6
+++ b/app/assets/javascripts/merge_request_widget/ci_bundle.js
@@ -15,14 +15,14 @@
});
$(document)
- .off('click', '.accept_merge_request')
- .on('click', '.accept_merge_request', () => {
- $('.js-merge-button').html('<i class="fa fa-spinner fa-spin"></i> Merge in progress');
+ .off('click', '.accept-merge-request')
+ .on('click', '.accept-merge-request', () => {
+ $('.js-merge-button, .js-merge-when-pipeline-succeeds-button').html('<i class="fa fa-spinner fa-spin"></i> Merge in progress');
});
$(document)
- .off('click', '.merge_when_pipeline_succeeds')
- .on('click', '.merge_when_pipeline_succeeds', () => {
+ .off('click', '.merge-when-pipeline-succeeds')
+ .on('click', '.merge-when-pipeline-succeeds', () => {
$('#merge_when_pipeline_succeeds').val('1');
});
diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 b/app/assets/javascripts/mini_pipeline_graph_dropdown.js
index 2145e531331..2145e531331 100644
--- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6
+++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js
diff --git a/app/assets/javascripts/network/branch_graph.js b/app/assets/javascripts/network/branch_graph.js
index 43dc9838977..5aad3908eb6 100644
--- a/app/assets/javascripts/network/branch_graph.js
+++ b/app/assets/javascripts/network/branch_graph.js
@@ -1,424 +1,347 @@
-/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, comma-dangle, one-var, one-var-declaration-per-line, no-mixed-operators, new-cap, no-loop-func, no-floating-decimal, consistent-return, no-unused-vars, prefer-template, prefer-arrow-callback, camelcase, max-len */
-/* global Raphael */
+/* eslint-disable func-names, space-before-function-paren, no-var, wrap-iife, quotes, comma-dangle, one-var, one-var-declaration-per-line, no-mixed-operators, no-loop-func, no-floating-decimal, consistent-return, no-unused-vars, prefer-template, prefer-arrow-callback, camelcase, max-len */
-(function() {
- var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; };
+import Raphael from './raphael';
- this.BranchGraph = (function() {
- function BranchGraph(element1, options1) {
- this.element = element1;
- this.options = options1;
- this.scrollTop = bind(this.scrollTop, this);
- this.scrollBottom = bind(this.scrollBottom, this);
- this.scrollRight = bind(this.scrollRight, this);
- this.scrollLeft = bind(this.scrollLeft, this);
- this.scrollUp = bind(this.scrollUp, this);
- this.scrollDown = bind(this.scrollDown, this);
- this.preparedCommits = {};
- this.mtime = 0;
- this.mspace = 0;
- this.parents = {};
- this.colors = ["#000"];
- this.offsetX = 150;
- this.offsetY = 20;
- this.unitTime = 30;
- this.unitSpace = 10;
- this.prev_start = -1;
- this.load();
- }
-
- BranchGraph.prototype.load = function() {
- return $.ajax({
- url: this.options.url,
- method: "get",
- dataType: "json",
- success: $.proxy(function(data) {
- $(".loading", this.element).hide();
- this.prepareData(data.days, data.commits);
- return this.buildGraph();
- }, this)
- });
- };
+export default (function() {
+ function BranchGraph(element1, options1) {
+ this.element = element1;
+ this.options = options1;
+ this.scrollTop = this.scrollTop.bind(this);
+ this.scrollBottom = this.scrollBottom.bind(this);
+ this.scrollRight = this.scrollRight.bind(this);
+ this.scrollLeft = this.scrollLeft.bind(this);
+ this.scrollUp = this.scrollUp.bind(this);
+ this.scrollDown = this.scrollDown.bind(this);
+ this.preparedCommits = {};
+ this.mtime = 0;
+ this.mspace = 0;
+ this.parents = {};
+ this.colors = ["#000"];
+ this.offsetX = 150;
+ this.offsetY = 20;
+ this.unitTime = 30;
+ this.unitSpace = 10;
+ this.prev_start = -1;
+ this.load();
+ }
- BranchGraph.prototype.prepareData = function(days, commits) {
- var c, ch, cw, j, len, ref;
- this.days = days;
- this.commits = commits;
- this.collectParents();
- this.graphHeight = $(this.element).height();
- this.graphWidth = $(this.element).width();
- ch = Math.max(this.graphHeight, this.offsetY + this.unitTime * this.mtime + 150);
- cw = Math.max(this.graphWidth, this.offsetX + this.unitSpace * this.mspace + 300);
- this.r = Raphael(this.element.get(0), cw, ch);
- this.top = this.r.set();
- this.barHeight = Math.max(this.graphHeight, this.unitTime * this.days.length + 320);
- ref = this.commits;
- for (j = 0, len = ref.length; j < len; j += 1) {
- c = ref[j];
- if (c.id in this.parents) {
- c.isParent = true;
- }
- this.preparedCommits[c.id] = c;
- this.markCommit(c);
- }
- return this.collectColors();
- };
-
- BranchGraph.prototype.collectParents = function() {
- var c, j, len, p, ref, results;
- ref = this.commits;
- results = [];
- for (j = 0, len = ref.length; j < len; j += 1) {
- c = ref[j];
- this.mtime = Math.max(this.mtime, c.time);
- this.mspace = Math.max(this.mspace, c.space);
- results.push((function() {
- var l, len1, ref1, results1;
- ref1 = c.parents;
- results1 = [];
- for (l = 0, len1 = ref1.length; l < len1; l += 1) {
- p = ref1[l];
- this.parents[p[0]] = true;
- results1.push(this.mspace = Math.max(this.mspace, p[1]));
- }
- return results1;
- }).call(this));
- }
- return results;
- };
+ BranchGraph.prototype.load = function() {
+ return $.ajax({
+ url: this.options.url,
+ method: "get",
+ dataType: "json",
+ success: $.proxy(function(data) {
+ $(".loading", this.element).hide();
+ this.prepareData(data.days, data.commits);
+ return this.buildGraph();
+ }, this)
+ });
+ };
- BranchGraph.prototype.collectColors = function() {
- var k, results;
- k = 0;
- results = [];
- while (k < this.mspace) {
- this.colors.push(Raphael.getColor(.8));
- // Skipping a few colors in the spectrum to get more contrast between colors
- Raphael.getColor();
- Raphael.getColor();
- results.push(k += 1);
+ BranchGraph.prototype.prepareData = function(days, commits) {
+ var c, ch, cw, j, len, ref;
+ this.days = days;
+ this.commits = commits;
+ this.collectParents();
+ this.graphHeight = $(this.element).height();
+ this.graphWidth = $(this.element).width();
+ ch = Math.max(this.graphHeight, this.offsetY + this.unitTime * this.mtime + 150);
+ cw = Math.max(this.graphWidth, this.offsetX + this.unitSpace * this.mspace + 300);
+ this.r = Raphael(this.element.get(0), cw, ch);
+ this.top = this.r.set();
+ this.barHeight = Math.max(this.graphHeight, this.unitTime * this.days.length + 320);
+ ref = this.commits;
+ for (j = 0, len = ref.length; j < len; j += 1) {
+ c = ref[j];
+ if (c.id in this.parents) {
+ c.isParent = true;
}
- return results;
- };
+ this.preparedCommits[c.id] = c;
+ this.markCommit(c);
+ }
+ return this.collectColors();
+ };
- BranchGraph.prototype.buildGraph = function() {
- var cuday, cumonth, day, j, len, mm, r, ref;
- r = this.r;
- cuday = 0;
- cumonth = "";
- r.rect(0, 0, 40, this.barHeight).attr({
- fill: "#222"
- });
- r.rect(40, 0, 30, this.barHeight).attr({
- fill: "#444"
- });
- ref = this.days;
- for (mm = j = 0, len = ref.length; j < len; mm = (j += 1)) {
- day = ref[mm];
- if (cuday !== day[0] || cumonth !== day[1]) {
- // Dates
- r.text(55, this.offsetY + this.unitTime * mm, day[0]).attr({
- font: "12px Monaco, monospace",
- fill: "#BBB"
- });
- cuday = day[0];
- }
- if (cumonth !== day[1]) {
- // Months
- r.text(20, this.offsetY + this.unitTime * mm, day[1]).attr({
- font: "12px Monaco, monospace",
- fill: "#EEE"
- });
- cumonth = day[1];
+ BranchGraph.prototype.collectParents = function() {
+ var c, j, len, p, ref, results;
+ ref = this.commits;
+ results = [];
+ for (j = 0, len = ref.length; j < len; j += 1) {
+ c = ref[j];
+ this.mtime = Math.max(this.mtime, c.time);
+ this.mspace = Math.max(this.mspace, c.space);
+ results.push((function() {
+ var l, len1, ref1, results1;
+ ref1 = c.parents;
+ results1 = [];
+ for (l = 0, len1 = ref1.length; l < len1; l += 1) {
+ p = ref1[l];
+ this.parents[p[0]] = true;
+ results1.push(this.mspace = Math.max(this.mspace, p[1]));
}
- }
- this.renderPartialGraph();
- return this.bindEvents();
- };
+ return results1;
+ }).call(this));
+ }
+ return results;
+ };
- BranchGraph.prototype.renderPartialGraph = function() {
- var commit, end, i, isGraphEdge, start, x, y;
- start = Math.floor((this.element.scrollTop() - this.offsetY) / this.unitTime) - 10;
- if (start < 0) {
- isGraphEdge = true;
- start = 0;
+ BranchGraph.prototype.collectColors = function() {
+ var k, results;
+ k = 0;
+ results = [];
+ while (k < this.mspace) {
+ this.colors.push(Raphael.getColor(.8));
+ // Skipping a few colors in the spectrum to get more contrast between colors
+ Raphael.getColor();
+ Raphael.getColor();
+ results.push(k += 1);
+ }
+ return results;
+ };
+
+ BranchGraph.prototype.buildGraph = function() {
+ var cuday, cumonth, day, j, len, mm, r, ref;
+ r = this.r;
+ cuday = 0;
+ cumonth = "";
+ r.rect(0, 0, 40, this.barHeight).attr({
+ fill: "#222"
+ });
+ r.rect(40, 0, 30, this.barHeight).attr({
+ fill: "#444"
+ });
+ ref = this.days;
+ for (mm = j = 0, len = ref.length; j < len; mm = (j += 1)) {
+ day = ref[mm];
+ if (cuday !== day[0] || cumonth !== day[1]) {
+ // Dates
+ r.text(55, this.offsetY + this.unitTime * mm, day[0]).attr({
+ font: "12px Monaco, monospace",
+ fill: "#BBB"
+ });
+ cuday = day[0];
}
- end = start + 40;
- if (this.commits.length < end) {
- isGraphEdge = true;
- end = this.commits.length;
+ if (cumonth !== day[1]) {
+ // Months
+ r.text(20, this.offsetY + this.unitTime * mm, day[1]).attr({
+ font: "12px Monaco, monospace",
+ fill: "#EEE"
+ });
+ cumonth = day[1];
}
- if (this.prev_start === -1 || Math.abs(this.prev_start - start) > 10 || isGraphEdge) {
- i = start;
- this.prev_start = start;
- while (i < end) {
- commit = this.commits[i];
- i += 1;
- if (commit.hasDrawn !== true) {
- x = this.offsetX + this.unitSpace * (this.mspace - commit.space);
- y = this.offsetY + this.unitTime * commit.time;
- this.drawDot(x, y, commit);
- this.drawLines(x, y, commit);
- this.appendLabel(x, y, commit);
- this.appendAnchor(x, y, commit);
- commit.hasDrawn = true;
- }
+ }
+ this.renderPartialGraph();
+ return this.bindEvents();
+ };
+
+ BranchGraph.prototype.renderPartialGraph = function() {
+ var commit, end, i, isGraphEdge, start, x, y;
+ start = Math.floor((this.element.scrollTop() - this.offsetY) / this.unitTime) - 10;
+ if (start < 0) {
+ isGraphEdge = true;
+ start = 0;
+ }
+ end = start + 40;
+ if (this.commits.length < end) {
+ isGraphEdge = true;
+ end = this.commits.length;
+ }
+ if (this.prev_start === -1 || Math.abs(this.prev_start - start) > 10 || isGraphEdge) {
+ i = start;
+ this.prev_start = start;
+ while (i < end) {
+ commit = this.commits[i];
+ i += 1;
+ if (commit.hasDrawn !== true) {
+ x = this.offsetX + this.unitSpace * (this.mspace - commit.space);
+ y = this.offsetY + this.unitTime * commit.time;
+ this.drawDot(x, y, commit);
+ this.drawLines(x, y, commit);
+ this.appendLabel(x, y, commit);
+ this.appendAnchor(x, y, commit);
+ commit.hasDrawn = true;
}
- return this.top.toFront();
}
- };
-
- BranchGraph.prototype.bindEvents = function() {
- var element;
- element = this.element;
- return $(element).scroll((function(_this) {
- return function(event) {
- return _this.renderPartialGraph();
- };
- })(this));
- };
-
- BranchGraph.prototype.scrollDown = function() {
- this.element.scrollTop(this.element.scrollTop() + 50);
- return this.renderPartialGraph();
- };
-
- BranchGraph.prototype.scrollUp = function() {
- this.element.scrollTop(this.element.scrollTop() - 50);
- return this.renderPartialGraph();
- };
-
- BranchGraph.prototype.scrollLeft = function() {
- this.element.scrollLeft(this.element.scrollLeft() - 50);
- return this.renderPartialGraph();
- };
-
- BranchGraph.prototype.scrollRight = function() {
- this.element.scrollLeft(this.element.scrollLeft() + 50);
- return this.renderPartialGraph();
- };
-
- BranchGraph.prototype.scrollBottom = function() {
- return this.element.scrollTop(this.element.find('svg').height());
- };
+ return this.top.toFront();
+ }
+ };
- BranchGraph.prototype.scrollTop = function() {
- return this.element.scrollTop(0);
- };
+ BranchGraph.prototype.bindEvents = function() {
+ var element;
+ element = this.element;
+ return $(element).scroll((function(_this) {
+ return function(event) {
+ return _this.renderPartialGraph();
+ };
+ })(this));
+ };
- BranchGraph.prototype.appendLabel = function(x, y, commit) {
- var label, r, rect, shortrefs, text, textbox, triangle;
- if (!commit.refs) {
- return;
- }
- r = this.r;
- shortrefs = commit.refs;
- // Truncate if longer than 15 chars
- if (shortrefs.length > 17) {
- shortrefs = shortrefs.substr(0, 15) + "…";
- }
- text = r.text(x + 4, y, shortrefs).attr({
- "text-anchor": "start",
- font: "10px Monaco, monospace",
- fill: "#FFF",
- title: commit.refs
- });
- textbox = text.getBBox();
- // Create rectangle based on the size of the textbox
- rect = r.rect(x, y - 7, textbox.width + 5, textbox.height + 5, 4).attr({
- fill: "#000",
- "fill-opacity": .5,
- stroke: "none"
- });
- triangle = r.path(["M", x - 5, y, "L", x - 15, y - 4, "L", x - 15, y + 4, "Z"]).attr({
- fill: "#000",
- "fill-opacity": .5,
- stroke: "none"
- });
- label = r.set(rect, text);
- label.transform(["t", -rect.getBBox().width - 15, 0]);
- // Set text to front
- return text.toFront();
- };
+ BranchGraph.prototype.scrollDown = function() {
+ this.element.scrollTop(this.element.scrollTop() + 50);
+ return this.renderPartialGraph();
+ };
- BranchGraph.prototype.appendAnchor = function(x, y, commit) {
- var anchor, options, r, top;
- r = this.r;
- top = this.top;
- options = this.options;
- anchor = r.circle(x, y, 10).attr({
- fill: "#000",
- opacity: 0,
- cursor: "pointer"
- }).click(function() {
- return window.open(options.commit_url.replace("%s", commit.id), "_blank");
- }).hover(function() {
- this.tooltip = r.commitTooltip(x + 5, y, commit);
- return top.push(this.tooltip.insertBefore(this));
- }, function() {
- return this.tooltip && this.tooltip.remove() && delete this.tooltip;
- });
- return top.push(anchor);
- };
+ BranchGraph.prototype.scrollUp = function() {
+ this.element.scrollTop(this.element.scrollTop() - 50);
+ return this.renderPartialGraph();
+ };
- BranchGraph.prototype.drawDot = function(x, y, commit) {
- var avatar_box_x, avatar_box_y, r;
- r = this.r;
- r.circle(x, y, 3).attr({
- fill: this.colors[commit.space],
- stroke: "none"
- });
- avatar_box_x = this.offsetX + this.unitSpace * this.mspace + 10;
- avatar_box_y = y - 10;
- r.rect(avatar_box_x, avatar_box_y, 20, 20).attr({
- stroke: this.colors[commit.space],
- "stroke-width": 2
- });
- r.image(commit.author.icon, avatar_box_x, avatar_box_y, 20, 20);
- return r.text(this.offsetX + this.unitSpace * this.mspace + 35, y, commit.message.split("\n")[0]).attr({
- "text-anchor": "start",
- font: "14px Monaco, monospace"
- });
- };
+ BranchGraph.prototype.scrollLeft = function() {
+ this.element.scrollLeft(this.element.scrollLeft() - 50);
+ return this.renderPartialGraph();
+ };
- BranchGraph.prototype.drawLines = function(x, y, commit) {
- var arrow, color, i, j, len, offset, parent, parentCommit, parentX1, parentX2, parentY, r, ref, results, route;
- r = this.r;
- ref = commit.parents;
- results = [];
- for (i = j = 0, len = ref.length; j < len; i = (j += 1)) {
- parent = ref[i];
- parentCommit = this.preparedCommits[parent[0]];
- parentY = this.offsetY + this.unitTime * parentCommit.time;
- parentX1 = this.offsetX + this.unitSpace * (this.mspace - parentCommit.space);
- parentX2 = this.offsetX + this.unitSpace * (this.mspace - parent[1]);
- // Set line color
- if (parentCommit.space <= commit.space) {
- color = this.colors[commit.space];
- } else {
- color = this.colors[parentCommit.space];
- }
- // Build line shape
- if (parent[1] === commit.space) {
- offset = [0, 5];
- arrow = "l-2,5,4,0,-2,-5,0,5";
- } else if (parent[1] < commit.space) {
- offset = [3, 3];
- arrow = "l5,0,-2,4,-3,-4,4,2";
- } else {
- offset = [-3, 3];
- arrow = "l-5,0,2,4,3,-4,-4,2";
- }
- // Start point
- route = ["M", x + offset[0], y + offset[1]];
- // Add arrow if not first parent
- if (i > 0) {
- route.push(arrow);
- }
- // Circumvent if overlap
- if (commit.space !== parentCommit.space || commit.space !== parent[1]) {
- route.push("L", parentX2, y + 10, "L", parentX2, parentY - 5);
- }
- // End point
- route.push("L", parentX1, parentY);
- results.push(r.path(route).attr({
- stroke: color,
- "stroke-width": 2
- }));
- }
- return results;
- };
+ BranchGraph.prototype.scrollRight = function() {
+ this.element.scrollLeft(this.element.scrollLeft() + 50);
+ return this.renderPartialGraph();
+ };
- BranchGraph.prototype.markCommit = function(commit) {
- var r, x, y;
- if (commit.id === this.options.commit_id) {
- r = this.r;
- x = this.offsetX + this.unitSpace * (this.mspace - commit.space);
- y = this.offsetY + this.unitTime * commit.time;
- r.path(["M", x + 5, y, "L", x + 15, y + 4, "L", x + 15, y - 4, "Z"]).attr({
- fill: "#000",
- "fill-opacity": .5,
- stroke: "none"
- });
- // Displayed in the center
- return this.element.scrollTop(y - this.graphHeight / 2);
- }
- };
+ BranchGraph.prototype.scrollBottom = function() {
+ return this.element.scrollTop(this.element.find('svg').height());
+ };
- return BranchGraph;
- })();
+ BranchGraph.prototype.scrollTop = function() {
+ return this.element.scrollTop(0);
+ };
- Raphael.prototype.commitTooltip = function(x, y, commit) {
- var boxHeight, boxWidth, icon, idText, messageText, nameText, rect, textSet, tooltip;
- boxWidth = 300;
- boxHeight = 200;
- icon = this.image(gon.relative_url_root + commit.author.icon, x, y, 20, 20);
- nameText = this.text(x + 25, y + 10, commit.author.name);
- idText = this.text(x, y + 35, commit.id);
- messageText = this.text(x, y + 50, commit.message.replace(/\r?\n/g, " \n "));
- textSet = this.set(icon, nameText, idText, messageText).attr({
+ BranchGraph.prototype.appendLabel = function(x, y, commit) {
+ var label, r, rect, shortrefs, text, textbox, triangle;
+ if (!commit.refs) {
+ return;
+ }
+ r = this.r;
+ shortrefs = commit.refs;
+ // Truncate if longer than 15 chars
+ if (shortrefs.length > 17) {
+ shortrefs = shortrefs.substr(0, 15) + "…";
+ }
+ text = r.text(x + 4, y, shortrefs).attr({
"text-anchor": "start",
- font: "12px Monaco, monospace"
- });
- nameText.attr({
- font: "14px Arial",
- "font-weight": "bold"
+ font: "10px Monaco, monospace",
+ fill: "#FFF",
+ title: commit.refs
});
- idText.attr({
- fill: "#AAA"
+ textbox = text.getBBox();
+ // Create rectangle based on the size of the textbox
+ rect = r.rect(x, y - 7, textbox.width + 5, textbox.height + 5, 4).attr({
+ fill: "#000",
+ "fill-opacity": .5,
+ stroke: "none"
});
- messageText.node.style["white-space"] = "pre";
- this.textWrap(messageText, boxWidth - 50);
- rect = this.rect(x - 10, y - 10, boxWidth, 100, 4).attr({
- fill: "#FFF",
- stroke: "#000",
- "stroke-linecap": "round",
- "stroke-width": 2
+ triangle = r.path(["M", x - 5, y, "L", x - 15, y - 4, "L", x - 15, y + 4, "Z"]).attr({
+ fill: "#000",
+ "fill-opacity": .5,
+ stroke: "none"
});
- tooltip = this.set(rect, textSet);
- rect.attr({
- height: tooltip.getBBox().height + 10,
- width: tooltip.getBBox().width + 10
+ label = r.set(rect, text);
+ label.transform(["t", -rect.getBBox().width - 15, 0]);
+ // Set text to front
+ return text.toFront();
+ };
+
+ BranchGraph.prototype.appendAnchor = function(x, y, commit) {
+ var anchor, options, r, top;
+ r = this.r;
+ top = this.top;
+ options = this.options;
+ anchor = r.circle(x, y, 10).attr({
+ fill: "#000",
+ opacity: 0,
+ cursor: "pointer"
+ }).click(function() {
+ return window.open(options.commit_url.replace("%s", commit.id), "_blank");
+ }).hover(function() {
+ this.tooltip = r.commitTooltip(x + 5, y, commit);
+ return top.push(this.tooltip.insertBefore(this));
+ }, function() {
+ return this.tooltip && this.tooltip.remove() && delete this.tooltip;
});
- tooltip.transform(["t", 20, 20]);
- return tooltip;
+ return top.push(anchor);
};
- Raphael.prototype.textWrap = function(t, width) {
- var abc, b, content, h, j, len, letterWidth, s, word, words, x;
- content = t.attr("text");
- abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
- t.attr({
- text: abc
+ BranchGraph.prototype.drawDot = function(x, y, commit) {
+ var avatar_box_x, avatar_box_y, r;
+ r = this.r;
+ r.circle(x, y, 3).attr({
+ fill: this.colors[commit.space],
+ stroke: "none"
});
- letterWidth = t.getBBox().width / abc.length;
- t.attr({
- text: content
+ avatar_box_x = this.offsetX + this.unitSpace * this.mspace + 10;
+ avatar_box_y = y - 10;
+ r.rect(avatar_box_x, avatar_box_y, 20, 20).attr({
+ stroke: this.colors[commit.space],
+ "stroke-width": 2
});
- words = content.split(" ");
- x = 0;
- s = [];
- for (j = 0, len = words.length; j < len; j += 1) {
- word = words[j];
- if (x + (word.length * letterWidth) > width) {
- s.push("\n");
- x = 0;
+ r.image(commit.author.icon, avatar_box_x, avatar_box_y, 20, 20);
+ return r.text(this.offsetX + this.unitSpace * this.mspace + 35, y, commit.message.split("\n")[0]).attr({
+ "text-anchor": "start",
+ font: "14px Monaco, monospace"
+ });
+ };
+
+ BranchGraph.prototype.drawLines = function(x, y, commit) {
+ var arrow, color, i, j, len, offset, parent, parentCommit, parentX1, parentX2, parentY, r, ref, results, route;
+ r = this.r;
+ ref = commit.parents;
+ results = [];
+ for (i = j = 0, len = ref.length; j < len; i = (j += 1)) {
+ parent = ref[i];
+ parentCommit = this.preparedCommits[parent[0]];
+ parentY = this.offsetY + this.unitTime * parentCommit.time;
+ parentX1 = this.offsetX + this.unitSpace * (this.mspace - parentCommit.space);
+ parentX2 = this.offsetX + this.unitSpace * (this.mspace - parent[1]);
+ // Set line color
+ if (parentCommit.space <= commit.space) {
+ color = this.colors[commit.space];
+ } else {
+ color = this.colors[parentCommit.space];
}
- if (word === "\n") {
- s.push("\n");
- x = 0;
+ // Build line shape
+ if (parent[1] === commit.space) {
+ offset = [0, 5];
+ arrow = "l-2,5,4,0,-2,-5,0,5";
+ } else if (parent[1] < commit.space) {
+ offset = [3, 3];
+ arrow = "l5,0,-2,4,-3,-4,4,2";
} else {
- s.push(word + " ");
- x += word.length * letterWidth;
+ offset = [-3, 3];
+ arrow = "l-5,0,2,4,3,-4,-4,2";
+ }
+ // Start point
+ route = ["M", x + offset[0], y + offset[1]];
+ // Add arrow if not first parent
+ if (i > 0) {
+ route.push(arrow);
+ }
+ // Circumvent if overlap
+ if (commit.space !== parentCommit.space || commit.space !== parent[1]) {
+ route.push("L", parentX2, y + 10, "L", parentX2, parentY - 5);
}
+ // End point
+ route.push("L", parentX1, parentY);
+ results.push(r.path(route).attr({
+ stroke: color,
+ "stroke-width": 2
+ }));
+ }
+ return results;
+ };
+
+ BranchGraph.prototype.markCommit = function(commit) {
+ var r, x, y;
+ if (commit.id === this.options.commit_id) {
+ r = this.r;
+ x = this.offsetX + this.unitSpace * (this.mspace - commit.space);
+ y = this.offsetY + this.unitTime * commit.time;
+ r.path(["M", x + 5, y, "L", x + 15, y + 4, "L", x + 15, y - 4, "Z"]).attr({
+ fill: "#000",
+ "fill-opacity": .5,
+ stroke: "none"
+ });
+ // Displayed in the center
+ return this.element.scrollTop(y - this.graphHeight / 2);
}
- t.attr({
- text: s.join("").trim()
- });
- b = t.getBBox();
- h = Math.abs(b.y2) + 1;
- return t.attr({
- y: h
- });
};
-}).call(window);
+
+ return BranchGraph;
+})();
diff --git a/app/assets/javascripts/network/network.js b/app/assets/javascripts/network/network.js
index 8e7027b44e7..a3fd22aff2a 100644
--- a/app/assets/javascripts/network/network.js
+++ b/app/assets/javascripts/network/network.js
@@ -1,20 +1,19 @@
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, quotes, quote-props, prefer-template, comma-dangle, max-len */
-/* global BranchGraph */
-(function() {
- this.Network = (function() {
- function Network(opts) {
- var vph;
- $("#filter_ref").click(function() {
- return $(this).closest('form').submit();
- });
- this.branch_graph = new BranchGraph($(".network-graph"), opts);
- vph = $(window).height() - 250;
- $('.network-graph').css({
- 'height': vph + 'px'
- });
- }
+import BranchGraph from './branch_graph';
- return Network;
- })();
-}).call(window);
+export default (function() {
+ function Network(opts) {
+ var vph;
+ $("#filter_ref").click(function() {
+ return $(this).closest('form').submit();
+ });
+ this.branch_graph = new BranchGraph($(".network-graph"), opts);
+ vph = $(window).height() - 250;
+ $('.network-graph').css({
+ 'height': vph + 'px'
+ });
+ }
+
+ return Network;
+})();
diff --git a/app/assets/javascripts/network/network_bundle.js b/app/assets/javascripts/network/network_bundle.js
index e5947586583..8aae2ad201c 100644
--- a/app/assets/javascripts/network/network_bundle.js
+++ b/app/assets/javascripts/network/network_bundle.js
@@ -1,21 +1,17 @@
/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, quotes, no-var, vars-on-top, camelcase, comma-dangle, consistent-return, max-len */
-/* global Network */
/* global ShortcutsNetwork */
-require('./branch_graph');
-require('./network');
+import Network from './network';
-(function() {
- $(function() {
- if (!$(".network-graph").length) return;
+$(function() {
+ if (!$(".network-graph").length) return;
- var network_graph;
- network_graph = new Network({
- url: $(".network-graph").attr('data-url'),
- commit_url: $(".network-graph").attr('data-commit-url'),
- ref: $(".network-graph").attr('data-ref'),
- commit_id: $(".network-graph").attr('data-commit-id')
- });
- return new ShortcutsNetwork(network_graph.branch_graph);
+ var network_graph;
+ network_graph = new Network({
+ url: $(".network-graph").attr('data-url'),
+ commit_url: $(".network-graph").attr('data-commit-url'),
+ ref: $(".network-graph").attr('data-ref'),
+ commit_id: $(".network-graph").attr('data-commit-id')
});
-}).call(window);
+ return new ShortcutsNetwork(network_graph.branch_graph);
+});
diff --git a/app/assets/javascripts/network/raphael.js b/app/assets/javascripts/network/raphael.js
new file mode 100644
index 00000000000..09dcf716148
--- /dev/null
+++ b/app/assets/javascripts/network/raphael.js
@@ -0,0 +1,74 @@
+import Raphael from 'raphael/raphael';
+
+Raphael.prototype.commitTooltip = function commitTooltip(x, y, commit) {
+ const boxWidth = 300;
+ const icon = this.image(gon.relative_url_root + commit.author.icon, x, y, 20, 20);
+ const nameText = this.text(x + 25, y + 10, commit.author.name);
+ const idText = this.text(x, y + 35, commit.id);
+ const messageText = this.text(x, y + 50, commit.message.replace(/\r?\n/g, ' \n '));
+ const textSet = this.set(icon, nameText, idText, messageText).attr({
+ 'text-anchor': 'start',
+ font: '12px Monaco, monospace',
+ });
+ nameText.attr({
+ font: '14px Arial',
+ 'font-weight': 'bold',
+ });
+ idText.attr({
+ fill: '#AAA',
+ });
+ messageText.node.style['white-space'] = 'pre';
+ this.textWrap(messageText, boxWidth - 50);
+ const rect = this.rect(x - 10, y - 10, boxWidth, 100, 4).attr({
+ fill: '#FFF',
+ stroke: '#000',
+ 'stroke-linecap': 'round',
+ 'stroke-width': 2,
+ });
+ const tooltip = this.set(rect, textSet);
+ rect.attr({
+ height: tooltip.getBBox().height + 10,
+ width: tooltip.getBBox().width + 10,
+ });
+ tooltip.transform(['t', 20, 20]);
+ return tooltip;
+};
+
+Raphael.prototype.textWrap = function testWrap(t, width) {
+ const content = t.attr('text');
+ const abc = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ t.attr({
+ text: abc,
+ });
+ const letterWidth = t.getBBox().width / abc.length;
+ t.attr({
+ text: content,
+ });
+ const words = content.split(' ');
+ let x = 0;
+ const s = [];
+ for (let j = 0, len = words.length; j < len; j += 1) {
+ const word = words[j];
+ if (x + (word.length * letterWidth) > width) {
+ s.push('\n');
+ x = 0;
+ }
+ if (word === '\n') {
+ s.push('\n');
+ x = 0;
+ } else {
+ s.push(`${word} `);
+ x += word.length * letterWidth;
+ }
+ }
+ t.attr({
+ text: s.join('').trim(),
+ });
+ const b = t.getBBox();
+ const h = Math.abs(b.y2) + 1;
+ return t.attr({
+ y: h,
+ });
+};
+
+export default Raphael;
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 47fa0f2eb96..df7a7d2a459 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -198,7 +198,7 @@ require('./task_list');
this.refreshing = true;
return $.ajax({
url: this.notes_url,
- data: "last_fetched_at=" + this.last_fetched_at,
+ headers: { "X-Last-Fetched-At": this.last_fetched_at },
dataType: "json",
success: (function(_this) {
return function(data) {
diff --git a/app/assets/javascripts/pager.js.es6 b/app/assets/javascripts/pager.js
index e35cf6d295e..e35cf6d295e 100644
--- a/app/assets/javascripts/pager.js.es6
+++ b/app/assets/javascripts/pager.js
diff --git a/app/assets/javascripts/pipelines.js.es6 b/app/assets/javascripts/pipelines.js
index 9203abefbbc..9203abefbbc 100644
--- a/app/assets/javascripts/pipelines.js.es6
+++ b/app/assets/javascripts/pipelines.js
diff --git a/app/assets/javascripts/profile/gl_crop.js.es6 b/app/assets/javascripts/profile/gl_crop.js
index 192b1192d07..cf1566eeb87 100644
--- a/app/assets/javascripts/profile/gl_crop.js.es6
+++ b/app/assets/javascripts/profile/gl_crop.js
@@ -1,5 +1,7 @@
/* eslint-disable no-useless-escape, max-len, quotes, no-var, no-underscore-dangle, func-names, space-before-function-paren, no-unused-vars, no-return-assign, object-shorthand, one-var, one-var-declaration-per-line, comma-dangle, consistent-return, class-methods-use-this, new-parens */
+import 'vendor/cropper';
+
((global) => {
// Matches everything but the file name
const FILENAMEREGEX = /^.*[\\\/]/;
diff --git a/app/assets/javascripts/profile/profile.js.es6 b/app/assets/javascripts/profile/profile.js
index 4ccea0624ee..4ccea0624ee 100644
--- a/app/assets/javascripts/profile/profile.js.es6
+++ b/app/assets/javascripts/profile/profile.js
diff --git a/app/assets/javascripts/project_label_subscription.js.es6 b/app/assets/javascripts/project_label_subscription.js
index 0a811627600..0a811627600 100644
--- a/app/assets/javascripts/project_label_subscription.js.es6
+++ b/app/assets/javascripts/project_label_subscription.js
diff --git a/app/assets/javascripts/project_variables.js.es6 b/app/assets/javascripts/project_variables.js
index 4ee2e49306d..4ee2e49306d 100644
--- a/app/assets/javascripts/project_variables.js.es6
+++ b/app/assets/javascripts/project_variables.js
diff --git a/app/assets/javascripts/projects_list.js b/app/assets/javascripts/projects_list.js
index acdf9b7eb5a..c67d59d2be5 100644
--- a/app/assets/javascripts/projects_list.js
+++ b/app/assets/javascripts/projects_list.js
@@ -1,50 +1,18 @@
-/* eslint-disable func-names, space-before-function-paren, object-shorthand, quotes, no-var, one-var, one-var-declaration-per-line, prefer-arrow-callback, consistent-return, no-unused-vars, camelcase, prefer-template, comma-dangle, max-len */
+import FilterableList from './filterable_list';
-(function() {
- window.ProjectsList = {
- init: function() {
- $(".projects-list-filter").off('keyup');
- this.initSearch();
- return this.initPagination();
- },
- initSearch: function() {
- var debounceFilter, projectsListFilter;
- projectsListFilter = $('.projects-list-filter');
- debounceFilter = _.debounce(window.ProjectsList.filterResults, 500);
- return projectsListFilter.on('keyup', function(e) {
- if (projectsListFilter.val() !== '') {
- return debounceFilter();
- }
- });
- },
- filterResults: function() {
- var form, project_filter_url, search;
- $('.projects-list-holder').fadeTo(250, 0.5);
- form = null;
- form = $("form#project-filter-form");
- search = $(".projects-list-filter").val();
- project_filter_url = form.attr('action') + '?' + form.serialize();
- return $.ajax({
- type: "GET",
- url: form.attr('action'),
- data: form.serialize(),
- complete: function() {
- return $('.projects-list-holder').fadeTo(250, 1);
- },
- success: function(data) {
- $('.projects-list-holder').replaceWith(data.html);
- return history.replaceState({
- page: project_filter_url
- // Change url so if user reload a page - search results are saved
- }, document.title, project_filter_url);
- },
- dataType: "json"
- });
- },
- initPagination: function() {
- return $('.projects-list-holder .pagination').on('ajax:success', function(e, data) {
- return $('.projects-list-holder').replaceWith(data.html);
- });
+/**
+ * Makes search request for projects when user types a value in the search input.
+ * Updates the html content of the page with the received one.
+ */
+export default class ProjectsList {
+ constructor() {
+ const form = document.querySelector('form#project-filter-form');
+ const filter = document.querySelector('.js-projects-list-filter');
+ const holder = document.querySelector('.js-projects-list-holder');
+
+ if (form && filter && holder) {
+ const list = new FilterableList(form, filter, holder);
+ list.initSearch();
}
- };
-}).call(window);
+ }
+}
diff --git a/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js
index e7fff57ff45..e7fff57ff45 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js.es6
+++ b/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js
diff --git a/app/assets/javascripts/protected_branches/protected_branch_create.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_create.js
index 57ea2f52814..57ea2f52814 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_create.js.es6
+++ b/app/assets/javascripts/protected_branches/protected_branch_create.js
diff --git a/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_dropdown.js
index 5cf28aa7a73..5cf28aa7a73 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6
+++ b/app/assets/javascripts/protected_branches/protected_branch_dropdown.js
diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_edit.js
index 6ef59e94384..6ef59e94384 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_edit.js.es6
+++ b/app/assets/javascripts/protected_branches/protected_branch_edit.js
diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit_list.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_edit_list.js
index 336fa6c57a7..336fa6c57a7 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_edit_list.js.es6
+++ b/app/assets/javascripts/protected_branches/protected_branch_edit_list.js
diff --git a/app/assets/javascripts/search_autocomplete.js.es6 b/app/assets/javascripts/search_autocomplete.js
index 6fd5345a0a6..6fd5345a0a6 100644
--- a/app/assets/javascripts/search_autocomplete.js.es6
+++ b/app/assets/javascripts/search_autocomplete.js
diff --git a/app/assets/javascripts/shortcuts_blob.js.es6 b/app/assets/javascripts/shortcuts_blob.js
index bfe90aef71e..bfe90aef71e 100644
--- a/app/assets/javascripts/shortcuts_blob.js.es6
+++ b/app/assets/javascripts/shortcuts_blob.js
diff --git a/app/assets/javascripts/shortcuts_navigation.js b/app/assets/javascripts/shortcuts_navigation.js
index 542cd586df0..09a58cad2b2 100644
--- a/app/assets/javascripts/shortcuts_navigation.js
+++ b/app/assets/javascripts/shortcuts_navigation.js
@@ -32,7 +32,7 @@ require('./shortcuts');
return ShortcutsNavigation.findAndFollowLink('.shortcuts-network');
});
Mousetrap.bind('g g', function() {
- return ShortcutsNavigation.findAndFollowLink('.shortcuts-graphs');
+ return ShortcutsNavigation.findAndFollowLink('.shortcuts-repository-charts');
});
Mousetrap.bind('g i', function() {
return ShortcutsNavigation.findAndFollowLink('.shortcuts-issues');
diff --git a/app/assets/javascripts/signin_tabs_memoizer.js.es6 b/app/assets/javascripts/signin_tabs_memoizer.js
index d811d1cd53a..d811d1cd53a 100644
--- a/app/assets/javascripts/signin_tabs_memoizer.js.es6
+++ b/app/assets/javascripts/signin_tabs_memoizer.js
diff --git a/app/assets/javascripts/smart_interval.js.es6 b/app/assets/javascripts/smart_interval.js
index d1bdc353be2..d1bdc353be2 100644
--- a/app/assets/javascripts/smart_interval.js.es6
+++ b/app/assets/javascripts/smart_interval.js
diff --git a/app/assets/javascripts/snippets_list.js.es6 b/app/assets/javascripts/snippets_list.js
index 2128007113f..2128007113f 100644
--- a/app/assets/javascripts/snippets_list.js.es6
+++ b/app/assets/javascripts/snippets_list.js
diff --git a/app/assets/javascripts/subbable_resource.js.es6 b/app/assets/javascripts/subbable_resource.js
index d8191605128..d8191605128 100644
--- a/app/assets/javascripts/subbable_resource.js.es6
+++ b/app/assets/javascripts/subbable_resource.js
diff --git a/app/assets/javascripts/subscription.js.es6 b/app/assets/javascripts/subscription.js
index 62d1604fe9e..62d1604fe9e 100644
--- a/app/assets/javascripts/subscription.js.es6
+++ b/app/assets/javascripts/subscription.js
diff --git a/app/assets/javascripts/templates/issuable_template_selector.js.es6 b/app/assets/javascripts/templates/issuable_template_selector.js
index e9e9aafd71a..e9e9aafd71a 100644
--- a/app/assets/javascripts/templates/issuable_template_selector.js.es6
+++ b/app/assets/javascripts/templates/issuable_template_selector.js
diff --git a/app/assets/javascripts/templates/issuable_template_selectors.js.es6 b/app/assets/javascripts/templates/issuable_template_selectors.js
index 97f6d37364d..97f6d37364d 100644
--- a/app/assets/javascripts/templates/issuable_template_selectors.js.es6
+++ b/app/assets/javascripts/templates/issuable_template_selectors.js
diff --git a/app/assets/javascripts/terminal/terminal.js.es6 b/app/assets/javascripts/terminal/terminal.js
index 6b9422b1816..6b9422b1816 100644
--- a/app/assets/javascripts/terminal/terminal.js.es6
+++ b/app/assets/javascripts/terminal/terminal.js
diff --git a/app/assets/javascripts/terminal/terminal_bundle.js.es6 b/app/assets/javascripts/terminal/terminal_bundle.js
index 13cf3a10a38..13cf3a10a38 100644
--- a/app/assets/javascripts/terminal/terminal_bundle.js.es6
+++ b/app/assets/javascripts/terminal/terminal_bundle.js
diff --git a/app/assets/javascripts/todos.js.es6 b/app/assets/javascripts/todos.js
index e9513725d9d..e9513725d9d 100644
--- a/app/assets/javascripts/todos.js.es6
+++ b/app/assets/javascripts/todos.js
diff --git a/app/assets/javascripts/u2f/authenticate.js.es6 b/app/assets/javascripts/u2f/authenticate.js
index 500b78fc5d8..500b78fc5d8 100644
--- a/app/assets/javascripts/u2f/authenticate.js.es6
+++ b/app/assets/javascripts/u2f/authenticate.js
diff --git a/app/assets/javascripts/user.js.es6 b/app/assets/javascripts/user.js
index 059e6c628b3..059e6c628b3 100644
--- a/app/assets/javascripts/user.js.es6
+++ b/app/assets/javascripts/user.js
diff --git a/app/assets/javascripts/user_callout.js b/app/assets/javascripts/user_callout.js
index 74b869502a4..99419e85b20 100644
--- a/app/assets/javascripts/user_callout.js
+++ b/app/assets/javascripts/user_callout.js
@@ -43,6 +43,8 @@ class UserCallout {
this.userCalloutBody.append($template);
$template.find(closeButton).on('click', e => this.dismissCallout(e));
$template.find(userCalloutBtn).on('click', e => this.dismissCallout(e));
+ } else {
+ this.userCalloutBody.remove();
}
}
@@ -50,7 +52,7 @@ class UserCallout {
Cookies.set(USER_CALLOUT_COOKIE, 'true');
const $currentTarget = $(e.currentTarget);
if ($currentTarget.hasClass('close-user-callout')) {
- this.userCalloutBody.empty();
+ this.userCalloutBody.remove();
}
}
}
diff --git a/app/assets/javascripts/user_tabs.js.es6 b/app/assets/javascripts/user_tabs.js
index 465618e3d53..465618e3d53 100644
--- a/app/assets/javascripts/user_tabs.js.es6
+++ b/app/assets/javascripts/user_tabs.js
diff --git a/app/assets/javascripts/username_validator.js.es6 b/app/assets/javascripts/username_validator.js
index 137cefa3b8e..137cefa3b8e 100644
--- a/app/assets/javascripts/username_validator.js.es6
+++ b/app/assets/javascripts/username_validator.js
diff --git a/app/assets/javascripts/users/calendar.js b/app/assets/javascripts/users/calendar.js
index 5111b260e1c..754d448564f 100644
--- a/app/assets/javascripts/users/calendar.js
+++ b/app/assets/javascripts/users/calendar.js
@@ -1,5 +1,6 @@
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, camelcase, vars-on-top, object-shorthand, comma-dangle, eqeqeq, no-mixed-operators, no-return-assign, newline-per-chained-call, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, prefer-template, quotes, no-unused-vars, no-else-return, max-len */
-/* global d3 */
+
+import d3 from 'd3';
(function() {
var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; };
diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js
index de33a31b411..27af859f7d8 100644
--- a/app/assets/javascripts/users_select.js
+++ b/app/assets/javascripts/users_select.js
@@ -60,6 +60,15 @@
});
};
+ $('.assign-to-me-link').on('click', (e) => {
+ e.preventDefault();
+ $(e.currentTarget).hide();
+ const $input = $(`input[name="${$dropdown.data('field-name')}"]`);
+ $input.val(gon.current_user_id);
+ selectedId = $input.val();
+ $dropdown.find('.dropdown-toggle-text').text(gon.current_user_fullname).removeClass('is-default');
+ });
+
$block.on('click', '.js-assign-yourself', function(e) {
e.preventDefault();
@@ -199,6 +208,11 @@
if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) {
e.preventDefault();
selectedId = user.id;
+ if (selectedId === gon.current_user_id) {
+ $('.assign-to-me-link').hide();
+ } else {
+ $('.assign-to-me-link').show();
+ }
return;
}
if ($el.closest('.add-issues-modal').length) {
@@ -234,11 +248,16 @@
id: function (user) {
return user.id;
},
+ opened: function(e) {
+ const $el = $(e.currentTarget);
+ $el.find('.is-active').removeClass('is-active');
+ $el.find(`li[data-user-id="${selectedId}"] .dropdown-menu-user-link`).addClass('is-active');
+ },
renderRow: function(user) {
var avatar, img, listClosingTags, listWithName, listWithUserName, selected, username;
username = user.username ? "@" + user.username : "";
avatar = user.avatar_url ? user.avatar_url : false;
- selected = user.id === selectedId ? "is-active" : "";
+ selected = user.id === parseInt(selectedId, 10) ? "is-active" : "";
img = "";
if (user.beforeDivider != null) {
"<li> <a href='#' class='" + selected + "'> " + user.name + " </a> </li>";
@@ -248,7 +267,7 @@
}
}
// split into three parts so we can remove the username section if nessesary
- listWithName = "<li> <a href='#' class='dropdown-menu-user-link " + selected + "'> " + img + " <strong class='dropdown-menu-user-full-name'> " + user.name + " </strong>";
+ listWithName = "<li data-user-id=" + user.id + "> <a href='#' class='dropdown-menu-user-link " + selected + "'> " + img + " <strong class='dropdown-menu-user-full-name'> " + user.name + " </strong>";
listWithUserName = "<span class='dropdown-menu-user-username'> " + username + " </span>";
listClosingTags = "</a> </li>";
if (username === '') {
diff --git a/app/assets/javascripts/version_check_image.js.es6 b/app/assets/javascripts/version_check_image.js
index d4f716acb72..d4f716acb72 100644
--- a/app/assets/javascripts/version_check_image.js.es6
+++ b/app/assets/javascripts/version_check_image.js
diff --git a/app/assets/javascripts/visibility_select.js.es6 b/app/assets/javascripts/visibility_select.js
index f712d7ba930..f712d7ba930 100644
--- a/app/assets/javascripts/visibility_select.js.es6
+++ b/app/assets/javascripts/visibility_select.js
diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js
index e7432afb56e..a90bd1518e9 100644
--- a/app/assets/javascripts/vue_pipelines_index/index.js.es6
+++ b/app/assets/javascripts/vue_pipelines_index/index.js
@@ -11,15 +11,10 @@ $(() => new Vue({
data() {
const project = document.querySelector('.pipelines');
- const svgs = document.querySelector('.pipeline-svgs').dataset;
-
- // Transform svgs DOMStringMap to a plain Object.
- const svgsObject = gl.utils.DOMStringMapToObject(svgs);
return {
scope: project.dataset.url,
store: new gl.PipelineStore(),
- svgs: svgsObject,
};
},
components: {
@@ -27,10 +22,8 @@ $(() => new Vue({
},
template: `
<vue-pipelines
- :scope='scope'
- :store='store'
- :svgs='svgs'
- >
+ :scope="scope"
+ :store="store">
</vue-pipelines>
`,
}));
diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js
index b50afe7c594..891f1f17fb3 100644
--- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6
+++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js
@@ -1,9 +1,10 @@
/* global Vue, Flash, gl */
-/* eslint-disable no-param-reassign, no-alert */
+/* eslint-disable no-param-reassign, no-alert */
+const playIconSvg = require('icons/_icon_play.svg');
((gl) => {
gl.VuePipelineActions = Vue.extend({
- props: ['pipeline', 'svgs'],
+ props: ['pipeline'],
computed: {
actions() {
return this.pipeline.details.manual_actions.length > 0;
@@ -31,6 +32,11 @@
}
},
},
+
+ data() {
+ return { playIconSvg };
+ },
+
template: `
<td class="pipeline-actions">
<div class="pull-right">
@@ -42,7 +48,7 @@
title="Manual job"
data-placement="top"
aria-label="Manual job">
- <span v-html="svgs.iconPlay" aria-hidden="true"></span>
+ <span v-html="playIconSvg" aria-hidden="true"></span>
<i class="fa fa-caret-down" aria-hidden="true"></i>
</button>
<ul class="dropdown-menu dropdown-menu-align-right">
@@ -50,8 +56,8 @@
<a
rel="nofollow"
data-method="post"
- :href="action.path">
- <span v-html="svgs.iconPlay" aria-hidden="true"></span>
+ :href="action.path" >
+ <span v-html="playIconSvg" aria-hidden="true"></span>
<span>{{action.name}}</span>
</a>
</li>
diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js
index ae5649f0519..ae5649f0519 100644
--- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6
+++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js
diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js
index 9275cdf78f7..601ef41e917 100644
--- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6
+++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js
@@ -27,7 +27,7 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s
pageRequest: false,
};
},
- props: ['scope', 'store', 'svgs'],
+ props: ['scope', 'store'],
created() {
const pagenum = gl.utils.getParameterByName('page');
const scope = gl.utils.getParameterByName('scope');
@@ -70,10 +70,7 @@ const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_s
</div>
<div class="table-holder" v-if='!pageRequest && pipelines.length'>
- <pipelines-table-component
- :pipelines='pipelines'
- :svgs='svgs'>
- </pipelines-table-component>
+ <pipelines-table-component :pipelines='pipelines'/>
</div>
<gl-pagination
diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js
index 67fdd729e41..f67ebd6a265 100644
--- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6
+++ b/app/assets/javascripts/vue_pipelines_index/stage.js
@@ -1,27 +1,42 @@
/* global Vue, Flash, gl */
/* eslint-disable no-param-reassign */
+import canceledSvg from 'icons/_icon_status_canceled_borderless.svg';
+import createdSvg from 'icons/_icon_status_created_borderless.svg';
+import failedSvg from 'icons/_icon_status_failed_borderless.svg';
+import manualSvg from 'icons/_icon_status_manual_borderless.svg';
+import pendingSvg from 'icons/_icon_status_pending_borderless.svg';
+import runningSvg from 'icons/_icon_status_running_borderless.svg';
+import skippedSvg from 'icons/_icon_status_skipped_borderless.svg';
+import successSvg from 'icons/_icon_status_success_borderless.svg';
+import warningSvg from 'icons/_icon_status_warning_borderless.svg';
((gl) => {
gl.VueStage = Vue.extend({
data() {
+ const svgsDictionary = {
+ icon_status_canceled: canceledSvg,
+ icon_status_created: createdSvg,
+ icon_status_failed: failedSvg,
+ icon_status_manual: manualSvg,
+ icon_status_pending: pendingSvg,
+ icon_status_running: runningSvg,
+ icon_status_skipped: skippedSvg,
+ icon_status_success: successSvg,
+ icon_status_warning: warningSvg,
+ };
+
return {
builds: '',
spinner: '<span class="fa fa-spinner fa-spin"></span>',
+ svg: svgsDictionary[this.stage.status.icon],
};
},
+
props: {
stage: {
type: Object,
required: true,
},
- svgs: {
- type: Object,
- required: true,
- },
- match: {
- type: Function,
- required: true,
- },
},
updated() {
@@ -73,11 +88,6 @@
tooltip() {
return `has-tooltip ci-status-icon ci-status-icon-${this.stage.status.group}`;
},
- svg() {
- const { icon } = this.stage.status;
- const stageIcon = icon.replace(/icon/i, 'stage_icon');
- return this.svgs[this.match(stageIcon)];
- },
triggerButtonClass() {
return `mini-pipeline-graph-dropdown-toggle has-tooltip js-builds-dropdown-button ci-status-icon-${this.stage.status.group}`;
},
@@ -91,8 +101,7 @@
data-placement="top"
data-toggle="dropdown"
type="button"
- :aria-label="stage.title"
- >
+ :aria-label="stage.title">
<span v-html="svg" aria-hidden="true"></span>
<i class="fa fa-caret-down" aria-hidden="true"></i>
</button>
@@ -101,8 +110,7 @@
<div
:class="dropdownClass"
class="js-builds-dropdown-list scrollable-menu"
- v-html="buildsOrSpinner"
- >
+ v-html="buildsOrSpinner">
</div>
</ul>
</div>
diff --git a/app/assets/javascripts/vue_pipelines_index/status.js b/app/assets/javascripts/vue_pipelines_index/status.js
new file mode 100644
index 00000000000..8d9f83ac113
--- /dev/null
+++ b/app/assets/javascripts/vue_pipelines_index/status.js
@@ -0,0 +1,64 @@
+/* global Vue, gl */
+/* eslint-disable no-param-reassign */
+
+import canceledSvg from 'icons/_icon_status_canceled.svg';
+import createdSvg from 'icons/_icon_status_created.svg';
+import failedSvg from 'icons/_icon_status_failed.svg';
+import manualSvg from 'icons/_icon_status_manual.svg';
+import pendingSvg from 'icons/_icon_status_pending.svg';
+import runningSvg from 'icons/_icon_status_running.svg';
+import skippedSvg from 'icons/_icon_status_skipped.svg';
+import successSvg from 'icons/_icon_status_success.svg';
+import warningSvg from 'icons/_icon_status_warning.svg';
+
+((gl) => {
+ gl.VueStatusScope = Vue.extend({
+ props: [
+ 'pipeline',
+ ],
+
+ data() {
+ const svgsDictionary = {
+ icon_status_canceled: canceledSvg,
+ icon_status_created: createdSvg,
+ icon_status_failed: failedSvg,
+ icon_status_manual: manualSvg,
+ icon_status_pending: pendingSvg,
+ icon_status_running: runningSvg,
+ icon_status_skipped: skippedSvg,
+ icon_status_success: successSvg,
+ icon_status_warning: warningSvg,
+ };
+
+ return {
+ svg: svgsDictionary[this.pipeline.details.status.icon],
+ };
+ },
+
+ computed: {
+ cssClasses() {
+ const cssObject = { 'ci-status': true };
+ cssObject[`ci-${this.pipeline.details.status.group}`] = true;
+ return cssObject;
+ },
+
+ detailsPath() {
+ const { status } = this.pipeline.details;
+ return status.has_details ? status.details_path : false;
+ },
+
+ content() {
+ return `${this.svg} ${this.pipeline.details.status.text}`;
+ },
+ },
+ template: `
+ <td class="commit-link">
+ <a
+ :class="cssClasses"
+ :href="detailsPath"
+ v-html="content">
+ </a>
+ </td>
+ `,
+ });
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/vue_pipelines_index/status.js.es6 b/app/assets/javascripts/vue_pipelines_index/status.js.es6
deleted file mode 100644
index 05175082704..00000000000
--- a/app/assets/javascripts/vue_pipelines_index/status.js.es6
+++ /dev/null
@@ -1,34 +0,0 @@
-/* global Vue, gl */
-/* eslint-disable no-param-reassign */
-
-((gl) => {
- gl.VueStatusScope = Vue.extend({
- props: [
- 'pipeline', 'svgs', 'match',
- ],
- computed: {
- cssClasses() {
- const cssObject = { 'ci-status': true };
- cssObject[`ci-${this.pipeline.details.status.group}`] = true;
- return cssObject;
- },
- svg() {
- return this.svgs[this.match(this.pipeline.details.status.icon)];
- },
- detailsPath() {
- const { status } = this.pipeline.details;
- return status.has_details ? status.details_path : false;
- },
- },
- template: `
- <td class="commit-link">
- <a
- :class='cssClasses'
- :href='detailsPath'
- v-html='svg + pipeline.details.status.text'
- >
- </a>
- </td>
- `,
- });
-})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js
index 909007267b9..909007267b9 100644
--- a/app/assets/javascripts/vue_pipelines_index/store.js.es6
+++ b/app/assets/javascripts/vue_pipelines_index/store.js
diff --git a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 b/app/assets/javascripts/vue_pipelines_index/time_ago.js
index 6048fa691dc..a383570857d 100644
--- a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6
+++ b/app/assets/javascripts/vue_pipelines_index/time_ago.js
@@ -4,14 +4,17 @@
window.Vue = require('vue');
require('../lib/utils/datetime_utility');
+const iconTimerSvg = require('../../../views/shared/icons/_icon_timer.svg');
+
((gl) => {
gl.VueTimeAgo = Vue.extend({
data() {
return {
currentTime: new Date(),
+ iconTimerSvg,
};
},
- props: ['pipeline', 'svgs'],
+ props: ['pipeline'],
computed: {
timeAgo() {
return gl.utils.getTimeago();
@@ -56,7 +59,7 @@ require('../lib/utils/datetime_utility');
template: `
<td class="pipelines-time-ago">
<p class="duration" v-if='duration'>
- <span v-html='svgs.iconTimer'></span>
+ <span v-html="iconTimerSvg"></span>
{{duration}}
</p>
<p class="finished-at" v-if='timeStopped'>
diff --git a/app/assets/javascripts/vue_realtime_listener/index.js.es6 b/app/assets/javascripts/vue_realtime_listener/index.js
index 30f6680a673..30f6680a673 100644
--- a/app/assets/javascripts/vue_realtime_listener/index.js.es6
+++ b/app/assets/javascripts/vue_realtime_listener/index.js
diff --git a/app/assets/javascripts/vue_shared/components/commit.js.es6 b/app/assets/javascripts/vue_shared/components/commit.js
index ff88e236829..4381487b79e 100644
--- a/app/assets/javascripts/vue_shared/components/commit.js.es6
+++ b/app/assets/javascripts/vue_shared/components/commit.js
@@ -1,5 +1,6 @@
/* global Vue */
window.Vue = require('vue');
+const commitIconSvg = require('icons/_icon_commit.svg');
(() => {
window.gl = window.gl || {};
@@ -69,11 +70,6 @@ window.Vue = require('vue');
required: false,
default: () => ({}),
},
-
- commitIconSvg: {
- type: String,
- required: false,
- },
},
computed: {
@@ -116,6 +112,10 @@ window.Vue = require('vue');
},
},
+ data() {
+ return { commitIconSvg };
+ },
+
template: `
<div class="branch-commit">
diff --git a/app/assets/javascripts/vue_shared/components/pipelines_table.js.es6 b/app/assets/javascripts/vue_shared/components/pipelines_table.js
index 34d3bbdd80d..0d8f85db965 100644
--- a/app/assets/javascripts/vue_shared/components/pipelines_table.js.es6
+++ b/app/assets/javascripts/vue_shared/components/pipelines_table.js
@@ -21,14 +21,6 @@ require('./pipelines_table_row');
default: () => ([]),
},
- /**
- * TODO: Remove this when we have webpack.
- */
- svgs: {
- type: Object,
- required: true,
- default: () => ({}),
- },
},
components: {
@@ -51,8 +43,7 @@ require('./pipelines_table_row');
<template v-for="model in pipelines"
v-bind:model="model">
<tr is="pipelines-table-row-component"
- :pipeline="model"
- :svgs="svgs"></tr>
+ :pipeline="model"></tr>
</template>
</tbody>
</table>
diff --git a/app/assets/javascripts/vue_shared/components/pipelines_table_row.js.es6 b/app/assets/javascripts/vue_shared/components/pipelines_table_row.js
index 61c1b72d9d2..e5e88186a85 100644
--- a/app/assets/javascripts/vue_shared/components/pipelines_table_row.js.es6
+++ b/app/assets/javascripts/vue_shared/components/pipelines_table_row.js
@@ -25,14 +25,6 @@ require('./commit');
default: () => ({}),
},
- /**
- * TODO: Remove this when we have webpack;
- */
- svgs: {
- type: Object,
- required: true,
- default: () => ({}),
- },
},
components: {
@@ -174,30 +166,9 @@ require('./commit');
},
},
- methods: {
- /**
- * FIXME: This should not be in this component but in the components that
- * need this function.
- *
- * Used to render SVGs in the following components:
- * - status-scope
- * - dropdown-stage
- *
- * @param {String} string
- * @return {String}
- */
- match(string) {
- return string.replace(/_([a-z])/g, (m, w) => w.toUpperCase());
- },
- },
-
template: `
<tr class="commit">
- <status-scope
- :pipeline="pipeline"
- :svgs="svgs"
- :match="match">
- </status-scope>
+ <status-scope :pipeline="pipeline"/>
<pipeline-url :pipeline="pipeline"></pipeline-url>
@@ -208,26 +179,20 @@ require('./commit');
:commit-url="commitUrl"
:short-sha="commitShortSha"
:title="commitTitle"
- :author="commitAuthor"
- :commit-icon-svg="svgs.commitIconSvg">
- </commit-component>
+ :author="commitAuthor"/>
</td>
<td class="stage-cell">
<div class="stage-container dropdown js-mini-pipeline-graph"
v-if="pipeline.details.stages.length > 0"
v-for="stage in pipeline.details.stages">
- <dropdown-stage
- :stage="stage"
- :svgs="svgs"
- :match="match">
- </dropdown-stage>
+ <dropdown-stage :stage="stage"/>
</div>
</td>
- <time-ago :pipeline="pipeline" :svgs="svgs"></time-ago>
+ <time-ago :pipeline="pipeline"/>
- <pipeline-actions :pipeline="pipeline" :svgs="svgs"></pipeline-actions>
+ <pipeline-actions :pipeline="pipeline" />
</tr>
`,
});
diff --git a/app/assets/javascripts/vue_shared/components/table_pagination.js.es6 b/app/assets/javascripts/vue_shared/components/table_pagination.js
index dd046405575..8943b850a72 100644
--- a/app/assets/javascripts/vue_shared/components/table_pagination.js.es6
+++ b/app/assets/javascripts/vue_shared/components/table_pagination.js
@@ -19,7 +19,6 @@ window.Vue = require('vue');
/**
This function will take the information given by the pagination component
- And make a new Turbolinks call
Here is an example `change` method:
diff --git a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js.es6 b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js
index d3229f9f730..d3229f9f730 100644
--- a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js.es6
+++ b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js
diff --git a/app/assets/javascripts/wikis.js.es6 b/app/assets/javascripts/wikis.js
index 75fd1394a03..75fd1394a03 100644
--- a/app/assets/javascripts/wikis.js.es6
+++ b/app/assets/javascripts/wikis.js