diff options
Diffstat (limited to 'app/assets/javascripts/contribution_events')
8 files changed, 365 insertions, 1 deletions
diff --git a/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_closed.vue b/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_closed.vue new file mode 100644 index 00000000000..85c42ca5485 --- /dev/null +++ b/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_closed.vue @@ -0,0 +1,43 @@ +<script> +import { + EVENT_CLOSED_I18N, + TARGET_TYPE_MERGE_REQUEST, + EVENT_CLOSED_ICONS, +} from 'ee_else_ce/contribution_events/constants'; +import { getValueByEventTarget } from '../../utils'; +import ContributionEventBase from './contribution_event_base.vue'; + +export default { + name: 'ContributionEventClosed', + components: { ContributionEventBase }, + props: { + event: { + type: Object, + required: true, + }, + }, + computed: { + targetType() { + return this.event.target.type; + }, + message() { + return getValueByEventTarget(EVENT_CLOSED_I18N, this.event); + }, + iconName() { + return getValueByEventTarget(EVENT_CLOSED_ICONS, this.event); + }, + iconClass() { + return this.targetType === TARGET_TYPE_MERGE_REQUEST ? 'gl-text-red-500' : 'gl-text-blue-500'; + }, + }, +}; +</script> + +<template> + <contribution-event-base + :event="event" + :message="message" + :icon-name="iconName" + :icon-class="iconClass" + /> +</template> diff --git a/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_commented.vue b/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_commented.vue new file mode 100644 index 00000000000..ee433c17792 --- /dev/null +++ b/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_commented.vue @@ -0,0 +1,71 @@ +<script> +import { GlSprintf, GlLink } from '@gitlab/ui'; +import { + EVENT_COMMENTED_I18N, + EVENT_COMMENTED_SNIPPET_I18N, +} from 'ee_else_ce/contribution_events/constants'; +import { SNIPPET_NOTEABLE_TYPE, COMMIT_NOTEABLE_TYPE } from '~/notes/constants'; +import SafeHtml from '~/vue_shared/directives/safe_html'; +import ResourceParentLink from '../resource_parent_link.vue'; +import ContributionEventBase from './contribution_event_base.vue'; + +export default { + name: 'ContributionEventCommented', + components: { ContributionEventBase, GlSprintf, GlLink, ResourceParentLink }, + directives: { + SafeHtml, + }, + props: { + event: { + type: Object, + required: true, + }, + }, + computed: { + resourceParent() { + return this.event.resource_parent; + }, + noteable() { + return this.event.noteable; + }, + noteableType() { + return this.noteable.type; + }, + message() { + if (this.noteableType === SNIPPET_NOTEABLE_TYPE) { + return ( + EVENT_COMMENTED_SNIPPET_I18N[this.resourceParent?.type] || + EVENT_COMMENTED_SNIPPET_I18N.fallback + ); + } + + return EVENT_COMMENTED_I18N[this.noteableType] || EVENT_COMMENTED_I18N.fallback; + }, + noteableLinkClass() { + if (this.noteableType === COMMIT_NOTEABLE_TYPE) { + return ['gl-font-monospace']; + } + + return []; + }, + }, +}; +</script> + +<template> + <contribution-event-base :event="event" icon-name="comment" icon-class="gl-text-blue-600"> + <gl-sprintf :message="message"> + <template #noteableLink> + <gl-link :class="noteableLinkClass" :href="noteable.web_url">{{ + noteable.reference_link_text + }}</gl-link> + </template> + <template #resourceParentLink> + <resource-parent-link :event="event" /> + </template> + </gl-sprintf> + <template v-if="noteable.first_line_in_markdown" #additional-info> + <div v-safe-html="noteable.first_line_in_markdown" class="md"></div> + </template> + </contribution-event-base> +</template> diff --git a/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_created.vue b/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_created.vue new file mode 100644 index 00000000000..7915cd6679d --- /dev/null +++ b/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_created.vue @@ -0,0 +1,62 @@ +<script> +import { + EVENT_CREATED_I18N, + TARGET_TYPE_DESIGN, + TYPE_FALLBACK, +} from 'ee_else_ce/contribution_events/constants'; +import { getValueByEventTarget } from '../../utils'; +import ContributionEventBase from './contribution_event_base.vue'; + +export default { + name: 'ContributionEventCreated', + components: { ContributionEventBase }, + props: { + event: { + type: Object, + required: true, + }, + }, + computed: { + target() { + return this.event.target; + }, + resourceParent() { + return this.event.resource_parent; + }, + message() { + if (!this.target) { + return EVENT_CREATED_I18N[this.resourceParent.type] || EVENT_CREATED_I18N[TYPE_FALLBACK]; + } + + return getValueByEventTarget(EVENT_CREATED_I18N, this.event); + }, + iconName() { + switch (this.target?.type) { + case TARGET_TYPE_DESIGN: + return 'upload'; + + default: + return 'status_open'; + } + }, + iconClass() { + switch (this.target?.type) { + case TARGET_TYPE_DESIGN: + return null; + + default: + return 'gl-text-green-500'; + } + }, + }, +}; +</script> + +<template> + <contribution-event-base + :event="event" + :message="message" + :icon-name="iconName" + :icon-class="iconClass" + /> +</template> diff --git a/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_reopened.vue b/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_reopened.vue new file mode 100644 index 00000000000..36c65950238 --- /dev/null +++ b/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_reopened.vue @@ -0,0 +1,36 @@ +<script> +import { + EVENT_REOPENED_I18N, + EVENT_REOPENED_ICONS, +} from 'ee_else_ce/contribution_events/constants'; +import { getValueByEventTarget } from '../../utils'; +import ContributionEventBase from './contribution_event_base.vue'; + +export default { + name: 'ContributionEventReopened', + components: { ContributionEventBase }, + props: { + event: { + type: Object, + required: true, + }, + }, + computed: { + message() { + return getValueByEventTarget(EVENT_REOPENED_I18N, this.event); + }, + iconName() { + return getValueByEventTarget(EVENT_REOPENED_ICONS, this.event); + }, + }, +}; +</script> + +<template> + <contribution-event-base + :event="event" + :message="message" + :icon-name="iconName" + icon-class="gl-text-green-500" + /> +</template> diff --git a/app/assets/javascripts/contribution_events/components/contribution_events.vue b/app/assets/javascripts/contribution_events/components/contribution_events.vue index 62c803b9217..8b42d77675f 100644 --- a/app/assets/javascripts/contribution_events/components/contribution_events.vue +++ b/app/assets/javascripts/contribution_events/components/contribution_events.vue @@ -8,6 +8,10 @@ import { EVENT_TYPE_PUSHED, EVENT_TYPE_PRIVATE, EVENT_TYPE_MERGED, + EVENT_TYPE_CREATED, + EVENT_TYPE_CLOSED, + EVENT_TYPE_REOPENED, + EVENT_TYPE_COMMENTED, } from '../constants'; import ContributionEventApproved from './contribution_event/contribution_event_approved.vue'; import ContributionEventExpired from './contribution_event/contribution_event_expired.vue'; @@ -16,6 +20,10 @@ import ContributionEventLeft from './contribution_event/contribution_event_left. import ContributionEventPushed from './contribution_event/contribution_event_pushed.vue'; import ContributionEventPrivate from './contribution_event/contribution_event_private.vue'; import ContributionEventMerged from './contribution_event/contribution_event_merged.vue'; +import ContributionEventCreated from './contribution_event/contribution_event_created.vue'; +import ContributionEventClosed from './contribution_event/contribution_event_closed.vue'; +import ContributionEventReopened from './contribution_event/contribution_event_reopened.vue'; +import ContributionEventCommented from './contribution_event/contribution_event_commented.vue'; export default { props: { @@ -131,6 +139,18 @@ export default { case EVENT_TYPE_MERGED: return ContributionEventMerged; + case EVENT_TYPE_CREATED: + return ContributionEventCreated; + + case EVENT_TYPE_CLOSED: + return ContributionEventClosed; + + case EVENT_TYPE_REOPENED: + return ContributionEventReopened; + + case EVENT_TYPE_COMMENTED: + return ContributionEventCommented; + default: return EmptyComponent; } diff --git a/app/assets/javascripts/contribution_events/components/target_link.vue b/app/assets/javascripts/contribution_events/components/target_link.vue index 6559d6c7272..a14574ed826 100644 --- a/app/assets/javascripts/contribution_events/components/target_link.vue +++ b/app/assets/javascripts/contribution_events/components/target_link.vue @@ -14,7 +14,7 @@ export default { return this.event.target; }, targetLinkText() { - return this.target.reference_link_text; + return this.target.reference_link_text || this.target.title; }, targetLinkAttributes() { return { diff --git a/app/assets/javascripts/contribution_events/constants.js b/app/assets/javascripts/contribution_events/constants.js index d4444e3bede..b5eddbf7e25 100644 --- a/app/assets/javascripts/contribution_events/constants.js +++ b/app/assets/javascripts/contribution_events/constants.js @@ -1,3 +1,11 @@ +import { s__ } from '~/locale'; +import { + ISSUE_NOTEABLE_TYPE, + MERGE_REQUEST_NOTEABLE_TYPE, + DESIGN_NOTEABLE_TYPE, + COMMIT_NOTEABLE_TYPE, +} from '~/notes/constants'; + // From app/models/event.rb#L16 export const EVENT_TYPE_CREATED = 'created'; export const EVENT_TYPE_UPDATED = 'updated'; @@ -16,3 +24,118 @@ export const EVENT_TYPE_PRIVATE = 'private'; // From app/models/push_event_payload.rb#L22 export const PUSH_EVENT_REF_TYPE_BRANCH = 'branch'; export const PUSH_EVENT_REF_TYPE_TAG = 'tag'; + +export const RESOURCE_PARENT_TYPE_PROJECT = 'project'; + +// From app/models/event.rb#L39 +export const TARGET_TYPE_ISSUE = 'Issue'; +export const TARGET_TYPE_MILESTONE = 'Milestone'; +export const TARGET_TYPE_MERGE_REQUEST = 'MergeRequest'; +export const TARGET_TYPE_WIKI = 'WikiPage::Meta'; +export const TARGET_TYPE_DESIGN = 'DesignManagement::Design'; +export const TARGET_TYPE_WORK_ITEM = 'WorkItem'; + +// From app/models/work_items/type.rb#L28 +export const WORK_ITEM_ISSUE_TYPE_ISSUE = 'issue'; +export const WORK_ITEM_ISSUE_TYPE_TASK = 'task'; +export const WORK_ITEM_ISSUE_TYPE_INCIDENT = 'incident'; + +export const TYPE_FALLBACK = 'fallback'; + +export const EVENT_CREATED_I18N = Object.freeze({ + [RESOURCE_PARENT_TYPE_PROJECT]: s__('ContributionEvent|Created project %{resourceParentLink}.'), + [TARGET_TYPE_MILESTONE]: s__( + 'ContributionEvent|Opened milestone %{targetLink} in %{resourceParentLink}.', + ), + [TARGET_TYPE_MERGE_REQUEST]: s__( + 'ContributionEvent|Opened merge request %{targetLink} in %{resourceParentLink}.', + ), + [TARGET_TYPE_WIKI]: s__( + 'ContributionEvent|Created wiki page %{targetLink} in %{resourceParentLink}.', + ), + [TARGET_TYPE_DESIGN]: s__( + 'ContributionEvent|Added design %{targetLink} in %{resourceParentLink}.', + ), + [WORK_ITEM_ISSUE_TYPE_ISSUE]: s__( + 'ContributionEvent|Opened issue %{targetLink} in %{resourceParentLink}.', + ), + [WORK_ITEM_ISSUE_TYPE_TASK]: s__( + 'ContributionEvent|Opened task %{targetLink} in %{resourceParentLink}.', + ), + [WORK_ITEM_ISSUE_TYPE_INCIDENT]: s__( + 'ContributionEvent|Opened incident %{targetLink} in %{resourceParentLink}.', + ), + [TYPE_FALLBACK]: s__('ContributionEvent|Created resource.'), +}); + +export const EVENT_CLOSED_I18N = Object.freeze({ + [TARGET_TYPE_MILESTONE]: s__( + 'ContributionEvent|Closed milestone %{targetLink} in %{resourceParentLink}.', + ), + [TARGET_TYPE_MERGE_REQUEST]: s__( + 'ContributionEvent|Closed merge request %{targetLink} in %{resourceParentLink}.', + ), + [WORK_ITEM_ISSUE_TYPE_ISSUE]: s__( + 'ContributionEvent|Closed issue %{targetLink} in %{resourceParentLink}.', + ), + [WORK_ITEM_ISSUE_TYPE_TASK]: s__( + 'ContributionEvent|Closed task %{targetLink} in %{resourceParentLink}.', + ), + [WORK_ITEM_ISSUE_TYPE_INCIDENT]: s__( + 'ContributionEvent|Closed incident %{targetLink} in %{resourceParentLink}.', + ), + [TYPE_FALLBACK]: s__('ContributionEvent|Closed resource.'), +}); + +export const EVENT_REOPENED_I18N = Object.freeze({ + [TARGET_TYPE_MILESTONE]: s__( + 'ContributionEvent|Reopened milestone %{targetLink} in %{resourceParentLink}.', + ), + [TARGET_TYPE_MERGE_REQUEST]: s__( + 'ContributionEvent|Reopened merge request %{targetLink} in %{resourceParentLink}.', + ), + [WORK_ITEM_ISSUE_TYPE_ISSUE]: s__( + 'ContributionEvent|Reopened issue %{targetLink} in %{resourceParentLink}.', + ), + [WORK_ITEM_ISSUE_TYPE_TASK]: s__( + 'ContributionEvent|Reopened task %{targetLink} in %{resourceParentLink}.', + ), + [WORK_ITEM_ISSUE_TYPE_INCIDENT]: s__( + 'ContributionEvent|Reopened incident %{targetLink} in %{resourceParentLink}.', + ), + [TYPE_FALLBACK]: s__('ContributionEvent|Reopened resource.'), +}); + +export const EVENT_COMMENTED_I18N = Object.freeze({ + [ISSUE_NOTEABLE_TYPE]: s__( + 'ContributionEvent|Commented on issue %{noteableLink} in %{resourceParentLink}.', + ), + [MERGE_REQUEST_NOTEABLE_TYPE]: s__( + 'ContributionEvent|Commented on merge request %{noteableLink} in %{resourceParentLink}.', + ), + [DESIGN_NOTEABLE_TYPE]: s__( + 'ContributionEvent|Commented on design %{noteableLink} in %{resourceParentLink}.', + ), + [COMMIT_NOTEABLE_TYPE]: s__( + 'ContributionEvent|Commented on commit %{noteableLink} in %{resourceParentLink}.', + ), + fallback: s__('ContributionEvent|Commented on %{noteableLink}.'), +}); + +export const EVENT_COMMENTED_SNIPPET_I18N = Object.freeze({ + [RESOURCE_PARENT_TYPE_PROJECT]: s__( + 'ContributionEvent|Commented on snippet %{noteableLink} in %{resourceParentLink}.', + ), + fallback: s__('ContributionEvent|Commented on snippet %{noteableLink}.'), +}); + +export const EVENT_CLOSED_ICONS = Object.freeze({ + [WORK_ITEM_ISSUE_TYPE_ISSUE]: 'issue-closed', + [TARGET_TYPE_MERGE_REQUEST]: 'merge-request-close', + [TYPE_FALLBACK]: 'status_closed', +}); + +export const EVENT_REOPENED_ICONS = Object.freeze({ + [TARGET_TYPE_MERGE_REQUEST]: 'merge-request-open', + [TYPE_FALLBACK]: 'status_open', +}); diff --git a/app/assets/javascripts/contribution_events/utils.js b/app/assets/javascripts/contribution_events/utils.js new file mode 100644 index 00000000000..0760b5187c6 --- /dev/null +++ b/app/assets/javascripts/contribution_events/utils.js @@ -0,0 +1,9 @@ +import { TYPE_FALLBACK } from './constants'; + +export const getValueByEventTarget = (map, event) => { + const { + target: { type: targetType, issue_type: issueType }, + } = event; + + return map[issueType || targetType] || map[TYPE_FALLBACK]; +}; |