Skip to content

Instantly share code, notes, and snippets.

@gistlyn
Last active February 8, 2023 02:52
Show Gist options
  • Save gistlyn/f0349678d7f09f38c66bb1ecd89b09a5 to your computer and use it in GitHub Desktop.
Save gistlyn/f0349678d7f09f38c66bb1ecd89b09a5 to your computer and use it in GitHub Desktop.
Northwind SharpData UI
{{
var AppSvgs = {
'action/home.svg': 'home',
'device/storage.svg': 'db',
'action/list.svg': 'table',
'navigation/first_page.svg': 'chevron-first',
'navigation/last_page.svg': 'chevron-last',
'navigation/expand_more.svg': 'chevron-down',
'navigation/chevron_left.svg': 'chevron-left',
'navigation/chevron_right.svg': 'chevron-right',
'navigation/expand_less.svg': 'chevron-up',
'content/clear.svg': 'clear',
'content/filter_list.svg': 'filter',
}
}}
{{#each AppSvgs}}
{{`/lib/svg/material/${it.Key}` |> svgAddFile(it.Value,'app')}}
{{/each}}
{{#svg fields app}}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="black" width="48px" height="48px">
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M4 5v13h17V5H4zm10 2v9h-3V7h3zM6 7h3v9H6V7zm13 9h-3V7h3v9z" fill="#ffffff"/>
</svg>
{{/svg}}
{{#svg external-link app}}
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" y1="14" x2="21" y2="3"/>
</svg>
{{/svg}}
{{#svg loading app}}
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="24px" height="30px" viewBox="0 0 24 30" style="enable-background:new 0 0 50 50">
<rect x="0" y="10" width="4" height="10" fill="#333" opacity="0.2">
<animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0s" dur="0.6s" repeatCount="indefinite" />
<animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0s" dur="0.6s" repeatCount="indefinite" />
<animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0s" dur="0.6s" repeatCount="indefinite" />
</rect>
<rect x="8" y="10" width="4" height="10" fill="#333" opacity="0.2">
<animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0.15s" dur="0.6s" repeatCount="indefinite" />
<animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0.15s" dur="0.6s" repeatCount="indefinite" />
<animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0.15s" dur="0.6s" repeatCount="indefinite" />
</rect>
<rect x="16" y="10" width="4" height="10" fill="#333" opacity="0.2">
<animate attributeName="opacity" attributeType="XML" values="0.2; 1; .2" begin="0.3s" dur="0.6s" repeatCount="indefinite" />
<animate attributeName="height" attributeType="XML" values="10; 20; 10" begin="0.3s" dur="0.6s" repeatCount="indefinite" />
<animate attributeName="y" attributeType="XML" values="10; 5; 10" begin="0.3s" dur="0.6s" repeatCount="indefinite" />
</rect>
</svg>
{{/svg}}
{{#svg logo app}}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#ffffff" width="48px" height="48px">
<path d="M18 4l2 4h-3l-2-4h-2l2 4h-3l-2-4H8l2 4H7L5 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4h-4z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>
{{/svg}}
{{#svg excel app}}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px">
<path fill="#4CAF50" d="M41,10H25v28h16c0.553,0,1-0.447,1-1V11C42,10.447,41.553,10,41,10z"/>
<path fill="#FFF" d="M32 15H39V18H32zM32 25H39V28H32zM32 30H39V33H32zM32 20H39V23H32zM25 15H30V18H25zM25 25H30V28H25zM25 30H30V33H25zM25 20H30V23H25z"/>
<path fill="#2E7D32" d="M27 42L6 38 6 10 27 6z"/>
<path fill="#FFF" d="M19.129,31l-2.411-4.561c-0.092-0.171-0.186-0.483-0.284-0.938h-0.037c-0.046,0.215-0.154,0.541-0.324,0.979L13.652,31H9.895l4.462-7.001L10.274,17h3.837l2.001,4.196c0.156,0.331,0.296,0.725,0.42,1.179h0.04c0.078-0.271,0.224-0.68,0.439-1.22L19.237,17h3.515l-4.199,6.939l4.316,7.059h-3.74V31z"/>
</svg>
{{/svg}}
{{htmlError}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="/favicon.png" rel="icon">
<link rel="stylesheet" href="/lib/css/bootstrap/bootstrap.css">
<title>{{ title ?? 'Sharp Data' }}</title>
</head>
<body>
{{ 'buttons,buttons-svg' |> cssIncludes }}
{{ 'app' |> cssIncludes |> svgFill('#444') }}
{{#if fileExists('/bundle.css') }}
<link rel="stylesheet" href="/bundle.css">
{{else}}
{{ 'content:/src/css/' |> bundleCss({ minify:false, cache:false, out:'/app.bundle.css' }) }}
{{/if}}
<style>
{{ {
'.home-link': ['home','#4183B8'],
'.first-link': ['chevron-first','#4183B8'],
'.left-link': ['chevron-left','#4183B8'],
'.right-link': ['chevron-right','#4183B8'],
'.last-link': ['chevron-last','#4183B8'],
} |> toList |> map => `${it.Key} { ${it.Value[0].svgBackgroundImageCss(it.Value[1])} }` |> joinln |> raw }}
.text-close::after { content:'\00D7'; }
</style>
<i hidden>{{ '/js/hot-fileloader.js' |> ifDebugIncludeScript }}</i>
<script>
CONFIG = {
debug: {{ debugMode |> json }},
desktop: {{ desktopInfo |> json }},
hasExcel: {{ (isWin ? typeofProgId('Excel.Application') != null : false) |> json }},
namedDbs: {{ dbNamedConnections |> json }},
tables: {}
}
{{#if resolveArg('tables')}}
CONFIG.tables.main = {{ resolveArg('tables').split(',') |> json }};
{{else}}
CONFIG.tables.main = {{ dbTableNames |> json }};
{{/if}}
{{#each dbNamedConnections}}
{{#if resolveArg(`tables_${it}`) }}
CONFIG.tables['{{it}}'] = {{ resolveArg(`tables_${it}`).split(',') |> json }};
{{else}}
CONFIG.tables['{{it}}'] = {{ {} |> dbTableNames({ namedConnection:it }) |> json }};
{{/if}}
{{/each}}
</script>
<noscript>You need to enable JavaScript to run this app.</noscript>
{{page}}
{{ [
`/lib/js/vue/vue.min.js`,
`/lib/js/vue-router/vue-router.min.js`,
`/lib/js/vue-class-component/vue-class-component.min.js`,
`/lib/js/vue-property-decorator/vue-property-decorator.min.js`,
`/lib/js/@servicestack/desktop/servicestack-desktop.min.js`,
`/lib/js/@servicestack/client/servicestack-client.min.js`,
`/lib/js/@servicestack/vue/servicestack-vue.min.js`,
] |> map => `<script src="${it}"></script>` |> joinln |> raw }}
<script>
var ALIASES = {
'vue': { default: Vue },
'vue-router': { default: VueRouter },
'vue-class-component': VueClassComponent,
'vue-property-decorator': VuePropertyDecorator,
'@servicestack/vue': ServiceStackVue
};
var global = window;
window.exports = {};
window.require = function(name) {
return ALIASES[name] || exports[name] || window[name] || exports;
};
Object.assign(window, window["@servicestack/desktop"], window["@servicestack/client"]);
</script>
{{#if fileExists('/bundle.js') }}
<script src="/bundle.js"></script>
{{else}}
{{ [
'content:/src/components/',
'content:/src/shared/',
'content:/src/',
] |> bundleJs({ minify:false, cache:false, iife:true, out:`/app.bundle.js` }) }}
{{/if}}
{{ ['custom/'] |> bundleJs({ minify:false, bundle:false }) }}
{{ scripts |> raw }}
{{initError |> htmlError}}
{{htmlError}}
</body>
</html>
debug false
name Northwind SharpData UI
appName sharpdata
# Configure below. Supported dialects: sqlite, mysql, postgres, sqlserver
db.connections[northwind] { db:sqlite, connection: 'northwind.sqlite' }
.grid-layout{display:grid;width:100vw;height:100vh;grid-column-gap:5px;grid-template-columns:250px auto;grid-template-rows:80px auto;grid-template-areas:"head head" "nav main"}header{background:#fff;grid-area:head;display:grid;grid-template-columns:auto auto;grid-template-areas:"breadcrumb auth"}.site-breadcrumbs{padding-left:0;height:80px}nav{background:#fff;grid-area:nav;padding:0 2px 0 10px;overflow-x:hidden;overflow-y:auto;display:grid;grid-template-rows:40px auto;grid-template-areas:"filter" "sidebar"}#nav-filter{grid-area:filter;margin:2px 0 0 0}#sidebar{grid-area:sidebar;overflow-x:hidden;overflow-y:scroll}main{background:#fff;grid-area:main;padding:2px;grid-row-gap:5px;overflow:auto;display:grid}.main-query,.loading-query{height:38px;font-size:20px;padding-top:1px}.main-container{overflow-y:scroll}
::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background-color:#f1f1f1}.navbar{border-radius:0;background:#4183b8!important}a{color:#4183b8}a:hover{text-decoration:none}.form-check input[type=checkbox],.form-check input[type=radio]{margin-top:7px}.breadcrumb{background:none}.result{margin:10px;color:#349268}.stacktrace{background:#f1f1f1;padding:1em;margin:1em 0 .5em 0;border-radius:5px;border:1px solid #ccc;white-space:pre-wrap}.results-none{color:#6c757d}table.results{border:1px solid #eee;background:#fefefe}table.results thead tr{background:#eee}table.results th{text-align:left;color:#757575;font-size:13px;line-height:18px;border-bottom:1px solid #e0e0e0;padding:5px;overflow:hidden;white-space:nowrap}table.results td{color:#212121;font-size:12px;padding:5px;max-width:300px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}table.results td.row-component{max-width:900px}table.results tr.filters td{text-overflow:unset}th .modal-content,td .modal-content{font-size:1rem}.noselect{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.svg-btn,.btn-link,.th-link{cursor:pointer;user-select:none}.btn-link{text-decoration:none}#sidebar .selected{font-weight:bold}.datamodel{white-space:nowrap}.close,.text-close{user-select:none}.text-close{cursor:pointer;font-size:1.5em;color:#999}.text-close:hover{color:#666}.results-label{color:#666;vertical-align:bottom;line-height:36px}table.results .filters td{padding:0 1px;margin:0}.filters input{min-width:50px;width:100%;font-size:11px}.btn-compact.btn-sm{padding:.1rem .4rem}.jsonviewer .ib{display:inline-block}.jsonviewer table{border-collapse:collapse;border:solid 1px #ccc;clear:left}.jsonviewer th{text-align:left;padding:4px 8px;text-shadow:#fff 1px 1px -1px;background:#f1f1f1;white-space:nowrap;font-weight:bold}.jsonviewer td{padding:8px 8px 0 8px;vertical-align:top;line-height:18px}.jsonviewer dl{margin:0;clear:left}.jsonviewer dt{font-weight:bold;width:160px;clear:left;float:left;display:block;white-space:nowrap;line-height:26px}.jsonviewer dd{display:block;float:left;line-height:26px;max-width:600px;margin:0}.jsonviewer dl dl dt{font-weight:bold}.jsonviewer hr{display:none}.jsonviewer td dl HR{display:block;padding:0;clear:left;border:0}.jsonviewer td dl{padding:4px;margin:0;height:100%;max-width:700px}.jsonviewer dl td dl dt{padding:2px;margin:0 10px 0 0;font-weight:bold;width:120px;overflow:hidden;clear:left;float:left;display:block}.jsonviewer dl td dl dd{margin:0;padding:2px;display:block;float:left}
(function(){
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [0, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var vue_1 = require("vue");
var vue_property_decorator_1 = require("vue-property-decorator");
var shared_1 = require("../../shared");
var client_1 = require("@servicestack/client");
var desktop_1 = require("@servicestack/desktop");
var FormatString = /** @class */ (function (_super) {
__extends(FormatString, _super);
function FormatString() {
return _super !== null && _super.apply(this, arguments) || this;
}
Object.defineProperty(FormatString.prototype, "lower", {
get: function () { return ("" + this.value).toLowerCase(); },
enumerable: true,
configurable: true
});
Object.defineProperty(FormatString.prototype, "isUrl", {
get: function () { return typeof this.value == "string" && this.value.startsWith('http'); },
enumerable: true,
configurable: true
});
Object.defineProperty(FormatString.prototype, "url", {
get: function () { return typeof this.value == "string" && this.value.substring(this.value.indexOf('://') + 3); },
enumerable: true,
configurable: true
});
Object.defineProperty(FormatString.prototype, "format", {
get: function () { return typeof this.value == "string" && this.value.startsWith('/Date(') ? client_1.toDateFmt(this.value) : this.value; },
enumerable: true,
configurable: true
});
__decorate([
vue_property_decorator_1.Prop({ default: '' })
], FormatString.prototype, "value", void 0);
__decorate([
vue_property_decorator_1.Prop({ default: '' })
], FormatString.prototype, "href", void 0);
FormatString = __decorate([
vue_property_decorator_1.Component({ template: "<a v-if=\"isUrl\" :href=\"value\" target=\"_blank\">{{url}}</a>\n <i v-else-if=\"lower == 'false'\" class=\"svg svg-md bool-off-muted\"></i>\n <i v-else-if=\"lower == 'true'\" class=\"svg svg-md bool-on-muted\"></i>\n <a v-else-if=\"href\" :href=\"href\">{{format}}</a>\n <span v-else>{{format}}</span>\n" })
], FormatString);
return FormatString;
}(vue_1.default));
vue_1.default.component('format', FormatString);
var Results = /** @class */ (function (_super) {
__extends(Results, _super);
function Results() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.showSelectColumns = false;
_this.skip = 0;
_this.take = 100;
_this.total = null;
_this.orderBy = '';
_this.filters = {};
_this.fields = [];
_this.results = [];
_this.openComponents = [];
_this.loading = false;
_this.responseStatus = null;
return _this;
}
Object.defineProperty(Results.prototype, "store", {
get: function () { return shared_1.store; },
enumerable: true,
configurable: true
});
Object.defineProperty(Results.prototype, "columns", {
get: function () { return shared_1.store.getColumnSchemas(this.db, this.table); },
enumerable: true,
configurable: true
});
Object.defineProperty(Results.prototype, "dirty", {
get: function () { return this.skip || this.orderBy || Object.keys(this.filters).length > 0 || this.fields.length > 0; },
enumerable: true,
configurable: true
});
Object.defineProperty(Results.prototype, "rowComponent", {
get: function () { return shared_1.getRowComponent(this.db, this.table); },
enumerable: true,
configurable: true
});
Object.defineProperty(Results.prototype, "fieldNames", {
get: function () {
var _this = this;
var ret = this.columns ? .map(function (x) { return x.columnName; }) : ;
if (this.fields.length > 0) {
ret = ret.filter(function (x) { return _this.fields.indexOf(x) >= 0; });
}
return ret;
},
enumerable: true,
configurable: true
});
Results.prototype.showRowComponent = function (rowIndex) { return this.openComponents.indexOf(rowIndex) >= 0; };
Results.prototype.toggleRowComponent = function (rowIndex) {
if (this.showRowComponent(rowIndex))
this.openComponents = this.openComponents.filter(function (x) { return x != rowIndex; });
else
this.openComponents.push(rowIndex);
};
Results.prototype.rowComponentClass = function (rowIndex) {
return "svg svg-chevron-" + (this.showRowComponent(rowIndex) ? 'down' : 'right') + " svg-md btn-link align-top";
};
Results.prototype.min = function (num1, num2) { return Math.min(num1, num2); };
Results.prototype.onUrlChange = function (newVal) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.reset()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Results.prototype.clear = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (this.$route.query.filter) {
this.$router.push(this.$route.path);
}
return [4 /*yield*/, shared_1.saveTableSettings(this.db, this.table, null)];
case 1:
_a.sent();
return [4 /*yield*/, this.reset()];
case 2:
_a.sent();
return [2 /*return*/];
}
});
});
};
Results.prototype.reset = function () {
return __awaiter(this, void 0, void 0, function () {
var settings, parts, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
settings = shared_1.getTableSettings(this.db, this.table) || {};
this.skip = settings.skip || 0;
this.orderBy = settings.orderBy || '';
this.filters = settings.filters || {};
this.fields = settings.fields || [];
if (this.$route.query.filter) {
parts = client_1.splitOnFirst(this.$route.query.filter, ':');
this.filters = (_a = {}, _a[parts[0]] = parts[1], _a);
}
this.results = [];
return [4 /*yield*/, shared_1.loadTable(this, this.db, this.table)];
case 1:
_b.sent();
return [4 /*yield*/, this.search()];
case 2:
_b.sent();
return [2 /*return*/];
}
});
});
};
Results.prototype.handleSelectColumns = function (e) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.showSelectColumns = false;
return [4 /*yield*/, this.search()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Results.prototype.viewNext = function (skip) {
return __awaiter(this, void 0, void 0, function () {
var lastPage;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.skip += skip;
if (typeof this.total != 'number')
return [2 /*return*/];
lastPage = Math.floor(this.total / 100) * 100;
if (this.skip > lastPage) {
this.skip = lastPage;
}
if (this.skip < 0) {
this.skip = 0;
}
return [4 /*yield*/, this.search()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Object.defineProperty(Results.prototype, "filterQuery", {
get: function () {
var _this = this;
var url = '';
Object.keys(this.filters).forEach(function (k) {
if (_this.filters[k]) {
url += '&';
url += encodeURIComponent(k) + '=' + encodeURIComponent(_this.filters[k]);
}
});
return url;
},
enumerable: true,
configurable: true
});
Results.prototype.filterSearch = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.skip = 0;
return [4 /*yield*/, this.search()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Results.prototype.createFilteredUrl = function (format) {
if (format === void 0) { format = "json"; }
var url = "/db/" + this.db + "/" + this.table + "?format=" + format;
url += this.filterQuery;
if (this.fields.length > 0) {
url += '&fields=' + encodeURIComponent(this.fields.join(','));
}
if (this.orderBy) {
url += '&orderBy=' + encodeURIComponent(this.orderBy);
}
return url;
};
Results.prototype.createUrl = function (format) {
if (format === void 0) { format = "json"; }
var url = this.createFilteredUrl(format);
if (this.skip > 0) {
url += '&skip=' + this.skip;
}
if (this.take) {
url += '&take=' + this.take;
}
//log('createUrl, filters', this.filters, 'orderBy', this.orderBy, 'take', this.take, 'URL', url);
return url;
};
Results.prototype.search = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
var _a, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
this.openComponents = [];
_a = this;
return [4 /*yield*/, shared_1.exec(this, function () { return __awaiter(_this, void 0, void 0, function () {
var url, r, json;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
url = this.createUrl();
return [4 /*yield*/, fetch(url)];
case 1:
r = _a.sent();
return [4 /*yield*/, r.text()];
case 2:
json = _a.sent();
return [2 /*return*/, json && JSON.parse(json) || []];
}
});
}); })];
case 1:
_a.results = _c.sent();
if (this.rowComponent && this.results.length == 1) {
this.openComponents.push(0);
}
_b = this;
return [4 /*yield*/, shared_1.exec(this, function () { return __awaiter(_this, void 0, void 0, function () {
var url, r, txtTotal;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
url = "/db/" + this.db + "/" + this.table + "/total?format=json";
url += this.filterQuery;
return [4 /*yield*/, fetch(url)];
case 1:
r = _a.sent();
return [4 /*yield*/, r.text()];
case 2:
txtTotal = _a.sent();
return [2 /*return*/, parseInt(txtTotal) || null];
}
});
}); })];
case 2:
_b.total = _c.sent();
return [4 /*yield*/, shared_1.saveTableSettings(this.db, this.table, {
skip: this.skip,
filters: this.filters,
orderBy: this.orderBy,
fields: this.fields,
})];
case 3:
_c.sent();
return [2 /*return*/];
}
});
});
};
Results.prototype.openCsv = function () {
return __awaiter(this, void 0, void 0, function () {
var url, downloadUrl;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
url = this.createFilteredUrl("csv");
downloadUrl = desktop_1.desktopSaveDownloadUrl(this.db + "-" + this.table + "-" + shared_1.dateFmtHMS() + ".csv", url) + "?open=true";
if (shared_1.store.hasExcel) {
downloadUrl += '&start=excel';
}
return [4 /*yield*/, fetch(downloadUrl)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Results.prototype.open = function (format) {
return __awaiter(this, void 0, void 0, function () {
var url;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
url = this.createUrl(format);
return [4 /*yield*/, shared_1.openUrl(url)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Results.prototype.mounted = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
shared_1.bus.$on('settings', function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.reset()];
case 1: return [2 /*return*/, _a.sent()];
}
}); }); });
return [4 /*yield*/, this.reset()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Results.prototype.humanize = function (s) { return client_1.humanize(s); };
Results.prototype.renderValue = function (o) {
return Array.isArray(o)
? o.join(', ')
: typeof o == "undefined"
? ""
: typeof o == "object"
? JSON.stringify(o)
: o + "";
};
Results.prototype.getField = function (o, name) { return client_1.getField(o, name); };
Results.prototype.getLink = function (o, name) {
var config = shared_1.store.dbConfigs[this.db];
var fnLink = config && config.links && config.links[this.table] && config.links[this.table][name];
return fnLink && fnLink(client_1.getField(o, name));
};
Results.prototype.setOrderBy = function (field) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (this.orderBy == field) {
this.orderBy = '-' + field;
}
else if (this.orderBy == '-' + field) {
this.orderBy = '';
}
else {
this.orderBy = field;
}
return [4 /*yield*/, this.search()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Results.prototype.helpFilters = function () {
return "Search Filters:\n Use '=null' or '!=null' to search NULL columns\n Use '<= < > >= <> !=' prefix to search with that operator\n Use ',' suffix to perform an IN(values) search on integers\n Use '%' prefix or suffix to perform a LIKE wildcard search\n Use '=' prefix to perform an exact coerced search\nOtherwise a 'string equality' search is performed";
};
__decorate([
vue_property_decorator_1.Prop()
], Results.prototype, "db", void 0);
__decorate([
vue_property_decorator_1.Prop()
], Results.prototype, "table", void 0);
__decorate([
vue_property_decorator_1.Watch('$route', { immediate: true, deep: true })
], Results.prototype, "onUrlChange", null);
Results = __decorate([
vue_property_decorator_1.Component({ template: "<div>\n <div v-if=\"!loading\" class=\"main-query text-nowrap\">\n <span class=\"btn svg svg-fields svg-2x\" title=\"View Columns\" @click=\"showSelectColumns=!showSelectColumns\"></span>\n <button class=\"btn first-link svg-2x\" :disabled=\"skip==0\" title=\"<< first\" @click=\"viewNext(-total)\"></button>\n <button class=\"btn left-link svg-2x\" :disabled=\"skip==0\" title=\"< previous\" @click=\"viewNext(-100)\"></button>\n <button class=\"btn right-link svg-2x\" :disabled=\"results.length < take\" title=\"next >\" @click=\"viewNext(100)\"></button>\n <button class=\"btn last-link svg-2x\" :disabled=\"results.length < take\" title=\"last >>\" @click=\"viewNext(total)\"></button>\n <span class=\"px-1 results-label\">Showing Results {{skip+1}} - {{min(skip + results.length,total)}} <span v-if=\"total!=null\">of {{total}}</span></span>\n <button v-if=\"dirty\" class=\"btn svg-clear svg-lg\" @click=\"clear()\" title=\"reset query\"></button>\n <button v-if=\"store.hasExcel\" class=\"btn btn-outline-success btn-sm btn-compact\" @click=\"openCsv()\" \n :title=\"store.hasExcel ? 'Open in Excel' : 'Open CSV'\"><i class=\"svg-md svg-excel\"></i>{{store.hasExcel ? 'excel' : 'csv' }}</button>\n <span class=\"btn btn-sm px-1\" @click=\"open('html')\"><i class=\"svg-md svg-external-link\"></i> html</span>\n <span class=\"btn btn-sm px-0\" @click=\"open('csv')\"><i class=\"svg-md svg-external-link\"></i> csv</span>\n <span class=\"btn btn-sm pl-1\" @click=\"open('json')\"><i class=\"svg-md svg-external-link\"></i> json</span>\n </div>\n <div v-else class=\"loading-query\">\n <span class=\"svg svg-loading svg-2x ml-1\"></span>Loading {{ this.columns?.length ? 'results' : 'schema' }}... \n </div>\n <div v-if=\"showSelectColumns\">\n <select-columns :columns=\"columns\" v-model=\"fields\" @done=\"handleSelectColumns($event)\" />\n </div>\n <table class=\"results\">\n <thead><tr class=\"noselect\">\n <th v-for=\"f in fieldNames\" :key=\"f\" @click=\"setOrderBy(f)\" class=\"th-link\">\n <div class=\"text-nowrap\">\n {{ humanize(f) }}\n <span v-if=\"orderBy==f\" class=\"svg svg-chevron-up svg-md align-top\"></span>\n <span v-else-if=\"orderBy=='-'+f\" class=\"svg svg-chevron-down svg-md align-top\"></span>\n </div>\n </th>\n </tr></thead>\n <tbody>\n <tr class=\"filters\">\n <td v-for=\"(f,j) in fieldNames\">\n <input type=\"text\" v-model=\"filters[f]\" @keydown.enter.stop=\"filterSearch()\">\n <span v-if=\"j==fieldNames.length-1\" style=\"margin:0 0 0 -23px;\"><i class=\"svg svg-btn svg-filter svg-md\" :title=\"helpFilters()\" /></span>\n </td>\n </tr>\n <template v-for=\"(r,i) in results\">\n <tr :key=\"i\">\n <td v-for=\"(f,j) in fieldNames\" :key=\"j\" :title=\"renderValue(getField(r,f))\">\n <span v-if=\"j == 0 && rowComponent\" :class=\"rowComponentClass(i)\" @click=\"toggleRowComponent(i)\"></span>\n <format :value=\"getField(r,f)\" :href=\"getLink(r,f)\" />\n </td>\n </tr>\n <tr v-if=\"showRowComponent(i)\">\n <td class=\"row-component\" :colspan=\"fieldNames.length\">\n <component :is=\"rowComponent\" :db=\"db\" :table=\"table\" :row=\"r\" :columns=\"columns\"></component>\n </td> \n </tr>\n </template>\n </tbody>\n </table>\n <error-view :responseStatus=\"responseStatus\" />\n</div>",
})
], Results);
return Results;
}(vue_1.default));
exports.Results = Results;
exports.default = Results;
vue_1.default.component('results', Results);
;
})();
(function(){
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
var vue_1 = require("vue");
var vue_property_decorator_1 = require("vue-property-decorator");
var SelectColumns = /** @class */ (function (_super) {
__extends(SelectColumns, _super);
function SelectColumns() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.selectedColumns = [];
return _this;
}
SelectColumns.prototype.mounted = function () {
this.selectedColumns = this.value;
this.$nextTick(function () { return document.querySelector('.modal') ? .focus() : ; });
};
SelectColumns.prototype.onInputValues = function (e) {
return this.selectedColumns;
};
__decorate([
vue_property_decorator_1.Prop()
], SelectColumns.prototype, "columns", void 0);
__decorate([
vue_property_decorator_1.Prop({ default: function () { return ([]); } })
], SelectColumns.prototype, "value", void 0);
__decorate([
vue_property_decorator_1.Emit('input')
], SelectColumns.prototype, "onInputValues", null);
SelectColumns = __decorate([
vue_property_decorator_1.Component({ template: "<div class=\"modal\" tabindex=\"-1\" role=\"dialog\" @keyup.esc=\"$emit('done')\" style=\"display:block;background:rgba(0,0,0,.25)\">\n <div class=\"modal-dialog\" role=\"document\" style=\"margin-top:120px\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h5 class=\"modal-title noselect\">\n Column Preferences\n </h5>\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\" @click=\"$emit('done')\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n </div>\n <div class=\"modal-body ml-2\">\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"radio\" name=\"exampleRadios\" id=\"allColumns\" :checked=\"selectedColumns.length==0\" \n @click=\"selectedColumns=[]\" @change=\"onInputValues\">\n <label class=\"form-check-label noselect\" for=\"allColumns\">View all columns</label>\n </div>\n <hr>\n <div v-for=\"c in columns\" :key=\"c.columnName\" class=\"form-check\">\n <input class=\"form-check-input\" type=\"checkbox\" :id=\"c.columnName\" :value=\"c.columnName\" v-model=\"selectedColumns\" @change=\"onInputValues\">\n <label class=\"form-check-label noselect\" :for=\"c.columnName\">{{c.columnName}}</label>\n </div>\n <div class=\"form-group text-right\">\n <span class=\"btn btn-link\" @click=\"$emit('done')\">Close</span>\n <button class=\"btn btn-primary\" @click=\"$emit('done')\">Done</button>\n </div>\n </div>\n </div>\n </div>\n</div>",
})
], SelectColumns);
return SelectColumns;
}(vue_1.default));
vue_1.default.component('select-columns', SelectColumns);
;
})();
(function(){
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [0, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var vue_property_decorator_1 = require("vue-property-decorator");
var shared_1 = require("../../shared");
var Viewer = /** @class */ (function (_super) {
__extends(Viewer, _super);
function Viewer() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.txtFilter = '';
_this.results = [];
_this.loading = false;
_this.responseStatus = null;
return _this;
}
Object.defineProperty(Viewer.prototype, "store", {
get: function () { return shared_1.store; },
enumerable: true,
configurable: true
});
Object.defineProperty(Viewer.prototype, "db", {
get: function () { return this.$route.params.db; },
enumerable: true,
configurable: true
});
Object.defineProperty(Viewer.prototype, "table", {
get: function () { return this.$route.params.table; },
enumerable: true,
configurable: true
});
Viewer.prototype.filtered = function (tables) {
var _this = this;
return this.txtFilter
? tables.filter(function (x) { return x.toLowerCase().indexOf(_this.txtFilter.toLowerCase()) >= 0; })
: tables;
};
Viewer.prototype.link = function (d, t) { return "/" + d + "/" + t; };
Viewer.prototype.tableName = function (db, table) {
var config = shared_1.store.dbConfigs[db];
return config && config.tableName ? config.tableName(table) ? ? table : table : : ;
};
Viewer.prototype.mounted = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/];
});
});
};
Viewer.prototype.submit = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/];
});
});
};
__decorate([
vue_property_decorator_1.Prop({ default: '' })
], Viewer.prototype, "name", void 0);
Viewer = __decorate([
vue_property_decorator_1.Component({ template: "<section id=\"home\" class=\"grid-layout\">\n <header id=\"header\">\n <h1>\n <nav class=\"site-breadcrumbs\">\n <ol class=\"breadcrumb\">\n <li class=\"breadcrumb-item\">\n <router-link to=\"/\"><i class=\"home-link svg-3x mb-1\" title=\"home\" /></router-link>\n </li>\n <li v-if=\"db\" class=\"breadcrumb-item\">{{db}}</li>\n <li v-if=\"table\" class=\"breadcrumb-item active\">{{table}}</li>\n <li v-if=\"!db && !table\" class=\"breadcrumb-item\">Select Table</li>\n <li v-if=\"loading\"><i class=\"svg-loading svg-lg ml-2 mb-1\" title=\"loading...\" /></li>\n </ol>\n </nav>\n </h1>\n <h1 v-else-if=\"loading\">\n <i class=\"fab fa-loading\"></i>\n Loading...\n </h1>\n <div v-else-if=\"responseStatus\">\n <error-summary :responseStatus=\"responseStatus\" />\n </div>\n </header>\n \n <nav id=\"left\">\n <div id=\"nav-filter\">\n <i v-if=\"txtFilter\" class=\"text-close\" style=\"position:absolute;margin:0 0 0 215px;\" title=\"clear\" @click=\"txtFilter=''\"></i>\n <v-input v-model=\"txtFilter\" id=\"txtFilter\" placeholder=\"filter\" inputClass=\"form-control\" />\n </div>\n <div id=\"sidebar\" class=\"\">\n <div>\n <template v-for=\"(tables,d) in store.tables\">\n <div v-if=\"filtered(tables).length > 0\" class=\"ml-1 mt-2\">\n <h4>\n <i class=\"svg-db svg-2x\"></i>\n {{d}}\n </h4>\n <div v-for=\"t in filtered(tables)\" :key=\"t\" :class=\"['datamodel',{selected:t==table}]\" :title=\"t\">\n <router-link class=\"ml-3\" :to=\"link(d,t)\">{{tableName(d,t)}}</router-link>\n <span v-if=\"store.getColumnTotal(d,t) != null\" class=\"text-muted\">({{store.getColumnTotal(d,t)}})</span>\n </div>\n </div>\n </template> \n </div>\n </div>\n </nav>\n \n <main v-if=\"db && table\">\n <div v-if=\"!responseStatus\" class=\"main-container\">\n <results :db=\"db\" :table=\"table\" />\n </div>\n <div v-else><error-view :responseStatus=\"responseStatus\" class=\"mt-5\" /></div>\n </main>\n \n </section>",
})
], Viewer);
return Viewer;
}(vue_property_decorator_1.Vue));
exports.Viewer = Viewer;
exports.default = Viewer;
vue_property_decorator_1.Vue.component('viewer', Viewer);
;
})();
(function(){
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [0, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var _this = this;
Object.defineProperty(exports, "__esModule", { value: true });
var vue_1 = require("vue");
var client_1 = require("@servicestack/client");
exports.client = new client_1.JsonServiceClient('/');
var desktop_1 = require("@servicestack/desktop");
var vue_property_decorator_1 = require("vue-property-decorator");
var RowComponent = /** @class */ (function (_super) {
__extends(RowComponent, _super);
function RowComponent() {
return _super !== null && _super.apply(this, arguments) || this;
}
__decorate([
vue_property_decorator_1.Prop()
], RowComponent.prototype, "db", void 0);
__decorate([
vue_property_decorator_1.Prop()
], RowComponent.prototype, "table", void 0);
__decorate([
vue_property_decorator_1.Prop()
], RowComponent.prototype, "row", void 0);
__decorate([
vue_property_decorator_1.Prop()
], RowComponent.prototype, "columns", void 0);
return RowComponent;
}(vue_1.default));
exports.RowComponent = RowComponent;
var rowComponents = {};
function getRowComponent(db, table) {
db = db.toLowerCase();
table = table.toLowerCase();
return rowComponents[db] && rowComponents[db][table] || null;
}
exports.getRowComponent = getRowComponent;
function registerRowComponent(db, table, constructor, component) {
vue_1.default.component(component, constructor);
db = db.toLowerCase();
table = table.toLowerCase();
if (!rowComponents[db])
rowComponents[db] = {};
rowComponents[db][table] = component;
}
exports.registerRowComponent = registerRowComponent;
var Roles;
(function (Roles) {
Roles["Admin"] = "Admin";
})(Roles = exports.Roles || (exports.Roles = {}));
exports.store = {
debug: global.CONFIG.debug,
desktop: global.CONFIG.desktop,
hasExcel: global.CONFIG.hasExcel,
namedDbs: global.CONFIG.namedDbs,
tables: global.CONFIG.tables,
totals: {},
columns: {},
getColumnTotal: function (db, table) {
var ret = this.totals[db] && this.totals[db][table];
return ret != null ? ret : null;
},
getColumnSchemas: function (db, table) {
return this.columns[db] && this.columns[db][table] || [];
},
dbConfigs: {},
};
function dbConfig(db, config) {
if (db != 'main' && exports.store.namedDbs.indexOf(db) < 0)
return;
if (config.showTables && config.showTables.length > 0) {
vue_1.default.set(exports.store.tables, db, config.showTables);
}
if (config.rowComponents) {
for (var _i = 0, _a = Object.keys(config.rowComponents); _i < _a.length; _i++) {
var table = _a[_i];
registerRowComponent(db, table, config.rowComponents[table], table);
}
}
vue_1.default.set(exports.store.dbConfigs, db, config);
}
exports.dbConfig = dbConfig;
exports.splitPascalCase = function (table) {
return client_1.humanize(table).split(' ').map(client_1.toPascalCase).join(' ');
};
var EventBus = /** @class */ (function (_super) {
__extends(EventBus, _super);
function EventBus() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.store = exports.store;
return _this;
}
return EventBus;
}(vue_1.default));
exports.bus = new EventBus({ data: exports.store });
var settings = {};
var settingsLoaded = false;
function loadSettings() {
return __awaiter(this, void 0, void 0, function () {
var settingsJson, _a, e_1;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 4, 5, 6]);
if (!exports.store.desktop) return [3 /*break*/, 2];
return [4 /*yield*/, desktop_1.desktopTextFile('settings.json')];
case 1:
_a = _b.sent();
return [3 /*break*/, 3];
case 2:
_a = localStorage.getItem('settings.json');
_b.label = 3;
case 3:
settingsJson = _a;
if (settingsJson) {
settings = JSON.parse(settingsJson) || {};
log('loaded', settings);
exports.bus.$emit('settings');
}
return [3 /*break*/, 6];
case 4:
e_1 = _b.sent();
log("Could not retrieve desktopTextFile 'settings.json'", e_1);
return [3 /*break*/, 6];
case 5:
settingsLoaded = true;
return [7 /*endfinally*/];
case 6: return [2 /*return*/];
}
});
});
}
exports.loadSettings = loadSettings;
function saveSettings() {
return __awaiter(this, void 0, void 0, function () {
var settingsJson, e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 4, , 5]);
settingsJson = JSON.stringify(settings);
if (!exports.store.desktop) return [3 /*break*/, 2];
return [4 /*yield*/, desktop_1.desktopSaveTextFile('settings.json', settingsJson)];
case 1:
_a.sent();
return [3 /*break*/, 3];
case 2:
localStorage.setItem('settings.json', settingsJson);
_a.label = 3;
case 3: return [3 /*break*/, 5];
case 4:
e_2 = _a.sent();
log("Could not retrieve saveDesktopTextFile 'settings.json'", e_2);
return [3 /*break*/, 5];
case 5: return [2 /*return*/];
}
});
});
}
exports.saveSettings = saveSettings;
function getTableSettings(db, table) {
return settings[db] && settings[db][table] || null;
}
exports.getTableSettings = getTableSettings;
function saveTableSettings(db, table, tableSettings) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!settingsLoaded)
return [2 /*return*/];
if (!settings[db]) {
settings[db] = {};
}
if (tableSettings) {
settings[db][table] = tableSettings;
}
else {
delete settings[db][table];
}
return [4 /*yield*/, saveSettings()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
}
exports.saveTableSettings = saveTableSettings;
function log() {
var o = [];
for (var _i = 0; _i < arguments.length; _i++) {
o[_i] = arguments[_i];
}
if (exports.store.debug)
console.log.apply(console, arguments);
return o;
}
exports.log = log;
exports.dateFmtHMS = function (d) {
if (d === void 0) { d = new Date(); }
return "" + (d.getFullYear() - 2000) + client_1.padInt(d.getMonth() + 1) + client_1.padInt(d.getDate()) + "-" + client_1.padInt(d.getHours()) + client_1.padInt(d.getMinutes()) + client_1.padInt(d.getSeconds());
};
function openUrl(url) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!exports.store.desktop) return [3 /*break*/, 2];
return [4 /*yield*/, desktop_1.evaluateCode("openUrl('" + url + "')")];
case 1:
_a.sent();
return [3 /*break*/, 3];
case 2:
window.open(url);
_a.label = 3;
case 3: return [2 /*return*/];
}
});
});
}
exports.openUrl = openUrl;
function exec(c, fn) {
return __awaiter(this, void 0, void 0, function () {
var e_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, 3, 4]);
c.loading = true;
c.responseStatus = null;
return [4 /*yield*/, fn()];
case 1: return [2 /*return*/, _a.sent()];
case 2:
e_3 = _a.sent();
log(e_3);
c.responseStatus = e_3.responseStatus || (typeof e_3 == 'string' ? { errorCode: 'Error', message: e_3 } : null) || e_3;
c.$emit('error', c.responseStatus);
return [3 /*break*/, 4];
case 3:
c.loading = false;
return [7 /*endfinally*/];
case 4: return [2 /*return*/];
}
});
});
}
exports.exec = exec;
function loadTable(c, db, table) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (exports.store.getColumnSchemas(db, table).length > 0)
return [2 /*return*/];
return [4 /*yield*/, exec(c, function () { return __awaiter(_this, void 0, void 0, function () {
var r, json, obj;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, fetch("/db/" + db + "/" + table + "/meta?format=json")];
case 1:
r = _a.sent();
return [4 /*yield*/, r.text()];
case 2:
json = _a.sent();
if (json) {
obj = JSON.parse(json);
if (!exports.store.columns[db])
vue_1.default.set(exports.store.columns, db, {});
vue_1.default.set(exports.store.columns[db], table, obj);
}
return [2 /*return*/];
}
});
}); })];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
}
exports.loadTable = loadTable;
function sharpData(db, table, args) {
return __awaiter(this, void 0, void 0, function () {
var url;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
url = "/db/" + db + "/" + table + "?format=json";
if (args) {
url = client_1.appendQueryString(url, args);
}
return [4 /*yield*/, fetch(url)];
case 1: return [4 /*yield*/, (_a.sent()).json()];
case 2: return [2 /*return*/, _a.sent()];
}
});
});
}
exports.sharpData = sharpData;
vue_1.default.filter('upper', function (value) {
return value ? .toUpperCase() : ;
});
vue_1.default.filter('json', function (value) {
return value && JSON.stringify(value);
});
(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, loadSettings()];
case 1:
_a.sent();
return [2 /*return*/];
}
}); }); })();
(function () { return __awaiter(_this, void 0, void 0, function () {
var _loop_1, _a, _b, _i, db;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_loop_1 = function (db) {
var r, json, kvps, columnTotals_1, e_4;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 3, , 4]);
return [4 /*yield*/, fetch("/db/" + db + "/totals?format=json")];
case 1:
r = _a.sent();
return [4 /*yield*/, r.text()];
case 2:
json = _a.sent();
if (json) {
kvps = JSON.parse(json);
columnTotals_1 = {};
kvps.forEach(function (x) {
columnTotals_1[x.key] = x.value;
});
vue_1.default.set(exports.store.totals, db, columnTotals_1);
}
return [3 /*break*/, 4];
case 3:
e_4 = _a.sent();
log("Can't retrieve totals for '" + db + "':", e_4);
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
};
_a = [];
for (_b in exports.store.tables)
_a.push(_b);
_i = 0;
_c.label = 1;
case 1:
if (!(_i < _a.length)) return [3 /*break*/, 4];
db = _a[_i];
return [5 /*yield**/, _loop_1(db)];
case 2:
_c.sent();
_c.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
}
});
}); })();
(function () { return __awaiter(_this, void 0, void 0, function () {
var _a, e_5;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 2, , 3]);
_a = exports.store;
return [4 /*yield*/, desktop_1.desktopInfo()];
case 1:
_a.desktop = _b.sent();
log('In Desktop app:', exports.store.desktop);
return [3 /*break*/, 3];
case 2:
e_5 = _b.sent();
log("Not in Desktop app:", e_5);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); })();
;
})();
(function(){
"use strict";var routes;Object.defineProperty(exports,"__esModule",{value:!0});var vue_1=require("vue"),vue_router_1=require("vue-router"),vue_2=require("@servicestack/vue"),Viewer_1=require("../components/Viewer"),Routes;(function(n){n.Home="/";n.ViewTable="/:db/:table";n.Forbidden="/forbidden"})(Routes=exports.Routes||(exports.Routes={}));vue_1.default.use(vue_router_1.default);routes=[{path:Routes.Home,component:Viewer_1.Viewer},{path:Routes.ViewTable,component:Viewer_1.Viewer},{path:Routes.Forbidden,component:vue_2.Forbidden},{path:"*",redirect:"/"},];exports.router=new vue_router_1.default({mode:"history",linkActiveClass:"active",routes:routes});exports.default=exports.router;exports.redirect=function(n){var t=n.indexOf("://")>=0;t?location.href=n:exports.router.push({path:n})};
})();
(function(){
"use strict";var __extends=this&&this.__extends||function(){var n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(n,t){n.__proto__=t}||function(n,t){for(var i in t)t.hasOwnProperty(i)&&(n[i]=t[i])};return function(t,i){function r(){this.constructor=t}n(t,i);t.prototype=i===null?Object.create(i):(r.prototype=i.prototype,new r)}}(),__decorate=this&&this.__decorate||function(n,t,i,r){var f=arguments.length,u=f<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,i):r,e,o;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")u=Reflect.decorate(n,t,i,r);else for(o=n.length-1;o>=0;o--)(e=n[o])&&(u=(f<3?e(u):f>3?e(t,i,u):e(t,i))||u);return f>3&&u&&Object.defineProperty(t,i,u),u};Object.defineProperty(exports,"__esModule",{value:!0});var vue_1=require("vue"),vue_property_decorator_1=require("vue-property-decorator"),shared_1=require("./shared"),App=function(n){function t(){return n!==null&&n.apply(this,arguments)||this}return __extends(t,n),Object.defineProperty(t.prototype,"store",{get:function(){return shared_1.store},enumerable:!0,configurable:!0}),__decorate([vue_property_decorator_1.Component({template:"<div>\n <router-view><\/router-view>\n <\/div>"})],t)}(vue_1.default);exports.App=App;exports.default=App;
})();
(function(){
"use strict";var __extends=this&&this.__extends||function(){var n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(n,t){n.__proto__=t}||function(n,t){for(var i in t)t.hasOwnProperty(i)&&(n[i]=t[i])};return function(t,i){function r(){this.constructor=t}n(t,i);t.prototype=i===null?Object.create(i):(r.prototype=i.prototype,new r)}}(),__decorate=this&&this.__decorate||function(n,t,i,r){var f=arguments.length,u=f<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,i):r,e,o;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")u=Reflect.decorate(n,t,i,r);else for(o=n.length-1;o>=0;o--)(e=n[o])&&(u=(f<3?e(u):f>3?e(t,i,u):e(t,i))||u);return f>3&&u&&Object.defineProperty(t,i,u),u},vue_property_decorator_1,ErrorView;Object.defineProperty(exports,"__esModule",{value:!0});vue_property_decorator_1=require("vue-property-decorator");ErrorView=function(n){function t(){var t=n!==null&&n.apply(this,arguments)||this;return t.showStackTrace=!1,t}return __extends(t,n),__decorate([vue_property_decorator_1.Prop({"default":null})],t.prototype,"responseStatus",void 0),__decorate([vue_property_decorator_1.Component({template:'<div v-if="responseStatus" class="noplugin-error alert alert-danger mt-3 mr-3">\n <div>{{responseStatus.errorCode}}: {{responseStatus.message}}<\/div>\n <div v-if="responseStatus.stackTrace">\n <button v-if="!showStackTrace" class="btn btn-link" style="margin-left: -1em" @click="showStackTrace=true">\n <i class="svg-chevron-right svg-lg mb-1" title="expand" />StackTrace<\/button>\n <div v-if="showStackTrace" class="stacktrace">{{responseStatus.stackTrace}}<\/div>\n <\/div>\n<\/div>'})],t)}(vue_property_decorator_1.Vue);exports.ErrorView=ErrorView;exports.default=ErrorView;vue_property_decorator_1.Vue.component("error-view",ErrorView);
})();
(function(){
"use strict";var __extends=this&&this.__extends||function(){var n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(n,t){n.__proto__=t}||function(n,t){for(var i in t)t.hasOwnProperty(i)&&(n[i]=t[i])};return function(t,i){function r(){this.constructor=t}n(t,i);t.prototype=i===null?Object.create(i):(r.prototype=i.prototype,new r)}}(),__decorate=this&&this.__decorate||function(n,t,i,r){var f=arguments.length,u=f<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,i):r,e,o;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")u=Reflect.decorate(n,t,i,r);else for(o=n.length-1;o>=0;o--)(e=n[o])&&(u=(f<3?e(u):f>3?e(t,i,u):e(t,i))||u);return f>3&&u&&Object.defineProperty(t,i,u),u};Object.defineProperty(exports,"__esModule",{value:!0});var vue_property_decorator_1=require("vue-property-decorator"),client_1=require("@servicestack/client"),show=function(n){return typeof n!="string"||n.substr(0,2)!=="__"},keyFmt=function(n){return client_1.humanize(client_1.toPascalCase(n))},uniqueKeys=function(n){for(var r,t,u={},i=0,f=n.length;i<f;i++){r=n[i];for(t in r)r.hasOwnProperty(t)&&show(t)&&(u[t]=t)}return u},valueFmt=function(n,t,i){return i},num=function(n){return n},date=function(n){return client_1.toDate(n)},pad=function(n){return n<10?"0"+n:n},dmft=function(n){return n.getFullYear()+"/"+pad(n.getMonth()+1)+"/"+pad(n.getDate())},str=function(n){return n.substr(0,6)==="/Date("?dmft(date(n)):n},obj=function(n){return"<dl>\n "+Object.keys(n).filter(show).map(function(t){return'<dt class="ib">'+keyFmt(t)+"<\/dt><dd>"+valueFmt(t,n[t],val(n[t]))+"<\/dd>"}).join("")+"\n <\/dl>"},arr=function(n){if(typeof n[0]=="string"||typeof n[0]=="number")return"<span>"+n.join(", ")+"<\/span>";var t=uniqueKeys(n);return"\n <table>\n <thead>\n <tr>\n "+Object.keys(t).map(function(n){return"<th><b><\/b>"+keyFmt(n)+"<\/th>"}).join("")+"\n <\/tr>\n <\/thead>\n <tbody>\n "+n.map(function(n){return"<tr>\n "+Object.keys(t).filter(show).map(function(t){return"<td>"+valueFmt(t,n[t],val(n[t]))+"<\/td>"}).join("")+"\n <\/tr>"}).join("")+"\n <\/tbody>\n <\/table>"},val=function(n,t){return(t&&(valueFmt=t),n==null)?"":typeof n=="number"?""+num(n):typeof n=="string"?str(n):typeof n=="boolean"?n?"true":"false":n.length?arr(n):obj(n)},JsonViewer=function(n){function t(){return n!==null&&n.apply(this,arguments)||this}return __extends(t,n),Object.defineProperty(t.prototype,"html",{get:function(){return this.json?val(JSON.parse(this.json)):val(this.value)},enumerable:!0,configurable:!0}),__decorate([vue_property_decorator_1.Prop({"default":null})],t.prototype,"value",void 0),__decorate([vue_property_decorator_1.Prop({"default":null})],t.prototype,"json",void 0),__decorate([vue_property_decorator_1.Component({template:'<div class="jsonviewer">\n <div v-html="html"><\/div>\n <span class="clearfix"><\/span>\n <\/div>'})],t)}(vue_property_decorator_1.Vue);exports.JsonViewer=JsonViewer;exports.default=JsonViewer;vue_property_decorator_1.Vue.component("jsonviewer",JsonViewer);
})();
(function(){
"use strict";var vue_1,vue_2;Object.defineProperty(exports,"__esModule",{value:!0});require("./app.scss");require("es6-shim");vue_1=require("vue");vue_2=require("@servicestack/vue");vue_1.default.use(vue_2.default);var App_1=require("./App"),router_1=require("./shared/router"),app=new vue_1.default({el:"#app",render:function(n){return n(App_1.App)},router:router_1.router});
})();
{{ {namedConnection:db} |> if (db && db != 'main') |> useDb }}
```code|quiet
var ignore = ['db','fields','format','skip','take','orderBy']
var fields = qs.fields ? qs.fields.split(',').map(x => sqlQuote(x)).join(',') : '*'
var sql = `SELECT ${fields} FROM ${sqlQuote(table)}`
var filters = []
var queryMap = qs.toObjectDictionary().withoutKeys(ignore)
#each queryMap.Keys.toList()
var search = queryMap[it.sqlVerifyFragment()].sqlVerifyFragment();
#if search == '=null' || search == '!=null'
`${sqlQuote(it)} ${search=='=null' ? 'IS' : 'IS NOT'} NULL` |> addTo => filters
queryMap[it] = null
else if search.startsWith('=')
`${sqlQuote(it)} = @${it}` |> addTo => filters
queryMap[it] = search.substring(1).coerce()
else if search.startsWith('<=') || search.startsWith('>=') || search.startsWith('<>') || search.startsWith('!=')
`${sqlQuote(it)} ${search.substring(0,2)} @${it}` |> addTo => filters
queryMap[it] = search.substring(2).coerce()
else if search.startsWith('<') || search.startsWith('>')
`${sqlQuote(it)} ${search.substring(0,1)} @${it}` |> addTo => filters
queryMap[it] = search.substring(1).coerce()
else if search.endsWith(',')
`${sqlQuote(it)} IN (${search.trimEnd(',').split(',').map(i => i.toLong()).join(',')})` |> addTo => filters
queryMap[it] = null
else if search.startsWith('%') || search.endsWith('%')
`${sqlQuote(it).sqlCast('varchar')} LIKE @${it}` |> addTo => filters
else
`${sqlQuote(it).sqlCast('varchar')} = @${it}` |> addTo => filters
/if
/each
#if !filters.isEmpty()
sql = `${sql} WHERE ${filters.join(' AND ')}`
/if
#if qs.orderBy
sql = `${sql} ORDER BY ${sqlOrderByFields(qs.orderBy)}`
/if
#if qs.skip || qs.take
sql = `${sql} ${sqlLimit(qs.skip,qs.take)}`
/if
sql |> dbSelect(queryMap) |> return
```
{{ ifError |> show(sql) }}
{{htmlError}}
{{ {namedConnection:db} |> if (db && db != 'main') |> useDb }}
{{ table |> dbColumns |> return }}
{{htmlError}}
{{ {namedConnection:db} |> if (db && db != 'main') |> useDb }}
```code|quiet
var ignore = ['db','fields','format','orderby','skip','take']
var sql = `SELECT COUNT(*) FROM ${sqlQuote(table)}`
var filters = []
var queryMap = qs.toObjectDictionary().withoutKeys(ignore)
#each queryMap.Keys.toList()
var search = queryMap[it.sqlVerifyFragment()].sqlVerifyFragment();
#if search == '=null' || search == '!=null'
`${sqlQuote(it)} ${search=='=null' ? 'IS' : 'IS NOT'} NULL` |> addTo => filters
queryMap[it] = null
else if search.startsWith('=')
`${sqlQuote(it)} = @${it}` |> addTo => filters
queryMap[it] = search.substring(1).coerce()
else if search.startsWith('<=') || search.startsWith('>=') || search.startsWith('<>') || search.startsWith('!=')
`${sqlQuote(it)} ${search.substring(0,2)} @${it}` |> addTo => filters
queryMap[it] = search.substring(2).coerce()
else if search.startsWith('<') || search.startsWith('>')
`${sqlQuote(it)} ${search.substring(0,1)} @${it}` |> addTo => filters
queryMap[it] = search.substring(1).coerce()
else if search.endsWith(',')
`${sqlQuote(it)} IN (${search.trimEnd(',').split(',').map(i => i.toLong()).join(',')})` |> addTo => filters
queryMap[it] = null
else if search.startsWith('%') || search.endsWith('%')
`${sqlQuote(it).sqlCast('varchar')} LIKE @${it}` |> addTo => filters
else
`${sqlQuote(it).sqlCast('varchar')} = @${it}` |> addTo => filters
/if
/each
#if !filters.isEmpty()
sql = `${sql} WHERE ${filters.join(' AND ')}`
/if
sql |> dbScalar(queryMap) |> return
```
{{ ifError |> show(sql) }}
{{htmlError}}
{{ {namedConnection:db} |> if (db && db != 'main') |> useDb }}
{{ {live:true} |> dbTableNamesWithRowCounts |> return }}
{{htmlError}}
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TUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MTwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6Q29tcHJlc3Npb24+NTwvdGlmZjpDb21wcmVzc2lvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzI8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjcyPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NDI8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjMyPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxMy0xMS0xNlQwODoxMToyMzwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAyLjIuMTwveG1wOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4Kpcq+GAAAAsFJREFUWAnVl19oj1EYx2f+lxmFpESZ0hrFhfwp2YU/F6zWSq3kwg3SolyQcqGE4krkguTSlUVJwi1Js7mQi9ViYvOn2VjNzPD52u+t0+l3znvO3td+vz312fu+53me83z3/jnn+VVUTBKbGqGzkthdMA964A9MmMUIlbBZcB+aoBo+wlcoSzuJKokWEnkTNkPZmR79G0jE6vgL7sJWKCs7jRpTaHIuwbdgdbmorUXIECQC7eMAPv0zVVBS0wrwBGyB9nUbMVtKqpTi5wKESrjuvD7AaVASa6SqfQd9163ELyqF0jqKjkaKfUn8hH9o8ynaHilUd/w95P7eTmFSCXKZ1tQW6ALfY7d9fcTvgNxMQpvhAZyADaBt1LaFDJyBAbBFua77id0OuZmWIi3iKvgbXsFF2AR2r7CGMfUCLnH2+BdiN0JutoSZesEsJNFP4RAsgMQk/gh8AzPedf6WuBrIzc4yk6/YKfyLjWrrOddX7soxx58RV23kZjpdS/ZPMAvY5+/wH4M5INO7exvsuGLXN4jTN5HZ9BF1QrEi9tgL4nYWKmpHuhyYt7+Qk/nwMLCghKuTugRJY3I+IPczMSshs4U+RvMOP6eqVgPZBTB9xc7vEKOVJpPdI7vY5Gljn8jbXah8PWCOPYXYcR207HQEFHGJ/kHuPtA8j1PmeY0/eWU4jbPlhH8Hl5CQ8RHy94K6KK0Qvpyj+MdlB8jyTRzqG2aebaDt09d9deFXLxFlM4nWkhMqJi1OW6d2o6spcx7EH2XaEtOKx/r1U2YFfPDM3YZvBgSZfrPHdEUxgtWRtYArR/1EPaSaRKrRdU2UdVytnrqwTk+Na/icNh3PYdBEWcWk5V+hxnFPnW58c+GfaSeYDXrB1bZ1QFqBvPxqdBpg0FOzIelWpHgZrAL1nrKkUxq7+n9/tQE8gnWw1FGm/S9DpCdmD6gwqwAAAABJRU5ErkJggg==
{{#raw}}
<div id="app">
<div class="container">
<div class="row p-4">
<div id="content">
<router-view></router-view>
</div>
</div>
</div>
</div>
{{/raw}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment