comments: add comments type into comments.
This commit is contained in:
parent
b52808ca95
commit
24ef7171f8
15 changed files with 285 additions and 79 deletions
|
|
@ -51,7 +51,7 @@ PYRAMID_SETTINGS = {}
|
|||
EXTENSIONS = {}
|
||||
|
||||
__version__ = ('.'.join((str(each) for each in VERSION[:3])))
|
||||
__dbversion__ = 63 # defines current db version for migrations
|
||||
__dbversion__ = 64 # defines current db version for migrations
|
||||
__platform__ = platform.system()
|
||||
__license__ = 'AGPLv3, and Commercial License'
|
||||
__author__ = 'RhodeCode GmbH'
|
||||
|
|
|
|||
|
|
@ -334,6 +334,8 @@ class ChangesetController(BaseRepoController):
|
|||
commit_id = revision
|
||||
status = request.POST.get('changeset_status', None)
|
||||
text = request.POST.get('text')
|
||||
comment_type = request.POST.get('comment_type')
|
||||
|
||||
if status:
|
||||
text = text or (_('Status change %(transition_icon)s %(status)s')
|
||||
% {'transition_icon': '>',
|
||||
|
|
@ -355,7 +357,8 @@ class ChangesetController(BaseRepoController):
|
|||
line_no=request.POST.get('line'),
|
||||
status_change=(ChangesetStatus.get_status_lbl(status)
|
||||
if status else None),
|
||||
status_change_type=status
|
||||
status_change_type=status,
|
||||
comment_type=comment_type
|
||||
)
|
||||
c.inline_comment = True if comment.line_no else False
|
||||
|
||||
|
|
|
|||
|
|
@ -903,6 +903,7 @@ class PullrequestsController(BaseRepoController):
|
|||
# as a changeset status, still we want to send it in one value.
|
||||
status = request.POST.get('changeset_status', None)
|
||||
text = request.POST.get('text')
|
||||
comment_type = request.POST.get('comment_type')
|
||||
if status and '_closed' in status:
|
||||
close_pr = True
|
||||
status = status.replace('_closed', '')
|
||||
|
|
@ -934,7 +935,8 @@ class PullrequestsController(BaseRepoController):
|
|||
if status and allowed_to_change_status else None),
|
||||
status_change_type=(status
|
||||
if status and allowed_to_change_status else None),
|
||||
closing_pr=close_pr
|
||||
closing_pr=close_pr,
|
||||
comment_type=comment_type
|
||||
)
|
||||
|
||||
if allowed_to_change_status:
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ from rhodecode.lib.utils2 import (
|
|||
str2bool, safe_unicode, AttributeDict, safe_int, md5, aslist)
|
||||
from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
|
||||
from rhodecode.model import meta
|
||||
from rhodecode.model.db import Repository, User
|
||||
from rhodecode.model.db import Repository, User, ChangesetComment
|
||||
from rhodecode.model.notification import NotificationModel
|
||||
from rhodecode.model.scm import ScmModel
|
||||
from rhodecode.model.settings import VcsSettingsModel, SettingsModel
|
||||
|
|
@ -299,6 +299,7 @@ def attach_context_attributes(context, request):
|
|||
context.visual.gravatar_url = rc_config.get('rhodecode_gravatar_url')
|
||||
context.visual.default_renderer = rc_config.get(
|
||||
'rhodecode_markup_renderer', 'rst')
|
||||
context.visual.comment_types = ChangesetComment.COMMENT_TYPES
|
||||
context.visual.rhodecode_support_url = \
|
||||
rc_config.get('rhodecode_support_url') or url('rhodecode_support')
|
||||
|
||||
|
|
|
|||
30
rhodecode/lib/dbmigrate/versions/064_version_4_6_0.py
Normal file
30
rhodecode/lib/dbmigrate/versions/064_version_4_6_0.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import logging
|
||||
|
||||
from sqlalchemy import Column, MetaData, Integer, Unicode, ForeignKey
|
||||
|
||||
from rhodecode.lib.dbmigrate.versions import _reset_base
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
"""
|
||||
Upgrade operations go here.
|
||||
Don't create your own engine; bind migrate_engine to your metadata
|
||||
"""
|
||||
_reset_base(migrate_engine)
|
||||
from rhodecode.lib.dbmigrate.schema import db_4_5_0_0 as db
|
||||
|
||||
# add comment type and link to resolve by id
|
||||
comment_table = db.ChangesetComment.__table__
|
||||
col1 = Column('comment_type', Unicode(128), nullable=True)
|
||||
col1.create(table=comment_table)
|
||||
|
||||
col1 = Column('resolved_comment_id', Integer(),
|
||||
ForeignKey('changeset_comments.comment_id'), nullable=True)
|
||||
col1.create(table=comment_table)
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
|
@ -44,6 +44,8 @@ from rhodecode.model.notification import NotificationModel
|
|||
from rhodecode.model.meta import Session
|
||||
from rhodecode.model.settings import VcsSettingsModel
|
||||
from rhodecode.model.notification import EmailNotificationModel
|
||||
from rhodecode.model.validation_schema.schemas import comment_schema
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -111,15 +113,32 @@ class CommentsModel(BaseModel):
|
|||
if not renderer:
|
||||
renderer = self._get_renderer()
|
||||
|
||||
repo = self._get_repo(repo)
|
||||
user = self._get_user(user)
|
||||
|
||||
schema = comment_schema.CommentSchema()
|
||||
validated_kwargs = schema.deserialize(dict(
|
||||
comment_body=text,
|
||||
comment_type=comment_type,
|
||||
comment_file=f_path,
|
||||
comment_line=line_no,
|
||||
renderer_type=renderer,
|
||||
status_change=status_change,
|
||||
|
||||
repo=repo,
|
||||
user=user,
|
||||
))
|
||||
|
||||
repo = self._get_repo(validated_kwargs['repo'])
|
||||
user = self._get_user(validated_kwargs['user'])
|
||||
|
||||
comment = ChangesetComment()
|
||||
comment.renderer = renderer
|
||||
comment.renderer = validated_kwargs['renderer_type']
|
||||
comment.text = validated_kwargs['comment_body']
|
||||
comment.f_path = validated_kwargs['comment_file']
|
||||
comment.line_no = validated_kwargs['comment_line']
|
||||
comment.comment_type = validated_kwargs['comment_type']
|
||||
|
||||
comment.repo = repo
|
||||
comment.author = user
|
||||
comment.text = text
|
||||
comment.f_path = f_path
|
||||
comment.line_no = line_no
|
||||
|
||||
pull_request_id = pull_request
|
||||
|
||||
|
|
|
|||
|
|
@ -2896,6 +2896,9 @@ class ChangesetComment(Base, BaseModel):
|
|||
)
|
||||
|
||||
COMMENT_OUTDATED = u'comment_outdated'
|
||||
COMMENT_TYPE_NOTE = u'note'
|
||||
COMMENT_TYPE_TODO = u'todo'
|
||||
COMMENT_TYPES = [COMMENT_TYPE_NOTE, COMMENT_TYPE_TODO]
|
||||
|
||||
comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
|
||||
repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
|
||||
|
|
@ -2912,6 +2915,9 @@ class ChangesetComment(Base, BaseModel):
|
|||
renderer = Column('renderer', Unicode(64), nullable=True)
|
||||
display_state = Column('display_state', Unicode(128), nullable=True)
|
||||
|
||||
comment_type = Column('comment_type', Unicode(128), nullable=True, default=COMMENT_TYPE_NOTE)
|
||||
resolved_comment_id = Column('resolved_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'), nullable=True)
|
||||
resolved_comment = relationship('ChangesetComment', remote_side=comment_id)
|
||||
author = relationship('User', lazy='joined')
|
||||
repo = relationship('Repository')
|
||||
status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
|
||||
|
|
|
|||
70
rhodecode/model/validation_schema/schemas/comment_schema.py
Normal file
70
rhodecode/model/validation_schema/schemas/comment_schema.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2017-2017 RhodeCode GmbH
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License, version 3
|
||||
# (only), as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# This program is dual-licensed. If you wish to learn more about the
|
||||
# RhodeCode Enterprise Edition, including its added features, Support services,
|
||||
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
||||
|
||||
import os
|
||||
|
||||
import colander
|
||||
|
||||
from rhodecode.translation import _
|
||||
from rhodecode.model.validation_schema import preparers
|
||||
from rhodecode.model.validation_schema import types
|
||||
|
||||
|
||||
@colander.deferred
|
||||
def deferred_lifetime_validator(node, kw):
|
||||
options = kw.get('lifetime_options', [])
|
||||
return colander.All(
|
||||
colander.Range(min=-1, max=60 * 24 * 30 * 12),
|
||||
colander.OneOf([x for x in options]))
|
||||
|
||||
|
||||
def unique_gist_validator(node, value):
|
||||
from rhodecode.model.db import Gist
|
||||
existing = Gist.get_by_access_id(value)
|
||||
if existing:
|
||||
msg = _(u'Gist with name {} already exists').format(value)
|
||||
raise colander.Invalid(node, msg)
|
||||
|
||||
|
||||
def filename_validator(node, value):
|
||||
if value != os.path.basename(value):
|
||||
msg = _(u'Filename {} cannot be inside a directory').format(value)
|
||||
raise colander.Invalid(node, msg)
|
||||
|
||||
|
||||
comment_types = ['note', 'todo']
|
||||
|
||||
|
||||
class CommentSchema(colander.MappingSchema):
|
||||
from rhodecode.model.db import ChangesetComment
|
||||
|
||||
comment_body = colander.SchemaNode(colander.String())
|
||||
comment_type = colander.SchemaNode(
|
||||
colander.String(),
|
||||
validator=colander.OneOf(ChangesetComment.COMMENT_TYPES))
|
||||
|
||||
comment_file = colander.SchemaNode(colander.String(), missing=None)
|
||||
comment_line = colander.SchemaNode(colander.String(), missing=None)
|
||||
status_change = colander.SchemaNode(colander.String(), missing=None)
|
||||
renderer_type = colander.SchemaNode(colander.String())
|
||||
|
||||
# do those ?
|
||||
user = colander.SchemaNode(types.StrOrIntType())
|
||||
repo = colander.SchemaNode(types.StrOrIntType())
|
||||
|
|
@ -186,3 +186,11 @@ class UserType(UserOrUserGroupType):
|
|||
|
||||
class UserGroupType(UserOrUserGroupType):
|
||||
scopes = ('usergroup',)
|
||||
|
||||
|
||||
class StrOrIntType(colander.String):
|
||||
def deserialize(self, node, cstruct):
|
||||
if isinstance(node, basestring):
|
||||
return super(StrOrIntType, self).deserialize(node, cstruct)
|
||||
else:
|
||||
return colander.Integer().deserialize(node, cstruct)
|
||||
|
|
|
|||
|
|
@ -880,8 +880,6 @@ input.filediff-collapse-state {
|
|||
display: inline;
|
||||
}
|
||||
|
||||
@comment-padding: 5px;
|
||||
|
||||
/**** COMMENTS ****/
|
||||
|
||||
.filediff-menu {
|
||||
|
|
@ -909,59 +907,6 @@ input.filediff-collapse-state {
|
|||
}
|
||||
}
|
||||
|
||||
.inline-comments {
|
||||
border-radius: @border-radius;
|
||||
.comment {
|
||||
margin: 0;
|
||||
border-radius: @border-radius;
|
||||
}
|
||||
.comment-outdated {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.comment-inline {
|
||||
background: white;
|
||||
padding: (@comment-padding + 3px) @comment-padding;
|
||||
border: @comment-padding solid @grey6;
|
||||
|
||||
.text {
|
||||
border: none;
|
||||
}
|
||||
.meta {
|
||||
border-bottom: 1px solid @grey6;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
.comment-selected {
|
||||
border-left: 6px solid @comment-highlight-color;
|
||||
}
|
||||
.comment-inline-form {
|
||||
padding: @comment-padding;
|
||||
display: none;
|
||||
}
|
||||
.cb-comment-add-button {
|
||||
margin: @comment-padding;
|
||||
}
|
||||
/* hide add comment button when form is open */
|
||||
.comment-inline-form-open ~ .cb-comment-add-button {
|
||||
display: none;
|
||||
}
|
||||
.comment-inline-form-open {
|
||||
display: block;
|
||||
}
|
||||
/* hide add comment button when form but no comments */
|
||||
.comment-inline-form:first-child + .cb-comment-add-button {
|
||||
display: none;
|
||||
}
|
||||
/* hide add comment button when no comments or form */
|
||||
.cb-comment-add-button:first-child {
|
||||
display: none;
|
||||
}
|
||||
/* hide add comment button when only comment is being deleted */
|
||||
.comment-deleting:first-child + .cb-comment-add-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
/**** END COMMENTS ****/
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,33 @@ tr.inline-comments div {
|
|||
visibility: hidden;
|
||||
}
|
||||
|
||||
.comment-label {
|
||||
float: left;
|
||||
|
||||
padding: 0.4em 0.4em;
|
||||
margin: 2px 5px 0px -10px;
|
||||
display: inline-block;
|
||||
min-height: 0;
|
||||
|
||||
text-align: center;
|
||||
font-size: 10px;
|
||||
line-height: .8em;
|
||||
|
||||
font-family: @text-italic;
|
||||
background: #fff none;
|
||||
color: @grey4;
|
||||
border: 1px solid @grey4;
|
||||
white-space: nowrap;
|
||||
|
||||
text-transform: uppercase;
|
||||
|
||||
&.todo {
|
||||
color: @color5;
|
||||
font-family: @text-bold-italic;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.comment {
|
||||
|
||||
&.comment-general {
|
||||
|
|
@ -60,15 +87,19 @@ tr.inline-comments div {
|
|||
|
||||
.rc-user {
|
||||
min-width: 0;
|
||||
margin: -2px .5em 0 0;
|
||||
margin: 0px .5em 0 0;
|
||||
|
||||
.user {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.meta {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin: 0 0 .5em 0;
|
||||
border-bottom: 1px solid @grey5;
|
||||
padding: 8px 0px;
|
||||
margin: -5px 0px;
|
||||
line-height: 24px;
|
||||
|
||||
&:hover .permalink {
|
||||
visibility: visible;
|
||||
|
|
@ -87,10 +118,10 @@ tr.inline-comments div {
|
|||
}
|
||||
|
||||
.author-general img {
|
||||
top: -3px;
|
||||
top: 3px;
|
||||
}
|
||||
.author-inline img {
|
||||
top: -3px;
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
.status-change,
|
||||
|
|
@ -182,7 +213,7 @@ tr.inline-comments div {
|
|||
}
|
||||
.pr-version-inline {
|
||||
float: left;
|
||||
margin: 1px 4px;
|
||||
margin: 0px 4px;
|
||||
}
|
||||
.pr-version-num {
|
||||
font-size: 10px;
|
||||
|
|
@ -190,6 +221,64 @@ tr.inline-comments div {
|
|||
|
||||
}
|
||||
|
||||
@comment-padding: 5px;
|
||||
|
||||
.inline-comments {
|
||||
border-radius: @border-radius;
|
||||
.comment {
|
||||
margin: 0;
|
||||
border-radius: @border-radius;
|
||||
}
|
||||
.comment-outdated {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.comment-inline {
|
||||
background: white;
|
||||
padding: @comment-padding @comment-padding;
|
||||
border: @comment-padding solid @grey6;
|
||||
|
||||
.text {
|
||||
border: none;
|
||||
}
|
||||
.meta {
|
||||
border-bottom: 1px solid @grey6;
|
||||
margin: -5px 0px;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
.comment-selected {
|
||||
border-left: 6px solid @comment-highlight-color;
|
||||
}
|
||||
.comment-inline-form {
|
||||
padding: @comment-padding;
|
||||
display: none;
|
||||
}
|
||||
.cb-comment-add-button {
|
||||
margin: @comment-padding;
|
||||
}
|
||||
/* hide add comment button when form is open */
|
||||
.comment-inline-form-open ~ .cb-comment-add-button {
|
||||
display: none;
|
||||
}
|
||||
.comment-inline-form-open {
|
||||
display: block;
|
||||
}
|
||||
/* hide add comment button when form but no comments */
|
||||
.comment-inline-form:first-child + .cb-comment-add-button {
|
||||
display: none;
|
||||
}
|
||||
/* hide add comment button when no comments or form */
|
||||
.cb-comment-add-button:first-child {
|
||||
display: none;
|
||||
}
|
||||
/* hide add comment button when only comment is being deleted */
|
||||
.comment-deleting:first-child + .cb-comment-add-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.show-outdated-comments {
|
||||
display: inline;
|
||||
color: @rcblue;
|
||||
|
|
@ -300,6 +389,12 @@ form.comment-form {
|
|||
}
|
||||
}
|
||||
|
||||
.comment-type {
|
||||
margin: 0px;
|
||||
border-radius: inherit;
|
||||
border-color: @grey6;
|
||||
}
|
||||
|
||||
.preview-box {
|
||||
min-height: 105px;
|
||||
margin-bottom: 15px;
|
||||
|
|
|
|||
|
|
@ -688,6 +688,7 @@ label {
|
|||
padding: 0;
|
||||
line-height: 1em;
|
||||
border: 1px solid @grey4;
|
||||
box-sizing: content-box;
|
||||
|
||||
&.gravatar-large {
|
||||
margin: -0.5em .25em -0.5em 0;
|
||||
|
|
|
|||
|
|
@ -132,13 +132,14 @@ var CommentForm = (function() {
|
|||
|
||||
this.editButton = this.withLineNo('#edit-btn');
|
||||
this.editContainer = this.withLineNo('#edit-container');
|
||||
|
||||
this.cancelButton = this.withLineNo('#cancel-btn');
|
||||
this.commentType = this.withLineNo('#comment_type');
|
||||
|
||||
this.statusChange = '#change_status';
|
||||
this.cmBox = this.withLineNo('#text');
|
||||
this.cm = initCommentBoxCodeMirror(this.cmBox, this.initAutocompleteActions);
|
||||
|
||||
this.statusChange = '#change_status';
|
||||
|
||||
this.submitForm = formElement;
|
||||
this.submitButton = $(this.submitForm).find('input[type="submit"]');
|
||||
this.submitButtonText = this.submitButton.val();
|
||||
|
|
@ -172,7 +173,9 @@ var CommentForm = (function() {
|
|||
this.getCommentStatus = function() {
|
||||
return $(this.submitForm).find(this.statusChange).val();
|
||||
};
|
||||
|
||||
this.getCommentType = function() {
|
||||
return $(this.submitForm).find(this.commentType).val();
|
||||
};
|
||||
this.isAllowedToSubmit = function() {
|
||||
return !$(this.submitButton).prop('disabled');
|
||||
};
|
||||
|
|
@ -256,6 +259,7 @@ var CommentForm = (function() {
|
|||
this.handleFormSubmit = function() {
|
||||
var text = self.cm.getValue();
|
||||
var status = self.getCommentStatus();
|
||||
var commentType = self.getCommentType();
|
||||
|
||||
if (text === "" && !status) {
|
||||
return;
|
||||
|
|
@ -268,6 +272,7 @@ var CommentForm = (function() {
|
|||
var postData = {
|
||||
'text': text,
|
||||
'changeset_status': status,
|
||||
'comment_type': commentType,
|
||||
'csrf_token': CSRF_TOKEN
|
||||
};
|
||||
|
||||
|
|
@ -536,6 +541,7 @@ var CommentsController = function() { /* comments controller */
|
|||
$filediff.removeClass('hide-comments');
|
||||
var f_path = $filediff.attr('data-f-path');
|
||||
var lineno = self.getLineNumber(node);
|
||||
|
||||
tmpl = tmpl.format(f_path, lineno);
|
||||
$form = $(tmpl);
|
||||
|
||||
|
|
@ -557,6 +563,7 @@ var CommentsController = function() { /* comments controller */
|
|||
// set a CUSTOM submit handler for inline comments.
|
||||
commentForm.setHandleFormSubmit(function(o) {
|
||||
var text = commentForm.cm.getValue();
|
||||
var commentType = commentForm.getCommentType();
|
||||
|
||||
if (text === "") {
|
||||
return;
|
||||
|
|
@ -579,6 +586,7 @@ var CommentsController = function() { /* comments controller */
|
|||
'text': text,
|
||||
'f_path': f_path,
|
||||
'line': lineno,
|
||||
'comment_type': commentType,
|
||||
'csrf_token': CSRF_TOKEN
|
||||
};
|
||||
var submitSuccessCallback = function(json_data) {
|
||||
|
|
|
|||
|
|
@ -18,8 +18,14 @@
|
|||
style="${'display: none;' if outdated_at_ver else ''}">
|
||||
|
||||
<div class="meta">
|
||||
<div class="comment-type-label tooltip">
|
||||
<div class="comment-label ${comment.comment_type or 'note'}">
|
||||
${comment.comment_type or 'note'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="author ${'author-inline' if inline else 'author-general'}">
|
||||
${base.gravatar_with_user(comment.author.email, 20)}
|
||||
${base.gravatar_with_user(comment.author.email, 16)}
|
||||
</div>
|
||||
<div class="date">
|
||||
${h.age_component(comment.modified_at, time_is_local=True)}
|
||||
|
|
@ -31,16 +37,14 @@
|
|||
% if comment.pull_request:
|
||||
<a href="${h.url('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id)}">
|
||||
% if comment.status_change:
|
||||
${_('Vote on pull request #%s') % comment.pull_request.pull_request_id}:
|
||||
${_('pull request #%s') % comment.pull_request.pull_request_id}:
|
||||
% else:
|
||||
${_('Comment on pull request #%s') % comment.pull_request.pull_request_id}
|
||||
${_('pull request #%s') % comment.pull_request.pull_request_id}
|
||||
% endif
|
||||
</a>
|
||||
% else:
|
||||
% if comment.status_change:
|
||||
${_('Status change on commit')}:
|
||||
% else:
|
||||
${_('Comment on commit')}
|
||||
% endif
|
||||
% endif
|
||||
</div>
|
||||
|
|
@ -185,6 +189,13 @@
|
|||
<li class="">
|
||||
<a href="#preview-btn" tabindex="-1" id="preview-btn">${_('Preview')}</a>
|
||||
</li>
|
||||
<li class="pull-right">
|
||||
<select class="comment-type" id="comment_type" name="comment_type">
|
||||
% for val in c.visual.comment_types:
|
||||
<option value="${val}">${val.upper()}</option>
|
||||
% endfor
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,13 @@ return h.url('', **new_args)
|
|||
<li class="">
|
||||
<a href="#preview-btn" tabindex="-1" id="preview-btn_{1}">${_('Preview')}</a>
|
||||
</li>
|
||||
<li class="pull-right">
|
||||
<select class="comment-type" id="comment_type_{1}" name="comment_type">
|
||||
% for val in c.visual.comment_types:
|
||||
<option value="${val}">${val.upper()}</option>
|
||||
% endfor
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue