Revision 123fd2f5
b/invitations/invitations.py | ||
---|---|---|
319 | 319 |
log.exception(e) |
320 | 320 |
return HttpResponseServerError("Error sending invitation email") |
321 | 321 |
|
322 |
return HttpResponse("Invitation has been resent")
|
|
322 |
return HttpResponse('{"resent":true}')
|
|
323 | 323 |
|
324 | 324 |
|
325 | 325 |
def get_invitee_level(source): |
b/invitations/templates/invitations.html | ||
---|---|---|
14 | 14 |
"updated": "{{ inv.updated|date }}", |
15 | 15 |
"accepted": {% if inv.accepted %}true{% else %}false{% endif %}, |
16 | 16 |
"targetname": "{{ inv.targetname|escapejs }}", |
17 |
"target": "{{ inv.target|escapejs }}" |
|
17 |
"target": "{{ inv.target|escapejs }}", |
|
18 |
"id": "{{ inv.id }}" |
|
18 | 19 |
}{% if not forloop.last %},{% endif %} |
19 | 20 |
{% endfor %} |
20 | 21 |
], |
b/ui/static/snf/css/main.css | ||
---|---|---|
5707 | 5707 |
.invitations-form .send-error { |
5708 | 5708 |
font-size: 0.8em; |
5709 | 5709 |
margin-bottom: 5px; |
5710 |
margin-top: 5px; |
|
5710 | 5711 |
color: #800; |
5711 | 5712 |
padding: 3px; |
5713 |
padding-left: 0; |
|
5712 | 5714 |
display: none; |
5713 | 5715 |
} |
5714 | 5716 |
|
... | ... | |
5729 | 5731 |
position: relative; |
5730 | 5732 |
} |
5731 | 5733 |
|
5734 |
.invitations-form h3 { |
|
5735 |
float: left; |
|
5736 |
} |
|
5737 |
|
|
5732 | 5738 |
.invitations-form .add-new-invitation { |
5733 |
position: absolute;
|
|
5739 |
float:left;
|
|
5734 | 5740 |
top:2px; |
5735 | 5741 |
right: 20px; |
5736 | 5742 |
width: 16px; |
... | ... | |
5738 | 5744 |
background-image: url("../images/option-action-add.png"); |
5739 | 5745 |
background-repeat: no-repeat; |
5740 | 5746 |
background-position: center; |
5741 |
text-indent: 2000em;
|
|
5747 |
text-indent: -50000em;
|
|
5742 | 5748 |
background-color: #4085A5; |
5749 |
margin-left: 15px; |
|
5750 |
cursor: pointer; |
|
5743 | 5751 |
} |
5744 | 5752 |
|
5745 | 5753 |
.invitations-view .left { |
... | ... | |
5761 | 5769 |
} |
5762 | 5770 |
|
5763 | 5771 |
.invitations-wrapper .invitations-list { |
5764 |
width: 33%;
|
|
5772 |
width: 40%;
|
|
5765 | 5773 |
float: left; |
5766 | 5774 |
padding-left: 10px; |
5767 | 5775 |
border-left: 1px solid #4085A5; |
... | ... | |
5769 | 5777 |
} |
5770 | 5778 |
|
5771 | 5779 |
.invitations-wrapper .invitations-form { |
5772 |
width: 65%;
|
|
5780 |
width: 57%;
|
|
5773 | 5781 |
float: left; |
5774 | 5782 |
border-right: 1px solid #4085A5; |
5775 | 5783 |
} |
... | ... | |
5791 | 5799 |
} |
5792 | 5800 |
|
5793 | 5801 |
.invitations-wrapper input.name { |
5794 |
width: 180px;
|
|
5802 |
width: 150px;
|
|
5795 | 5803 |
} |
5796 | 5804 |
|
5797 | 5805 |
.invitations-wrapper input { |
5798 | 5806 |
font-size: 0.9em; |
5799 |
width: 160px;
|
|
5807 |
width: 155px;
|
|
5800 | 5808 |
padding:4px; |
5801 | 5809 |
} |
5802 | 5810 |
|
... | ... | |
5804 | 5812 |
border-bottom: 1px solid #A1C8DB; |
5805 | 5813 |
padding-bottom: 5px; |
5806 | 5814 |
margin-bottom: 5px; |
5815 |
position: relative; |
|
5807 | 5816 |
} |
5808 | 5817 |
|
5809 | 5818 |
.invitations-view h3 { |
... | ... | |
5817 | 5826 |
} |
5818 | 5827 |
|
5819 | 5828 |
|
5820 |
.invitations-list .email { |
|
5829 |
.invitations-list .invitation-sent .email {
|
|
5821 | 5830 |
color: #D98147; |
5822 | 5831 |
font-size: 0.8em; |
5823 | 5832 |
font-weight: bold; |
5824 | 5833 |
margin-top: 2px; |
5825 | 5834 |
} |
5826 | 5835 |
|
5836 |
.invitations-list .pagination a, |
|
5837 |
.invitations-list .pagination span { |
|
5838 |
padding: 0.2em 0.3em; |
|
5839 |
} |
|
5840 |
|
|
5841 |
.invitations-list .pagination { |
|
5842 |
font-size: 0.75em; |
|
5843 |
} |
|
5844 |
|
|
5827 | 5845 |
.invitations-list .name { |
5828 | 5846 |
color: #444; |
5829 | 5847 |
font-size: 0.9em; |
5830 | 5848 |
} |
5849 |
|
|
5850 |
.invitations-list .status.sending { |
|
5851 |
background-image: url("../images/icons/indicators/small/progress.gif"); |
|
5852 |
} |
|
5853 |
|
|
5854 |
.invitations-list .status.sent { |
|
5855 |
background-image: url("../images/invitation_accepted.png"); |
|
5856 |
} |
|
5857 |
|
|
5858 |
.invitations-list .status.resend { |
|
5859 |
background-image: url("../images/resend.png"); |
|
5860 |
} |
|
5861 |
|
|
5862 |
.invitations-list .status.resend { |
|
5863 |
cursor: pointer; |
|
5864 |
} |
|
5865 |
|
|
5866 |
.invitations-list .status { |
|
5867 |
width: 20px; |
|
5868 |
height: 15px; |
|
5869 |
position: absolute; |
|
5870 |
top:5px; |
|
5871 |
right: 2px; |
|
5872 |
background-repeat: no-repeat; |
|
5873 |
background-position: center; |
|
5874 |
} |
|
5875 |
|
|
5876 |
.invitations-form .form-entry:last-child { |
|
5877 |
border-bottom: none; |
|
5878 |
} |
|
5879 |
|
|
5880 |
.invitations-form .form-entry { |
|
5881 |
position: relative; |
|
5882 |
margin-bottom: 10px; |
|
5883 |
padding-bottom: 10px; |
|
5884 |
border-bottom: 1px solid #ddd; |
|
5885 |
margin-right: 10px; |
|
5886 |
} |
|
5887 |
|
|
5888 |
.invitations-form .send-invitations { |
|
5889 |
float: left; |
|
5890 |
padding: 5px; |
|
5891 |
color: #fff; |
|
5892 |
margin-right: 10px; |
|
5893 |
margin-top: 10px; |
|
5894 |
} |
|
5895 |
|
|
5896 |
.invitations-form .form-entry.error { |
|
5897 |
padding-bottom: 0px; |
|
5898 |
} |
|
5899 |
|
|
5900 |
.invitations-form .form-entry.error .remove-invitation { |
|
5901 |
bottom: 32px; |
|
5902 |
} |
|
5903 |
|
|
5904 |
.invitations-form .remove-invitation { |
|
5905 |
padding: 5px; |
|
5906 |
background-image: url("../images/option-action-remove.png"); |
|
5907 |
background-position: center; |
|
5908 |
background-repeat: no-repeat; |
|
5909 |
color: #fff; |
|
5910 |
width: 15px; |
|
5911 |
height: 15px; |
|
5912 |
cursor: pointer; |
|
5913 |
text-indent: -50000px; |
|
5914 |
position: absolute; |
|
5915 |
right: -10px; |
|
5916 |
bottom: 14px; |
|
5917 |
} |
|
5918 |
|
|
5919 |
.invitations-list .resent-info, |
|
5920 |
.invitations-form .top-info { |
|
5921 |
font-size: 0.8em; |
|
5922 |
margin-bottom: 10px; |
|
5923 |
} |
|
5924 |
|
|
5925 |
.invitations-list .msg .email, |
|
5926 |
.invitations-form .success .msg .email { |
|
5927 |
font-weight: bold; |
|
5928 |
} |
|
5929 |
|
|
5930 |
.invitations-list .msg.err-msg, |
|
5931 |
.invitations-list .success.msg, |
|
5932 |
.invitations-form .success .msg { |
|
5933 |
background-color: #080; |
|
5934 |
color: white; |
|
5935 |
padding: 5px; |
|
5936 |
margin-right: 10px; |
|
5937 |
margin-bottom: 5px; |
|
5938 |
} |
|
5939 |
.invitations-list .msg.err-msg, |
|
5940 |
.invitations-list .success.msg { |
|
5941 |
margin-right: 0px; |
|
5942 |
} |
|
5943 |
.invitations-list .msg.err-msg { |
|
5944 |
background-color: #800; |
|
5945 |
} |
b/ui/static/snf/js/ui/web/ui_invitations_view.js | ||
---|---|---|
24 | 24 |
overlay_id: "invitations-overlay", |
25 | 25 |
|
26 | 26 |
subtitle: "", |
27 |
title: "Invitations",
|
|
27 |
title: "Invite friends",
|
|
28 | 28 |
|
29 | 29 |
initialize: function(options) { |
30 | 30 |
views.InvitationsView.__super__.initialize.apply(this, arguments); |
... | ... | |
45 | 45 |
this.inv_sent_per_page = 9; |
46 | 46 |
|
47 | 47 |
this.init_handlers(); |
48 |
|
|
49 |
this.invitations_retrieved = false; |
|
50 |
this.loading_invitations = this.$(".loading-invitations"); |
|
48 | 51 |
}, |
49 | 52 |
|
50 | 53 |
init_handlers: function() { |
51 | 54 |
var self = this; |
52 |
this.add.click(this.add_new_entry); |
|
55 |
this.add.click(function(){ |
|
56 |
self.add_new_entry().find("input.name").focus(); |
|
57 |
}); |
|
53 | 58 |
this.send.click(this.send_entries); |
54 | 59 |
this.remove.live('click', function() { |
55 | 60 |
return self.remove_entry($(this).parent().parent()); |
56 | 61 |
}); |
62 |
|
|
57 | 63 |
}, |
58 | 64 |
|
59 | 65 |
remove_entry: function(entry) { |
... | ... | |
64 | 70 |
|
65 | 71 |
add_new_entry: function() { |
66 | 72 |
var new_entry = this.create_form_entry().show() |
73 |
|
|
74 |
var name = "inv-entry-" + this.get_entries().length; |
|
75 |
new_entry.find("input.name").attr("name", "name-" + name); |
|
76 |
new_entry.find("input.email").attr("name", "email-" + name); |
|
77 |
|
|
78 |
var self = this; |
|
79 |
new_entry.find("input").bind("keydown", function(e){ |
|
80 |
e.keyCode = e.keyCode || e.which; |
|
81 |
if (e.keyCode == 13) { self.send_entries() }; |
|
82 |
}) |
|
83 |
|
|
67 | 84 |
this.form_entries.append(new_entry).show(); |
68 |
$(new_entry.find("input").get(0)).focus(); |
|
69 | 85 |
this.fix_entries(); |
86 |
return new_entry; |
|
70 | 87 |
}, |
71 | 88 |
|
72 | 89 |
show_entry_error: function(entry, error) { |
... | ... | |
84 | 101 |
entry_is_valid: function(entry) { |
85 | 102 |
var data = this.get_entry_data(entry); |
86 | 103 |
|
104 |
if (data.name == "" && data.email == "") { |
|
105 |
return false; |
|
106 |
} |
|
107 |
|
|
87 | 108 |
entry.find(".send-error").hide(); |
88 | 109 |
entry.removeClass("error"); |
89 | 110 |
entry.find("input").removeClass("has-errors"); |
... | ... | |
92 | 113 |
if (!data.name || data.name.split(" ").length == 1) { |
93 | 114 |
error = "Invalid name"; |
94 | 115 |
entry.find("input.name").addClass("has-errors"); |
116 |
entry.find("input.name").focus(); |
|
95 | 117 |
} |
96 | 118 |
|
97 | 119 |
var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/; |
98 | 120 |
if (!data.email || reg.test(data.email) == false) { |
99 | 121 |
error = "Invalid email"; |
100 | 122 |
entry.find("input.email").addClass("has-errors"); |
123 |
entry.find("input.email").focus(); |
|
101 | 124 |
} |
102 | 125 |
|
103 | 126 |
if (error) { this.show_entry_error(entry, error) }; |
... | ... | |
108 | 131 |
var self = this; |
109 | 132 |
this.form_entries.find(".form-entry").each(function(index, el) { self.entry_is_valid($(el)) }); |
110 | 133 |
var entries_to_send = this.form_entries.find(".form-entry:not(.error):not(.sending)"); |
111 |
this._send_entries(entries_to_send); |
|
134 |
|
|
135 |
entries = _.filter(entries_to_send, function(e){ |
|
136 |
var data = self.get_entry_data($(e)); |
|
137 |
if (data.name == "" && data.email == "") { |
|
138 |
return false; |
|
139 |
} |
|
140 |
return true; |
|
141 |
}) |
|
142 |
this._send_entries(entries); |
|
112 | 143 |
}, |
113 | 144 |
|
114 | 145 |
_send_entries: function(entries) { |
... | ... | |
126 | 157 |
|
127 | 158 |
invitation_send: function(entry, data) { |
128 | 159 |
entry.removeClass("sending"); |
129 |
if (data.errors && data.errors.length) { |
|
130 |
this.show_entry_error($(entry), data.errors[0]); |
|
160 |
if (data.errors && data.errors.length > 0) {
|
|
161 |
this.show_entry_error($(entry), data.errors[0].msg);
|
|
131 | 162 |
return; |
132 | 163 |
} else { |
133 | 164 |
entry.remove(); |
... | ... | |
136 | 167 |
}, |
137 | 168 |
|
138 | 169 |
show_send_success: function(to, data) { |
139 |
var msg = "Invitation to " + to + " was sent.";
|
|
170 |
var msg = 'Invitation to <span class="email">' + to + '</span> was sent.';
|
|
140 | 171 |
var msg_el = $('<div class="msg">{0}</div>'.format(msg)); |
141 | 172 |
|
142 | 173 |
this.top_info.append(msg_el); |
143 | 174 |
|
144 | 175 |
window.setTimeout(function(){ |
145 | 176 |
msg_el.fadeOut(600, function(){$(this).remove()}); |
146 |
}, 2000);
|
|
177 |
}, 5000);
|
|
147 | 178 |
|
148 | 179 |
this.fix_entries(); |
149 | 180 |
this.reset_invitations_sent(); |
... | ... | |
175 | 206 |
this.$(".remove-invitation").hide(); |
176 | 207 |
if (this.get_entries().length == 0) { |
177 | 208 |
this.add_new_entry(); |
209 |
this.add_new_entry(); |
|
178 | 210 |
} |
179 | 211 |
|
180 | 212 |
if (this.get_entries().length > 1) { |
... | ... | |
183 | 215 |
this.$(".form-entry:first-child label").show(); |
184 | 216 |
this.$(".form-entry:not(:first-child) label").hide(); |
185 | 217 |
}, |
186 |
|
|
218 |
|
|
187 | 219 |
show: function() { |
188 | 220 |
views.InvitationsView.__super__.show.apply(this, arguments); |
189 | 221 |
this.current_page = 0; |
190 |
this.reset_invitations_sent();
|
|
222 |
this.reset_sent(); |
|
191 | 223 |
this.reset(); |
192 | 224 |
|
193 | 225 |
this.add_new_entry(); |
194 | 226 |
this.add_new_entry(); |
195 |
this.add_new_entry(); |
|
227 |
|
|
228 |
if (this.invitations_retrieved) { |
|
229 |
this.loading_invitations.hide(); |
|
230 |
} |
|
231 |
}, |
|
232 |
|
|
233 |
reset_sent: function() { |
|
234 |
this.reset_invitations_sent(); |
|
235 |
this.add_invitations_sent([]); |
|
196 | 236 |
}, |
197 | 237 |
|
198 | 238 |
create_form_entry: function() { |
... | ... | |
218 | 258 |
var url = snf.config.invitations_url; |
219 | 259 |
params = { |
220 | 260 |
success: function(data) { |
261 |
self.invitations_retrieved = true; |
|
262 |
self.loading_invitations.hide(); |
|
263 |
|
|
221 | 264 |
if (!data || !data.invitations) { |
222 | 265 |
self.show_invitations_sent_error(); |
223 | 266 |
} else { |
... | ... | |
244 | 287 |
|
245 | 288 |
snf.api.sync("read", undefined, params); |
246 | 289 |
}, |
290 |
|
|
291 |
resend_succeed: function(inv, el) { |
|
292 |
el.find(".status.sent").removeClass("hidden").hide(); |
|
293 |
el.find(".status.resend").removeClass("hidden").show(); |
|
294 |
el.find(".status.sending").removeClass("hidden").hide(); |
|
295 |
|
|
296 |
var msg = $('<div class="msg success">Invitation has been resent to <span class="email">{0}</span>.</div>'.format(inv.target)); |
|
297 |
this.$(".resent-info").append(msg); |
|
298 |
setTimeout(function(){ $(msg).fadeOut(600)}, 5000); |
|
299 |
}, |
|
300 |
|
|
301 |
resend_failed: function(inv, el) { |
|
302 |
el.find(".status.sent").removeClass("hidden").hide(); |
|
303 |
el.find(".status.resend").removeClass("hidden").show(); |
|
304 |
el.find(".status.sending").removeClass("hidden").hide(); |
|
305 |
|
|
306 |
var msg = $('<div class="msg err-msg">Resend to <span class="email">{0}</span> failed.</div>'.format(inv.target)); |
|
307 |
this.$(".resent-info").append(msg); |
|
308 |
setTimeout(function(){ $(msg).fadeOut(600)}, 5000); |
|
309 |
}, |
|
310 |
|
|
311 |
resend_invitation: function(id, el, inv) { |
|
312 |
var self = this; |
|
313 |
var inv = inv; |
|
314 |
var id = id; |
|
315 |
var el = el; |
|
316 |
|
|
317 |
el.find(".status.sent").removeClass("hidden").hide(); |
|
318 |
el.find(".status.resend").removeClass("hidden").hide(); |
|
319 |
el.find(".status.sending").removeClass("hidden").show(); |
|
320 |
|
|
321 |
var url = snf.config.invitations_url + "/resend/"; |
|
322 |
var payload = "invid=" + id; |
|
323 |
params = { |
|
324 |
success: function(data) { |
|
325 |
self.resend_succeed(inv, el); |
|
326 |
}, |
|
327 |
error: function() { |
|
328 |
self.resend_failed(inv, el); |
|
329 |
}, |
|
330 |
data: payload, |
|
331 |
url: url, |
|
332 |
skip_api_error: true |
|
333 |
} |
|
334 |
|
|
335 |
snf.api.sync("create", undefined, params); |
|
336 |
}, |
|
247 | 337 |
|
248 | 338 |
add_invitations_sent: function(invs) { |
339 |
var self = this; |
|
249 | 340 |
_.each(invs, _.bind(function(inv) { |
250 | 341 |
var el = this.new_invitation_sent_el(); |
342 |
var invitation = inv; |
|
343 |
|
|
251 | 344 |
el.find(".name").text(inv.targetname); |
252 | 345 |
el.find(".email").text(inv.target); |
253 |
el.find(".action").addClass("sent"); |
|
346 |
|
|
347 |
el.find(".status.sent").removeClass("hidden").show(); |
|
348 |
el.find(".status.resend").removeClass("hidden").hide(); |
|
349 |
el.find(".status.sending").removeClass("hidden").hide(); |
|
350 |
|
|
254 | 351 |
if (!inv.accepted) { |
255 |
el.find(".action").removeClass("resend").addClass("resend") |
|
352 |
el.find(".status.resend").show(); |
|
353 |
el.find(".status.sent").hide(); |
|
354 |
el.find(".status.sending").hide(); |
|
256 | 355 |
} |
356 |
|
|
357 |
el.find(".status.resend").click(function(){ |
|
358 |
self.resend_invitation(invitation.id, el, invitation); |
|
359 |
}) |
|
360 |
|
|
257 | 361 |
el.removeClass("hidden"); |
258 | 362 |
this.sent.append(el); |
259 | 363 |
}, this)); |
260 | 364 |
this.update_pagination(); |
261 | 365 |
this.sent_pages.trigger("setPage", this.current_page || 0); |
262 | 366 |
}, |
367 |
|
|
368 |
onOpen: function() { |
|
369 |
views.InvitationsView.__super__.onOpen.apply(this, arguments); |
|
370 |
setTimeout(function(){$(this.$("input.name:visible").get(0)).focus()}, 100); |
|
371 |
}, |
|
263 | 372 |
|
264 | 373 |
inv_sent_per_page: 5, |
265 | 374 |
update_pagination: function() { |
266 | 375 |
this.sent.css({minHeight:this.inv_sent_per_page * 35 + "px"}) |
267 |
this.sent_pages.pagination(this.sent.children().length, {items_per_page:this.inv_sent_per_page, callback: this.page_cb}); |
|
376 |
this.sent_pages.pagination(this.sent.children().length, |
|
377 |
{items_per_page:this.inv_sent_per_page, callback: this.page_cb}); |
|
268 | 378 |
}, |
269 | 379 |
|
270 | 380 |
page_cb: function(index, pager) { |
b/ui/templates/home.html | ||
---|---|---|
544 | 544 |
synnefo.ui.init(); |
545 | 545 |
|
546 | 546 |
synnefo.ui.main.bind("initial", function(){ |
547 |
$(".usermenu .invitations").click(); |
|
548 | 547 |
}) |
549 | 548 |
|
550 | 549 |
}) |
b/ui/templates/partials/invitations.html | ||
---|---|---|
1 | 1 |
{% load i18n %} |
2 | 2 |
<div id="invitations-overlay-content" class="hidden overlay-content invitations-view"> |
3 | 3 |
<div class="description"> |
4 |
<p>You have <span class="left"></span> invitations left</p> |
|
4 |
<p>You have <span class="left">...</span> invitations left</p>
|
|
5 | 5 |
</div> |
6 | 6 |
<div class="invitations-wrapper clearfix"> |
7 | 7 |
<div class="invitations-form clearfix"> |
8 |
<div class="invitations-send-header clearfix"> |
|
8 | 9 |
<h3>{% trans "Send new intivations" %}</h3> |
9 |
<div class="add-new-invitation">add</div> |
|
10 |
<div class="add-new-invitation" title="{% trans "Add new invitation" %}">add</div> |
|
11 |
</div> |
|
10 | 12 |
<div class="top-info success"></div> |
11 | 13 |
<div class="form-entry-tpl clearfix hidden"> |
12 | 14 |
<div class="fields clearfix"> |
... | ... | |
18 | 20 |
<label>Email</label> |
19 | 21 |
<input type="text" class="email"/> |
20 | 22 |
</div> |
21 |
<div class="remove-invitation">remove</div> |
|
23 |
<div class="remove-invitation" title="{% trans "Remove invitation" %}">remove</div>
|
|
22 | 24 |
</div> |
23 | 25 |
<div class="send-error"></div> |
24 | 26 |
<div class="sending-msg hidden">{% trans "Sending..." %}</div> |
25 | 27 |
</div> |
26 | 28 |
<div class="form-entries"> |
27 | 29 |
</div> |
28 |
<div class="send-invitations">send invitations</div> |
|
30 |
<div vlcass="form-actions"> |
|
31 |
<span class="form-action create send-invitations">send invitations</span> |
|
32 |
</div> |
|
29 | 33 |
</div> |
30 | 34 |
<div class="invitations-list clearfix"> |
31 | 35 |
<h3>{% trans "Intivations sent" %}</h3> |
32 |
<div class="invitation-sent-tpl hidden"> |
|
33 |
<div class="action resend"></div> |
|
36 |
<div class="resent-info"></div> |
|
37 |
<div class="loading-invitations">Loading...</div> |
|
38 |
<div class="invitation-sent-tpl hidden clearfix"> |
|
34 | 39 |
<div class="name"></div> |
35 | 40 |
<div class="email"></div> |
41 |
<div class="status resend hidden" title="{% trans "Resend invitation" %}"></div> |
|
42 |
<div class="status sent hidden" title="{% trans "Invitation accepted" %}"></div> |
|
43 |
<div class="status sending hidden"></div> |
|
36 | 44 |
</div> |
37 |
<div class="invitations-sent-cont"> |
|
38 |
</div> |
|
45 |
<form> |
|
46 |
<div class="invitations-sent-cont"> |
|
47 |
</div> |
|
48 |
</form> |
|
39 | 49 |
<div class="invitations-sent-pages"></div> |
40 | 50 |
<div class="hidden invitations-sent-error">{% trans "Cannot display invitations history" %}</div> |
41 | 51 |
</div> |
Also available in: Unified diff