|
@@ -0,0 +1,234 @@
|
|
|
+@extends('app.stat-tree.stat-trees.single')
|
|
|
+@section('page')
|
|
|
+
|
|
|
+<div id="statTreeViewPage">
|
|
|
+ <div id="statTreeView" class="row">
|
|
|
+ @if(count($statTree->lines))
|
|
|
+ <div class="col-12">
|
|
|
+ <div class="d-flex align-items-center justify-content-between mb-2">
|
|
|
+ <h6 class="font-weight-bold m-0">{{$statTree->name}}</h6>
|
|
|
+ <div class="ml-auto">
|
|
|
+ <button @click="refreshTreeCountQueries" class="btn btn-sm btn-danger text-white">
|
|
|
+ <span v-if="!refreshing"><i class="fas fa-sync-alt"></i> Refresh Counts</span>
|
|
|
+ <span v-else><i class="fas fa-circle-notch fa-spin"></i> Refreshing...</span>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ @include('app.stat-tree.tree', ['slug' => 'rm-tree'])
|
|
|
+ </div>
|
|
|
+ @endif
|
|
|
+
|
|
|
+ <div class="col-12">
|
|
|
+ <h6 class="font-weight-bold bg-light p-3 mt-3">Replace Stat Tree Lines</h6>
|
|
|
+ <div class="row">
|
|
|
+ <div class="col-md-6">
|
|
|
+ <div class="bg-white p-3">
|
|
|
+ <h6 class="font-weight-bold">TSV</h6>
|
|
|
+ <div class="input-group">
|
|
|
+ <textarea v-model="content" class="form-control" rows="10" @keyup="splitContents"></textarea>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="col-md-6">
|
|
|
+ <div class="bg-white p-3">
|
|
|
+ <h6 class="font-weight-bold">JSON Structure</h6>
|
|
|
+ <textarea class="form-control" rows="10">@{{jsonStructure}}</textarea>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <template v-if="rows.length">
|
|
|
+ <div class="row my-3">
|
|
|
+ <div class="col">
|
|
|
+ <div class="bg-white p-3">
|
|
|
+ <h6 class="font-weight-bold">Table output:</h6>
|
|
|
+ <div class="table-responsive">
|
|
|
+ <table class="table table-bordered table-hover">
|
|
|
+ <tbody>
|
|
|
+ <tr v-for="(row, rowIndex) in rows">
|
|
|
+ <td v-for="(column, columnIndex) in columns[rowIndex]" class="p-0">
|
|
|
+ <input class="border-0 form-control p-1" type="text" v-model="columns[rowIndex][columnIndex]" @keyup="updateColumns(rowIndex, columnIndex)">
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ </tbody>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <div class="row">
|
|
|
+ <div class="col-md-12">
|
|
|
+ <div class="px-3">
|
|
|
+ <button type="button" class="btn btn-sm btn-primary" @click="submit">Submit</button>
|
|
|
+ <button type="button" class="btn btn-sm btn-secondary" @click="generateAutoFilledJson">Fill</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+
|
|
|
+<script>
|
|
|
+ (function() {
|
|
|
+ function init() {
|
|
|
+ new Vue({
|
|
|
+ el: '#statTreeView',
|
|
|
+ data: {
|
|
|
+ content: '',
|
|
|
+ rowSplitter: '\n',
|
|
|
+ columnSplitter: '\t',
|
|
|
+ rows: [],
|
|
|
+ columns: [],
|
|
|
+ maxColumn: 0,
|
|
|
+ jsonStructure: '',
|
|
|
+ isAutoFilled: false,
|
|
|
+ refreshing: false,
|
|
|
+ refreshingLine: false
|
|
|
+ },
|
|
|
+ delimiters: ['@{{', '}}'],
|
|
|
+ methods: {
|
|
|
+ updateColumns(rowIndex, columnIndex) {
|
|
|
+ try {
|
|
|
+ this.rows[rowIndex] = this.columns[rowIndex].join(this.columnSplitter);
|
|
|
+ this.content = this.rows.join('\n');
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error);
|
|
|
+ this.rows = [];
|
|
|
+ this.content = '';
|
|
|
+ }
|
|
|
+ this.updateJsonStructure();
|
|
|
+ },
|
|
|
+ splitContents() {
|
|
|
+ this.isAutoFilled = false;
|
|
|
+ this.maxColumn = 0;
|
|
|
+ try {
|
|
|
+ this.rows = this.content.split(this.rowSplitter);
|
|
|
+ this.rows.map((row, index) => {
|
|
|
+ this.columns[index] = row.split(this.columnSplitter);
|
|
|
+ const length = this.columns[index].length;
|
|
|
+ if (length > this.maxColumn) {
|
|
|
+ this.maxColumn = length
|
|
|
+ }
|
|
|
+ const emptyFields = this.maxColumn - length;
|
|
|
+ for (ii = 0; ii < emptyFields; ii++) {
|
|
|
+ this.columns[index].push('');
|
|
|
+
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error);
|
|
|
+ this.rows = [];
|
|
|
+ }
|
|
|
+ this.updateJsonStructure();
|
|
|
+ },
|
|
|
+ updateJsonStructure() {
|
|
|
+ try {
|
|
|
+ this.jsonStructure = JSON.stringify(this.columns, null, '\t');
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error);
|
|
|
+ this.jsonStructure = JSON.stringify([], null, '\t');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ numberOfTabs: function (text) {
|
|
|
+ var count = 0;
|
|
|
+ var index = 0;
|
|
|
+ while (text.charAt(index++) === "\t") {
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ return count;
|
|
|
+ },
|
|
|
+ generateAutoFilledJson: function () {
|
|
|
+ if(this.isAutoFilled) return;
|
|
|
+ var string = tsvToArray.getAutoFilledTabContent(this.content);
|
|
|
+ this.content = string;
|
|
|
+ this.splitContents();
|
|
|
+ this.isAutoFilled = true;
|
|
|
+ },
|
|
|
+ submit: function () {
|
|
|
+ var data = JSON.stringify(this.columns);
|
|
|
+ $.post('{{ route("practice-management.api.statTree.replaceAllLines") }}', {
|
|
|
+ statTreeID: "{{ $statTree->id }}",
|
|
|
+ data
|
|
|
+ }, function (response) {
|
|
|
+ if (response.success) {
|
|
|
+ location.href = "{{ route('practice-management.statTrees.view.dashboard', $statTree) }}";
|
|
|
+ } else {
|
|
|
+ alert(response.message);
|
|
|
+ }
|
|
|
+ }, 'json');
|
|
|
+ },
|
|
|
+ refreshTreeCountQueries: function (evt) {
|
|
|
+ evt.preventDefault();
|
|
|
+ var self = this;
|
|
|
+ if (self.refreshing) return;
|
|
|
+
|
|
|
+ self.refreshing = true;
|
|
|
+ $.post("{{ route('practice-management.api.statTree.refreshTreeCountQueries') }}", {
|
|
|
+ statTreeID: "{{ $statTree->id }}"
|
|
|
+ }, function (response) {
|
|
|
+ self.refreshing = false;
|
|
|
+ if (response.success) {
|
|
|
+ fastLoad("{{ route('practice-management.statTrees.view.dashboard', $statTree) }}");
|
|
|
+ //fastReload()
|
|
|
+
|
|
|
+ } else {
|
|
|
+ toastr.error(response.message);
|
|
|
+ }
|
|
|
+ }, 'json');
|
|
|
+ },
|
|
|
+ initRefreshLineQuery: function () {
|
|
|
+ var self = this;
|
|
|
+
|
|
|
+ $('[refresh-line-query]').click(function () {
|
|
|
+ var element = $(this);
|
|
|
+ var id = element.data('id');
|
|
|
+ if (self.refreshingLine) return;
|
|
|
+ self.refreshingLine = true;
|
|
|
+ element.html('<i class="fas fa-circle-notch fa-spin"></i> Refreshing...');
|
|
|
+ $.post("{{ route('practice-management.api.statTreeLine.refreshCountQuery') }}", {
|
|
|
+ statTreeLineID: id
|
|
|
+ }, function (response) {
|
|
|
+ self.refreshingLine = false;
|
|
|
+ if (response.success) {
|
|
|
+ $('#line-' + id).text(response.data);
|
|
|
+ toastr.success('Updated value: ' + response.data);
|
|
|
+ } else {
|
|
|
+ toastr.error(reasponse.message);
|
|
|
+ }
|
|
|
+ element.html('Refresh');
|
|
|
+ }, 'json');
|
|
|
+ });
|
|
|
+ },
|
|
|
+ init: function () {
|
|
|
+ this.initRefreshLineQuery();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted: function () {
|
|
|
+ this.init();
|
|
|
+ },
|
|
|
+ updated: function () {
|
|
|
+ var self = this;
|
|
|
+ self.$nextTick(function () {
|
|
|
+
|
|
|
+ });
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ maxColumn(maxColumn) {
|
|
|
+ this.columns.map((column, index) => {
|
|
|
+ const emptyFields = maxColumn - column.length;
|
|
|
+ if (emptyFields) {
|
|
|
+ for (ii = 0; ii < emptyFields; ii++) {
|
|
|
+ this.columns[index].push('');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ addMCInitializer('statTreeView', init, '#statTreeViewPage')
|
|
|
+ }).call(window);
|
|
|
+</script>
|
|
|
+
|
|
|
+@endsection
|