浏览代码

Stat tree - multi-pro view - group by version + delete pro

Vijayakrishnan 3 年之前
父节点
当前提交
b577773621

+ 82 - 1
app/Http/Controllers/StatTreeController.php

@@ -329,7 +329,7 @@ class StatTreeController extends Controller
             $nodes[] = [
                 "text" => $clause->label,
                 "state" => [
-                    "opened" => false,
+                    "opened" => true,
                     "disabled" => false,
                     "selected" => false,
                 ],
@@ -421,6 +421,69 @@ class StatTreeController extends Controller
         return $result;
     }
 
+    private function applyStatTreeLineQueryClausesGroupByPros(StatTreeLine $statTreeLine, $proUids)
+    {
+        $model = $statTreeLine->statTree->model;
+        $clauses = [];
+        foreach ($statTreeLine->lineClauses as $lineClause) {
+            $clauseText = $lineClause->clause->clause_text;
+
+            // apply arg values
+            foreach ($lineClause->clause->clauseArgs as $clauseArg) {
+
+                $value = null;
+                foreach ($lineClause->lineClauseArgs as $lineClauseArg) {
+                    if($lineClauseArg->clause_arg_id === $clauseArg->id) {
+                        $value = $lineClauseArg->value;
+                    }
+                }
+
+                if(!is_null($value)) {
+                    $clauseText = str_replace(
+                        ':' . $clauseArg->arg_text,                         // search for :xxx
+                        "'" . $value . "'::" . $clauseArg->field_type,      // replace with '$value'::$field_type
+                        $clauseText);
+                }
+            }
+
+            //dump($clauseText);
+            /*$isValid = $this->cleanupClause($clauseText);
+            if ($isValid) {*/
+            array_push($clauses, $clauseText);
+            //}
+        }
+
+        // if stat tree bound to a pro, apply pro_scope_clause
+        /*if(!$proUid) {
+            if($statTreeLine->statTree->pro && $statTreeLine->statTree->pro_scope_clause) {
+                $clauses[] = str_replace('@PRO_ID', $statTreeLine->statTree->pro->id, $statTreeLine->statTree->pro_scope_clause);
+            }
+        }
+        else {
+            $mvPro = Pro::where('uid', $proUid)->first();
+            if($statTreeLine->statTree->pro_scope_clause) {
+                $clauses[] = str_replace('@PRO_ID', $mvPro->id, $statTreeLine->statTree->pro_scope_clause);
+            }
+            $query = 'SELECT COUNT(*) FROM '.$model.' WHERE '. implode(" AND ", $clauses);
+        }*/
+
+        $proUids = explode(",", $proUids);
+        $proUids = array_map(function($_x) {
+            return "'{$_x}'";
+        }, $proUids);
+        $clauses[] = "_j_pro.uid IN (" . implode(",", $proUids) . ")";
+        $proJoinClause = 'JOIN pro _j_pro on ' . str_replace('@PRO_ID', '_j_pro.id', $statTreeLine->statTree->pro_scope_clause);
+        $query = "SELECT COUNT(*), _j_pro.uid as _v_pro_uid FROM {$model} {$proJoinClause} WHERE " . implode(" AND ", $clauses) . " GROUP BY _j_pro.uid";
+        try {
+            //dump($query);
+            $result = DB::select($query);
+        }
+        catch (\Exception $ex) {
+            $result = 'error';
+        }
+        return $result;
+    }
+
     public function linesJSON(Request $request, StatTree $statTree) {
 
         // refresh counts
@@ -461,6 +524,24 @@ class StatTreeController extends Controller
         return json_encode($result);
     }
 
+    public function getCountsForPros(Request $request) {
+        $statTreeUid = $request->get('uid');
+        if (!$statTreeUid) return $this->fail('No specified stat tree!');
+        $statTree = StatTree::where('uid',  $statTreeUid)->first();
+        $lines = $statTree->lines;
+        $result = [];
+        foreach ($lines as $line) {
+            $query = $this->applyStatTreeLineQueryClausesGroupByPros($line, $request->input('proUids'));
+            if ($query && $query !== 'error') {
+                $result[$line->uid] = $query;
+            }
+            else {
+                $result[$line->uid] = -1;
+            }
+        }
+        return json_encode($result);
+    }
+
     private function lineObject(StatTreeLine  $line) {
 
         // columns

+ 7 - 1
app/Http/Controllers/StatTreeLineController.php

@@ -191,7 +191,13 @@ class StatTreeLineController extends Controller
         }
 
         // if stat tree bound to a pro, apply pro_scope_clause
