#733 Add the possibility to create templates for issues
Merged 8 years ago by pingou. Opened 8 years ago by pingou.

@@ -318,3 +318,74 @@ 

              'message': branches,

          }

      )

+ 

+ 

+ @PV.route('/<repo>/issue/template', methods=['POST'])

+ @PV.route('/fork/<username>/<repo>/issue/template',

+            methods=['POST'])

+ def get_ticket_template(repo, username=None):

+     """ Return the template asked for the specified project

+     """

+ 

+     form = pagure.forms.ConfirmationForm()

+     if not form.validate_on_submit():

+         response = flask.jsonify({

+             'code': 'ERROR',

+             'message': 'Invalid input submitted',

+         })

+         response.status_code = 400

+         return response

+ 

+     template = flask.request.args.get('template', None)

+     if not template:

+         response = flask.jsonify({

+             'code': 'ERROR',

+             'message': 'No template provided',

+         })

+         response.status_code = 400

+         return response

+ 

+     repo = pagure.lib.get_project(pagure.SESSION, repo, user=username)

+ 

+     if repo is None:

+         response = flask.jsonify({

+             'code': 'ERROR',

+             'message': 'Project not found',

+         })

+         response.status_code = 404

+         return response

+ 

+     if not repo.settings.get('issue_tracker', True):

+         response = flask.jsonify({

+             'code': 'ERROR',

+             'message': 'No issue tracker found for this project',

+         })

+         response.status_code = 404

+         return response

+ 

+     ticketrepopath = os.path.join(

+         pagure.APP.config['TICKETS_FOLDER'], repo.path)

+     content = None

+     if os.path.exists(ticketrepopath):

+         ticketrepo = pygit2.Repository(ticketrepopath)

+         if not ticketrepo.is_empty and not ticketrepo.head_is_unborn:

+             commit = ticketrepo[ticketrepo.head.target]

+             # Get the asked template

+             content_file = pagure.__get_file_in_tree(

+                 ticketrepo, commit.tree, ['templates', '%s.md' % template],

+                 bail_on_tree=True)

+             if content_file:

+                 content, _ = pagure.doc_utils.convert_readme(

+                         content_file.data, 'md')

+     if content:

+         response = flask.jsonify({

+             'code': 'OK',

+             'message': content,

+         })

+     else:

+         response = flask.jsonify({

+             'code': 'ERROR',

+             'message': 'No such template found',

+         })

+         response.status_code = 404

+     return response

file modified
+2 -1
@@ -2559,7 +2559,8 @@ 

          attrs['img'] = filter_img_src

  

      tags = bleach.ALLOWED_TAGS + [

-         'p', 'br', 'div', 'h1', 'h2', 'h3', 'table', 'td', 'tr', 'th',

+         'p', 'br', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',

+         'table', 'td', 'tr', 'th',

          'col', 'tbody', 'pre', 'img', 'hr', 'dl', 'dt', 'dd', 'span',

      ]

      if ignore:

@@ -25,7 +25,7 @@ 

            <span class="c-indicator"></span>

            <strong>{{ field.label }}</strong>

          </label>

-         </br>

+         <br />

          {% if field_description %}

            <small class="text-muted">{{ field_description }}</small>

          {% endif %}

file modified
+92 -45
@@ -38,13 +38,31 @@ 

          {% if type == 'edit' %}

              {{ render_bootstrap_field(form.status, field_description="bug status") }}

          {% endif %}

+         {% if types %}

+         <fieldset class="form-group  ">

+           <strong><label for="status">Type</label></strong>

+           <select class="form-control c-select" id="type" name="type">

+             {% for type in types %}

+             <option selected value="{{ type }}">{{ type }}</option>

+             {% endfor %}

+           </select>

+           <div>

+             <small class="text-muted">Ticket type</small>

+           </div>

+         </fieldset>

+         {% endif %}

          {{ render_bootstrap_field(form.private, field_description="Do you want to keep the issue private?") }}

            <fieldset class="form-group">

              <label for="issue_content"><strong>Description</strong></label>

-             <small class="text-muted pull-xs-right"><span class="btn btn-sm btn-secondary inactive" aria-pressed="false" id="previewinmarkdown">Preview</span></small>

+             <small class="text-muted pull-xs-right">

+               <span class="btn btn-sm btn-secondary inactive"

+                 aria-pressed="false" id="previewinmarkdown">Preview</span>

+             </small>

              <textarea class="form-control" rows="8" id="issue_content" name="issue_content"

                  placeholder="Describe your issue">

-               {%- if issue %}{{ issue.content }}{% endif -%}

+               {%- if issue %}{{ issue.content }}{%

+                   elif default %}{{ default }}{%

+               endif -%}

              </textarea>

              <div>

  
@@ -63,7 +81,6 @@ 

            </fieldset>

          Attach file <input id="file-picker" type="file" name="filestream" accept="image/*" multiple>

  

- 

          <p class="buttons indent">

            {% if not type or type == 'new' %}

            <input type="submit" class="btn btn-primary" value="Create">
@@ -72,24 +89,26 @@ 

            {% endif %}

            <input type="button" value="Cancel" class="btn btn-secondary" onclick="history.back();">

            {{ form.csrf_token }}

+           <a href="http://daringfireball.net/projects/markdown/syntax"

+             target="_blank">Markdown Syntax</a>

          </p>

        </form>

        </div>

      </div>

  

- {% if authenticated and repo_admin and type and type == 'edit' %}

- <form method="post" class="pull-xs-right" action="{{ url_for('.delete_issue',

-                     username=username, repo=repo.name, issueid=issueid) }}">

