postmortem 0.2.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +4 -46
- data/.ruby-version +1 -1
- data/Gemfile +0 -2
- data/Makefile +4 -0
- data/README.md +21 -12
- data/layout/default.html.erb +51 -12
- data/layout/dependencies.css +0 -4
- data/layout/dependencies.js +3 -1
- data/layout/favicon.b64 +1 -0
- data/layout/layout.css +155 -15
- data/layout/layout.js +286 -81
- data/lib/postmortem.rb +3 -2
- data/lib/postmortem/adapters.rb +1 -1
- data/lib/postmortem/adapters/action_mailer.rb +6 -41
- data/lib/postmortem/adapters/base.rb +35 -2
- data/lib/postmortem/adapters/mail.rb +3 -3
- data/lib/postmortem/adapters/pony.rb +3 -6
- data/lib/postmortem/delivery.rb +4 -0
- data/lib/postmortem/index.rb +2 -1
- data/lib/postmortem/layout.rb +8 -0
- data/lib/postmortem/plugins/action_mailer.rb +7 -0
- data/lib/postmortem/plugins/pony.rb +7 -3
- data/lib/postmortem/version.rb +1 -1
- data/postmortem.gemspec +6 -3
- metadata +49 -7
- data/doc/screenshot.png +0 -0
data/layout/layout.js
CHANGED
@@ -1,17 +1,29 @@
|
|
1
1
|
(function () {
|
2
|
+
if (POSTMORTEM && POSTMORTEM.downloadedPreview) document.title = 'PostMortem';
|
3
|
+
|
2
4
|
let previousInbox;
|
3
5
|
let currentView;
|
4
6
|
let reloadIdentityIframeTimeout;
|
5
7
|
let identityUuid;
|
6
8
|
let indexUuid;
|
7
|
-
let
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
let twoColumnView;
|
10
|
+
let headersView;
|
11
|
+
let indexIframeTimeout;
|
12
|
+
let requestedId;
|
13
|
+
let requestedPending = false;
|
14
|
+
|
15
|
+
const inboxContent = [];
|
16
|
+
const headers = document.querySelector('.headers');
|
17
|
+
const inbox = document.querySelector('#inbox-container');
|
18
|
+
const inboxInfo = document.querySelector('#inbox-info');
|
19
|
+
const columnSwitch = document.querySelector('.column-switch');
|
20
|
+
const headersViewSwitch = document.querySelector('.headers-view-switch');
|
21
|
+
const readAllButton = document.querySelector('.read-all-button');
|
22
|
+
const showHideReadButton = document.querySelector('.show-hide-read-button');
|
23
|
+
const showHideReadIcon = document.querySelector('.show-hide-read-icon');
|
24
|
+
const getIndexIframe = () => document.querySelector("#index-iframe");
|
25
|
+
const getIdentityIframe = () => document.querySelector("#identity-iframe");
|
26
|
+
const sourceHighlightBundle = [
|
15
27
|
'<link rel="stylesheet"',
|
16
28
|
' href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.3/styles/agate.min.css"',
|
17
29
|
' integrity="sha512-mMMMPADD4HAIogAWZbv+WjZTC0itafUZNI0jQm48PMBTApXt11omF5jhS7U1kp3R2Pr6oGJ+JwQKiUkUwCQaUQ=="',
|
@@ -22,52 +34,60 @@
|
|
22
34
|
'<script>hljs.initHighlightingOnLoad();</' + 'script>',
|
23
35
|
].join('\n');
|
24
36
|
|
37
|
+
const storage = window.localStorage;
|
38
|
+
|
25
39
|
const initialize = () => {
|
26
|
-
|
27
|
-
|
28
|
-
reloadIdentityIframeTimeout = setTimeout(() => identityIframe.src += '', 3000);
|
29
|
-
|
30
|
-
window.addEventListener('message', function (ev) {
|
31
|
-
switch (ev.data.type) {
|
32
|
-
case 'index':
|
33
|
-
renderInbox(ev.data.uuid, ev.data.mails);
|
34
|
-
break;
|
35
|
-
case 'identity':
|
36
|
-
compareIdentity(ev.data.uuid);
|
37
|
-
break;
|
38
|
-
};
|
39
|
-
});
|
40
|
+
reloadIdentityIframeTimeout = setTimeout(() => getIdentityIframe().src += '', 1000);
|
40
41
|
|
41
|
-
setInterval(function () {
|
42
|
-
setInterval(function () { identityIframe.contentWindow.postMessage('HELO', '*'); }, 1000);
|
42
|
+
setInterval(function () { getIdentityIframe().contentWindow.postMessage('HELO', '*'); }, 200);
|
43
43
|
|
44
|
-
toolbar.html.onclick
|
45
|
-
toolbar.text.onclick
|
46
|
-
toolbar.source.onclick
|
47
|
-
toolbar.headers.onclick
|
48
|
-
columnSwitch.onclick
|
44
|
+
toolbar.html.onclick = (ev) => setView('html', ev);
|
45
|
+
toolbar.text.onclick = (ev) => setView('text', ev);
|
46
|
+
toolbar.source.onclick = (ev) => setView('source', ev);
|
47
|
+
toolbar.headers.onclick = () => setHeadersView(!headersView);
|
48
|
+
columnSwitch.onclick = () => setColumnView(!twoColumnView);
|
49
|
+
readAllButton.onclick = () => markAllAsRead();
|
50
|
+
showHideReadButton.onclick = () => toggleHideReadMessages();
|
49
51
|
|
50
|
-
if (hasHtml) {
|
52
|
+
if (POSTMORTEM.hasHtml) {
|
51
53
|
setView('html');
|
52
54
|
} else {
|
53
55
|
setView('text');
|
54
56
|
}
|
55
57
|
|
56
|
-
setColumnView(
|
58
|
+
setColumnView(!POSTMORTEM.downloadedPreview);
|
57
59
|
setHeadersView(true);
|
60
|
+
setEnabled(columnSwitch);
|
61
|
+
setOn(columnSwitch);
|
62
|
+
setHidden(inbox, POSTMORTEM.downloadedPreview);
|
63
|
+
|
64
|
+
if (POSTMORTEM.downloadedPreview) {
|
65
|
+
setHidden(toolbar.download, true);
|
66
|
+
setHidden(columnSwitch, true);
|
67
|
+
loadMail(POSTMORTEM.initialData);
|
68
|
+
} else {
|
69
|
+
requestLoad(window.location.hash.replace('#', ''));
|
70
|
+
window.addEventListener('message', function (ev) {
|
71
|
+
switch (ev.data.type) {
|
72
|
+
case 'index':
|
73
|
+
loadInbox(ev.data.uuid, ev.data.mails);
|
74
|
+
break;
|
75
|
+
case 'identity':
|
76
|
+
compareIdentity(ev.data.uuid);
|
77
|
+
break;
|
78
|
+
};
|
79
|
+
});
|
80
|
+
}
|
58
81
|
|
59
82
|
$('[data-toggle="tooltip"]').tooltip();
|
60
83
|
}
|
61
84
|
|
85
|
+
const requestLoad = (id) => {
|
86
|
+
requestedId = id;
|
87
|
+
requestedPending = true;
|
88
|
+
};
|
62
89
|
|
63
|
-
|
64
|
-
var headersView;
|
65
|
-
var headers = document.querySelector('.headers');
|
66
|
-
var inbox = document.querySelector('#inbox');
|
67
|
-
var columnSwitch = document.querySelector('.column-switch');
|
68
|
-
var headersViewSwitch = document.querySelector('.headers-view-switch');
|
69
|
-
|
70
|
-
var setHeadersView = function (enableHeadersView) {
|
90
|
+
const setHeadersView = (enableHeadersView) => {
|
71
91
|
headersView = enableHeadersView;
|
72
92
|
if (enableHeadersView) {
|
73
93
|
setOn(headersViewSwitch);
|
@@ -78,11 +98,11 @@
|
|
78
98
|
}
|
79
99
|
};
|
80
100
|
|
81
|
-
|
82
|
-
if (!
|
101
|
+
const setColumnView = (enableTwoColumnView) => {
|
102
|
+
if (!inbox) return;
|
83
103
|
|
84
|
-
|
85
|
-
twoColumnView = enableTwoColumnView;
|
104
|
+
const container = document.querySelector('.container');
|
105
|
+
twoColumnView = POSTMORTEM.downloadedPreview ? false : enableTwoColumnView;
|
86
106
|
if (twoColumnView) {
|
87
107
|
setVisible(inbox, true);
|
88
108
|
setOn(columnSwitch);
|
@@ -94,42 +114,51 @@
|
|
94
114
|
}
|
95
115
|
};
|
96
116
|
|
97
|
-
|
117
|
+
const contexts = ['source', 'text', 'html'];
|
98
118
|
|
99
|
-
|
119
|
+
const views = {
|
100
120
|
source: document.querySelector('.source-view'),
|
101
121
|
html: document.querySelector('.html-view'),
|
102
122
|
text: document.querySelector('.text-view'),
|
103
123
|
};
|
104
124
|
|
105
|
-
|
125
|
+
const toolbar = {
|
106
126
|
source: document.querySelector('.source-view-switch'),
|
107
127
|
html: document.querySelector('.html-view-switch'),
|
108
128
|
text: document.querySelector('.text-view-switch'),
|
109
129
|
headers: document.querySelector('.headers-view-switch'),
|
130
|
+
download: document.querySelector('#download-link'),
|
110
131
|
};
|
111
132
|
|
112
|
-
|
133
|
+
const setOn = function(element) {
|
113
134
|
element.classList.add('text-primary');
|
114
135
|
element.classList.remove('text-secondary');
|
115
136
|
};
|
116
137
|
|
117
|
-
|
138
|
+
const setOff = function(element) {
|
118
139
|
element.classList.add('text-secondary');
|
119
140
|
element.classList.remove('text-primary');
|
120
141
|
};
|
121
142
|
|
122
|
-
|
143
|
+
const setDisabled = function(element) {
|
123
144
|
element.classList.add('disabled');
|
124
145
|
element.classList.remove('text-secondary');
|
125
146
|
};
|
126
147
|
|
127
|
-
|
148
|
+
const setEnabled = function(element) {
|
128
149
|
element.classList.remove('disabled');
|
129
150
|
element.classList.add('text-secondary');
|
130
151
|
};
|
131
152
|
|
132
|
-
|
153
|
+
const setHidden = function(element, hidden) {
|
154
|
+
if (hidden) {
|
155
|
+
element.classList.add('hidden');
|
156
|
+
} else {
|
157
|
+
element.classList.remove('hidden');
|
158
|
+
}
|
159
|
+
};
|
160
|
+
|
161
|
+
const setVisible = function(element, visible) {
|
133
162
|
if (visible) {
|
134
163
|
element.classList.add('visible');
|
135
164
|
} else {
|
@@ -137,9 +166,9 @@
|
|
137
166
|
}
|
138
167
|
};
|
139
168
|
|
140
|
-
|
169
|
+
const setView = function(context, ev) {
|
141
170
|
if (ev && $(ev.target).hasClass('disabled')) return;
|
142
|
-
|
171
|
+
let key;
|
143
172
|
for (i = 0; i < contexts.length; i++) {
|
144
173
|
key = contexts[i];
|
145
174
|
if (key === context) {
|
@@ -194,43 +223,211 @@
|
|
194
223
|
setEnabled(toolbar.source);
|
195
224
|
}
|
196
225
|
|
197
|
-
setDisabled(columnSwitch);
|
198
226
|
setView(currentView);
|
199
227
|
};
|
200
228
|
|
201
|
-
const
|
202
|
-
|
203
|
-
htmlIframeDocument.write(mail.htmlBody);
|
204
|
-
htmlIframeDocument.close();
|
229
|
+
const setContent = (selector, content) => {
|
230
|
+
const target = document.querySelector(selector).contentDocument;
|
205
231
|
|
206
|
-
|
207
|
-
|
208
|
-
|
232
|
+
target.open();
|
233
|
+
target.write(content);
|
234
|
+
target.close();
|
235
|
+
};
|
209
236
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
237
|
+
const loadMail = (mail) => {
|
238
|
+
const initializeScript = document.querySelector("#initialize-script");
|
239
|
+
const initObject = {
|
240
|
+
initialData: mail,
|
241
|
+
hasHtml: !!mail.htmlBody,
|
242
|
+
hasText: !!mail.textBody,
|
243
|
+
downloadedPreview: true,
|
244
|
+
};
|
245
|
+
|
246
|
+
initializeScript.text = [
|
247
|
+
`const POSTMORTEM = ${JSON.stringify(initObject)};`
|
248
|
+
].join('\n\n');
|
249
|
+
|
250
|
+
setContent('#html-iframe', mail.htmlBody);
|
251
|
+
setContent('#text-iframe', `<pre>${htmlEscape(mail.textBody)}</pre>`);
|
252
|
+
setContent('#source-iframe', `<pre><code style="padding: 1rem;" class="language-html">${htmlEscape(mail.htmlBody)}</code></pre>` + sourceHighlightBundle);
|
214
253
|
|
215
254
|
loadHeaders(mail);
|
216
255
|
loadToolbar(mail);
|
217
|
-
loadDownloadLink();
|
256
|
+
loadDownloadLink(mail);
|
257
|
+
loadUploadLink(mail);
|
258
|
+
|
259
|
+
highlightMail(mail);
|
260
|
+
markAsRead(mail);
|
261
|
+
updateInboxInfo();
|
262
|
+
};
|
263
|
+
|
264
|
+
const markAsRead = (mail) => {
|
265
|
+
storage.setItem(mail.id, 'read');
|
266
|
+
$(`li[data-email-id="${mail.id}"]`).removeClass('unread');
|
267
|
+
$(readAllButton).blur();
|
268
|
+
};
|
269
|
+
|
270
|
+
const showReadMessages = (show) => {
|
271
|
+
if (show) {
|
272
|
+
inbox.classList.remove('hide-read');
|
273
|
+
} else {
|
274
|
+
inbox.classList.add('hide-read');
|
275
|
+
}
|
276
|
+
};
|
277
|
+
|
278
|
+
const toggleHideReadMessages = () => {
|
279
|
+
const $target = $(showHideReadButton);
|
280
|
+
const $icon = $(showHideReadIcon);
|
281
|
+
|
282
|
+
if ($target.data('state') === 'hide') {
|
283
|
+
$target.data('state', 'show');
|
284
|
+
$target.attr('data-original-title', 'Hide read messages');
|
285
|
+
$target.attr('title', 'Hide read messages');
|
286
|
+
$icon.removeClass('fa-eye-slash');
|
287
|
+
$icon.addClass('fa fa-eye text-primary');
|
288
|
+
showReadMessages(true);
|
289
|
+
} else {
|
290
|
+
$target.data('state', 'hide');
|
291
|
+
$target.attr('data-original-title', 'Show read messages');
|
292
|
+
$target.attr('title', 'Show read messages');
|
293
|
+
$icon.removeClass('fa-eye text-primary');
|
294
|
+
$icon.addClass('fa fa-eye-slash');
|
295
|
+
showReadMessages(false);
|
296
|
+
}
|
297
|
+
|
298
|
+
$target.blur();
|
299
|
+
};
|
300
|
+
|
301
|
+
const markAllAsRead = () => {
|
302
|
+
inboxContent.forEach(mail => markAsRead(mail));
|
303
|
+
updateInboxInfo();
|
304
|
+
};
|
305
|
+
|
306
|
+
const isNewMail = (mail) => {
|
307
|
+
if (!storage.getItem(mail.id)) return true;
|
308
|
+
|
309
|
+
return false;
|
218
310
|
};
|
219
311
|
|
220
|
-
const
|
221
|
-
|
312
|
+
const highlightMail = (mail) => {
|
313
|
+
window.location.hash = mail.id;
|
314
|
+
const $target = $(`li[data-email-id="${mail.id}"]`);
|
315
|
+
$('.inbox-item').removeClass('active');
|
316
|
+
$target.addClass('active');
|
317
|
+
};
|
318
|
+
|
319
|
+
const alertUploadFailure = (response, content) => {
|
320
|
+
alert(`Upload failed. Got: ${response.status} ${response.statusText}: ${content}`);
|
321
|
+
};
|
322
|
+
|
323
|
+
const copyToClipboard = (text) => {
|
324
|
+
const textArea = document.createElement("textarea");
|
325
|
+
textArea.style.position = 'fixed';
|
326
|
+
textArea.style.top = 0;
|
327
|
+
textArea.style.left = 0;
|
328
|
+
textArea.style.width = '2em';
|
329
|
+
textArea.style.height = '2em';
|
330
|
+
textArea.style.padding = 0;
|
331
|
+
textArea.style.border = 'none';
|
332
|
+
textArea.style.outline = 'none';
|
333
|
+
textArea.style.boxShadow = 'none';
|
334
|
+
textArea.style.background = 'transparent';
|
335
|
+
textArea.value = text;
|
336
|
+
document.body.appendChild(textArea);
|
337
|
+
textArea.focus();
|
338
|
+
textArea.select();
|
339
|
+
|
340
|
+
let success;
|
341
|
+
|
342
|
+
try {
|
343
|
+
success = document.execCommand('copy');
|
344
|
+
} catch (err) {
|
345
|
+
console.log('Clipboard copy error');
|
346
|
+
}
|
347
|
+
|
348
|
+
document.body.removeChild(textArea);
|
349
|
+
return success;
|
350
|
+
};
|
351
|
+
|
352
|
+
const alertUploadSuccess = (data) => {
|
353
|
+
const popup = document.querySelector("#upload-popup");
|
354
|
+
const uploadedEmailLink = document.querySelector("#uploaded-email-link");
|
355
|
+
const copyUploadedEmailLink = document.querySelector("#copy-uploaded-email-link");
|
356
|
+
const url = `https://postmortem.delivery/${data.uri}`;
|
357
|
+
|
358
|
+
uploadedEmailLink.textContent = `postmortem.delivery/${data.uri}`;
|
359
|
+
uploadedEmailLink.href = url;
|
360
|
+
copyUploadedEmailLink.onclick = (ev) => {
|
361
|
+
ev.stopPropagation();
|
362
|
+
ev.preventDefault();
|
363
|
+
const success = copyToClipboard(url);
|
364
|
+
console.log(success);
|
365
|
+
};
|
366
|
+
|
367
|
+
popup.classList.remove("hidden");
|
368
|
+
popup.classList.add("fade-in");
|
369
|
+
};
|
370
|
+
|
371
|
+
const loadDownloadLink = (mail) => {
|
372
|
+
const html = document.documentElement.innerHTML;
|
373
|
+
const start = html.indexOf('<!--INBOX-START-->');
|
374
|
+
const end = html.indexOf('<!--INBOX-END-->') + '<!--INBOX-END-->'.length;
|
375
|
+
const modifiedHtml = [html.substring(0, start), html.substring(end + 1, html.length)].join('');
|
376
|
+
const blob = new Blob([modifiedHtml], { type: 'application/octet-stream' });
|
222
377
|
const uri = window.URL.createObjectURL(blob);
|
223
378
|
$("#download-link").attr('href', uri);
|
379
|
+
$("#download-link").attr('download', mail.subject.replace(/[^0-9a-zA-Z_ -]/gi, '') + '.html');
|
380
|
+
};
|
381
|
+
|
382
|
+
const loadUploadLink = (email) => {
|
383
|
+
const link = document.querySelector("#upload-link");
|
384
|
+
|
385
|
+
link.onclick = async (ev) => {
|
386
|
+
ev.stopPropagation();
|
387
|
+
ev.preventDefault();
|
388
|
+
|
389
|
+
const response = await fetch(POSTMORTEM.uploadUrl, {
|
390
|
+
method: 'POST',
|
391
|
+
cache: 'no-cache',
|
392
|
+
headers: { 'Content-Type': 'application/json' },
|
393
|
+
body: JSON.stringify({ email })
|
394
|
+
});
|
395
|
+
|
396
|
+
if (response.ok) {
|
397
|
+
const data = await response.json();
|
398
|
+
alertUploadSuccess(data);
|
399
|
+
} else {
|
400
|
+
const content = await response.text();
|
401
|
+
alertUploadFailure(response, content);
|
402
|
+
}
|
403
|
+
|
404
|
+
return false;
|
405
|
+
};
|
224
406
|
};
|
225
407
|
|
226
408
|
const compareIdentity = (uuid) => {
|
227
409
|
clearTimeout(reloadIdentityIframeTimeout);
|
228
|
-
reloadIdentityIframeTimeout = setTimeout(() =>
|
229
|
-
if (identityUuid !== uuid)
|
410
|
+
reloadIdentityIframeTimeout = setTimeout(() => getIdentityIframe().src += '', 1000);
|
411
|
+
if (identityUuid !== uuid) {
|
412
|
+
getIndexIframe().src += '';
|
413
|
+
clearTimeout(indexIframeTimeout);
|
414
|
+
indexIframeTimeout = setInterval(function () { getIndexIframe().contentWindow.postMessage('HELO', '*'); }, 200);
|
415
|
+
}
|
230
416
|
identityUuid = uuid;
|
231
417
|
};
|
232
418
|
|
233
|
-
const
|
419
|
+
const updateInboxInfo = () => {
|
420
|
+
if (!inboxContent.length) return;
|
421
|
+
|
422
|
+
const unreadCount = inboxContent.filter((mail) => isNewMail(mail)).length;
|
423
|
+
document.title = `PostMortem ${unreadCount}/${inboxContent.length} (unread/total)`;
|
424
|
+
inboxInfo.textContent = `${inboxContent.length} emails (${unreadCount} unread)`;
|
425
|
+
inboxInfo.innerHTML = `— ${inboxInfo.innerHTML}`;
|
426
|
+
};
|
427
|
+
|
428
|
+
const loadInbox = (uuid, mails) => {
|
429
|
+
clearTimeout(indexIframeTimeout);
|
430
|
+
inboxContent.splice(0, Infinity, ...mails)
|
234
431
|
if (uuid === indexUuid) {
|
235
432
|
return;
|
236
433
|
}
|
@@ -239,28 +436,36 @@
|
|
239
436
|
const parsedTimestamp = new Date(mail.timestamp);
|
240
437
|
const timestampSpan = `<span class="timestamp">${parsedTimestamp.toLocaleString()}</span>`;
|
241
438
|
const classes = ['list-group-item', 'inbox-item'];
|
439
|
+
|
242
440
|
if (window.location.hash === '#' + mail.id) classes.push('active');
|
441
|
+
|
442
|
+
if (isNewMail(mail)) classes.push('unread');
|
443
|
+
|
243
444
|
mailsById[mail.id] = mail;
|
244
|
-
|
445
|
+
|
446
|
+
if (requestedPending && mail.id === requestedId) {
|
447
|
+
requestedPending = false;
|
448
|
+
requestedId = null;
|
449
|
+
setTimeout(() => loadMail(mail.content), 0);
|
450
|
+
}
|
451
|
+
|
452
|
+
return [`<li data-email-id="${mail.id}" class="${classes.join(' ')}">`,
|
453
|
+
`<a title="${mail.subject}" href="javascript:void(0)">`,
|
454
|
+
`<i class="fa fa-envelope-open read-icon"></i>`,
|
455
|
+
`<i class="fa fa-envelope unread-icon"></i>${mail.subject}`,
|
456
|
+
`</a>`,
|
457
|
+
`${timestampSpan}</li>`].join('');
|
245
458
|
});
|
459
|
+
updateInboxInfo();
|
246
460
|
if (arrayIdentical(html, previousInbox)) return;
|
247
461
|
previousInbox = html;
|
248
462
|
$('#inbox').html('<ul class="list-group">' + html.join('\n') + '</ul>');
|
249
463
|
$('.inbox-item').click((ev) => {
|
250
464
|
const $target = $(ev.currentTarget);
|
251
465
|
const id = $target.data('email-id');
|
252
|
-
$('.inbox-item').removeClass('active');
|
253
|
-
$target.addClass('active');
|
254
|
-
window.location.hash = id;
|
255
466
|
setTimeout(() => loadMail(mailsById[id].content), 0);
|
256
467
|
});
|
257
468
|
|
258
|
-
if (!inboxInitialized) {
|
259
|
-
setEnabled(columnSwitch);
|
260
|
-
setColumnView(true);
|
261
|
-
setVisible(inbox, true);
|
262
|
-
}
|
263
|
-
inboxInitialized = true;
|
264
469
|
indexUuid = uuid;
|
265
470
|
};
|
266
471
|
|