1
0
Bläddra i källkod

группировкa + переиспользование групп

kpmy 7 år sedan
förälder
incheckning
481ec6f9ac
8 ändrade filer med 116 tillägg och 29 borttagningar
  1. 4 6
      src/api.js
  2. 11 0
      src/dao.js
  3. 1 1
      src/frontend.js
  4. 2 0
      src/global.css
  5. 2 1
      src/index.html
  6. 1 0
      src/nav/knav.js
  7. 41 10
      src/root.html
  8. 54 11
      src/root.js

+ 4 - 6
src/api.js

@@ -4,19 +4,17 @@ let fileRepo = require('./dao.js').FileRepo;
 let groupRepo = require('./dao.js').GroupRepo;
 
 ipc.on('get:files', function (e, data) {
-    console.log('do get files');
     e.returnValue = fileRepo.findAllByCategoryInAndDateBetween(data.cats, data.from, data.to);
-    console.log('done get files')
 });
 
 ipc.on('set:groups', function (e, data) {
-    console.log('do set groups');
     e.returnValue = groupRepo.save(data);
-    console.log('done set groups');
 });
 
 ipc.on('get:groups', function (e, data) {
-    console.log('do get groups');
     e.returnValue = groupRepo.findAllByFileIdIn(data);
-    console.log('done get groups');
+});
+
+ipc.on('get:groups:find', function (e, data) {
+    e.returnValue = groupRepo.findAllByNameLike(data);
 });

+ 11 - 0
src/dao.js

@@ -1,5 +1,6 @@
 let SQL = require('./db.js');
 let _ = require('underscore');
+let S = require('underscore.string');
 
 function listResult(q) {
     try {
@@ -93,6 +94,16 @@ class GroupRepo extends Repo {
         })
     }
 
