Commit ea090291 authored by Eric Eastwood's avatar Eric Eastwood

Rename "Slash commands" to "Quick actions"

Fix https://gitlab.com/gitlab-org/gitlab-ce/issues/27070

Deprecate "chat commands" in favor of "slash commands"

We looked for things like:

 - `slash commmand`
 - `slash_command`
 - `slash-command`
 - `SlashCommand`
parent 42aaae99
......@@ -34,7 +34,7 @@ class GfmAutoComplete {
const $input = $(input);
$input.off('focus.setupAtWho').on('focus.setupAtWho', this.setupAtWho.bind(this, $input));
// This triggers at.js again
// Needed for slash commands with suffixes (ex: /label ~)
// Needed for quick actions with suffixes (ex: /label ~)
$input.on('inserted-commands.atwho', $input.trigger.bind($input, 'keyup'));
$input.on('clear-commands-cache.atwho', () => this.clearCache());
});
......@@ -48,8 +48,8 @@ class GfmAutoComplete {
if (this.enableMap.mergeRequests) this.setupMergeRequests($input);
if (this.enableMap.labels) this.setupLabels($input);
// We don't instantiate the slash commands autocomplete for note and issue/MR edit forms
$input.filter('[data-supports-slash-commands="true"]').atwho({
// We don't instantiate the quick actions autocomplete for note and issue/MR edit forms
$input.filter('[data-supports-quick-actions="true"]').atwho({
at: '/',
alias: 'commands',
searchKey: 'search',
......
......@@ -41,7 +41,7 @@
<textarea
id="issue-description"
class="note-textarea js-gfm-input js-autosize markdown-area"
data-supports-slash-commands="false"
data-supports-quick-actionss="false"
aria-label="Description"
v-model="formState.description"
ref="textarea"
......
......@@ -32,7 +32,7 @@ const normalizeNewlines = function(str) {
(function() {
this.Notes = (function() {
const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
const REGEX_SLASH_COMMANDS = /^\/\w+.*$/gm;
const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
Notes.interval = null;
......@@ -280,7 +280,7 @@ const normalizeNewlines = function(str) {
return this.initRefresh();
};
Notes.prototype.handleSlashCommands = function(noteEntity) {
Notes.prototype.handleQuickActions = function(noteEntity) {
var votesBlock;
if (noteEntity.commands_changes) {
if ('merge' in noteEntity.commands_changes) {
......@@ -1198,27 +1198,27 @@ const normalizeNewlines = function(str) {
};
/**
* Identify if comment has any slash commands
* Identify if comment has any quick actions
*/
Notes.prototype.hasSlashCommands = function(formContent) {
return REGEX_SLASH_COMMANDS.test(formContent);
Notes.prototype.hasQuickActions = function(formContent) {
return REGEX_QUICK_ACTIONS.test(formContent);
};
/**
* Remove slash commands and leave comment with pure message
* Remove quick actions and leave comment with pure message
*/
Notes.prototype.stripSlashCommands = function(formContent) {
return formContent.replace(REGEX_SLASH_COMMANDS, '').trim();
Notes.prototype.stripQuickActions = function(formContent) {
return formContent.replace(REGEX_QUICK_ACTIONS, '').trim();
};
/**
* Gets appropriate description from slash commands found in provided `formContent`
* Gets appropriate description from quick actions found in provided `formContent`
*/
Notes.prototype.getSlashCommandDescription = function (formContent, availableSlashCommands = []) {
Notes.prototype.getQuickActionDescription = function (formContent, availableQuickActions = []) {
let tempFormContent;
// Identify executed slash commands from `formContent`
const executedCommands = availableSlashCommands.filter((command, index) => {
// Identify executed quick actions from `formContent`
const executedCommands = availableQuickActions.filter((command, index) => {
const commandRegex = new RegExp(`/${command.name}`);
return commandRegex.test(formContent);
});
......@@ -1276,7 +1276,7 @@ const normalizeNewlines = function(str) {
};
/**
* Create Placeholder System Note DOM element populated with slash command description
* Create Placeholder System Note DOM element populated with quick action description
*/
Notes.prototype.createPlaceholderSystemNote = function ({ formContent, uniqueId }) {
const $tempNote = $(
......@@ -1325,7 +1325,7 @@ const normalizeNewlines = function(str) {
const { formData, formContent, formAction } = this.getFormData($form);
let noteUniqueId;
let systemNoteUniqueId;
let hasSlashCommands = false;
let hasQuickActions = false;
let $notesContainer;
let tempFormContent;
......@@ -1344,9 +1344,9 @@ const normalizeNewlines = function(str) {
}
tempFormContent = formContent;
if (this.hasSlashCommands(formContent)) {
tempFormContent = this.stripSlashCommands(formContent);
hasSlashCommands = true;
if (this.hasQuickActions(formContent)) {
tempFormContent = this.stripQuickActions(formContent);
hasQuickActions = true;
}
// Show placeholder note
......@@ -1363,10 +1363,10 @@ const normalizeNewlines = function(str) {
}
// Show placeholder system note
if (hasSlashCommands) {
if (hasQuickActions) {
systemNoteUniqueId = _.uniqueId('tempSystemNote_');
$notesContainer.append(this.createPlaceholderSystemNote({
formContent: this.getSlashCommandDescription(formContent, AjaxCache.get(gl.GfmAutoComplete.dataSources.commands)),
formContent: this.getQuickActionDescription(formContent, AjaxCache.get(gl.GfmAutoComplete.dataSources.commands)),
uniqueId: systemNoteUniqueId,
}));
}
......@@ -1388,7 +1388,7 @@ const normalizeNewlines = function(str) {
$notesContainer.find(`#${noteUniqueId}`).remove();
// Reset cached commands list when command is applied
if (hasSlashCommands) {
if (hasQuickActions) {
$form.find('textarea.js-note-text').trigger('clear-commands-cache.atwho');
}
......@@ -1422,7 +1422,7 @@ const normalizeNewlines = function(str) {
}
if (note.commands_changes) {
this.handleSlashCommands(note);
this.handleQuickActions(note);
}
$form.trigger('ajax:success', [note]);
......@@ -1430,7 +1430,7 @@ const normalizeNewlines = function(str) {
// Submission failed, remove placeholder note and show Flash error message
$notesContainer.find(`#${noteUniqueId}`).remove();
if (hasSlashCommands) {
if (hasQuickActions) {
$notesContainer.find(`#${systemNoteUniqueId}`).remove();
}
......
......@@ -3,7 +3,7 @@
// MarkdownPreview
//
// Handles toggling the "Write" and "Preview" tab clicks, rendering the preview
// (including the explanation of slash commands), and showing a warning when
// (including the explanation of quick actions), and showing a warning when
// more than `x` users are referenced.
//
(function () {
......
......@@ -15,10 +15,10 @@ export default {
<div class="time-tracking-help-state">
<div class="time-tracking-info">
<h4>
Track time with slash commands
Track time with quick actions
</h4>
<p>
Slash commands can be used in the issues description and comment boxes.
Quick actions can be used in the issues description and comment boxes.
</p>
<p>
<code>
......
......@@ -16,10 +16,10 @@ export default {
'issuable-time-tracker': timeTracker,
},
methods: {
listenForSlashCommands() {
$(document).on('ajax:success', '.gfm-form', this.slashCommandListened);
listenForQuickActions() {
$(document).on('ajax:success', '.gfm-form', this.quickActionListened);
},
slashCommandListened(e, data) {
quickActionListened(e, data) {
const subscribedCommands = ['spend_time', 'time_estimate'];
let changedCommands;
if (data !== undefined) {
......@@ -35,7 +35,7 @@ export default {
},
},
mounted() {
this.listenForSlashCommands();
this.listenForQuickActions();
},
template: `
<div class="block">
......
......@@ -10,8 +10,8 @@ module NotesHelper
Ability.can_edit_note?(current_user, note)
end
def note_supports_slash_commands?(note)
Notes::SlashCommandsService.supported?(note, current_user)
def note_supports_quick_actions?(note)
Notes::QuickActionsService.supported?(note, current_user)
end
def noteable_json(noteable)
......
......@@ -889,7 +889,7 @@ class MergeRequest < ActiveRecord::Base
!has_commits?
end
def mergeable_with_slash_command?(current_user, autocomplete_precheck: false, last_diff_sha: nil)
def mergeable_with_quick_action?(current_user, autocomplete_precheck: false, last_diff_sha: nil)
return false unless can_be_merged_by?(current_user)
return true if autocomplete_precheck
......
......@@ -32,7 +32,7 @@ class Note < ActiveRecord::Base
# Banzai::ObjectRenderer
attr_accessor :user_visible_reference_count
# Attribute used to store the attributes that have ben changed by slash commands.
# Attribute used to store the attributes that have ben changed by quick actions.
attr_accessor :commands_changes
default_value_for :system, false
......
class MattermostSlashCommandsService < ChatSlashCommandsService
class MattermostSlashCommandsService < SlashCommandsService
include TriggersHelper
prop_accessor :token
......
class SlackSlashCommandsService < ChatSlashCommandsService
class SlackSlashCommandsService < SlashCommandsService
include TriggersHelper
def title
......
# Base class for Chat services
# This class is not meant to be used directly, but only to inherrit from.
class ChatSlashCommandsService < Service
class SlashCommandsService < Service
default_value_for :category, 'chat'
prop_accessor :token
......@@ -33,10 +33,10 @@ class ChatSlashCommandsService < Service
user = find_chat_user(params)
if user
Gitlab::ChatCommands::Command.new(project, user, params).execute
Gitlab::SlashCommands::Command.new(project, user, params).execute
else
url = authorize_chat_name_url(params)
Gitlab::ChatCommands::Presenters::Access.new(url).authorize
Gitlab::SlashCommands::Presenters::Access.new(url).authorize
end
end
......
......@@ -10,7 +10,7 @@ class GlobalPolicy < BasePolicy
can! :access_api
can! :access_git
can! :receive_notifications
can! :use_slash_commands
can! :use_quick_actions
end
end
end
......@@ -142,9 +142,9 @@ class IssuableBaseService < BaseService
LabelsFinder.new(current_user, project_id: @project.id).execute
end
def merge_slash_commands_into_params!(issuable)
def merge_quick_actions_into_params!(issuable)
description, command_params =
SlashCommands::InterpretService.new(project, current_user).
QuickActions::InterpretService.new(project, current_user).
execute(params[:description], issuable)
# Avoid a description already set on an issuable to be overwritten by a nil
......@@ -162,7 +162,7 @@ class IssuableBaseService < BaseService
end
def create(issuable)
merge_slash_commands_into_params!(issuable)
merge_quick_actions_into_params!(issuable)
filter_params(issuable)
params.delete(:state_event)
......
......@@ -7,7 +7,7 @@ module MergeRequests
params.except!(:target_project_id)
params.except!(:source_branch)
merge_from_slash_command(merge_request) if params[:merge]
merge_from_quick_action(merge_request) if params[:merge]
if merge_request.closed_without_fork?
params.except!(:target_branch, :force_remove_source_branch)
......@@ -74,9 +74,9 @@ module MergeRequests
end
end
def merge_from_slash_command(merge_request)
def merge_from_quick_action(merge_request)
last_diff_sha = params.delete(:merge)
return unless merge_request.mergeable_with_slash_command?(current_user, last_diff_sha: last_diff_sha)
return unless merge_request.mergeable_with_quick_action?(current_user, last_diff_sha: last_diff_sha)
merge_request.update(merge_error: nil)
......
......@@ -9,11 +9,11 @@ module Notes
# We execute commands (extracted from `params[:note]`) on the noteable
# **before** we save the note because if the note consists of commands
# only, there is no need be create a note!
slash_commands_service = SlashCommandsService.new(project, current_user)
quick_actions_service = QuickActionsService.new(project, current_user)
if slash_commands_service.supported?(note)
if quick_actions_service.supported?(note)
options = { merge_request_diff_head_sha: merge_request_diff_head_sha }
content, command_params = slash_commands_service.extract_commands(note, options)
content, command_params = quick_actions_service.extract_commands(note, options)
only_commands = content.empty?
......@@ -30,7 +30,7 @@ module Notes
end
if command_params.present?
slash_commands_service.execute(command_params, note)
quick_actions_service.execute(command_params, note)
# We must add the error after we call #save because errors are reset
# when #save is called
......
module Notes
class SlashCommandsService < BaseService
class QuickActionsService < BaseService
UPDATE_SERVICES = {
'Issue' => Issues::UpdateService,
'MergeRequest' => MergeRequests::UpdateService
......@@ -22,7 +22,7 @@ module Notes
def extract_commands(note, options = {})
return [note.note, {}] unless supported?(note)
SlashCommands::InterpretService.new(project, current_user, options).
QuickActions::InterpretService.new(project, current_user, options).
execute(note.note, note.noteable)
end
......
class PreviewMarkdownService < BaseService
def execute
text, commands = explain_slash_commands(params[:text])
text, commands = explain_quick_actions(params[:text])
users = find_user_references(text)
success(
......@@ -12,11 +12,11 @@ class PreviewMarkdownService < BaseService
private
def explain_slash_commands(text)
def explain_quick_actions(text)
return text, [] unless %w(Issue MergeRequest).include?(commands_target_type)
slash_commands_service = SlashCommands::InterpretService.new(project, current_user)
slash_commands_service.explain(text, find_commands_target)
quick_actions_service = QuickActions::InterpretService.new(project, current_user)
quick_actions_service.explain(text, find_commands_target)
end
def find_user_references(text)
......@@ -36,10 +36,10 @@ class PreviewMarkdownService < BaseService
end
def commands_target_type
params[:slash_commands_target_type]
params[:quick_actions_target_type]
end
def commands_target_id
params[:slash_commands_target_id]
params[:quick_actions_target_id]
end
end
......@@ -32,7 +32,7 @@ module Projects
issuable: noteable,
current_user: current_user
}
SlashCommands::InterpretService.command_definitions.map do |definition|
QuickActions::InterpretService.command_definitions.map do |definition|
next unless definition.available?(opts)
definition.to_h(opts)
......
module SlashCommands
module QuickActions
class InterpretService < BaseService
include Gitlab::SlashCommands::Dsl
include Gitlab::QuickActions::Dsl
attr_reader :issuable
# Takes a text and interprets the commands that are extracted from it.
# Returns the content without commands, and hash of changes to be applied to a record.
def execute(content, issuable)
return [content, {}] unless current_user.can?(:use_slash_commands)
return [content, {}] unless current_user.can?(:use_quick_actions)
@issuable = issuable
@updates = {}
......@@ -20,7 +20,7 @@ module SlashCommands
# Takes a text and interprets the commands that are extracted from it.
# Returns the content without commands, and array of changes explained.
def explain(content, issuable)
return [content, []] unless current_user.can?(:use_slash_commands)
return [content, []] unless current_user.can?(:use_quick_actions)
@issuable = issuable
......@@ -32,7 +32,7 @@ module SlashCommands
private
def extractor
Gitlab::SlashCommands::Extractor.new(self.class.command_definitions)
Gitlab::QuickActions::Extractor.new(self.class.command_definitions)
end
desc do
......@@ -71,7 +71,7 @@ module SlashCommands
last_diff_sha = params && params[:merge_request_diff_head_sha]
issuable.is_a?(MergeRequest) &&
issuable.persisted? &&
issuable.mergeable_with_slash_command?(current_user, autocomplete_precheck: !last_diff_sha, last_diff_sha: last_diff_sha)
issuable.mergeable_with_quick_action?(current_user, autocomplete_precheck: !last_diff_sha, last_diff_sha: last_diff_sha)
end
command :merge do
@updates[:merge] = params[:merge_request_diff_head_sha]
......
- @gfm_form = true
- current_text ||= nil
- supports_slash_commands = local_assigns.fetch(:supports_slash_commands, false)
- supports_quick_actions = local_assigns.fetch(:supports_quick_actions, false)
.zen-backdrop
- classes << ' js-gfm-input js-autosize markdown-area'
- if defined?(f) && f
= f.text_area attr, class: classes, placeholder: placeholder, data: { supports_slash_commands: supports_slash_commands }
= f.text_area attr, class: classes, placeholder: placeholder, data: { supports_quick_actions: supports_quick_actions }
- else
= text_area_tag attr, current_text, class: classes, placeholder: placeholder
%a.zen-control.zen-control-leave.js-zen-leave{ href: "#" }
......
......@@ -20,7 +20,7 @@
%p
The subject will be used as the title of the new issue, and the message will be the description.
= link_to 'Slash commands', help_page_path('user/project/slash_commands'), target: '_blank', tabindex: -1
= link_to 'Quick actions', help_page_path('user/project/quick_actions'), target: '_blank', tabindex: -1
and styling with
= link_to 'Markdown', help_page_path('user/markdown'), target: '_blank', tabindex: -1
are supported.
......
......@@ -2,10 +2,10 @@
- model = local_assigns.fetch(:model)
- form = local_assigns.fetch(:form)
- supports_slash_commands = model.new_record?
- supports_quick_actions = model.new_record?
- if supports_slash_commands
- preview_url = preview_markdown_path(project, slash_commands_target_type: model.class.name)
- if supports_quick_actions
- preview_url = preview_markdown_path(project, quick_actions_target_type: model.class.name)
- else
- preview_url = preview_markdown_path(project)
......@@ -17,7 +17,7 @@
= render 'projects/zen', f: form, attr: :description,
classes: 'note-textarea',
placeholder: "Write a comment or drag your files here...",
supports_slash_commands: supports_slash_commands
= render 'shared/notes/hints', supports_slash_commands: supports_slash_commands
supports_quick_actions: supports_quick_actions
= render 'shared/notes/hints', supports_quick_actions: supports_quick_actions
.clearfix
.error-alert
- supports_slash_commands = note_supports_slash_commands?(@note)
- if supports_slash_commands
- preview_url = preview_markdown_path(@project, slash_commands_target_type: @note.noteable_type, slash_commands_target_id: @note.noteable_id)
- supports_quick_actions = note_supports_quick_actions?(@note)
- if supports_quick_actions
- preview_url = preview_markdown_path(@project, quick_actions_target_type: @note.noteable_type, quick_actions_target_id: @note.noteable_id)
- else
- preview_url = preview_markdown_path(@project)
......@@ -27,8 +27,8 @@
attr: :note,
classes: 'note-textarea js-note-text',
placeholder: "Write a comment or drag your files here...",
supports_slash_commands: supports_slash_commands
= render 'shared/notes/hints', supports_slash_commands: supports_slash_commands
supports_quick_actions: supports_quick_actions
= render 'shared/notes/hints', supports_quick_actions: supports_quick_actions
.error-alert
.note-form-actions.clearfix
......
- supports_slash_commands = local_assigns.fetch(:supports_slash_commands, false)
- supports_quick_actions = local_assigns.fetch(:supports_quick_actions, false)
.comment-toolbar.clearfix
.toolbar-text
= link_to 'Markdown', help_page_path('user/markdown'), target: '_blank', tabindex: -1
- if supports_slash_commands
- if supports_quick_actions
and
= link_to 'slash commands', help_page_path('user/project/slash_commands'), target: '_blank', tabindex: -1
= link_to 'quick actions', help_page_path('user/project/quick_actions'), target: '_blank', tabindex: -1
are
- else
is
......
---
title: Rename "Slash commands" to "Quick actions" and deprecate "chat commands" in favor
of "slash commands"
merge_request:
author:
......@@ -24,7 +24,7 @@ Shortcuts to GitLab's most visited docs:
- [GitLab Workflow](workflow/README.md): Enhance your workflow with the best of GitLab Workflow.
- See also [GitLab Workflow - an overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/).
- [GitLab Markdown](user/markdown.md): GitLab's advanced formatting system (GitLab Flavored Markdown).
- [GitLab Slash Commands](user/project/slash_commands.md): Textual shortcuts for common actions on issues or merge requests that are usually done by clicking buttons or dropdowns in GitLab's UI.
- [GitLab Quick Actions](user/project/quick_actions.md): Textual shortcuts for common actions on issues or merge requests that are usually done by clicking buttons or dropdowns in GitLab's UI.
### User account
......
......@@ -166,8 +166,8 @@ For instance this kind of thing:
= render 'projects/zen', f: form, attr: :description,
classes: 'note-textarea',
placeholder: "Write a comment or drag your files here...",
supports_slash_commands: !issuable.persisted?
= render 'projects/notes/hints', supports_slash_commands: !issuable.persisted?
supports_quick_actions: !issuable.persisted?
= render 'projects/notes/hints', supports_quick_actions: !issuable.persisted?
.clearfix
.error-alert
- if issuable.is_a?(Issue)
......
# Chat Commands
Chat commands in Mattermost and Slack (also called Slack slash commands) allow you to control GitLab and view GitLab content right inside your chat client, without having to leave it. For Slack, this requires a [project service configuration](../user/project/integrations/slack_slash_commands.md). Simply type the command as a message in your chat client to activate it.
Commands are scoped to a project, with a trigger term that is specified during configuration. (We suggest you use the project name as the trigger term for simplicty and clarity.) Taking the trigger term as `project-name`, the commands are:
| Command | Effect |
| ------- | ------ |
| `/project-name help` | Shows all available chat commands |
| `/project-name issue new <title> <shift+return> <description>` | Creates a new issue with title `<title>` and description `<description>` |
| `/project-name issue show <id>` | Shows the issue with id `<id>` |
| `/project-name issue search <query>` | Shows up to 5 issues matching `<query>` |
| `/project-name deploy <from> to <to>` | Deploy from the `<from>` environment to the `<to>` environment |
\ No newline at end of file
This document was moved to [integration/slash_commands.md](slash_commands.md).
# Slash Commands
Slash commands in Mattermost and Slack allow you to control GitLab and view GitLab content right inside your chat client, without having to leave it. For Slack, this requires a [project service configuration](../user/project/integrations/slack_slash_commands.md). Simply type the command as a message in your chat client to activate it.
Commands are scoped to a project, with a trigger term that is specified during configuration. (We suggest you use the project name as the trigger term for simplicty and clarity.) Taking the trigger term as `project-name`, the commands are:
| Command | Effect |
| ------- | ------ |
| `/project-name help` | Shows all available slash commands |
| `/project-name issue new <title> <shift+return> <description>` | Creates a new issue with title `<title>` and description `<description>` |
| `/project-name issue show <id>` | Shows the issue with id `<id>` |
| `/project-name issue search <query>` | Shows up to 5 issues matching `<query>` |
| `/project-name deploy <from> to <to>` | Deploy from the `<from>` environment to the `<to>` environment |
......@@ -10,7 +10,7 @@ You can leave a comment in the following places:
- commits
- commit diffs
The comment area supports [Markdown] and [slash commands]. One can edit their
The comment area supports [Markdown] and [quick actions]. One can edit their
own comment at any time, and anyone with [Master access level][permissions] or
higher can also edit a comment made by someone else.
......@@ -146,5 +146,5 @@ comments in greater detail.
[discussion-view]: img/discussion_view.png
[discussions-resolved]: img/discussions_resolved.png
[markdown]: ../markdown.md
[slash commands]: ../project/slash_commands.md
[quick actions]: ../project/quick_actions.md
[permissions]: ../permissions.md
......@@ -2,7 +2,7 @@
> Introduced in GitLab 8.15
Slack slash commands (also known as chat commmands) allow you to control GitLab and view content right inside Slack, without having to leave it. This requires configurations in both Slack and GitLab.
Slack slash commands allow you to control GitLab and view content right inside Slack, without having to leave it. This requires configurations in both Slack and GitLab.
> Note: GitLab can also send events (e.g. issue created) to Slack as notifications. This is the separately configured [Slack Notifications Service](slack.md).
......@@ -20,4 +20,4 @@ Slack slash commands (also known as chat commmands) allow you to control GitLab
## Usage
You can now use the [Slack slash commands](../../../integration/chat_commands.md).
\ No newline at end of file
You can now use the [Slack slash commands](../../../integration/slash_commands.md).
......@@ -68,7 +68,7 @@ This feature is available only in [GitLab Enterprise Edition](https://about.gitl
- Spend: add the time spent on the implementation of that issue
> **Note:**
both estimate and spend times are set via [GitLab Slash Commands](../slash_commands.md).
both estimate and spend times are set via [GitLab Quick Actions](../quick_actions.md).
Learn more on the [Time Tracking documentation](https://docs.gitlab.com/ee/workflow/time_tracking.html).
......@@ -147,7 +147,7 @@ or in the issue thread.
#### 15. Award emoji
- Award an emoji to that issue.
- Award an emoji to that issue.
> **Tip:**
Posting "+1" as comments in threads spam all
......
# GitLab quick actions
Quick actions are textual shortcuts for common actions on issues or merge
requests that are usually done by clicking buttons or dropdowns in GitLab's UI.
You can enter these commands while creating a new issue or merge request, and
in comments. Each command should be on a separate line in order to be properly
detected and executed. The commands are removed from the issue, merge request or
comment body before it is saved and will not be visible to anyone else.
Below is a list of all of the available commands and descriptions about what they
do.
| Command | Action |
|:---------------------------|:-------------|
| `/close` | Close the issue or merge request |
| `/reopen` | Reopen the issue or merge request |
| `/merge` | Merge (when pipeline succeeds) |
| `/title <New title>` | Change title |
| `/assign @username` | Assign |
| `/unassign` | Remove assignee |
| `/milestone %milestone` | Set milestone |
| `/remove_milestone` | Remove milestone |
| `/label ~foo ~"bar baz"` | Add label(s) |
| `/unlabel ~foo ~"bar baz"` | Remove all or specific label(s) |
| `/relabel ~foo ~"bar baz"` | Replace all label(s) |
| `/todo` | Add a todo |
| `/done` | Mark todo as done |
| `/subscribe` | Subscribe |
| `/unsubscribe` | Unsubscribe |
| <code>/due &lt;in 2 days &#124; this Friday &#124; December 31st&gt;</code> | Set due date |
| `/remove_due_date` | Remove due date |
| `/wip` | Toggle the Work In Progress status |
| <code>/estimate &lt;1w 3d 2h 14m&gt;</code> | Set time estimate |
| `/remove_estimate` | Remove estimated time |
| <code>/spend &lt;1h 30m &#124; -1h 5m&gt;</code> | Add or subtract spent time |
| `/remove_time_spent` | Remove time spent |
| `/target_branch <Branch Name>` | Set target branch for current merge request |
| `/award :emoji:` | Toggle award for :emoji: |
| `/board_move ~column` | Move issue to column on the board |