diff --git a/funenc_json_widget/__init__.py b/funenc_json_widget/__init__.py new file mode 100644 index 000000000..40a96afc6 --- /dev/null +++ b/funenc_json_widget/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/funenc_json_widget/__manifest__.py b/funenc_json_widget/__manifest__.py new file mode 100644 index 000000000..a2996a5a0 --- /dev/null +++ b/funenc_json_widget/__manifest__.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +{ + 'name': "funenc_json_widget", + + 'summary': """ + json widget for odoo + """, + + 'description': """ + json widget for odoo + json + template widget + template + color widget + color + """, + + 'author': "Funenc", + 'website': "http://odoo.funenc.com", + "images": [ + "static/description/description.gif" + ], + + 'category': 'App/json', + 'version': '17.0.0.1', + 'price': 5, + 'license': 'OPL-1', + + 'depends': ['base', 'web'], + 'data': [], + + 'assets': { + 'web.assets_backend': [ + 'funenc_json_widget/static/src/json_widget.js', + ] + } +} diff --git a/funenc_json_widget/static/description/anita_description.png b/funenc_json_widget/static/description/anita_description.png new file mode 100644 index 000000000..1a9031c40 Binary files /dev/null and b/funenc_json_widget/static/description/anita_description.png differ diff --git a/funenc_json_widget/static/description/anita_screenshot.png b/funenc_json_widget/static/description/anita_screenshot.png new file mode 100644 index 000000000..9157fc68c Binary files /dev/null and b/funenc_json_widget/static/description/anita_screenshot.png differ diff --git a/funenc_json_widget/static/description/anita_switcher.png b/funenc_json_widget/static/description/anita_switcher.png new file mode 100644 index 000000000..f7309adcc Binary files /dev/null and b/funenc_json_widget/static/description/anita_switcher.png differ diff --git a/funenc_json_widget/static/description/banner.png b/funenc_json_widget/static/description/banner.png new file mode 100644 index 000000000..73860a046 Binary files /dev/null and b/funenc_json_widget/static/description/banner.png differ diff --git a/funenc_json_widget/static/description/description.gif b/funenc_json_widget/static/description/description.gif new file mode 100644 index 000000000..182dda2e3 Binary files /dev/null and b/funenc_json_widget/static/description/description.gif differ diff --git a/funenc_json_widget/static/description/description.png b/funenc_json_widget/static/description/description.png new file mode 100644 index 000000000..f96b82b58 Binary files /dev/null and b/funenc_json_widget/static/description/description.png differ diff --git a/funenc_json_widget/static/description/icon.png b/funenc_json_widget/static/description/icon.png new file mode 100644 index 000000000..29b122848 Binary files /dev/null and b/funenc_json_widget/static/description/icon.png differ diff --git a/funenc_json_widget/static/description/index.html b/funenc_json_widget/static/description/index.html new file mode 100644 index 000000000..2e005d1d6 --- /dev/null +++ b/funenc_json_widget/static/description/index.html @@ -0,0 +1,67 @@ +
+ +
+
+
+
+

+ This is a json widget for odoo!!! it used to format json data to html. +

+
+
+
+ +

(Current Release V15.0.0.1 -- 2022.08.09)

+ +
+ +
+ +
+
+

+ Our Other Apps +