-        if($statTreeLine->statTree->pro && $statTreeLine->statTree->pro_scope_clause) {
+        if($request->input('proUid') && $statTreeLine->statTree->pro_scope_clause) {
+            $pro = Pro::where('uid', $request->input('proUid'))->first();
+            if($pro) {
+                $clauses[] = str_replace('@PRO_ID', $pro->id, $statTreeLine->statTree->pro_scope_clause);
+            }
+        }
+        elseif($statTreeLine->statTree->pro && $statTreeLine->statTree->pro_scope_clause) {
             $clauses[] = str_replace('@PRO_ID', $statTreeLine->statTree->pro->id, $statTreeLine->statTree->pro_scope_clause);
         }
 

+ 15 - 0
public/css/style.css

@@ -2840,6 +2840,7 @@ table.stag-compact-grid>tbody>tr>td [if-grid-view] {
     background: #eee;
     line-height: 22px;
     padding: 0 5px;
+    padding-right: 0;
     font-weight: normal;
     color: #777;
     border: 0;
@@ -2892,6 +2893,20 @@ table.stag-compact-grid>tbody>tr>td [if-grid-view] {
     font-weight: bold;
     color: #777;
 }
+.multi-pro-view th .mv-delete-pro-trigger {
+    position: absolute;
+    right: 2px;
+    top: 2px;
+    width: 16px;
+    height: 16px;
+    line-height: 16px;
+    font-size: 10px;
+    text-align: center;
+    display: none;
+}
+.multi-pro-view th:hover .mv-delete-pro-trigger {
+    display: block;
+}
 body .vakata-context li>a {
     padding: 1px 5px;
     padding-right: 10px;

+ 69 - 5
resources/views/app/stat-tree/stat-trees/sub/edit.blade.php

@@ -315,7 +315,9 @@
                                                             </th>
                                                             @foreach($multiPros as $multiPro)
                                                                 <th data-pro-uid="{{$multiPro->uid}}" count-required>
-                                                                    <div class="pro-label" title="{{$multiPro->name_display}}">{{$multiPro->name_display}}</div>
+                                                                    <div class="pro-label position-relative" title="{{$multiPro->name_display}}">{{$multiPro->name_display}}
+                                                                        <a href="#" class="mv-delete-pro-trigger rounded-circle bg-white c-pointer" data-pro-uid="{{$multiPro->uid}}"><i class="fa fa-times text-danger"></i></a>
+                                                                    </div>
                                                                 </th>
                                                             @endforeach
                                                         </tr>
@@ -323,14 +325,14 @@
                                                         <tbody>
                                                         @foreach($linesFlat as $line)
                                                             <tr data-line-uid="{{$line->uid}}" {!! $line->parent ? 'data-parent-line-uid="' . $line->parent->uid . '"' : '' !!}>
-                                                                <td class="p-0">
+                                                                <td class="p-0 on-hover-aliceblue c-pointer mv-view-data-trigger">
                                                                     <div class="count-label">
                                                                         <div class="count">{{$line->last_refresh_count}}</div>
                                                                         <div class="drop-percent"></div>
                                                                     </div>
                                                                 </td>
                                                                 @foreach($multiPros as $multiPro)
-                                                                    <td class="p-0" data-pro-uid="{{$multiPro->uid}}">
+                                                                    <td class="p-0 on-hover-aliceblue c-pointer mv-view-data-trigger" data-pro-uid="{{$multiPro->uid}}">
                                                                         <div class="count-label">
                                                                             <div class="count"></div>
                                                                             <div class="drop-percent"></div>
@@ -1357,8 +1359,33 @@
                                     return false;
                                 });
 
+                            $(document)
+                                .off('click', '.mv-view-data-trigger')
+                                .on('click', '.mv-view-data-trigger', function() {
+                                    let title = 'View Data';
+                                    if($(this).attr('data-pro-uid')) {
+                                        let tdIndex = $(this).index();
+                                        title = 'View Data for ' + $(this).closest('table').find('thead tr th:eq(' + tdIndex + ')').text();
+                                    }
+                                    openDynamicStagPopup('/practice-management/stat-tree-lines/view-data/' + $(this).closest('tr').attr('data-line-uid') + '?proUid=' + $(this).attr('data-pro-uid'),
+                                        null,
+                                        title,
+                                        false,
+                                        'medium');
+                                    return false;
+                                });
+
+                            $(document)
+                                .off('click', '.mv-delete-pro-trigger')
+                                .on('click', '.mv-delete-pro-trigger', function() {
+                                    debugger
+                                    let proUids = '{{request()->input('multi-pro-uids')}}'.split(',').filter(_x => _x !== $(this).attr('data-pro-uid'));
+                                    fastLoad('/practice-management/stat-trees/view/{{$statTree->uid}}/edit?multi-pro=1&multi-pro-uids=' + proUids.join(','));
+                                    return false;
+                                });
+
                             @if($multiProView)
-                            $('[count-required]').each(function() {
+                            /*$('[count-required]').each(function() {
                                 $.post('{{route('practice-management.api.statTree.getCountsForPro')}}', {
                                     uid: '{{$statTree->uid}}',
                                     proUid: $(this).attr('data-pro-uid')
@@ -1395,7 +1422,44 @@
                                     });
 
                                 }, 'json');
-                            });
+                            });*/
+                            $.get('{{route('practice-management.api.statTree.getCountsForPros')}}', {
+                                uid: '{{$statTree->uid}}',
+                                proUids: '{{request()->input('multi-pro-uids')}}'
+                            }, _data => {
+                                for(let x in _data) {
+                                    let lineTR = $('.multi-pro-stats-table tr[data-line-uid="' + x + '"]');
+                                    for (let i = 0; i < _data[x].length; i++) {
+                                        lineTR.find('>td[data-pro-uid="' + _data[x][i]._v_pro_uid + '"] .count').text(_data[x][i].count);
+                                    }
+                                }
+                                // calculate drop %
+                                $('.multi-pro-stats-table tr[data-line-uid][data-parent-line-uid]').each(function() {
+                                    for (let i = 0; i < $(this).find('>td').length; i++) {
+                                        let parentCount = $('.multi-pro-stats-table tr[data-line-uid="' + $(this).attr('data-parent-line-uid') + '"]>td:eq(' + i + ') .count').first().text(),
+                                            myCount = $(this).find('>td:eq(' + i + ') .count').first().text();
+                                        if(parentCount && myCount && !Number.isNaN(+parentCount) && !Number.isNaN(+myCount) && +parentCount > 0) {
+                                            parentCount = +parentCount;
+                                            myCount = +myCount;
+                                            let element = $(this).find('>td:eq(' + i + ') .drop-percent').first(), cssClass = '';
+                                            let dropPercent = ((parentCount - myCount) / parentCount) * 100;
+                                            if(dropPercent > 75) {
+                                                cssClass = 'mv-drop-76-100';
+                                            }
+                                            else if(dropPercent > 50 && dropPercent <= 75) {
+                                                cssClass = 'mv-drop-51-75';
+                                            }
+                                            else if(dropPercent > 25 && dropPercent <= 50) {
+                                                cssClass = 'mv-drop-26-50';
+                                            }
+                                            else if(dropPercent > 0 && dropPercent <= 25) {
+                                                cssClass = 'mv-drop-0-25';
+                                            }
+                                            element.removeClass().addClass('drop-percent').addClass(cssClass).text(dropPercent.toFixed(1) + '% ⤵');
+                                        }
+                                    }
+                                });
+                            }, 'json');
                             @endif
 
                             ClausesTree.load();

+ 1 - 0
routes/web.php

@@ -376,6 +376,7 @@ Route::middleware('pro.auth')->group(function () {
                 Route::post('replace-all-lines-json', 'StatTreeController@replaceAllLinesJSON')->name('replaceAllLinesJSON');
                 Route::post('refresh-tree-count-queries', 'StatTreeController@refreshTreeCountQueries')->name('refreshTreeCountQueries');
                 Route::post('get-counts-for-pro', 'StatTreeController@getCountsForPro')->name('getCountsForPro');
+                Route::any('get-counts-for-pros', 'StatTreeController@getCountsForPros')->name('getCountsForPros');
             });
 
             //Stat Tree Line