comparison src/plugins/plugin_misc_tickets.py @ 2420:03da3ef5fb5b

plugin tickets: added ticketsSet and ticketsSchemaGet methods: those methods are high level methods specialised for tickets. ticketsSet will use default tickets node if node is not set, set "created" and "updated" fields, create comments node if the ticket is new, and associate it with "comments_uri" field. ticketsSchemaGet is like getUISchema with node defaulting to tickets default node.
author Goffi <goffi@goffi.org>
date Sun, 05 Nov 2017 15:36:06 +0100
parents f05c884cd3ef
children 3faf18111d61
comparison
equal deleted inserted replaced
2419:c38c54c47e16 2420:03da3ef5fb5b
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 twisted.words.protocols.jabber import jid 22 from twisted.words.protocols.jabber import jid
23 from twisted.internet import defer 23 from twisted.internet import defer
24 from wokkel import generic
24 from sat.tools import utils 25 from sat.tools import utils
26 from sat.tools.common import uri
25 from sat.core.log import getLogger 27 from sat.core.log import getLogger
28 import shortuuid
26 log = getLogger(__name__) 29 log = getLogger(__name__)
27 30
28 NS_TICKETS = 'org.salut-a-toi.tickets:0' 31 NS_TICKETS = 'org.salut-a-toi.tickets:0'
29 32
30 PLUGIN_INFO = { 33 PLUGIN_INFO = {
31 C.PI_NAME: _("Tickets management"), 34 C.PI_NAME: _("Tickets management"),
32 C.PI_IMPORT_NAME: "TICKETS", 35 C.PI_IMPORT_NAME: "TICKETS",
33 C.PI_TYPE: "EXP", 36 C.PI_TYPE: "EXP",
34 C.PI_PROTOCOLS: [], 37 C.PI_PROTOCOLS: [],
35 C.PI_DEPENDENCIES: ["XEP-0060", "PUBSUB_SCHEMA"], 38 C.PI_DEPENDENCIES: ["XEP-0060", "PUBSUB_SCHEMA", "XEP-0277"],
36 C.PI_MAIN: "Tickets", 39 C.PI_MAIN: "Tickets",
37 C.PI_HANDLER: "no", 40 C.PI_HANDLER: "no",
38 C.PI_DESCRIPTION: _("""Tickets management plugin""") 41 C.PI_DESCRIPTION: _("""Tickets management plugin""")
39 } 42 }
40 43
44 def __init__(self, host): 47 def __init__(self, host):
45 log.info(_(u"Tickets plugin initialization")) 48 log.info(_(u"Tickets plugin initialization"))
46 self.host = host 49 self.host = host
47 self._p = self.host.plugins["XEP-0060"] 50 self._p = self.host.plugins["XEP-0060"]
48 self._s = self.host.plugins["PUBSUB_SCHEMA"] 51 self._s = self.host.plugins["PUBSUB_SCHEMA"]
52 self._m = self.host.plugins["XEP-0277"]
49 host.bridge.addMethod("ticketsGet", ".plugin", 53 host.bridge.addMethod("ticketsGet", ".plugin",
50 in_sign='ssiassa{ss}s', out_sign='(asa{ss})', 54 in_sign='ssiassa{ss}s', out_sign='(asa{ss})',
51 method=self._get, 55 method=self._get,
52 async=True 56 async=True
53 ) 57 )
58 host.bridge.addMethod("ticketsSet", ".plugin",
59 in_sign='ssa{sas}ssa{ss}s', out_sign='s',
60 method=self._set,
61 async=True)
62 host.bridge.addMethod("ticketsSchemaGet", ".plugin",
63 in_sign='sss', out_sign='s',
64 method=self._getSchema,
65 async=True)
54 66
55 def _labelsFilter(self, widget_type, args, kwargs): 67 def _labelsFilter(self, widget_type, args, kwargs):
56 if widget_type != u'textbox': 68 if widget_type != u'textbox':
57 return widget_type, args, kwargs 69 return widget_type, args, kwargs
58 widget_type = u'list' 70 widget_type = u'list'
105 extra = extra, 117 extra = extra,
106 filters = filters, 118 filters = filters,
107 ) 119 )
108 120
109 defer.returnValue((tickets, metadata)) 121 defer.returnValue((tickets, metadata))
122
123 def _set(self, service, node, values, schema=None, item_id=None, extra=None, profile_key=C.PROF_KEY_NONE):
124 client = self.host.getClient(profile_key)
125 service = None if not service else jid.JID(service)
126 if schema:
127 schema = generic.parseXml(schema.encode('utf-8'))
128 else:
129 schema = None
130 d = self.set(client, service, node or None, values, schema, item_id or None, extra, deserialise=True)
131 d.addCallback(lambda ret: ret or u'')
132 return d
133
134 @defer.inlineCallbacks
135 def set(self, client, service, node, values, schema=None, item_id=None, extra=None, deserialise=False):
136 """Publish a tickets
137
138 @param node(unicode, None): Pubsub node to use
139 None to use default tickets node
140 @param values(dict[key(unicode), [iterable[object], object]]): values of the ticket
141 if not iterable, will be put in a list
142 'created' and 'updated' will be forced to current time:
143 - 'created' is set if item_id is None, i.e. if it's a new ticket
144 - 'updated' is set everytime
145 other arguments are same as for [self._s.sendDataFormItem]
146 @return (unicode): id of the created item
147 """
148 if not node:
149 node = NS_TICKETS
150 now = utils.xmpp_date()
151 if not item_id:
152 values['created'] = now
153 comments_service = self._m.getCommentsService(client)
154
155 # we need to use uuid for comments node, because we don't know item id in advance
156 # (we don't want to set it ourselves to let the server choose, so we can have
157 # a nicer id if serial ids is activated)
158 comments_node = self._m.getCommentsNode(node + u'_' + unicode(shortuuid.uuid()))
159 options = {self._p.OPT_ACCESS_MODEL: self._p.ACCESS_OPEN,
160 self._p.OPT_PERSIST_ITEMS: 1,
161 self._p.OPT_MAX_ITEMS: -1,
162 self._p.OPT_DELIVER_PAYLOADS: 1,
163 self._p.OPT_SEND_ITEM_SUBSCRIBE: 1,
164 self._p.OPT_PUBLISH_MODEL: self._p.ACCESS_OPEN,
165 }
166 yield self._p.createNode(client, comments_service, comments_node, options)
167 values['comments_uri'] = uri.buildXMPPUri(u'pubsub', subtype='microblog', path=comments_service.full(), node=comments_node)
168
169 values['updated'] = now
170 item_id = yield self._s.sendDataFormItem(client, service, node, values, schema, item_id, extra, deserialise)
171 defer.returnValue(item_id)
172
173 def _getSchema(self, service, node, profile_key=C.PROF_KEY_NONE):
174 if not node:
175 node = NS_TICKETS
176 return self._s._getUISchema(service, node, profile_key)