+
+
+
+
+
+ + + +
+
+
+
+
+
+ + + +
+
+
+
+
+
+ + + +
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/funenc_json_widget/static/src/json_widget.js b/funenc_json_widget/static/src/json_widget.js new file mode 100644 index 000000000..964680c9a --- /dev/null +++ b/funenc_json_widget/static/src/json_widget.js @@ -0,0 +1,57 @@ +/** @odoo-module **/ + +import { registry } from "@web/core/registry"; +import { _t } from "@web/core/l10n/translation"; +import { standardFieldProps } from "@web/views/fields/standard_field_props"; +import { Component, xml } from "@odoo/owl"; + +export class JsonTemplateWidget extends Component { + + static template = xml` +
+ +
` + + static props = { + ...standardFieldProps, + }; + + setup() { + console.log(this) + } + + get isReadonly() { + return true; + } + + get_template_id() { + if (!this.template_id) { + try { + debugger + let name = this.props.name; + let data = this.props.record.data; + let value = data[name] || "{}" + this.value = JSON.parse(value); + if (!this.value || !this.value.template) { + this.template_id = xml``; + } else { + this.template_id = this.value.template; + } + } catch (e) { + this.template_id = xml`${e.message}`; + } + } + return this.template_id; + } +} + + + +export const JsonTemplateField = { + component: JsonTemplateWidget, + displayName: _t("Json Template"), + supportedTypes: ["char", "text"], + isEmpty: () => false +}; + +registry.category("fields").add("json_template", JsonTemplateField); diff --git a/preview_easy/__manifest__.py b/preview_easy/__manifest__.py index 5929f3b8f..9ec4f3da5 100644 --- a/preview_easy/__manifest__.py +++ b/preview_easy/__manifest__.py @@ -11,33 +11,34 @@ 'author': 'zxltwins', 'website': "www.odoo.com", 'version': '17.0', - "depends": ["base", 'sale'], + "depends": ["base",'sale'], "external_dependencies": {"python": ["mammoth"]}, "data": [ 'security/ir.model.access.csv', 'views/preview.xml'], 'assets': { - 'web._assets_primary_variables': [ + 'web._assets_primary_variables': [ - ], - 'web.assets_backend': [ - 'preview_easy/static/src/js/qweb.js', - 'preview_easy/static/src/xml/qweb.xml' - ], - 'web.assets_frontend': [ + ], + 'web.assets_backend': [ + 'preview_easy/static/src/js/qweb.js', + 'preview_easy/static/src/xml/qweb.xml' + ], + 'web.assets_frontend': [ - ], - 'web.assets_tests': [ - ], + ], + 'web.assets_tests': [ - 'web.report_assets_common': [ + ], - ], - 'web.report_assets_pdf': [ + 'web.report_assets_common': [ - ], - }, + ], + 'web.report_assets_pdf': [ + + ], + }, 'images': [ 'static/description/main_screenshot.png', diff --git a/preview_easy/controllers/preview.py b/preview_easy/controllers/preview.py index f6c05b9a6..02515578b 100644 --- a/preview_easy/controllers/preview.py +++ b/preview_easy/controllers/preview.py @@ -10,16 +10,14 @@ import mammoth class preview(http.Controller): - - @http.route('/web/content/preview/', type='http', method=['Get'], auth="user") + @http.route('/web/content/preview/', type='http', method=['Get'], auth="public") def content_preview(self, id=None): ir_attach = request.env['ir.attachment'].sudo() attach = ir_attach.browse(id) image = ['image/jpeg', 'image/png', 'image/bmp', 'image/gif', 'image/jpg', 'image/svg'] html = ['text/html'] video = ['video/mp4', 'video/webm', 'video/wmv', 'video/asf', 'video/divx', 'video/rm', 'video/mkv', - 'video/flv', 'video/3gp', - 'video/wma', 'video/wav', 'video/ape', 'video/mpeg', 'video/mpg'] + 'video/flv', 'video/3gp', 'video/wma', 'video/wav', 'video/ape', 'video/mpeg', 'video/mpg'] pdf = ['application/pdf'] txt = ['text/plain'] excel = ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel'] @@ -36,23 +34,25 @@ class preview(http.Controller): html = result.value return template.render(html=html) elif attach.mimetype in excel: - # base_url = env['ir.config_parameter'].sudo().get_param('web.base.url') + # base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url') # env.cr.dbname - # html = "https://view.officeapps.live.com/op/view.aspx?src=" + "https://pengyuthon.com" + "/web/content/" + id - html = "https://view.officeapps.live.com/op/view.aspx?src=" + "http://youthpower.ltd/blogger_lib_admin/test.xlsx" + # /web/content/ir.attachment/2/datas?download = true 这个是下载 + url_login = "https://pengyuthon.com/web/content/ir.attachment/" + str(id) + '/datas' + url = "https://pengyuthon.com/web/content/preview/" + str(id) + "/" + html = "https://view.officeapps.live.com/op/view.aspx?src=" + url + # html = "https://view.officeapps.live.com/op/view.aspx?src=" + "http://youthpower.ltd/blogger_lib_admin/test.xlsx" return werkzeug.wrappers.Response(f""" - - - - - - - - + "http://www.w3.org/TR/html4/loose.dtd"> + + + + + + + + """, status=200, headers=[('Content-Type', 'text/html'), ('charset', 'utf-8')]) - else: return werkzeug.wrappers.Response('This format is not currently supported', status=200, headers=[('Content-Type', 'text/html'),('charset','utf-8')]) diff --git a/preview_easy/static/src/js/qweb.js b/preview_easy/static/src/js/qweb.js index df481f6eb..66e5508ad 100644 --- a/preview_easy/static/src/js/qweb.js +++ b/preview_easy/static/src/js/qweb.js @@ -6,19 +6,40 @@ import {standardFieldProps} from "@web/views/fields/standard_field_props"; import { FileInput } from "@web/core/file_input/file_input"; import { useX2ManyCrud } from "@web/views/fields/relational_utils"; import { Component } from "@odoo/owl"; +import { TagsList } from "@web/core/tags_list/tags_list"; import { Dialog } from "@web/core/dialog/dialog"; -export class Many2ManyBinaryField extends Component { +import { + Many2XAutocomplete, + useActiveActions, +} from "@web/views/fields/relational_utils"; +import { Many2ManyTagsField, many2ManyTagsField } from "@web/views/fields/many2many_tags/many2many_tags_field"; + +export class Many2ManyBinaryField extends Many2ManyTagsField { static template = "web.Many2ManyBinaryField"; static components = { FileInput, + TagsList, + Many2XAutocomplete, }; static props = { ...standardFieldProps, acceptedFileExtensions: { type: String, optional: true }, className: { type: String, optional: true }, + canCreate: { type: Boolean, optional: true }, + canQuickCreate: { type: Boolean, optional: true }, + canCreateEdit: { type: Boolean, optional: true }, + colorField: { type: String, optional: true }, + createDomain: { type: [Array, Boolean], optional: true }, + domain: { type: [Array, Function], optional: true }, + context: { type: Object, optional: true }, + placeholder: { type: String, optional: true }, + nameCreateField: { type: String, optional: true }, + string: { type: String, optional: true }, + noSearchMore: { type: Boolean, optional: true }, }; setup() { + super.setup() this.orm = useService("orm"); this.notification = useService("notification"); this.operations = useX2ManyCrud(() => this.props.record.data[this.props.name], true); diff --git a/preview_easy/static/src/xml/qweb.xml b/preview_easy/static/src/xml/qweb.xml index 6c7046c6e..4410d398c 100644 --- a/preview_easy/static/src/xml/qweb.xml +++ b/preview_easy/static/src/xml/qweb.xml @@ -2,10 +2,28 @@ - - - - + + + + + + + + diff --git a/preview_easy/views/preview.xml b/preview_easy/views/preview.xml index c134bc35f..c3ac528bd 100644 --- a/preview_easy/views/preview.xml +++ b/preview_easy/views/preview.xml @@ -8,6 +8,7 @@ + diff --git a/room/models/room_booking.py b/room/models/room_booking.py index 8f4802950..bcd030d7d 100644 --- a/room/models/room_booking.py +++ b/room/models/room_booking.py @@ -18,8 +18,8 @@ class RoomBooking(models.Model): name = fields.Char(string="名称", required=True, tracking=1) room_id = fields.Many2one("room.room", string="Room", required=True, ondelete="cascade", group_expand="_read_group_room_id", tracking=4) - start_datetime = fields.Date(string="Start Datetime", required=True, tracking=2) - stop_datetime = fields.Date(string="End Datetime", required=True, tracking=3) + start_datetime = fields.Datetime(string="Start Datetime", required=True, tracking=2) + stop_datetime = fields.Datetime(string="End Datetime", required=True, tracking=3) organizer_id = fields.Many2one("res.users", string="Organizer", default=lambda self: self.env.user.id if not self.env.user._is_public() else False, tracking=5) diff --git a/yuthon_issue/__manifest__.py b/yuthon_issue/__manifest__.py index 11ac93363..b79446153 100644 --- a/yuthon_issue/__manifest__.py +++ b/yuthon_issue/__manifest__.py @@ -10,7 +10,7 @@ 'category': 'Human Resources/Attendances', 'version': '0.1', 'license': 'LGPL-3', - 'depends': ['mail', 'base', 'documents', 'room','soong_workflow'], + 'depends': ['mail', 'base', 'documents', 'room', 'soong_workflow', 'funenc_json_widget'], 'data': [ 'security/ir.model.access.csv', 'data/issue_library_code_data.xml', @@ -24,7 +24,7 @@ ], 'assets': { 'web.assets_backend': [ - 'yuthon_issue/static/xml/meeting.xml' + 'yuthon_issue/static/xml/issue_approval.xml' ], }, 'installable': True, diff --git a/yuthon_issue/models/inherit_room_booking.py b/yuthon_issue/models/inherit_room_booking.py index 04ab078de..c1a9c45e1 100644 --- a/yuthon_issue/models/inherit_room_booking.py +++ b/yuthon_issue/models/inherit_room_booking.py @@ -1,13 +1,7 @@ -import qrcode -import base64 -from io import BytesIO from odoo import api, fields, models, _ -from odoo.exceptions import ValidationError, UserError -import os -from datetime import timedelta -class InheritRoomBooking(models.Model): +class RoomBooking(models.Model): _inherit = 'room.booking' room_booking_library_ids = fields.One2many('issue.library', 'room_booking_id') @@ -16,7 +10,7 @@ class InheritRoomBooking(models.Model): @api.model_create_multi def create(self, vals_list): - records = super(InheritRoomBooking, self).create(vals_list) + records = super(RoomBooking, self).create(vals_list) for vals in vals_list: if vals['room_booking_library_ids']: for library_id in vals['room_booking_library_ids']: diff --git a/yuthon_issue/models/issue_approval.py b/yuthon_issue/models/issue_approval.py index 485eb880d..f1af4f1ae 100644 --- a/yuthon_issue/models/issue_approval.py +++ b/yuthon_issue/models/issue_approval.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from odoo import api, fields, models, tools from odoo.exceptions import UserError, ValidationError - +from datetime import date, datetime, time class IssueApproval(models.Model): _name = "issue.approval" @@ -9,7 +9,7 @@ class IssueApproval(models.Model): _inherit = ['soong.workflow.mixin'] _rec_name = 'name' - name = fields.Char(string='标题',required=True) + name = fields.Char(string='标题', required=True) code = fields.Char(string='编号', required=True, copy=False, default=lambda self: self.env['ir.sequence'].next_by_code('issue_approval_code')) yuthon_company = fields.Selection([('thtz', '天河投资集团'), ('thwg', '天河物管'), ('thlc', '天河粮储'), ('tctj', '天投城建'), @@ -18,9 +18,6 @@ class IssueApproval(models.Model): department_id = fields.Many2one('hr.department', string="部门") create_time = fields.Date(string='创建日期', default=lambda self: fields.Date.today()) user_id = fields.Many2one('res.users', string="经办人", default=lambda self: self.env.user) - - agenda_items = fields.Char(string="议题事项", compute='_compute_agenda_items') - decision_checklist = fields.Char(string="决策清单", compute='_compute_decision_checklist') meeting_details = fields.Char(string="会议详情") job_id = fields.Many2one('hr.job', string="岗位") is_attend = fields.Boolean(string="是否上会", default=True) @@ -28,17 +25,58 @@ class IssueApproval(models.Model): notice_documents_ids = fields.Many2many('ir.attachment', string='议题附件') approval_decision_id = fields.Many2one('issue.approval.decision', string="关联决策清单") - issue_library_ids = fields.One2many('issue.library', 'issue_approval_id', string="关联议题") - approval_decision_ids = fields.One2many('issue.approval.decision', 'issue_approval_id', string="决策清单") - room_approval_ids = fields.One2many('issue.approval.room.line', 'room_approval_id', string="会议详情明细行") + issue_library_ids = fields.One2many('issue.library', 'issue_approval_id', string="关联议题", store=True) + approval_decision_ids = fields.One2many('issue.approval.decision', 'issue_approval_id', string="决策清单", store=True) + room_approval_ids = fields.One2many('issue.approval.room.line', 'room_approval_id', string="会议详情明细行", store=True) + issue_data = fields.Char(string="议题事项js") + decision_data = fields.Char(string="决策清单js") + meeting_data = fields.Char(string="会议详情js") + issue_display = fields.Char(string="议题事项", default='{"template": "yuthon_issue.html_issue_demo"}') + decision_display = fields.Char(string="决策清单", default='{"template": "yuthon_issue.html_decision_demo"}') + meeting_display = fields.Char(string="会议详情", default='{"template": "yuthon_issue.table_meet_demo"}') + + is_parent_unit = fields.Boolean(string="上级单位", compute="_compute_is_parent_unit") @api.depends('issue_library_ids') - def _compute_agenda_items(self): - for record in self: - names = [item.name for item in record.issue_library_ids if item.name] - record.agenda_items = '、'.join(names) + def _compute_is_parent_unit(self): + for line in self: + line.is_parent_unit = bool(line.issue_library_ids.filtered('is_note')) + + @api.onchange('issue_library_ids') + def _onchange_issue_data(self): + self.issue_data = '' + names = [] + if self.issue_library_ids: + for record in self.issue_library_ids: + names += [item.name for item in record] + self.issue_data += ';'.join(names) + + @api.onchange('approval_decision_ids') + def _onchange_decision_data(self): + self.decision_data = '' + names = [] + if self.approval_decision_ids: + for record in self.approval_decision_ids: + names += [item.specifics for item in record] + self.decision_data += ';'.join(names) + + + @api.onchange('room_approval_ids') + def _onchange_meeting_data(self): + meet_str = '' + if self.room_approval_ids: + for record in self.room_approval_ids: + record_list = [] + record_list.append(record.meeting_type_id.name) + record_list.append(record.date_start.strftime('%Y%m%d')) + record_list.append(record.room_booking_id.name) + record_list.append(dict(record._fields['decision_results'].selection).get(record.decision_results) if record.decision_results else ' ') + meet_str = meet_str + '、'.join(record_list) + ';' + self.meeting_data = meet_str + else: + self.meeting_data = '' @api.model_create_multi def create(self, vals_list): @@ -48,12 +86,6 @@ class IssueApproval(models.Model): issue_id.write({'issue_approval_id': issue_id.id}) return super().create(vals_list) - @api.depends('approval_decision_ids') - def _compute_decision_checklist(self): - for record in self: - names = [item.specifics for item in record.approval_decision_ids] - record.decision_checklist = ','.join(names) - def pub_meeting_minutes(self): pass @@ -82,7 +114,7 @@ class IssueApprovalRoomLine(models.Model): date_end = fields.Date(string="结束时间") decision_results = fields.Selection([('agree', '通过'), ('disagree', '未通过')], string="决策结果") - # 为room_users_ids 传值 + # 为room_users_ids 传值 department_ids = fields.Many2many('hr.department', string='部门范围') employee_ids = fields.Many2many('hr.employee', string='人员范围') users_role_ids = fields.Many2many('soong.user.role', string='角色范围') diff --git a/yuthon_issue/models/issue_approval_decision.py b/yuthon_issue/models/issue_approval_decision.py index a3d095f93..f54e3a781 100644 --- a/yuthon_issue/models/issue_approval_decision.py +++ b/yuthon_issue/models/issue_approval_decision.py @@ -1,5 +1,4 @@ from odoo import api, fields, models, tools -from odoo.exceptions import ValidationError class IssueApprovalDecision(models.Model): @@ -35,26 +34,4 @@ class IssueApprovalDecision(models.Model): seq.sequence = '' - # @api.onchange('sequence', 'decision_id') - # def _onchange_department_code(self): - # for code in self: - # if code.sequence and code.decision_id: - # code.sequence = code.decision_id.sequence + ('.' + code.sequence if code.sequence else '') - # else: - # code.sequence = code.sequence - # code._update_child_sequences() - # - # def _update_child_sequences(self): - # def recursive_update(parent, parent_sequence): - # # 遍历每个子记录 - # for child in parent.child_ids: - # # 使用父级的 sequence 更新子级的 sequence - # new_sequence = parent_sequence + ('.' + child.sequence.split('.')[-1] if child.sequence else '') - # self.env['issue.approval.decision'].search([('id', '=', child.id.origin)]).write({'sequence': new_sequence}) - # # 递归处理孙级 - # recursive_update(child, new_sequence) - # # 从当前记录开始递归更新所有子孙级别 - # recursive_update(self, self.sequence) - - diff --git a/yuthon_issue/models/issue_approval_decision_type.py b/yuthon_issue/models/issue_approval_decision_type.py index 03cfcd7db..580db50b6 100644 --- a/yuthon_issue/models/issue_approval_decision_type.py +++ b/yuthon_issue/models/issue_approval_decision_type.py @@ -1,5 +1,4 @@ from odoo import api, fields, models, tools -from odoo.exceptions import ValidationError class IssueApprovalDecisionType(models.Model): @@ -26,12 +25,8 @@ class IssueApprovalDecisionType(models.Model): def _update_child_sequences(self): def recursive_update(parent, parent_sequence): - # 遍历每个子记录 for child in parent.child_ids: - # 使用父级的 sequence 更新子级的 sequence new_sequence = parent_sequence + ('.' + child.sequence.split('.')[-1] if child.sequence else '') self.env['issue.approval.decision.type'].search([('id', '=', child.id.origin)]).write({'sequence': new_sequence}) - # 递归处理孙级 recursive_update(child, new_sequence) - # 从当前记录开始递归更新所有子孙级别 - recursive_update(self, self.sequence) \ No newline at end of file + recursive_update(self, self.sequence) diff --git a/yuthon_issue/models/issue_library.py b/yuthon_issue/models/issue_library.py index bceb7237f..e9161e539 100644 --- a/yuthon_issue/models/issue_library.py +++ b/yuthon_issue/models/issue_library.py @@ -26,21 +26,7 @@ class IssueLibrary(models.Model): issue_library_line_ids = fields.One2many('issue.library.line', 'issue_library_id', string="决策明细") issue_library_approval_line_ids = fields.One2many('issue.library.approval.line', 'issue_approval_id', string='流程记录') room_booking_id = fields.Many2one('room.booking', string="会议室") - - # 审批中 # ☑ - # 已上会 - - # tree_ids - # json_content = fields.Text(string="json content", default={"name": "crax", "template": "yuthon_issue.meeting"}) # 配置 - # json_display = fields.Char(string="json display", default={"name": "crax", "template": "yuthon_issue.meeting"}) # 效果 - # - # @api.onchange('json_content') - # def _onchange_json_content(self): - # if self.json_content: - # self.json_display = self.json_content - # else: - # self.json_display = False def issue_pull(self): for record in self: @@ -63,9 +49,9 @@ class IssueLibrary(models.Model): self.write({"state": "cancel"}) def all_issue_pull(self): - # for record in self: - # if record.state in ['approval', 'cancel']: - # raise UserError("当前状态不允许提交") + for record in self: + if record.state in ['approval', 'cancel']: + raise UserError("当前状态不允许提交") issue_active_ids = self.env["issue.library"].browse(self._context.get('active_ids', self._context.get('active_id'))) form_id = self.env.ref("yuthon_issue.issue_library_approval_form").id self.write({"state": "approval"}) @@ -84,8 +70,6 @@ class IssueLibrary(models.Model): } } - - @api.depends('issue_library_line_ids') def _compute_issue_library_line_ids(self): for line in self: diff --git a/yuthon_issue/static/xml/issue_approval.xml b/yuthon_issue/static/xml/issue_approval.xml new file mode 100644 index 000000000..f245ea963 --- /dev/null +++ b/yuthon_issue/static/xml/issue_approval.xml @@ -0,0 +1,73 @@ + + + + +
+

+ + +
+
+

+
+
+ + + +
+

+ + +
+
+

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
会议类型会议时间会议名称决策结果
☑
☑上级单位 + + + +
+
+ +
\ No newline at end of file diff --git a/yuthon_issue/static/xml/meeting.xml b/yuthon_issue/static/xml/meeting.xml deleted file mode 100644 index b11c5a14f..000000000 --- a/yuthon_issue/static/xml/meeting.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
3Larry the Bird@twitter
-
-
\ No newline at end of file diff --git a/yuthon_issue/views/issue_approval_views.xml b/yuthon_issue/views/issue_approval_views.xml index 1bc82afac..b3033a1bf 100644 --- a/yuthon_issue/views/issue_approval_views.xml +++ b/yuthon_issue/views/issue_approval_views.xml @@ -4,13 +4,15 @@ issue.approval.tree issue.approval - + + + - - - + + +