+    findAllByNameLike(q) {
+        SQL.db.create_function('like_js', (x, y) => S.include(x.toUpperCase(), y.toUpperCase()) ? 1 : 0);
+        let groups = listResult(`SELECT * FROM groups WHERE like_js(name, '${q}')`);
+        let files = listResult(`SELECT * FROM filegroups WHERE groupId IN (${groups.map(g => g.id).join(",")})`);
+        return groups.map(g => {
+            g.files = files.filter(fg => fg.groupId == g.id).map(fg => fg.fileId);
+            return g;
+        })
+    }
+
     _insertFiles(item) {
         SQL.db.run("DELETE FROM filegroups WHERE groupId = ?", [item.id]);
         Array.from(item.files).forEach(i => {

+ 1 - 1
src/frontend.js

@@ -3,7 +3,7 @@ const S = require('underscore.string');
 const fs = require('fs');
 const path = require('path');
 
-require('angular').module('Ks', [require('angular-ui-router'), require('angular-messages'), require('angular-sanitize'), require('angular-material'), require('angular-material-data-table')]);
+require('angular').module('Ks', [require('angular-ui-router'), require('angular-messages'), require('angular-sanitize'), require('angular-material'), require('angular-material-data-table'), 'ngMdBadge']);
 
 require('angular').module('UnderscoreStringFilter', []);
 

+ 2 - 0
src/global.css

@@ -1,6 +1,8 @@
 @import "../node_modules/angular-material/angular-material.css";
 @import "../thirdparty/iconfont/material-icons.css";
 @import "../node_modules/angular-material-data-table/dist/md-data-table.css";
+@import "../node_modules/angular-material-badge/angular-material-badge.min.css";
+
 html, body {
     width: 100%;
     height: 100%;

+ 2 - 1
src/index.html

@@ -9,7 +9,8 @@
 <body ui-view ng-cloak>
 <script>
     require('./frontend.js');
-    require('../node_modules/angular-i18n/angular-locale_ru-ru.js')
+    require('../node_modules/angular-i18n/angular-locale_ru-ru.js');
+    require('../node_modules/angular-material-badge/angular-material-badge.min.js');
 </script>
 </body>
 </html>

+ 1 - 0
src/nav/knav.js

@@ -7,6 +7,7 @@ require('angular').module('Ks').directive('toolbar', function () {
         replace: true,
         templateUrl: path.join(__dirname, 'knav.html'),
         controller: function ($scope, $rootScope) {
+            $scope._ = $rootScope._ = require('underscore');
             $scope.ipc = {
                 send: function (to, data) {
                     ipc.send(to, data);

+ 41 - 10
src/root.html

@@ -3,6 +3,11 @@
         max-height: 1em;
         margin-top: -1px
     }
+
+    .sub-header {
+        color: rgba(0, 0, 0, 0.54);
+        font-size: 13px;
+    }
 </style>
 <div layout="column" class="main">
     <toolbar></toolbar>
@@ -39,13 +44,19 @@
             </div>
         </div>
         <md-content flex>
-            <md-table-container>
-                <table md-table md-row-select="true" multiple="true" ng-model="table.selected">
+            <md-table-container ng-init="hover = {}">
+                <table md-table md-row-select="table.selected.length > 0" multiple="true" ng-model="table.selected">
                     <tbody md-body>
-                    <tr md-row md-select="i.id" md-on-select="selectTableRow" ng-disabled="i.class == 'group'"
-                        ng-repeat="i in table.itemList">
+                    <tr md-row md-select="i.id" md-on-select="selectTableRow" ng-disabled="i.class == 'group'" ng-repeat="i in table.itemList">
+                        <td md-cell style="padding-right: 5px;" ng-mouseenter="hover[i.id] = true" ng-mouseleave="hover[i.id] = false" ng-if="table.selected.length == 0">
+                            <span ng-if="!hover[i.id] || i.class == 'group'">
+                                <md-icon ng-if="i.class == 'file'">link</md-icon>
+                                <md-icon ng-if="i.class == 'group'">merge_type</md-icon>
+                            </span>
+                            <md-checkbox ng-if="hover[i.id] && i.class == 'file'" ng-checked="_.indexOf(table.selected, i.id) >= 0" ng-click="hover[i.id] = triggerTableRow(i.id)"></md-checkbox>
+                        </td>
                         <td md-cell>{{i.name}}</td>
-                        <td md-cell>{{i.lev | number: 3}}</td>
+                        <!--<td md-cell>{{i.lev | number: 3}}</td>-->
                         <td md-cell>{{i.date | date : 'shortDate'}}</td>
                     </tr>
                     </tbody>
@@ -75,13 +86,33 @@
             </div>
         </md-toolbar>
         <form name="itemForm">
-            <div layout="column" layout-align="start">
-                <md-input-container>
-                    <label for="name">Название</label>
-                    <input type="text" id="name" ng-model="ctrl.item.name"/>
-                </md-input-container>
+            <div layout="column" layout-align="start" layout-margin>
+                <!--<label for="name" class="sub-header">Название</label>-->
+                <md-autocomplete id="name" md-input-id="name"
+                                 md-input-name="name"
+                                 md-no-cache="true"
+                                 md-selected-item="ctrl.ac.group.selected"
+                                 md-search-text="ctrl.ac.group.search"
+                                 md-selected-item-change="ctrl.ac.group.change(item)"
+                                 md-items="item in ctrl.ac.group.query(ctrl.ac.group.search)"
+                                 md-item-text="item.name"
+                                 md-min-length="1"
+                                 md-delay="200"
+                                 placeholder="название группы..." required>
+                    <md-item-template>
+                        <span>{{item.name}}</span><span ng-if="item.fake">&nbsp;<md-badge>новая</md-badge></span>
+                    </md-item-template>
+                    <md-not-found>
+                        <div>По запросу "{{ctrl.ac.group.search}}" ничего не найдено.</div>
+                    </md-not-found>
+                </md-autocomplete>
             </div>
         </form>
+        <div>
+            <ul>
+                <li ng-repeat="i in ctrl.items">{{i.name}}</li>
+            </ul>
+        </div>
         <md-content layout="row" layout-align="end center">
             <md-button ng-click="ctrl.save(itemForm)" class="md-primary md-raised">Готово</md-button>
             <md-button ng-click="ctrl.cancel()" class="md-warn md-raised">Закрыть</md-button>

+ 54 - 11
src/root.js

@@ -7,6 +7,7 @@ let string_similarity = require('string-similarity');
 require('../thirdparty/naturalSort');
 
 require('angular').module('Ks').controller('RootController', function ($scope, $mdPanel) {
+    $scope._ = _;
 
     let tabCats = {
         0: [1, 5],
@@ -54,8 +55,8 @@ require('angular').module('Ks').controller('RootController', function ($scope, $
         openMergeDialog(undefined, Array.from($scope.table.selected).map(id => $scope.table.items[id]))
     };
 
-    $scope.selectTableRow = function (row) {
-        let i = _.findIndex($scope.table.itemList, i => i.id == row);
+    $scope.selectTableRow = function (id) {
+        let i = _.findIndex($scope.table.itemList, i => i.id == id);
         i++;
         while (i < $scope.table.itemList.length && $scope.table.itemList[i].lev > 0.5) {
             if ($scope.table.itemList[i].class === 'file') $scope.table.selected.push($scope.table.itemList[i].id);
@@ -63,6 +64,11 @@ require('angular').module('Ks').controller('RootController', function ($scope, $
         }
     };
 
+    $scope.triggerTableRow = function (id) {
+        $scope.table.selected.push(id);
+        $scope.selectTableRow(id);
+    };
+
     const defaultPanel = {
         panelClass: 'item-dialog',
         controllerAs: 'ctrl',
@@ -80,17 +86,54 @@ require('angular').module('Ks').controller('RootController', function ($scope, $
             controller: ["$mdToast", "$http", "mdPanelRef", "$timeout", function ($mdToast, $http, mdPanelRef, $timeout) {
                 var ctrl = this;
                 ctrl._ = _;
-                ctrl.new = _.isUndefined(id);
+                ctrl.items = items;
 
-                if (ctrl.new) {
-                    ctrl.item = {
-                        name: _.first(items).name,
-                        files: _.map(items, i => i.id)
-                    }
-                } else {
-                    //ctrl.item = _.extend({}, item);
+                ctrl.item = {};
+
+                function resetItem() {
+                    ctrl.item.files = _.uniq(_.map(items, i => i.id));
                 }
 
+                ctrl.ac = {
+                    group: {
+                        selected: null,
+                        search: null,
+                        query: function (q) {
+                            return new Promise((rs, rj) => {
+                                $timeout(() => {
+                                    let candidates = ipc.sendSync('get:groups:find', q);
+                                    if (_.isEmpty(candidates)) candidates.push({fake: true, name: q, files: []});
+                                    rs(candidates)
+                                })
+                            })
+                        },
+                        init: function (id) {
+                            if (_.isUndefined(id)) {
+                                let name = ctrl.item.name = this.search = _.first(_.map(items, i => i.name));
+                                this.selected = {fake: true, name: name, files: []};
+                                resetItem();
+                            }
+                        },
+                        change: function () {
+                            resetItem();
+                            if (_.isObject(this.selected)) {
+                                ctrl.item.name = this.selected.name;
+                                if (this.selected.fake) {
+                                    ctrl.item.id = undefined;
+                                } else {
+                                    ctrl.item.id = this.selected.id;
+                                    ctrl.item.files = _.uniq(ctrl.item.files.concat(this.selected.files));
+                                }
+                            } else {
+                                ctrl.item.name = undefined;
+                                ctrl.item.id = undefined;
+                            }
+                        }
+                    }
+                };
+
+                ctrl.ac.group.init(id);
+
                 ctrl.cancel = function () {
                     mdPanelRef.close();
                 };
@@ -99,7 +142,7 @@ require('angular').module('Ks').controller('RootController', function ($scope, $
                     if (itemForm.$valid) {
                         ipc.sendSync('set:groups', [ctrl.item]);
                         mdPanelRef.close();
-                        $timeout(_ => getPage())
+                        $timeout(() => getPage())
                     } else {
                         $mdToast.showSimple('Невозможно сохранить объект. Форма заполнена неверно.')
                     }