Mercurial > libervia-backend
comparison src/plugins/plugin_misc_tickets.py @ 2447:9e692f09f367
plugin tickets: handle "update" flag + various improvments:
- ticketsSet renamed to ticketSet as only one ticket is set at a time
- dateFilter is not crashing anymore if value can't be parsed: the value is then return unmodified
- form_ns can be specified in get, so the method can be used by other plugins
- new "update" flag: if set in extra, an previous ticket of the same id will be retrieved, and used as a basis for an update
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 30 Nov 2017 20:34:41 +0100 |
parents | 81a45e7886c9 |
children | 544c4d2fec45 |
comparison
equal
deleted
inserted
replaced
2446:bfd1e9d737c4 | 2447:9e692f09f367 |
---|---|
17 # You should have received a copy of the GNU Affero General Public License | 17 # You should have received a copy of the GNU Affero General Public License |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
20 from sat.core.i18n import _ | 20 from sat.core.i18n import _ |
21 from sat.core.constants import Const as C | 21 from sat.core.constants import Const as C |
22 from sat.core import exceptions | |
22 from twisted.words.protocols.jabber import jid | 23 from twisted.words.protocols.jabber import jid |
23 from twisted.internet import defer | 24 from twisted.internet import defer |
24 from wokkel import generic | 25 from wokkel import generic |
25 from sat.tools import utils | 26 from sat.tools import utils |
26 from sat.tools.common import uri | 27 from sat.tools.common import uri |
27 from sat.core.log import getLogger | 28 from sat.core.log import getLogger |
28 import shortuuid | 29 import shortuuid |
30 from wokkel import data_form | |
29 log = getLogger(__name__) | 31 log = getLogger(__name__) |
30 | 32 |
31 NS_TICKETS = 'org.salut-a-toi.tickets:0' | 33 NS_TICKETS = 'org.salut-a-toi.tickets:0' |
32 | 34 |
33 PLUGIN_INFO = { | 35 PLUGIN_INFO = { |
55 host.bridge.addMethod("ticketsGet", ".plugin", | 57 host.bridge.addMethod("ticketsGet", ".plugin", |
56 in_sign='ssiassa{ss}s', out_sign='(asa{ss})', | 58 in_sign='ssiassa{ss}s', out_sign='(asa{ss})', |
57 method=self._get, | 59 method=self._get, |
58 async=True | 60 async=True |
59 ) | 61 ) |
60 host.bridge.addMethod("ticketsSet", ".plugin", | 62 host.bridge.addMethod("ticketSet", ".plugin", |
61 in_sign='ssa{sas}ssa{ss}s', out_sign='s', | 63 in_sign='ssa{sas}ssa{ss}s', out_sign='s', |
62 method=self._set, | 64 method=self._set, |
63 async=True) | 65 async=True) |
64 host.bridge.addMethod("ticketsSchemaGet", ".plugin", | 66 host.bridge.addMethod("ticketsSchemaGet", ".plugin", |
65 in_sign='sss', out_sign='s', | 67 in_sign='sss', out_sign='s', |
87 'name': kwargs.get('name'), | 89 'name': kwargs.get('name'), |
88 'styles': (u'noselect', u'extensible', u'reducible')} | 90 'styles': (u'noselect', u'extensible', u'reducible')} |
89 return widget_type, args, kwargs | 91 return widget_type, args, kwargs |
90 | 92 |
91 def _dateFilter(self, form_xmlui, widget_type, args, kwargs): | 93 def _dateFilter(self, form_xmlui, widget_type, args, kwargs): |
92 if widget_type != u'string': | 94 if widget_type != u'string' or not args[0]: |
93 return widget_type, args, kwargs | 95 return widget_type, args, kwargs |
94 # we convert XMPP date to timestamp | 96 # we convert XMPP date to timestamp |
95 args[0] = unicode(utils.date_parse(args[0])) | 97 try: |
98 args[0] = unicode(utils.date_parse(args[0])) | |
99 except Exception as e: | |
100 log.warning(_(u"Can't parse date field: {msg}").format(msg=e)) | |
96 return widget_type, args, kwargs | 101 return widget_type, args, kwargs |
97 | 102 |
98 def _get(self, service='', node='', max_items=10, item_ids=None, sub_id=None, extra_dict=None, profile_key=C.PROF_KEY_NONE): | 103 def _get(self, service='', node='', max_items=10, item_ids=None, sub_id=None, extra_dict=None, profile_key=C.PROF_KEY_NONE): |
99 client = self.host.getClient(profile_key) | 104 client = self.host.getClient(profile_key) |
100 service = jid.JID(service) if service else None | 105 service = jid.JID(service) if service else None |
103 d = self.get(client, service, node or None, max_items, item_ids, sub_id or None, extra.rsm_request, extra.extra) | 108 d = self.get(client, service, node or None, max_items, item_ids, sub_id or None, extra.rsm_request, extra.extra) |
104 d.addCallback(self._p.serItemsData) | 109 d.addCallback(self._p.serItemsData) |
105 return d | 110 return d |
106 | 111 |
107 @defer.inlineCallbacks | 112 @defer.inlineCallbacks |
108 def get(self, client, service=None, node=None, max_items=None, item_ids=None, sub_id=None, rsm_request=None, extra=None): | 113 def get(self, client, service=None, node=None, max_items=None, item_ids=None, sub_id=None, rsm_request=None, extra=None, form_ns=NS_TICKETS): |
109 """Retrieve tickets and convert them to XMLUI | 114 """Retrieve tickets and convert them to XMLUI |
110 | 115 |
116 @param service(None, jid.JID): Pubsub service to use | |
111 @param node(unicode, None): PubSub node to use | 117 @param node(unicode, None): PubSub node to use |
112 if None, default ticket node will be used | 118 if None, default ticket node will be used |
113 other parameters as the same as for [XEP_0060.getItems] | 119 other parameters as the same as for [XEP_0060.getItems] |
114 @return (list[unicode]): XMLUI of the tickets | 120 @return (tuple(list[unicode], dict[unicode, object])): |
121 - XMLUI of the tickets | |
122 - metadata dict | |
115 """ | 123 """ |
116 if not node: | 124 if not node: |
117 node = NS_TICKETS | 125 node = NS_TICKETS |
118 filters = {u'reporter': lambda *args: self._reporterFilter(client, *args), | 126 filters = {u'reporter': lambda *args: self._reporterFilter(client, *args), |
119 u'labels': self._labelsFilter, | 127 u'labels': self._labelsFilter, |
120 u'created': self._dateFilter, | 128 u'created': self._dateFilter, |
121 u'updated': self._dateFilter, | 129 u'updated': self._dateFilter, |
122 } | 130 } |
123 tickets, metadata = yield self._s.getDataFormItems( | 131 tickets, metadata = yield self._s.getDataFormItems( |
124 client, | 132 client, |
125 NS_TICKETS, | 133 form_ns, |
126 service, | 134 service, |
127 node, | 135 node, |
128 max_items = max_items, | 136 max_items = max_items, |
129 item_ids = item_ids, | 137 item_ids = item_ids, |
130 sub_id = sub_id, | 138 sub_id = sub_id, |
140 service = None if not service else jid.JID(service) | 148 service = None if not service else jid.JID(service) |
141 if schema: | 149 if schema: |
142 schema = generic.parseXml(schema.encode('utf-8')) | 150 schema = generic.parseXml(schema.encode('utf-8')) |
143 else: | 151 else: |
144 schema = None | 152 schema = None |
153 if extra and u'update' in extra: | |
154 extra[u'update'] = C.bool(extra[u'update']) | |
145 d = self.set(client, service, node or None, values, schema, item_id or None, extra, deserialise=True) | 155 d = self.set(client, service, node or None, values, schema, item_id or None, extra, deserialise=True) |
146 d.addCallback(lambda ret: ret or u'') | 156 d.addCallback(lambda ret: ret or u'') |
147 return d | 157 return d |
148 | 158 |
149 @defer.inlineCallbacks | 159 @defer.inlineCallbacks |
150 def set(self, client, service, node, values, schema=None, item_id=None, extra=None, deserialise=False): | 160 def set(self, client, service, node, values, schema=None, item_id=None, extra=None, deserialise=False, form_ns=NS_TICKETS): |
151 """Publish a tickets | 161 """Publish a tickets |
152 | 162 |
153 @param node(unicode, None): Pubsub node to use | 163 @param node(unicode, None): Pubsub node to use |
154 None to use default tickets node | 164 None to use default tickets node |
155 @param values(dict[key(unicode), [iterable[object], object]]): values of the ticket | 165 @param values(dict[key(unicode), [iterable[object], object]]): values of the ticket |
156 if not iterable, will be put in a list | 166 if not iterable, will be put in a list |
157 'created' and 'updated' will be forced to current time: | 167 'created' and 'updated' will be forced to current time: |
158 - 'created' is set if item_id is None, i.e. if it's a new ticket | 168 - 'created' is set if item_id is None, i.e. if it's a new ticket |
159 - 'updated' is set everytime | 169 - 'updated' is set everytime |
170 @param extra(dict, None): same as for [XEP-0060.sendItem] with additional keys: | |
171 - update(bool): if True, get previous item data to merge with current one | |
172 if True, item_id must be None | |
160 other arguments are same as for [self._s.sendDataFormItem] | 173 other arguments are same as for [self._s.sendDataFormItem] |
161 @return (unicode): id of the created item | 174 @return (unicode): id of the created item |
162 """ | 175 """ |
163 if not node: | 176 if not node: |
164 node = NS_TICKETS | 177 node = NS_TICKETS |
178 self._p.OPT_SEND_ITEM_SUBSCRIBE: 1, | 191 self._p.OPT_SEND_ITEM_SUBSCRIBE: 1, |
179 self._p.OPT_PUBLISH_MODEL: self._p.ACCESS_OPEN, | 192 self._p.OPT_PUBLISH_MODEL: self._p.ACCESS_OPEN, |
180 } | 193 } |
181 yield self._p.createNode(client, comments_service, comments_node, options) | 194 yield self._p.createNode(client, comments_service, comments_node, options) |
182 values['comments_uri'] = uri.buildXMPPUri(u'pubsub', subtype='microblog', path=comments_service.full(), node=comments_node) | 195 values['comments_uri'] = uri.buildXMPPUri(u'pubsub', subtype='microblog', path=comments_service.full(), node=comments_node) |
196 elif extra.get(u'update', False): | |
197 if item_id is None: | |
198 raise exceptions.DataError(_(u'if extra["update"] is set, item_id must be set too')) | |
199 try: | |
200 # we get previous item | |
201 items_data = yield self._p.getItems(client, service, node, item_ids=[item_id]) | |
202 item_elt = items_data[0][0] | |
203 except Exception as e: | |
204 log.warning(_(u"Can't get previous item, update ignored: {reason}").format( | |
205 reason = e)) | |
206 else: | |
207 # and parse it | |
208 form = data_form.findForm(item_elt, form_ns) | |
209 if form is None: | |
210 log.warning(_(u"Can't parse previous item, update ignored: data form not found").format( | |
211 reason = e)) | |
212 else: | |
213 for name, field in form.fields.iteritems(): | |
214 if name not in values: | |
215 values[name] = u'\n'.join(unicode(v) for v in field.values) | |
183 | 216 |
184 values['updated'] = now | 217 values['updated'] = now |
185 if not values.get('reporter'): | 218 if not values.get('reporter'): |
186 identity = yield self._i.getIdentity(client, client.jid) | 219 identity = yield self._i.getIdentity(client, client.jid) |
187 values['reporter'] = identity['nick'] | 220 values['reporter'] = identity['nick'] |