diff options
author | Kushal Pandya <kushalspandya@gmail.com> | 2018-11-30 09:27:27 +0000 |
---|---|---|
committer | Kushal Pandya <kushalspandya@gmail.com> | 2018-11-30 09:27:27 +0000 |
commit | b6e70c8ae48e7816a81e738242bedca9cfcf1fd1 (patch) | |
tree | 470a0d6864bb44957b0ad719adfb65544d28cddb /app | |
parent | df02784966c121a4dde7a6ddb0a0266ce0acc68f (diff) | |
parent | e3bddb6223ceba9e1258df28cfa046641d12710f (diff) | |
download | gitlab-ce-b6e70c8ae48e7816a81e738242bedca9cfcf1fd1.tar.gz |
Merge branch 'winh-timeline-entry-component' into 'master'
Extract shared timeline entry component
See merge request gitlab-org/gitlab-ce!23447
Diffstat (limited to 'app')
8 files changed, 378 insertions, 368 deletions
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index 884ccca7bde..841fcec96e8 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -4,6 +4,7 @@ import { mapActions, mapGetters, mapState } from 'vuex'; import _ from 'underscore'; import Autosize from 'autosize'; import { __, sprintf } from '~/locale'; +import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import Flash from '../../flash'; import Autosave from '../../autosave'; import { @@ -30,6 +31,7 @@ export default { markdownField, userAvatarLink, loadingButton, + TimelineEntryItem, }, mixins: [issuableStateMixin], props: { @@ -309,137 +311,135 @@ Please check your network connection and try again.`; <div> <note-signed-out-widget v-if="!isLoggedIn" /> <discussion-locked-widget v-else-if="!canCreateNote" :issuable-type="issuableTypeTitle" /> - <div v-else-if="canCreateNote" class="notes notes-form timeline"> - <div class="timeline-entry note-form"> - <div class="timeline-entry-inner"> - <div class="flash-container error-alert timeline-content"></div> - <div class="timeline-icon d-none d-sm-none d-md-block"> - <user-avatar-link - v-if="author" - :link-href="author.path" - :img-src="author.avatar_url" - :img-alt="author.name" - :img-size="40" - /> - </div> - <div class="timeline-content timeline-content-form"> - <form ref="commentForm" class="new-note common-note-form gfm-form js-main-target-form"> - <div class="error-alert"></div> + <ul v-else-if="canCreateNote" class="notes notes-form timeline"> + <timeline-entry-item class="note-form"> + <div class="flash-container error-alert timeline-content"></div> + <div class="timeline-icon d-none d-sm-none d-md-block"> + <user-avatar-link + v-if="author" + :link-href="author.path" + :img-src="author.avatar_url" + :img-alt="author.name" + :img-size="40" + /> + </div> + <div class="timeline-content timeline-content-form"> + <form ref="commentForm" class="new-note common-note-form gfm-form js-main-target-form"> + <div class="error-alert"></div> - <issue-warning - v-if="hasWarning(getNoteableData)" - :is-locked="isLocked(getNoteableData)" - :is-confidential="isConfidential(getNoteableData)" - /> + <issue-warning + v-if="hasWarning(getNoteableData)" + :is-locked="isLocked(getNoteableData)" + :is-confidential="isConfidential(getNoteableData)" + /> - <markdown-field - ref="markdownField" - :markdown-preview-path="markdownPreviewPath" - :markdown-docs-path="markdownDocsPath" - :quick-actions-docs-path="quickActionsDocsPath" - :markdown-version="markdownVersion" - :add-spacing-classes="false" - > - <textarea - id="note-body" - ref="textarea" - slot="textarea" - v-model="note" - :disabled="isSubmitting" - name="note[note]" - class="note-textarea js-vue-comment-form js-note-text + <markdown-field + ref="markdownField" + :markdown-preview-path="markdownPreviewPath" + :markdown-docs-path="markdownDocsPath" + :quick-actions-docs-path="quickActionsDocsPath" + :markdown-version="markdownVersion" + :add-spacing-classes="false" + > + <textarea + id="note-body" + ref="textarea" + slot="textarea" + v-model="note" + :disabled="isSubmitting" + name="note[note]" + class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area js-vue-textarea qa-comment-input" - data-supports-quick-actions="true" - aria-label="Description" - placeholder="Write a comment or drag your files here…" - @keydown.up="editCurrentUserLastNote();" - @keydown.meta.enter="handleSave();" - @keydown.ctrl.enter="handleSave();" - > - </textarea> - </markdown-field> - <div class="note-form-actions"> - <div - class="float-left btn-group + data-supports-quick-actions="true" + aria-label="Description" + placeholder="Write a comment or drag your files here…" + @keydown.up="editCurrentUserLastNote();" + @keydown.meta.enter="handleSave();" + @keydown.ctrl.enter="handleSave();" + > + </textarea> + </markdown-field> + <div class="note-form-actions"> + <div + class="float-left btn-group append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown" - > - <button - :disabled="isSubmitButtonDisabled" - class="btn btn-create comment-btn js-comment-button js-comment-submit-button + > + <button + :disabled="isSubmitButtonDisabled" + class="btn btn-create comment-btn js-comment-button js-comment-submit-button qa-comment-button" - type="submit" - @click.prevent="handleSave();" - > - {{ __(commentButtonTitle) }} - </button> - <button - :disabled="isSubmitButtonDisabled" - name="button" - type="button" - class="btn comment-btn note-type-toggle js-note-new-discussion dropdown-toggle qa-note-dropdown" - data-display="static" - data-toggle="dropdown" - aria-label="Open comment type dropdown" - > - <i aria-hidden="true" class="fa fa-caret-down toggle-icon"> </i> - </button> - - <ul class="note-type-dropdown dropdown-open-top dropdown-menu"> - <li :class="{ 'droplab-item-selected': noteType === 'comment' }"> - <button - type="button" - class="btn btn-transparent" - @click.prevent="setNoteType('comment');" - > - <i aria-hidden="true" class="fa fa-check icon"> </i> - <div class="description"> - <strong>Comment</strong> - <p>Add a general comment to this {{ noteableDisplayName }}.</p> - </div> - </button> - </li> - <li class="divider droplab-item-ignore"></li> - <li :class="{ 'droplab-item-selected': noteType === 'discussion' }"> - <button - type="button" - class="btn btn-transparent qa-discussion-option" - @click.prevent="setNoteType('discussion');" - > - <i aria-hidden="true" class="fa fa-check icon"> </i> - <div class="description"> - <strong>Start discussion</strong> - <p>{{ startDiscussionDescription }}</p> - </div> - </button> - </li> - </ul> - </div> - - <loading-button - v-if="canUpdateIssue" - :loading="isToggleStateButtonLoading" - :container-class="[ - actionButtonClassNames, - 'btn btn-comment btn-comment-and-close js-action-button', - ]" - :disabled="isToggleStateButtonLoading || isSubmitting" - :label="issueActionButtonTitle" - @click="handleSave(true);" - /> - + type="submit" + @click.prevent="handleSave();" + > + {{ __(commentButtonTitle) }} + </button> <button - v-if="note.length" + :disabled="isSubmitButtonDisabled" + name="button" type="button" - class="btn btn-cancel js-note-discard" - @click="discard" + class="btn comment-btn note-type-toggle js-note-new-discussion dropdown-toggle qa-note-dropdown" + data-display="static" + data-toggle="dropdown" + aria-label="Open comment type dropdown" > - Discard draft + <i aria-hidden="true" class="fa fa-caret-down toggle-icon"> </i> </button> + + <ul class="note-type-dropdown dropdown-open-top dropdown-menu"> + <li :class="{ 'droplab-item-selected': noteType === 'comment' }"> + <button + type="button" + class="btn btn-transparent" + @click.prevent="setNoteType('comment');" + > + <i aria-hidden="true" class="fa fa-check icon"> </i> + <div class="description"> + <strong>Comment</strong> + <p>Add a general comment to this {{ noteableDisplayName }}.</p> + </div> + </button> + </li> + <li class="divider droplab-item-ignore"></li> + <li :class="{ 'droplab-item-selected': noteType === 'discussion' }"> + <button + type="button" + class="btn btn-transparent qa-discussion-option" + @click.prevent="setNoteType('discussion');" + > + <i aria-hidden="true" class="fa fa-check icon"> </i> + <div class="description"> + <strong>Start discussion</strong> + <p>{{ startDiscussionDescription }}</p> + </div> + </button> + </li> + </ul> </div> - </form> - </div> + + <loading-button + v-if="canUpdateIssue" + :loading="isToggleStateButtonLoading" + :container-class="[ + actionButtonClassNames, + 'btn btn-comment btn-comment-and-close js-action-button', + ]" + :disabled="isToggleStateButtonLoading || isSubmitting" + :label="issueActionButtonTitle" + @click="handleSave(true);" + /> + + <button + v-if="note.length" + type="button" + class="btn btn-cancel js-note-discard" + @click="discard" + > + Discard draft + </button> + </div> + </form> </div> - </div> - </div> + </timeline-entry-item> + </ul> </div> </template> diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index da78c6e21a1..4eb3b49392c 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -6,6 +6,7 @@ import { truncateSha } from '~/lib/utils/text_utility'; import { s__, __, sprintf } from '~/locale'; import systemNote from '~/vue_shared/components/notes/system_note.vue'; import icon from '~/vue_shared/components/icon.vue'; +import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import Flash from '../../flash'; import { SYSTEM_NOTE } from '../constants'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; @@ -37,6 +38,7 @@ export default { placeholderNote, placeholderSystemNote, systemNote, + TimelineEntryItem, }, directives: { GlTooltip: GlTooltipDirective, @@ -301,162 +303,156 @@ Please check your network connection and try again.`; </script> <template> - <li class="note note-discussion timeline-entry" :class="componentClassName"> - <div class="timeline-entry-inner"> - <div class="timeline-content"> - <div :data-discussion-id="discussion.id" class="discussion js-discussion-container"> - <div v-if="shouldRenderDiffs" class="discussion-header note-wrapper"> - <div v-once class="timeline-icon"> - <user-avatar-link - v-if="author" - :link-href="author.path" - :img-src="author.avatar_url" - :img-alt="author.name" - :img-size="40" - /> - </div> - <note-header - :author="author" - :created-at="initialDiscussion.created_at" - :note-id="initialDiscussion.id" - :include-toggle="true" - :expanded="discussion.expanded" - @toggleHandler="toggleDiscussionHandler" - > - <span v-html="actionText"></span> - </note-header> - <note-edited-text - v-if="discussion.resolved" - :edited-at="discussion.resolved_at" - :edited-by="discussion.resolved_by" - :action-text="resolvedText" - class-name="discussion-headline-light js-discussion-headline" - /> - <note-edited-text - v-else-if="lastUpdatedAt" - :edited-at="lastUpdatedAt" - :edited-by="lastUpdatedBy" - action-text="Last updated" - class-name="discussion-headline-light js-discussion-headline" + <timeline-entry-item class="note note-discussion" :class="componentClassName"> + <div class="timeline-content"> + <div :data-discussion-id="discussion.id" class="discussion js-discussion-container"> + <div v-if="shouldRenderDiffs" class="discussion-header note-wrapper"> + <div v-once class="timeline-icon"> + <user-avatar-link + v-if="author" + :link-href="author.path" + :img-src="author.avatar_url" + :img-alt="author.name" + :img-size="40" /> </div> - <div v-if="shouldShowDiscussions" class="discussion-body"> - <component - :is="wrapperComponent" - v-bind="wrapperComponentProps" - class="card discussion-wrapper" - > - <div class="discussion-notes"> - <ul class="notes"> - <template v-if="shouldGroupReplies"> - <component - :is="componentName(initialDiscussion)" - :note="componentData(initialDiscussion)" - @handleDeleteNote="deleteNoteHandler" - > - <slot slot="avatar-badge" name="avatar-badge"></slot> - </component> - <toggle-replies-widget - v-if="hasReplies" - :collapsed="isRepliesCollapsed" - :replies="replies" - @toggle="toggleReplies" - /> - <template v-if="!isRepliesCollapsed"> - <component - :is="componentName(note)" - v-for="note in replies" - :key="note.id" - :note="componentData(note)" - @handleDeleteNote="deleteNoteHandler" - /> - </template> - </template> - <template v-else> + <note-header + :author="author" + :created-at="initialDiscussion.created_at" + :note-id="initialDiscussion.id" + :include-toggle="true" + :expanded="discussion.expanded" + @toggleHandler="toggleDiscussionHandler" + > + <span v-html="actionText"></span> + </note-header> + <note-edited-text + v-if="discussion.resolved" + :edited-at="discussion.resolved_at" + :edited-by="discussion.resolved_by" + :action-text="resolvedText" + class-name="discussion-headline-light js-discussion-headline" + /> + <note-edited-text + v-else-if="lastUpdatedAt" + :edited-at="lastUpdatedAt" + :edited-by="lastUpdatedBy" + action-text="Last updated" + class-name="discussion-headline-light js-discussion-headline" + /> + </div> + <div v-if="shouldShowDiscussions" class="discussion-body"> + <component + :is="wrapperComponent" + v-bind="wrapperComponentProps" + class="card discussion-wrapper" + > + <div class="discussion-notes"> + <ul class="notes"> + <template v-if="shouldGroupReplies"> + <component + :is="componentName(initialDiscussion)" + :note="componentData(initialDiscussion)" + @handleDeleteNote="deleteNoteHandler" + > + <slot slot="avatar-badge" name="avatar-badge"></slot> + </component> + <toggle-replies-widget + v-if="hasReplies" + :collapsed="isRepliesCollapsed" + :replies="replies" + @toggle="toggleReplies" + /> + <template v-if="!isRepliesCollapsed"> <component :is="componentName(note)" - v-for="(note, index) in discussion.notes" + v-for="note in replies" :key="note.id" :note="componentData(note)" @handleDeleteNote="deleteNoteHandler" - > - <slot v-if="index === 0" slot="avatar-badge" name="avatar-badge"></slot> - </component> + /> </template> - </ul> - <div - v-if="!isRepliesCollapsed" - :class="{ 'is-replying': isReplying }" - class="discussion-reply-holder" - > - <template v-if="!isReplying && canReply"> - <div class="discussion-with-resolve-btn"> + </template> + <template v-else> + <component + :is="componentName(note)" + v-for="(note, index) in discussion.notes" + :key="note.id" + :note="componentData(note)" + @handleDeleteNote="deleteNoteHandler" + > + <slot v-if="index === 0" slot="avatar-badge" name="avatar-badge"></slot> + </component> + </template> + </ul> + <div + v-if="!isRepliesCollapsed" + :class="{ 'is-replying': isReplying }" + class="discussion-reply-holder" + > + <template v-if="!isReplying && canReply"> + <div class="discussion-with-resolve-btn"> + <button + type="button" + class="js-vue-discussion-reply btn btn-text-field mr-sm-2 qa-discussion-reply" + title="Add a reply" + @click="showReplyForm" + > + Reply... + </button> + <div v-if="discussion.resolvable"> <button type="button" - class="js-vue-discussion-reply btn btn-text-field mr-sm-2 qa-discussion-reply" - title="Add a reply" - @click="showReplyForm" + class="btn btn-default mr-sm-2" + @click="resolveHandler();" > - Reply... + <i v-if="isResolving" aria-hidden="true" class="fa fa-spinner fa-spin"></i> + {{ resolveButtonTitle }} </button> - <div v-if="discussion.resolvable"> + </div> + <div + v-if="discussion.resolvable" + class="btn-group discussion-actions ml-sm-2" + role="group" + > + <div v-if="!discussionResolved" class="btn-group" role="group"> + <a + v-gl-tooltip + :href="discussion.resolve_with_issue_path" + :title="s__('MergeRequests|Resolve this discussion in a new issue')" + class="new-issue-for-discussion btn btn-default discussion-create-issue-btn" + > + <icon name="issue-new" /> + </a> + </div> + <div v-if="hasUnresolvedDiscussions" class="btn-group" role="group"> <button - type="button" - class="btn btn-default mr-sm-2" - @click="resolveHandler();" + v-gl-tooltip + class="btn btn-default discussion-next-btn" + title="Jump to next unresolved discussion" + @click="jumpToNextDiscussion" > - <i - v-if="isResolving" - aria-hidden="true" - class="fa fa-spinner fa-spin" - ></i> - {{ resolveButtonTitle }} + <icon name="comment-next" /> </button> </div> - <div - v-if="discussion.resolvable" - class="btn-group discussion-actions ml-sm-2" - role="group" - > - <div v-if="!discussionResolved" class="btn-group" role="group"> - <a - v-gl-tooltip - :href="discussion.resolve_with_issue_path" - :title="s__('MergeRequests|Resolve this discussion in a new issue')" - class="new-issue-for-discussion btn btn-default discussion-create-issue-btn" - > - <icon name="issue-new" /> - </a> - </div> - <div v-if="hasUnresolvedDiscussions" class="btn-group" role="group"> - <button - v-gl-tooltip - class="btn btn-default discussion-next-btn" - title="Jump to next unresolved discussion" - @click="jumpToNextDiscussion" - > - <icon name="comment-next" /> - </button> - </div> - </div> </div> - </template> - <note-form - v-if="isReplying" - ref="noteForm" - :discussion="discussion" - :is-editing="false" - save-button-title="Comment" - @handleFormUpdate="saveReply" - @cancelForm="cancelReplyForm" - /> - <note-signed-out-widget v-if="!canReply" /> - </div> + </div> + </template> + <note-form + v-if="isReplying" + ref="noteForm" + :discussion="discussion" + :is-editing="false" + save-button-title="Comment" + @handleFormUpdate="saveReply" + @cancelForm="cancelReplyForm" + /> + <note-signed-out-widget v-if="!canReply" /> </div> - </component> - </div> + </div> + </component> </div> </div> </div> - </li> + </timeline-entry-item> </template> diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue index fc37fe1c7af..a17be51353e 100644 --- a/app/assets/javascripts/notes/components/noteable_note.vue +++ b/app/assets/javascripts/notes/components/noteable_note.vue @@ -2,6 +2,7 @@ import $ from 'jquery'; import { mapGetters, mapActions } from 'vuex'; import { escape } from 'underscore'; +import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import Flash from '../../flash'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import noteHeader from './note_header.vue'; @@ -18,6 +19,7 @@ export default { noteHeader, noteActions, noteBody, + TimelineEntryItem, }, mixins: [noteable, resolvable], props: { @@ -169,62 +171,60 @@ export default { </script> <template> - <li + <timeline-entry-item :id="noteAnchorId" :class="classNameBindings" :data-award-url="note.toggle_award_path" :data-note-id="note.id" - class="note timeline-entry note-wrapper" + class="note note-wrapper" > - <div class="timeline-entry-inner"> - <div v-once class="timeline-icon"> - <user-avatar-link - :link-href="author.path" - :img-src="author.avatar_url" - :img-alt="author.name" - :img-size="40" - > - <slot slot="avatar-badge" name="avatar-badge"> </slot> - </user-avatar-link> - </div> - <div class="timeline-content"> - <div class="note-header"> - <note-header - v-once - :author="author" - :created-at="note.created_at" - :note-id="note.id" - action-text="commented" - /> - <note-actions - :author-id="author.id" - :note-id="note.id" - :note-url="note.noteable_note_url" - :access-level="note.human_access" - :can-edit="note.current_user.can_edit" - :can-award-emoji="note.current_user.can_award_emoji" - :can-delete="note.current_user.can_edit" - :can-report-as-abuse="canReportAsAbuse" - :can-resolve="note.current_user.can_resolve" - :report-abuse-path="note.report_abuse_path" - :resolvable="note.resolvable" - :is-resolved="note.resolved" - :is-resolving="isResolving" - :resolved-by="note.resolved_by" - @handleEdit="editHandler" - @handleDelete="deleteHandler" - @handleResolve="resolveHandler" - /> - </div> - <note-body - ref="noteBody" - :note="note" + <div v-once class="timeline-icon"> + <user-avatar-link + :link-href="author.path" + :img-src="author.avatar_url" + :img-alt="author.name" + :img-size="40" + > + <slot slot="avatar-badge" name="avatar-badge"> </slot> + </user-avatar-link> + </div> + <div class="timeline-content"> + <div class="note-header"> + <note-header + v-once + :author="author" + :created-at="note.created_at" + :note-id="note.id" + action-text="commented" + /> + <note-actions + :author-id="author.id" + :note-id="note.id" + :note-url="note.noteable_note_url" + :access-level="note.human_access" :can-edit="note.current_user.can_edit" - :is-editing="isEditing" - @handleFormUpdate="formUpdateHandler" - @cancelForm="formCancelHandler" + :can-award-emoji="note.current_user.can_award_emoji" + :can-delete="note.current_user.can_edit" + :can-report-as-abuse="canReportAsAbuse" + :can-resolve="note.current_user.can_resolve" + :report-abuse-path="note.report_abuse_path" + :resolvable="note.resolvable" + :is-resolved="note.resolved" + :is-resolving="isResolving" + :resolved-by="note.resolved_by" + @handleEdit="editHandler" + @handleDelete="deleteHandler" + @handleResolve="resolveHandler" /> </div> + <note-body + ref="noteBody" + :note="note" + :can-edit="note.current_user.can_edit" + :is-editing="isEditing" + @handleFormUpdate="formUpdateHandler" + @cancelForm="formCancelHandler" + /> </div> - </li> + </timeline-entry-item> </template> diff --git a/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue b/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue index b1faebf409b..8d3a3009c55 100644 --- a/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue +++ b/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue @@ -17,12 +17,14 @@ * /> */ import { mapGetters } from 'vuex'; +import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import userAvatarLink from '../user_avatar/user_avatar_link.vue'; export default { name: 'PlaceholderNote', components: { userAvatarLink, + TimelineEntryItem, }, props: { note: { @@ -37,30 +39,28 @@ export default { </script> <template> - <li class="note being-posted fade-in-half timeline-entry"> - <div class="timeline-entry-inner"> - <div class="timeline-icon"> - <user-avatar-link - :link-href="getUserData.path" - :img-src="getUserData.avatar_url" - :img-size="40" - /> - </div> - <div :class="{ discussion: !note.individual_note }" class="timeline-content"> - <div class="note-header"> - <div class="note-header-info"> - <a :href="getUserData.path"> - <span class="d-none d-sm-inline-block">{{ getUserData.name }}</span> - <span class="note-headline-light">@{{ getUserData.username }}</span> - </a> - </div> + <timeline-entry-item class="note being-posted fade-in-half"> + <div class="timeline-icon"> + <user-avatar-link + :link-href="getUserData.path" + :img-src="getUserData.avatar_url" + :img-size="40" + /> + </div> + <div :class="{ discussion: !note.individual_note }" class="timeline-content"> + <div class="note-header"> + <div class="note-header-info"> + <a :href="getUserData.path"> + <span class="d-none d-sm-inline-block">{{ getUserData.name }}</span> + <span class="note-headline-light">@{{ getUserData.username }}</span> + </a> </div> - <div class="note-body"> - <div class="note-text"> - <p>{{ note.body }}</p> - </div> + </div> + <div class="note-body"> + <div class="note-text"> + <p>{{ note.body }}</p> </div> </div> </div> - </li> + </timeline-entry-item> </template> diff --git a/app/assets/javascripts/vue_shared/components/notes/placeholder_system_note.vue b/app/assets/javascripts/vue_shared/components/notes/placeholder_system_note.vue index 674f923478d..7689425eb52 100644 --- a/app/assets/javascripts/vue_shared/components/notes/placeholder_system_note.vue +++ b/app/assets/javascripts/vue_shared/components/notes/placeholder_system_note.vue @@ -1,4 +1,6 @@ <script> +import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; + /** * Common component to render a placeholder system note. * @@ -9,6 +11,9 @@ */ export default { name: 'PlaceholderSystemNote', + components: { + TimelineEntryItem, + }, props: { note: { type: Object, @@ -19,11 +24,9 @@ export default { </script> <template> - <li class="note system-note timeline-entry being-posted fade-in-half"> - <div class="timeline-entry-inner"> - <div class="timeline-content"> - <em>{{ note.body }}</em> - </div> + <timeline-entry-item class="note system-note being-posted fade-in-half"> + <div class="timeline-content"> + <em>{{ note.body }}</em> </div> - </li> + </timeline-entry-item> </template> diff --git a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue index c6cf4661222..e61d1fd2031 100644 --- a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue +++ b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue @@ -1,22 +1,22 @@ <script> import { GlSkeletonLoading } from '@gitlab/ui'; +import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; export default { name: 'SkeletonNote', components: { GlSkeletonLoading, + TimelineEntryItem, }, }; </script> <template> - <li class="timeline-entry note note-wrapper"> - <div class="timeline-entry-inner"> - <div class="timeline-icon"></div> - <div class="timeline-content"> - <div class="note-header"></div> - <div class="note-body"><gl-skeleton-loading /></div> - </div> + <timeline-entry-item class="note note-wrapper"> + <div class="timeline-icon"></div> + <div class="timeline-content"> + <div class="note-header"></div> + <div class="note-body"><gl-skeleton-loading /></div> </div> - </li> + </timeline-entry-item> </template> diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue index fb86262d0b4..31df26f7b05 100644 --- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue +++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue @@ -20,6 +20,7 @@ import $ from 'jquery'; import { mapGetters } from 'vuex'; import noteHeader from '~/notes/components/note_header.vue'; import Icon from '~/vue_shared/components/icon.vue'; +import TimelineEntryItem from './timeline_entry_item.vue'; import { spriteIcon } from '../../../lib/utils/common_utils'; const MAX_VISIBLE_COMMIT_LIST_COUNT = 3; @@ -29,6 +30,7 @@ export default { components: { Icon, noteHeader, + TimelineEntryItem, }, props: { note: { @@ -73,36 +75,34 @@ export default { </script> <template> - <li + <timeline-entry-item :id="noteAnchorId" :class="{ target: isTargetNote }" - class="note system-note timeline-entry note-wrapper" + class="note system-note note-wrapper" > - <div class="timeline-entry-inner"> - <div class="timeline-icon" v-html="iconHtml"></div> - <div class="timeline-content"> - <div class="note-header"> - <note-header :author="note.author" :created-at="note.created_at" :note-id="note.id"> - <span v-html="actionTextHtml"></span> - </note-header> - </div> - <div class="note-body"> - <div - :class="{ - 'system-note-commit-list': hasMoreCommits, - 'hide-shade': expanded, - }" - class="note-text" - v-html="note.note_html" - ></div> - <div v-if="hasMoreCommits" class="flex-list"> - <div class="system-note-commit-list-toggler flex-row" @click="expanded = !expanded;"> - <icon :name="toggleIcon" :size="8" class="append-right-5" /> - <span>Toggle commit list</span> - </div> + <div class="timeline-icon" v-html="iconHtml"></div> + <div class="timeline-content"> + <div class="note-header"> + <note-header :author="note.author" :created-at="note.created_at" :note-id="note.id"> + <span v-html="actionTextHtml"></span> + </note-header> + </div> + <div class="note-body"> + <div + :class="{ + 'system-note-commit-list': hasMoreCommits, + 'hide-shade': expanded, + }" + class="note-text" + v-html="note.note_html" + ></div> + <div v-if="hasMoreCommits" class="flex-list"> + <div class="system-note-commit-list-toggler flex-row" @click="expanded = !expanded;"> + <icon :name="toggleIcon" :size="8" class="append-right-5" /> + <span>Toggle commit list</span> </div> </div> </div> </div> - </li> + </timeline-entry-item> </template> diff --git a/app/assets/javascripts/vue_shared/components/notes/timeline_entry_item.vue b/app/assets/javascripts/vue_shared/components/notes/timeline_entry_item.vue new file mode 100644 index 00000000000..06974a12aed --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/notes/timeline_entry_item.vue @@ -0,0 +1,11 @@ +<script> +export default { + name: 'TimelineEntryItem', +}; +</script> + +<template> + <li class="timeline-entry"> + <div class="timeline-entry-inner"><slot></slot></div> + </li> +</template> |