From 53835ec00875dd5600e65e56e81108446beb67a1 Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Sat, 30 Jul 2016 08:59:32 -0600 Subject: [PATCH 1/3] Initial implementation of note templates. Only parts of it work at the moment. Based off Adam Butler's original implementation in !3516. --- app/assets/javascripts/dispatcher.js.es6 | 5 ++ app/assets/javascripts/dropzone_input.js | 2 +- .../note_template_dropdown_create.js.es6 | 18 ++++++ app/assets/javascripts/note_templates.js.es6 | 37 ++++++++++++ app/assets/javascripts/project.js | 4 +- .../stylesheets/framework/dropdowns.scss | 9 +++ .../profiles/note_templates_controller.rb | 60 +++++++++++++++++++ app/controllers/profiles_controller.rb | 14 +++++ app/models/note_template.rb | 4 ++ app/models/user.rb | 1 + app/views/layouts/nav/_profile.html.haml | 4 ++ .../profiles/note_templates/_form.html.haml | 45 ++++++++++++++ .../profiles/note_templates/edit.html.haml | 7 +++ .../profiles/note_templates/index.html.haml | 29 +++++++++ app/views/projects/_md_preview.html.haml | 18 +++++- app/views/projects/_zen.html.haml | 2 + app/views/projects/notes/_hints.html.haml | 7 ++- app/views/projects/wikis/_form.html.haml | 2 +- config/routes/profile.rb | 2 + .../20160730140922_create_note_templates.rb | 36 +++++++++++ db/schema.rb | 10 ++++ .../note_templates_controller_spec.rb | 31 ++++++++++ spec/factories/note_templates.rb | 7 +++ spec/models/note_template_spec.rb | 13 ++++ spec/routing/routing_spec.rb | 6 ++ 25 files changed, 365 insertions(+), 8 deletions(-) create mode 100644 app/assets/javascripts/note_template_dropdown_create.js.es6 create mode 100644 app/assets/javascripts/note_templates.js.es6 create mode 100644 app/controllers/profiles/note_templates_controller.rb create mode 100644 app/models/note_template.rb create mode 100644 app/views/profiles/note_templates/_form.html.haml create mode 100644 app/views/profiles/note_templates/edit.html.haml create mode 100644 app/views/profiles/note_templates/index.html.haml create mode 100644 db/migrate/20160730140922_create_note_templates.rb create mode 100644 spec/controllers/profiles/note_templates_controller_spec.rb create mode 100644 spec/factories/note_templates.rb create mode 100644 spec/models/note_template_spec.rb diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index 99a34651639b..05f745b9258a 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -275,6 +275,10 @@ case 'ci:lints:show': new gl.CILintEditor(); break; + case 'profiles:note_templates:index': + case 'profiles:note_templates:edit': + new GLForm($('.js-note-template-form')); + break; } switch (path.first()) { case 'admin': @@ -308,6 +312,7 @@ case 'projects': new Project(); new ProjectAvatar(); + new gl.NoteTemplateDropdownsCreate(); switch (path[1]) { case 'compare': new CompareAutocomplete(); diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js index 56cb39be642d..869b043a3003 100644 --- a/app/assets/javascripts/dropzone_input.js +++ b/app/assets/javascripts/dropzone_input.js @@ -19,7 +19,7 @@ btnAlert = ""; project_uploads_path = window.project_uploads_path || null; max_file_size = gon.max_file_size || 10; - form_textarea = $(form).find(".js-gfm-input"); + form_textarea = $(form).find(".js-gfm-input:not(.js-gfm-input-no-attachments)"); form_textarea.wrap("
"); form_textarea.on('paste', (function(_this) { return function(event) { diff --git a/app/assets/javascripts/note_template_dropdown_create.js.es6 b/app/assets/javascripts/note_template_dropdown_create.js.es6 new file mode 100644 index 000000000000..724d6bd3853b --- /dev/null +++ b/app/assets/javascripts/note_template_dropdown_create.js.es6 @@ -0,0 +1,18 @@ +(global => { + global.gl = global.gl || {}; + + gl.NoteTemplateDropdownsCreate = class { + constructor() { + this.buildDropdowns(); + } + + buildDropdowns() { + $('.js-note-template-btn').each(function() { + new NoteTemplateDropdown({ + $dropdown: $(this) + }); + }); + } + } + +})(window); diff --git a/app/assets/javascripts/note_templates.js.es6 b/app/assets/javascripts/note_templates.js.es6 new file mode 100644 index 000000000000..776d6e33ff8c --- /dev/null +++ b/app/assets/javascripts/note_templates.js.es6 @@ -0,0 +1,37 @@ +class NoteTemplateDropdown { + constructor(options) { + this.$dropdown = options.$dropdown; + this.$textarea = this.$dropdown.parents(".md-area").find("textarea"); + this.buildDropdown(); + } + + buildDropdown() { + var _this = this; + this.$dropdown.glDropdown({ + data(term, callback) { + return $.ajax({ + url: _this.$dropdown.data('note-templates-url'), + dataType: "json" + }).done(function(templates) { + return callback(templates); + }); + }, + selectable: true, + filterable: true, + filterByText: true, + search: { + fields: ['note'] + }, + renderRow(template) { + return _.template('
  • <%- title %><%- note %>
  • ')({ title: template.title, note: template.note }); + }, + id(obj, $el) { + return $el.attr('data-note-template'); + }, + clicked(selected, $el, e) { + e.preventDefault(); + return window.gl.text.updateText(_this.$textarea, selected.note, false, false); + } + }); + } +} diff --git a/app/assets/javascripts/project.js b/app/assets/javascripts/project.js index fcf3a4af9566..5a37bfe6efd5 100644 --- a/app/assets/javascripts/project.js +++ b/app/assets/javascripts/project.js @@ -94,13 +94,13 @@ return $el.text().trim(); }, clicked: function(selected, $el, e) { - e.preventDefault() + e.preventDefault(); if ($('input[name="ref"]').length) { var $form = $dropdown.closest('form'), action = $form.attr('action'), divider = action.indexOf('?') < 0 ? '?' : '&'; Turbolinks.visit(action + '' + divider + '' + $form.serialize()); - } + }; } }); }); diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 755eddefa42c..5a2b6bf2df5c 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -271,11 +271,14 @@ } } +.dropdown-menu-item-with-description, .dropdown-menu-user-link { padding-top: 10px; padding-bottom: 7px; } + +.dropdown-menu-item-header, .dropdown-menu-user-full-name { display: block; font-weight: 500; @@ -283,8 +286,14 @@ text-overflow: ellipsis; overflow: hidden; white-space: nowrap; + + &.dropdown-menu-note-template-header { + font-weight: 600; + padding-bottom: 4px; + } } +.dropdown-menu-item-body, .dropdown-menu-user-username { display: block; line-height: 16px; diff --git a/app/controllers/profiles/note_templates_controller.rb b/app/controllers/profiles/note_templates_controller.rb new file mode 100644 index 000000000000..5ed7487dcd2a --- /dev/null +++ b/app/controllers/profiles/note_templates_controller.rb @@ -0,0 +1,60 @@ +class Profiles::NoteTemplatesController < Profiles::ApplicationController + before_action :authenticate_user! + before_action :set_note_template, only: [:edit, :update, :destroy] + + def index + @note_template = NoteTemplate.new + @note_templates = current_user.note_templates + + respond_to do |format| + format.html + format.json do + render json: @note_templates, only: [:title, :note] + end + end + end + + def edit + end + + def create + @note_template = NoteTemplate.new(note_template_params) + @note_template.user = current_user + + if @note_template.save + redirect_to( + profile_note_templates_path, + notice: "'#{@note_template.title}' was successfully created." + ) + else + render 'index' + end + end + + def update + if @note_template.update_attributes(note_template_params) + redirect_to( + profile_note_templates_path, + notice: "'#{@note_template.title}' was successfully updated." + ) + else + flash[:alert] = 'Failed to save note template.' + end + end + + def destroy + if @note_template.destroy + redirect_to(profile_note_templates_path, notice: "Note template was successfully deleted.") + end + end + + private + + def note_template_params + params.require(:note_template).permit(:note, :title) + end + + def set_note_template + @note_template = current_user.note_templates.find(params["id"]) + end +end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index f0c71725ea8c..30abea8bf864 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -54,6 +54,20 @@ def update_username end end + def preview_markdown + text = params[:text] + + ext = Gitlab::ReferenceExtractor.new(@project, current_user) + ext.analyze(text, author: current_user) + + render json: { + body: view_context.markdown(text), + references: { + users: ext.users.map(&:username) + } + } + end + private def user diff --git a/app/models/note_template.rb b/app/models/note_template.rb new file mode 100644 index 000000000000..b947a701e152 --- /dev/null +++ b/app/models/note_template.rb @@ -0,0 +1,4 @@ +class NoteTemplate < ActiveRecord::Base + belongs_to :user + validates :user, :note, :title, presence: true +end diff --git a/app/models/user.rb b/app/models/user.rb index 06dd98a31885..1fd70078dbaa 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -93,6 +93,7 @@ class User < ActiveRecord::Base has_many :todos, dependent: :destroy has_many :notification_settings, dependent: :destroy has_many :award_emoji, dependent: :destroy + has_many :note_templates, dependent: :destroy # # Validations diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index e06301bda147..7e255d125195 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -51,3 +51,7 @@ = link_to audit_log_profile_path, title: 'Audit Log' do %span Audit Log + = nav_link(controller: :note_templates) do + = link_to profile_note_templates_path, title: 'Note Templates' do + %span + Note Templates diff --git a/app/views/profiles/note_templates/_form.html.haml b/app/views/profiles/note_templates/_form.html.haml new file mode 100644 index 000000000000..34132502c9bb --- /dev/null +++ b/app/views/profiles/note_templates/_form.html.haml @@ -0,0 +1,45 @@ +- form_class = inline ? '' : 'form-horizontal' +- label_class = inline ? 'label-light' : 'control-label' +- note_template_form_url = inline ? profile_note_templates_path : profile_note_template_path(@note_template) + += form_for @note_template, url: note_template_form_url, html: { class: "#{form_class} common-note-form js-quick-submit js-requires-input js-note-template-form" } do |f| + .form-group + = f.label :title, 'Title', class: "#{label_class}" + - if inline + = f.text_field :title, class: "form-control", tabindex: 2, autofocus: true, required: true + - else + .col-sm-10 + = f.text_field :title, class: "form-control", tabindex: 2, autofocus: true, required: true + + .form-group.detail-page-description + = f.label :note, 'Note', class: "#{label_class}" + - if inline + = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true, disable_note_templates: true } do + = render 'projects/zen', f: f, attr: :note, + classes: 'note-textarea', + placeholder: "Write a note template", + no_attachments: true + = render 'projects/notes/hints', no_attachments: true + .clearfix + .error-alert + - else + .col-sm-10 + = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true, disable_note_templates: true } do + = render 'projects/zen', f: f, attr: :note, + classes: 'note-textarea', + placeholder: "Write a note template", + no_attachments: true + = render 'projects/notes/hints', no_attachments: true + .clearfix + .error-alert + + - if inline + .prepend-top-default + = f.submit 'Create note template', class: "btn btn-create", tabindex: 4 + - else + .form-actions + = f.submit 'Save note template', class: "btn btn-create", tabindex: 4 + = link_to 'Cancel', profile_note_templates_path, class: 'btn btn-cancel' + +:javascript + window.preview_markdown_path = "#{preview_markdown_profile_path}"; diff --git a/app/views/profiles/note_templates/edit.html.haml b/app/views/profiles/note_templates/edit.html.haml new file mode 100644 index 000000000000..b79276864a60 --- /dev/null +++ b/app/views/profiles/note_templates/edit.html.haml @@ -0,0 +1,7 @@ +- page_title "Edit Note Template" + +%h3.page-title + Edit Note Template +%hr + += render "form", inline: false diff --git a/app/views/profiles/note_templates/index.html.haml b/app/views/profiles/note_templates/index.html.haml new file mode 100644 index 000000000000..33e4c25cc3bd --- /dev/null +++ b/app/views/profiles/note_templates/index.html.haml @@ -0,0 +1,29 @@ +- page_title "Note Templates" + +.row.prepend-top-default + .col-lg-3.profile-settings-sidebar + %h4.prepend-top-0 + = page_title + %p Note templates can be used in issues, merge requests, and comments across GitLab. + %p They allow you to respond more quickly to common issues and questions. + .col-lg-9 + %h5.prepend-top-0 + Add a Note Template + = render "form", inline: true + %hr + %h5 + Note Templates (#{@note_templates.size}) + - if @note_templates.any? + %ul.content-list + - @note_templates.each do |note_template| + %li + .controls + = link_to 'Edit', edit_profile_note_template_path(note_template), class: "btn" + = link_to 'Delete', profile_note_template_path(note_template), data: { confirm: "Are you sure?"}, method: :delete, class: "btn btn-remove" + .title + = link_to note_template.title, edit_profile_note_template_path(note_template) + .description + %p= note_template.note + - else + %p.settings-message.text-center + You haven't created any note templates yet. diff --git a/app/views/projects/_md_preview.html.haml b/app/views/projects/_md_preview.html.haml index 085f79de7850..1ea5ebbfe291 100644 --- a/app/views/projects/_md_preview.html.haml +++ b/app/views/projects/_md_preview.html.haml @@ -1,5 +1,17 @@ .md-area .md-header + - unless defined?(disable_note_templates) + .js-note-template-dropdown.dropdown + .dropdown-menu.dropdown-menu-large.dropdown-menu-align-right + = dropdown_title "Select note template" + = dropdown_filter "Search your note templates" + = dropdown_content + = dropdown_footer do + %ul.dropdown-footer-list + %li + = link_to "Create new note template", profile_note_templates_path + = dropdown_loading + %ul.nav-links.clearfix %li.active %a.js-md-write-button{ href: "#md-write-holder", tabindex: -1 } @@ -22,8 +34,12 @@ = markdown_toolbar_button({ icon: "list-ul fw", data: { "md-tag" => "* ", "md-prepend" => true }, title: "Add a bullet list" }) = markdown_toolbar_button({ icon: "list-ol fw", data: { "md-tag" => "1. ", "md-prepend" => true }, title: "Add a numbered list" }) = markdown_toolbar_button({ icon: "check-square-o fw", data: { "md-tag" => "* [ ] ", "md-prepend" => true }, title: "Add a task list" }) + - unless defined?(disable_note_templates) + %button.toolbar-btn.js-note-template-btn.has-tooltip.hidden-xs{ type: "button", tabindex: -1, title: "Add a note template", data: { note_templates_url: profile_note_templates_path, target: '.js-note-template-dropdown', toggle: 'dropdown' } } + = icon("sticky-note fw") + .toolbar-group - %button.toolbar-btn.js-zen-enter.has-tooltip.hidden-xs{ type: "button", tabindex: -1, aria: { label: "Go full screen" }, title: "Go full screen", data: { container: "body" } } + %button.toolbar-btn.js-zen-enter.has-tooltip.hidden-xs{ type: "button", tabindex: -1, title: "Go full screen", data: { container: "body" } } = icon("arrows-alt fw") .md-write-holder diff --git a/app/views/projects/_zen.html.haml b/app/views/projects/_zen.html.haml index 0c8241053e74..6bd34b02a95a 100644 --- a/app/views/projects/_zen.html.haml +++ b/app/views/projects/_zen.html.haml @@ -2,6 +2,8 @@ - supports_slash_commands = local_assigns.fetch(:supports_slash_commands, false) .zen-backdrop - classes << ' js-gfm-input js-autosize markdown-area' + - if defined?(no_attachments) && no_attachments + - classes << ' js-gfm-input-no-attachments' - if defined?(f) && f = f.text_area attr, class: classes, placeholder: placeholder, data: { supports_slash_commands: supports_slash_commands } - else diff --git a/app/views/projects/notes/_hints.html.haml b/app/views/projects/notes/_hints.html.haml index 6c14f48d41bc..248167c87657 100644 --- a/app/views/projects/notes/_hints.html.haml +++ b/app/views/projects/notes/_hints.html.haml @@ -10,6 +10,7 @@ - else is supported - %button.toolbar-button.markdown-selector{ type: 'button', tabindex: '-1' } - = icon('file-image-o', class: 'toolbar-button-icon') - Attach a file + - unless defined?(no_attachments) + %button.toolbar-button.markdown-selector{ type: 'button', tabindex: '-1' } + = icon('file-image-o', class: 'toolbar-button-icon') + Attach a file diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml index c52527332bc5..a214c39ef245 100644 --- a/app/views/projects/wikis/_form.html.haml +++ b/app/views/projects/wikis/_form.html.haml @@ -10,7 +10,7 @@ .form-group = f.label :content, class: 'control-label' .col-sm-10 - = render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do + = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", disable_note_templates: true } do = render 'projects/zen', f: f, attr: :content, classes: 'note-textarea', placeholder: 'Write your content or drag files here...' = render 'projects/notes/hints' diff --git a/config/routes/profile.rb b/config/routes/profile.rb index 6b91485da9e6..4babb2ef42fc 100644 --- a/config/routes/profile.rb +++ b/config/routes/profile.rb @@ -6,6 +6,7 @@ put :reset_private_token put :reset_incoming_email_token put :update_username + post :preview_markdown end scope module: :profiles do @@ -15,6 +16,7 @@ end end resource :notifications, only: [:show, :update] + resources :note_templates, only: [:index, :edit, :update, :create, :destroy] resource :password, only: [:new, :create, :edit, :update] do member do put :reset diff --git a/db/migrate/20160730140922_create_note_templates.rb b/db/migrate/20160730140922_create_note_templates.rb new file mode 100644 index 000000000000..332eb43397ff --- /dev/null +++ b/db/migrate/20160730140922_create_note_templates.rb @@ -0,0 +1,36 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class CreateNoteTemplates < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + # When a migration requires downtime you **must** uncomment the following + # constant and define a short and easy to understand explanation as to why the + # migration requires downtime. + # DOWNTIME_REASON = '' + + # When using the methods "add_concurrent_index" or "add_column_with_default" + # you must disable the use of transactions as these methods can not run in an + # existing transaction. When using "add_concurrent_index" make sure that this + # method is the _only_ method called in the migration, any other changes + # should go in a separate migration. This ensures that upon failure _only_ the + # index creation fails and can be retried or reverted easily. + # + # To disable transactions uncomment the following line and remove these + # comments: + # disable_ddl_transaction! + + def change + create_table :note_templates do |t| + t.integer :user_id + t.string :title + t.text :note + + t.timestamps null: false + end + add_index :note_templates, :user_id + end +end diff --git a/db/schema.rb b/db/schema.rb index c58a886b0fa4..aa549503760b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -758,6 +758,16 @@ add_index "namespaces", ["path"], name: "index_namespaces_on_path_trigram", using: :gin, opclasses: {"path"=>"gin_trgm_ops"} add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree + create_table "note_templates", force: :cascade do |t| + t.integer "user_id" + t.string "title" + t.text "note" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "note_templates", ["user_id"], name: "index_note_templates_on_user_id", using: :btree + create_table "notes", force: :cascade do |t| t.text "note" t.string "noteable_type" diff --git a/spec/controllers/profiles/note_templates_controller_spec.rb b/spec/controllers/profiles/note_templates_controller_spec.rb new file mode 100644 index 000000000000..4b3d09e5faa9 --- /dev/null +++ b/spec/controllers/profiles/note_templates_controller_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Profiles::NoteTemplatesController do + let(:user) { create(:user) } + + before do + sign_in(user) + + allow(subject).to receive(:current_user).and_return(user) + end + + describe 'GET #index' do + let(:note_template) { create(:note_template) } + + it 'should list the note templates' do + get :index + + expect(response).to be_success + end + end + + describe 'POST #create' do + it 'should create a new note template' do + expect do + post :create, note_template: { title: 'Lorem ipsum dolor', note: 'Lorem ipsum dolor' } + end.to change { user.note_templates.count }.by(1) + + expect(response).to redirect_to(profile_note_templates_path) + end + end +end diff --git a/spec/factories/note_templates.rb b/spec/factories/note_templates.rb new file mode 100644 index 000000000000..6aef48c352e8 --- /dev/null +++ b/spec/factories/note_templates.rb @@ -0,0 +1,7 @@ +FactoryGirl.define do + factory :note_template do + title { FFaker::BaconIpsum.characters(25) } + note { FFaker::BaconIpsum.characters(100) } + user + end +end diff --git a/spec/models/note_template_spec.rb b/spec/models/note_template_spec.rb new file mode 100644 index 000000000000..cf99c8c41fa8 --- /dev/null +++ b/spec/models/note_template_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +describe NoteTemplate, type: :model do + describe 'associations' do + it { is_expected.to belong_to(:user) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:user) } + it { is_expected.to validate_presence_of(:title) } + it { is_expected.to validate_presence_of(:note) } + end +end diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 9f6defe14507..bf392e01fcc2 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -225,6 +225,12 @@ end end +describe Profiles::NoteTemplatesController, "routing" do + it "to #index" do + expect(get("/profile/note_templates")).to route_to('profiles/note_templates#index') + end +end + # dashboard GET /dashboard(.:format) dashboard#show # dashboard_issues GET /dashboard/issues(.:format) dashboard#issues # dashboard_merge_requests GET /dashboard/merge_requests(.:format) dashboard#merge_requests -- GitLab From 47cc91b4555e8fc1a588152d33e4ffd2a3e8fc2d Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Fri, 13 Jan 2017 17:52:08 -0500 Subject: [PATCH 2/3] Add note templates to the API. --- lib/api/api.rb | 1 + lib/api/note_templates.rb | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 lib/api/note_templates.rb diff --git a/lib/api/api.rb b/lib/api/api.rb index 6cf6b5010219..ed849283ffd9 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -59,6 +59,7 @@ class API < Grape::API mount ::API::Milestones mount ::API::Namespaces mount ::API::Notes + mount ::API::NoteTemplates mount ::API::NotificationSettings mount ::API::Pipelines mount ::API::ProjectHooks diff --git a/lib/api/note_templates.rb b/lib/api/note_templates.rb new file mode 100644 index 000000000000..f4ae76e7791a --- /dev/null +++ b/lib/api/note_templates.rb @@ -0,0 +1,16 @@ +module API + class NoteTemplates < Grape::API + before { authenticate! } + + resource :note_templates + desc 'Get global notification level settings and email, defaults to Participate' do + success Entities::NoteTemplates + end + get do + + end + put do + + end + end +end -- GitLab From 6b0e2b2a714709ce23e600207b96578d84e82baa Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Fri, 13 Jan 2017 18:27:37 -0500 Subject: [PATCH 3/3] Add more to the Note Templates API. --- lib/api/entities.rb | 6 +++ lib/api/note_templates.rb | 62 ++++++++++++++++++++++-- spec/requests/api/note_templates_spec.rb | 20 ++++++++ 3 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 spec/requests/api/note_templates_spec.rb diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 885ce7d44bc6..0cc0db621385 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -337,6 +337,12 @@ class Note < Grape::Entity expose(:downvote?) { |note| false } end + class NoteTemplate < Grape::Entity + expose :id + expose :title + expose :note + end + class AwardEmoji < Grape::Entity expose :id expose :name diff --git a/lib/api/note_templates.rb b/lib/api/note_templates.rb index f4ae76e7791a..720b3e2013cf 100644 --- a/lib/api/note_templates.rb +++ b/lib/api/note_templates.rb @@ -1,16 +1,68 @@ module API class NoteTemplates < Grape::API + include PaginationParams + before { authenticate! } - resource :note_templates - desc 'Get global notification level settings and email, defaults to Participate' do - success Entities::NoteTemplates + resource :note_templates do + desc 'Get all note templates for the authenticated user' do + success Entities::NoteTemplate end get do - + NoteTemplate.all + end + + desc 'Get a note templates for the authenticated user' do + success Entities::NoteTemplate + end + params do + requires :id, type: Integer, desc: "The ID of the note template." + end + get "note_templates/:id" do + note_template = NoteTemplate.find_by(id: params[:id]) + + present note_template, with: Entities::NoteTemplate + end + + desc 'Create a note template for the authenticated user' do + success Entities::NoteTemplate + end + params do + requires :title, type: String, desc: "The title of the note template." + requires :note, type: String, desc: "The body of the note template." end - put do + post do + note_template = NoteTemplate.create!(declared(params, include_parent_namespaces: false).to_h) + + present note_template, with: Entities::NoteTemplate, current_user: current_user + end + + desc 'Update a note template for the authenticated user' do + success Entities::NoteTemplate + end + params do + requires :id, type: Integer, desc: "The ID of the note template." + optional :title, type: String, desc: "The title of the note template." + optional :note, type: String, desc: "The body of the note template." + at_least_one_of :title, :note + end + put "note_templates/:id" do + note_template = NoteTemplate.find(params[:id]) + note_template.update_attributes(declared(params, include_parent_namespaces: false).to_h) + + present note_template, with: Entities::NoteTemplate + end + + desc 'Delete a note template for the authenticated user' do + success Entities::NoteTemplate + end + params do + requires :id, type: Integer, desc: "The ID of the note template." + end + delete "note_templates/:id" do + puts 'test' end + end end end diff --git a/spec/requests/api/note_templates_spec.rb b/spec/requests/api/note_templates_spec.rb new file mode 100644 index 000000000000..37b6ccb5b3de --- /dev/null +++ b/spec/requests/api/note_templates_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe API::Notes, api: true do + include ApiHelpers + + let(:user) { create(:user) } + let(:note_template) { create(:note_template) } + + describe "GET /note_templates" do + + end + + describe "PUT /note_templates" do + + end + + describe "DELETE /note_templates/ :id" do + + end +end -- GitLab