diff options
author | Rémy Coutable <remy@rymai.me> | 2016-06-30 18:34:19 +0300 |
---|---|---|
committer | Rémy Coutable <remy@rymai.me> | 2016-08-13 01:05:57 +0300 |
commit | 0eea8c885743575b0e93a98846b3663e9903aa66 (patch) | |
tree | 9b1903bcb03789d15ed255b76be5d683f3b1e547 /app/services/slash_commands | |
parent | 11eefba891f214eefc1efa334adbcc9e979c0ce3 (diff) |
Support slash commands in noteable description and notes
Some important things to note:
- commands are removed from noteable.description / note.note
- commands are translated to params so that they are treated as normal
params in noteable Creation services
- the logic is not in the models but in the Creation services, which is
the right place for advanced logic that has nothing to do with what
models should be responsible of!
- UI/JS needs to be updated to handle notes which consist of commands
only
- the `/merge` command is not handled yet
Other improvements:
- Don't process commands in commit notes and display a flash is note is only commands
- Add autocomplete for slash commands
- Add description and params to slash command DSL methods
- Ensure replying by email with a commands-only note works
- Use :subscription_event instead of calling noteable.subscribe
- Support :todo_event in IssuableBaseService
Signed-off-by: Rémy Coutable <remy@rymai.me>
Diffstat (limited to 'app/services/slash_commands')
-rw-r--r-- | app/services/slash_commands/interpret_service.rb | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/app/services/slash_commands/interpret_service.rb b/app/services/slash_commands/interpret_service.rb new file mode 100644 index 00000000000..2c92a4f7de5 --- /dev/null +++ b/app/services/slash_commands/interpret_service.rb @@ -0,0 +1,133 @@ +module SlashCommands + class InterpretService < BaseService + include Gitlab::SlashCommands::Dsl + + # Takes a text and interpret the commands that are extracted from it. + # Returns a hash of changes to be applied to a record. + def execute(content) + @updates = {} + + commands = extractor.extract_commands!(content) + commands.each do |command| + __send__(*command) + end + + @updates + end + + private + + def extractor + @extractor ||= Gitlab::SlashCommands::Extractor.new(self.class.command_names) + end + + desc 'Close this issue or merge request' + command :close do + @updates[:state_event] = 'close' + end + + desc 'Reopen this issue or merge request' + command :open, :reopen do + @updates[:state_event] = 'reopen' + end + + desc 'Reassign' + params '@user' + command :assign, :reassign do |assignee_param| + user = extract_references(assignee_param, :user).first + return unless user + + @updates[:assignee_id] = user.id + end + + desc 'Remove assignee' + command :unassign, :remove_assignee do + @updates[:assignee_id] = nil + end + + desc 'Change milestone' + params '%"milestone"' + command :milestone do |milestone_param| + milestone = extract_references(milestone_param, :milestone).first + return unless milestone + + @updates[:milestone_id] = milestone.id + end + + desc 'Remove milestone' + command :clear_milestone, :remove_milestone do + @updates[:milestone_id] = nil + end + + desc 'Add label(s)' + params '~label1 ~"label 2"' + command :label, :labels do |labels_param| + label_ids = find_label_ids(labels_param) + return if label_ids.empty? + + @updates[:add_label_ids] = label_ids + end + + desc 'Remove label(s)' + params '~label1 ~"label 2"' + command :unlabel, :remove_label, :remove_labels do |labels_param| + label_ids = find_label_ids(labels_param) + return if label_ids.empty? + + @updates[:remove_label_ids] = label_ids + end + + desc 'Remove all labels' + command :clear_labels, :clear_label do + @updates[:label_ids] = [] + end + + desc 'Add a todo' + command :todo do + @updates[:todo_event] = 'mark' + end + + desc 'Mark todo as done' + command :done do + @updates[:todo_event] = 'done' + end + + desc 'Subscribe' + command :subscribe do + @updates[:subscription_event] = 'subscribe' + end + + desc 'Unsubscribe' + command :unsubscribe do + @updates[:subscription_event] = 'unsubscribe' + end + + desc 'Set a due date' + params '<YYYY-MM-DD> | <N days>' + command :due_date do |due_date_param| + due_date = begin + Time.now + ChronicDuration.parse(due_date_param) + rescue ChronicDuration::DurationParseError + Date.parse(due_date_param) rescue nil + end + + @updates[:due_date] = due_date if due_date + end + + desc 'Remove due date' + command :clear_due_date do + @updates[:due_date] = nil + end + + def find_label_ids(labels_param) + extract_references(labels_param, :label).map(&:id) + end + + def extract_references(cmd_arg, type) + ext = Gitlab::ReferenceExtractor.new(project, current_user) + ext.analyze(cmd_arg, author: current_user) + + ext.references(type) + end + end +end |