-   <button class="btn btn-danger" type="submit"

-       onclick="return confirm('Are you sure to delete this ticket? \nThis is final and cannot be un-done.');"

-       title="Delete this ticket">

-     <span class="icon icon-trash blue"></span>

-     Delete issue

-   </button>

-   {{ form.csrf_token }}

- </form>

- {% endif %}

- 

+     {% if authenticated and repo_admin and type and type == 'edit' %}

+     <form method="post" class="pull-xs-right" action="{{

+         url_for('.delete_issue',

+                 username=username, repo=repo.name, issueid=issueid) }}">

+       <button class="btn btn-danger" type="submit"

+           onclick="return confirm('Are you sure to delete this ticket? \nThis is final and cannot be un-done.');"

+           title="Delete this ticket">

+         <span class="icon icon-trash blue"></span>

+         Delete issue

+       </button>

+       {{ form.csrf_token }}

+     </form>

+     {% endif %}

  

    </div>

  </div>
@@ -131,43 +150,71 @@ 

    var json_url = '{{ url_for("static", filename="emoji/emoji_strategy.json") }}';

    emoji_complete(json_url, folder);

  

+   $("#type").on("change", function() {

+     if ( !confirm('Do you want to load the new template?')){

+       return false;

+     }

+ 

+     var _type = $("#type").val();

+     var _url = "{{

+       url_for('internal_ns.get_ticket_template',

+               username=repo.username if repo.is_fork else None,

+               repo=repo.name) }}";

+     _url += '?template=' + _type;

+     $.ajax({

+       url: _url ,

+       type: 'POST',

+       data: {

+         csrf_token: "{{ form.csrf_token.current_token }}",

+       },

+       dataType: 'json',

+       success: function(res) {

+         $("#issue_content").val(res.message);

+       },

+       error: function(res) {

+         alert('Unable to get this template');

+       }

+     });

+   });

+ 

  });

+ 

  {% endif %}

  

  $(function() {

    $( "#preview" ).hide();

    $( "#previewinmarkdown" ).click(

      function(event, ui) {

-         if ($( "#previewinmarkdown" ).hasClass("inactive")){

-           var _text = $( "#issue_content" ).val();

-           var _url = "{{ url_for('markdown_preview') }}";

-             $.ajax({

-                 url: _url ,

-                 type: 'POST',

-                 data: {

-                   content: _text,

-                   csrf_token: "{{ form.csrf_token.current_token }}",

-                 },

-                 dataType: 'html',

-                 success: function(res) {

-                     var preview = emojione.toImage(res);

-                     $( "#preview" ).html(preview);

-                     $( "#previewinmarkdown" ).removeClass("inactive");

-                     $( "#previewinmarkdown" ).addClass("active");

-                     $( "#issue_content" ).hide();

-                     $( "#preview" ).show();

-                 },

-                 error: function() {

-                     alert('Unable to generate preview!'+error);

-                 }

-             });

-             return false;

-           } else if ($( "#previewinmarkdown" ).hasClass("active")){

-             $( "#previewinmarkdown" ).addClass("inactive");

-             $( "#previewinmarkdown" ).removeClass("active");

-             $( "#issue_content" ).show();

-             $( "#preview" ).hide();

+       if ($( "#previewinmarkdown" ).hasClass("inactive")){

+         var _text = $( "#issue_content" ).val();

+         var _url = "{{ url_for('markdown_preview') }}";

+         $.ajax({

+           url: _url ,

+           type: 'POST',

+           data: {

+             content: _text,

+             csrf_token: "{{ form.csrf_token.current_token }}",

+           },

+           dataType: 'html',

+           success: function(res) {

+             var preview = emojione.toImage(res);

+             $( "#preview" ).html(preview);

+             $( "#previewinmarkdown" ).removeClass("inactive");

+             $( "#previewinmarkdown" ).addClass("active");

+             $( "#issue_content" ).hide();

+             $( "#preview" ).show();

+           },

+           error: function() {

+             alert('Unable to generate preview!'+error);

            }

+         });

+         return false;

+       } else if ($( "#previewinmarkdown" ).hasClass("active")){

+         $( "#previewinmarkdown" ).addClass("inactive");

+         $( "#previewinmarkdown" ).removeClass("active");

+         $( "#issue_content" ).show();

+         $( "#preview" ).hide();

+       }

      }

    );

  });

file modified
+23
@@ -478,6 +478,27 @@ 

              SESSION.rollback()

              flask.flash(str(err), 'error')

  

+     types = None

+     default = None

+     ticketrepopath = os.path.join(APP.config['TICKETS_FOLDER'], repo.path)

+     if os.path.exists(ticketrepopath):

+         ticketrepo = pygit2.Repository(ticketrepopath)

+         if not ticketrepo.is_empty and not ticketrepo.head_is_unborn:

+             commit = ticketrepo[ticketrepo.head.target]

+             # Get the different ticket types

+             files = __get_file_in_tree(

+                 ticketrepo, commit.tree, ['templates'],

+                 bail_on_tree=True)

+             if files:

+                 types = [f.name.rstrip('.md') for f in files]

+             # Get the default template

+             default_file = __get_file_in_tree(

+                 ticketrepo, commit.tree, ['templates', 'default.md'],

+                 bail_on_tree=True)

+             if default_file:

+                 default, _ = pagure.doc_utils.convert_readme(

+                         default_file.data, 'md')

+ 

      return flask.render_template(

          'new_issue.html',

          select='issues',
@@ -485,6 +506,8 @@ 

          repo=repo,

          username=username,

          repo_admin=is_repo_admin(repo),

+         types=types,

+         default=default,

      )