refactor render service

This commit is contained in:
Jake McDermott
2018-08-25 00:57:50 -04:00
parent 04dbc2fcc4
commit d608402dc1

View File

@@ -1,6 +1,5 @@
import Ansi from 'ansi-to-html';
import Entities from 'html-entities';
import getUUID from 'uuid';
import {
EVENT_START_PLAY,
@@ -36,24 +35,18 @@ const hasAnsi = input => re.test(input);
function JobRenderService ($q, $sce, $window) {
this.init = ({ compile, toggles }) => {
this.hooks = { compile };
this.el = $(OUTPUT_ELEMENT_TBODY);
this.parent = null;
this.state = {
head: null,
tail: null,
head: 0,
tail: 0,
collapseAll: false,
toggleMode: toggles,
};
this.counters = {};
this.lines = {};
this.records = {};
this.uuids = {};
this.missingCounterRecords = {};
this.missingCounterUUIDs = {};
};
this.setCollapseAll = value => {
@@ -87,73 +80,54 @@ function JobRenderService ($q, $sce, $window) {
for (let i = 0; i <= events.length - 1; i++) {
const current = events[i];
const tailCounter = this.getTailCounter();
if (tailCounter && (current.counter !== tailCounter + 1)) {
if (this.state.tail && current.counter !== this.state.tail + 1) {
const missing = this.appendMissingEventGroup(current);
html += missing.html;
lines += missing.count;
}
const line = this.transformEvent(current);
const eventLines = this.transformEvent(current);
html += line.html;
lines += line.count;
html += eventLines.html;
lines += eventLines.count;
}
return { html, lines };
};
this.appendMissingEventGroup = event => {
const tailCounter = this.getTailCounter();
const tail = this.lookupRecord(tailCounter);
const tailMissing = this.isCounterMissing(tailCounter);
const tailUUID = this.uuids[this.state.tail];
const tailRecord = this.records[tailUUID];
if (!tailMissing && (!tail || !tail.counter)) {
if (!tailRecord) {
return { html: '', count: 0 };
}
let uuid;
if (tailMissing) {
uuid = this.missingCounterUUIDs[tailCounter];
if (tailRecord.isMissing) {
uuid = tailUUID;
} else {
uuid = getUUID();
uuid = `${event.counter}-${tailUUID}`;
this.records[uuid] = { uuid, counters: [], lineCount: 1, isMissing: true };
}
const counters = [];
for (let i = tailCounter + 1; i < event.counter; i++) {
if (tailMissing) {
this.missingCounterRecords[uuid].counters.push(i);
} else {
counters.push(i);
}
this.missingCounterUUIDs[i] = uuid;
for (let i = this.state.tail + 1; i < event.counter; i++) {
this.records[uuid].counters.push(i);
this.uuids[i] = uuid;
}
if (tailMissing) {
if (tailRecord.isMissing) {
return { html: '', count: 0 };
}
const record = {
counters,
uuid,
start: tail.end,
end: event.start_line,
};
if (record.start === record.end) {
if (tailRecord.end === event.start_line) {
return { html: '', count: 0 };
}
this.missingCounterRecords[uuid] = record;
const html = `<div id="${uuid}" class="at-Stdout-row">
<div class="at-Stdout-toggle"></div>
<div class="at-Stdout-line-clickable" ng-click="vm.showMissingEvents('${uuid}')">...</div></div>`;
const html = this.buildRowHTML(this.records[uuid]);
const count = 1;
return { html, count };
@@ -167,84 +141,65 @@ function JobRenderService ($q, $sce, $window) {
for (let i = events.length - 1; i >= 0; i--) {
const current = events[i];
const headCounter = this.getHeadCounter();
if (headCounter && (current.counter !== headCounter - 1)) {
if (this.state.head && current.counter !== this.state.head - 1) {
const missing = this.prependMissingEventGroup(current);
html = missing.html + html;
lines += missing.count;
}
const line = this.transformEvent(current);
const eventLines = this.transformEvent(current);
html = line.html + html;
lines += line.count;
html = eventLines.html + html;
lines += eventLines.count;
}
return { html, lines };
};
this.prependMissingEventGroup = event => {
const headCounter = this.getHeadCounter();
const head = this.lookupRecord(headCounter);
const headMissing = this.isCounterMissing(headCounter);
const headUUID = this.uuids[this.state.head];
const headRecord = this.records[headUUID];
if (!headMissing && (!head || !head.counter)) {
if (!headRecord) {
return { html: '', count: 0 };
}
let uuid;
if (headMissing) {
uuid = this.missingCounterUUIDs[headCounter];
if (headRecord.isMissing) {
uuid = headUUID;
} else {
uuid = getUUID();
uuid = `${headUUID}-${event.counter}`;
this.records[uuid] = { uuid, counters: [], lineCount: 1, isMissing: true };
}
const counters = [];
for (let i = headCounter - 1; i > event.counter; i--) {
if (headMissing) {
this.missingCounterRecords[uuid].counters.unshift(i);
} else {
counters.unshift(i);
}
this.missingCounterUUIDs[i] = uuid;
for (let i = this.state.head - 1; i > event.counter; i--) {
this.records[uuid].counters.unshift(i);
this.uuids[i] = uuid;
}
if (headMissing) {
if (headRecord.isMissing) {
return { html: '', count: 0 };
}
const record = {
counters,
uuid,
start: event.end_line,
end: head.start,
};
if (record.start === record.end) {
if (event.end_line === headRecord.start) {
return { html: '', count: 0 };
}
this.missingCounterRecords[uuid] = record;
const html = `<div id="${uuid}" class="at-Stdout-row">
<div class="at-Stdout-toggle"></div>
<div class="at-Stdout-line-clickable" ng-click="vm.showMissingEvents('${uuid}')">...</div></div>`;
const html = this.buildRowHTML(this.records[uuid]);
const count = 1;
return { html, count };
};
this.transformEvent = event => {
if (event.uuid && this.records[event.uuid]) {
if (!event || !event.stdout) {
return { html: '', count: 0 };
}
if (!event || !event.stdout) {
if (event.uuid && this.records[event.uuid]) {
return { html: '', count: 0 };
}
@@ -262,10 +217,10 @@ function JobRenderService ($q, $sce, $window) {
const line = lines[i];
const isLastLine = i === lines.length - 1;
let row = this.createRow(record, ln, line);
let row = this.buildRowHTML(record, ln, line);
if (record && record.isTruncated && isLastLine) {
row += this.createRow(record);
row += this.buildRowHTML(record);
count++;
}
@@ -280,20 +235,19 @@ function JobRenderService ($q, $sce, $window) {
return null;
}
this.lines[event.counter] = event.end_line - event.start_line;
if (this.state.tail === null ||
this.state.tail < event.counter) {
this.state.tail = event.counter;
}
if (this.state.head === null ||
this.state.head > event.counter) {
if (!this.state.head || event.counter < this.state.head) {
this.state.head = event.counter;
}
if (!this.state.tail || event.counter > this.state.tail) {
this.state.tail = event.counter;
}
if (!event.uuid) {
return null;
this.uuids[event.counter] = event.counter;
this.records[event.counter] = { counters: [event.counter], lineCount: lines.length };
return this.records[event.counter];
}
let isHost = false;
@@ -317,7 +271,7 @@ function JobRenderService ($q, $sce, $window) {
isTruncated: (event.end_line - event.start_line) > lines.length,
lineCount: lines.length,
isCollapsed: this.state.collapseAll,
counter: event.counter,
counters: [event.counter],
};
if (event.parent_uuid) {
@@ -355,9 +309,8 @@ function JobRenderService ($q, $sce, $window) {
record.line++;
}
this.uuids[event.counter] = record.uuid;
this.counters[event.uuid] = record.counter;
this.records[event.uuid] = record;
this.uuids[event.counter] = event.uuid;
return record;
};
@@ -374,25 +327,7 @@ function JobRenderService ($q, $sce, $window) {
return list;
};
this.deleteRecord = counter => {
const uuid = this.uuids[counter];
delete this.records[uuid];
delete this.counters[uuid];
delete this.uuids[counter];
delete this.lines[counter];
};
this.getTimestamp = created => {
const date = new Date(created);
const hour = date.getHours() < 10 ? `0${date.getHours()}` : date.getHours();
const minute = date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes();
const second = date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds();
return `${hour}:${minute}:${second}`;
};
this.createRow = (record, ln, content) => {
this.buildRowHTML = (record, ln, content) => {
let id = '';
let icon = '';
let timestamp = '';
@@ -400,6 +335,12 @@ function JobRenderService ($q, $sce, $window) {
let tdEvent = '';
let classList = '';
if (record.isMissing) {
return `<div id="${record.uuid}" class="at-Stdout-row">
<div class="at-Stdout-toggle"></div>
<div class="at-Stdout-line-clickable" ng-click="vm.showMissingEvents('${record.uuid}')">...</div></div>`;
}
content = content || '';
if (hasAnsi(content)) {
@@ -459,6 +400,15 @@ function JobRenderService ($q, $sce, $window) {
</div>`;
};
this.getTimestamp = created => {
const date = new Date(created);
const hour = date.getHours() < 10 ? `0${date.getHours()}` : date.getHours();
const minute = date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes();
const second = date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds();
return `${hour}:${minute}:${second}`;
};
//
// Element Operations
//
@@ -532,70 +482,25 @@ function JobRenderService ($q, $sce, $window) {
this.sanitize = html => entities.encode(html);
//
// Event Counter Methods - External code should use these.
// Event Counter Methods - External code should prefer these.
//
this.getTailCounter = () => {
if (this.state.tail === null) {
return 0;
}
if (this.state.tail < 0) {
return 0;
}
return this.state.tail;
};
this.getHeadCounter = () => {
if (this.state.head === null) {
return 0;
}
if (this.state.head < 0) {
return 0;
}
return this.state.head;
};
this.getCapacity = () => OUTPUT_EVENT_LIMIT - Object.keys(this.lines).length;
this.lookupRecord = counter => this.records[this.uuids[counter]];
this.getLineCount = counter => {
const record = this.lookupRecord(counter);
if (record && record.lineCount) {
return record.lineCount;
}
if (this.lines[counter]) {
return this.lines[counter];
}
return 0;
};
this.deleteMissingCounterRecord = counter => {
const uuid = this.missingCounterUUIDs[counter];
delete this.missingCounterRecords[counter];
delete this.missingCounterUUIDs[uuid];
};
this.clear = () => this.removeAll()
.then(() => {
const head = this.getHeadCounter();
const tail = this.getTailCounter();
for (let i = head; i <= tail; ++i) {
this.deleteRecord(i);
this.deleteMissingCounterRecord(i);
const uuid = this.uuids[i];
if (uuid) {
delete this.records[uuid];
delete this.uuids[i];
}
}
this.state.head = null;
this.state.tail = null;
this.state.head = 0;
this.state.tail = 0;
return $q.resolve();
});
@@ -613,73 +518,35 @@ function JobRenderService ($q, $sce, $window) {
return this.prepend(events.filter(({ counter }) => counter < head || counter > tail));
};
this.popMissing = counter => {
const uuid = this.missingCounterUUIDs[counter];
if (!this.missingCounterRecords[uuid]) {
return 0;
}
this.missingCounterRecords[uuid].counters.pop();
if (this.missingCounterRecords[uuid].counters.length > 0) {
return 0;
}
delete this.missingCounterRecords[uuid];
delete this.missingCounterUUIDs[counter];
return 1;
};
this.shiftMissing = counter => {
const uuid = this.missingCounterUUIDs[counter];
if (!this.missingCounterRecords[uuid]) {
return 0;
}
this.missingCounterRecords[uuid].counters.shift();
if (this.missingCounterRecords[uuid].counters.length > 0) {
return 0;
}
delete this.missingCounterRecords[uuid];
delete this.missingCounterUUIDs[counter];
return 1;
};
this.isCounterMissing = counter => this.missingCounterUUIDs[counter];
this.popFront = count => {
if (!count || count <= 0) {
return $q.resolve();
}
const max = this.getTailCounter();
const max = this.state.tail;
const min = max - count;
let lines = 0;
for (let i = max; i >= min; --i) {
if (this.isCounterMissing(i)) {
lines += this.popMissing(i);
} else {
lines += this.getLineCount(i);
const uuid = this.uuids[i];
if (!uuid) {
continue;
}
this.records[uuid].counters.pop();
delete this.uuids[i];
if (this.records[uuid].counters.length === 0) {
lines += this.records[uuid].lineCount;
delete this.records[uuid];
this.state.tail--;
}
}
return this.pop(lines)
.then(() => {
for (let i = max; i >= min; --i) {
this.deleteRecord(i);
this.state.tail--;
}
return $q.resolve();
});
return this.pop(lines);
};
this.popBack = count => {
@@ -687,29 +554,35 @@ function JobRenderService ($q, $sce, $window) {
return $q.resolve();
}
const min = this.getHeadCounter();
const min = this.state.head;
const max = min + count;
let lines = 0;
for (let i = min; i <= max; ++i) {
if (this.isCounterMissing(i)) {
lines += this.popMissing(i);
} else {
lines += this.getLineCount(i);
const uuid = this.uuids[i];
if (!uuid) {
continue;
}
this.records[uuid].counters.shift();
delete this.uuids[i];
if (this.records[uuid].counters.length === 0) {
lines += this.records[uuid].lineCount;
delete this.records[uuid];
this.state.head++;
}
}
return this.shift(lines)
.then(() => {
for (let i = min; i <= max; ++i) {
this.deleteRecord(i);
this.state.head++;
}
return $q.resolve();
});
return this.shift(lines);
};
this.getHeadCounter = () => this.state.head;
this.getTailCounter = () => this.state.tail;
this.getCapacity = () => OUTPUT_EVENT_LIMIT - (this.getTailCounter() - this.getHeadCounter());
}
JobRenderService.$inject = ['$q', '$sce', '$window'];