fontastic 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/macos.yml +0 -7
- package/.github/workflows/ubuntu.yml +0 -7
- package/.github/workflows/windows.yml +0 -7
- package/README.md +1 -0
- package/app/core/ConnectionManager.js +7 -1
- package/app/core/ConnectionManager.ts +11 -3
- package/app/core/MessageHandler.js +24 -0
- package/app/core/MessageHandler.ts +29 -0
- package/app/core/menu/templates/DarwinTemplate.js +16 -1
- package/app/core/menu/templates/DarwinTemplate.ts +16 -1
- package/app/core/menu/templates/SystemTemplate.js +16 -1
- package/app/core/menu/templates/SystemTemplate.ts +16 -1
- package/app/database/entity/SmartCollection.schema.js +66 -0
- package/app/database/entity/SmartCollection.schema.ts +39 -0
- package/app/database/entity/index.js +1 -0
- package/app/database/entity/index.ts +2 -1
- package/app/database/repository/SmartCollection.repository.js +47 -0
- package/app/database/repository/SmartCollection.repository.ts +30 -0
- package/app/database/repository/Store.repository.js +107 -0
- package/app/database/repository/Store.repository.ts +106 -0
- package/app/database/repository/index.js +1 -0
- package/app/database/repository/index.ts +2 -1
- package/app/enums/ChannelType.js +5 -0
- package/app/enums/ChannelType.ts +6 -0
- package/app/enums/StorageType.js +1 -0
- package/app/enums/StorageType.ts +1 -0
- package/app/package.json +1 -1
- package/app/types/FontMetrics.js +3 -0
- package/app/types/SmartCollection.js +3 -0
- package/app/types/SmartCollection.ts +5 -0
- package/app/types/SystemConfig.ts +2 -1
- package/app/types/index.js +2 -0
- package/app/types/index.ts +1 -0
- package/package.json +1 -1
- package/src/app/core/services/database/database.service.ts +70 -1
- package/src/app/core/services/message/message.service.ts +23 -0
- package/src/app/core/services/presentation/presentation.service.ts +62 -9
- package/src/app/layout/header/header.component.html +5 -5
- package/src/app/layout/layout.component.html +1 -1
- package/src/app/layout/main/main.component.html +3 -3
- package/src/app/layout/main/main.component.ts +2 -2
- package/src/app/layout/navigation/navigation.component.html +70 -4
- package/src/app/layout/navigation/navigation.component.ts +131 -27
- package/src/app/shared/components/context-menu/context-menu.component.ts +70 -21
- package/src/app/shared/components/datagrid/datagrid.component.html +82 -2
- package/src/app/shared/components/{inspector/inspector.component.html → glyphs/glyphs.component.html} +1 -1
- package/src/app/shared/components/glyphs/glyphs.component.ts +60 -0
- package/src/app/shared/components/index.ts +2 -1
- package/src/app/shared/components/rule-builder/rule-builder.component.html +94 -0
- package/src/app/shared/components/rule-builder/rule-builder.component.ts +136 -0
- package/src/app/shared/components/toolbar/toolbar.component.html +0 -81
- package/src/app/shared/components/toolbar/toolbar.component.ts +1 -2
- package/src/styles/base/variables.css +16 -0
- package/src/styles/components/spinner.css +4 -3
- package/src/app/shared/components/inspector/inspector.component.ts +0 -41
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@ Fontastic is a cross-platform font management and cataloging application built w
|
|
|
17
17
|
## Features
|
|
18
18
|
|
|
19
19
|
- Nested collections — organize fonts into hierarchical groups with drag-and-drop
|
|
20
|
+
- Smart collections — auto-populate collections using rule-based filters on font metadata
|
|
20
21
|
- Advanced search — quickly find fonts with powerful search and filtering
|
|
21
22
|
- Glyph inspector — browse and examine individual characters and Unicode points
|
|
22
23
|
- Waterfall preview — compare text rendering across multiple sizes at a glance
|
|
@@ -15,7 +15,7 @@ const repository_1 = require("../database/repository");
|
|
|
15
15
|
const StorageType_1 = require("../enums/StorageType");
|
|
16
16
|
class ConnectionManager {
|
|
17
17
|
constructor(configManager) {
|
|
18
|
-
this.schemas = [entity_1.Collection, entity_1.Store, entity_1.Logger];
|
|
18
|
+
this.schemas = [entity_1.Collection, entity_1.Store, entity_1.Logger, entity_1.SmartCollection];
|
|
19
19
|
this.subscribers = [];
|
|
20
20
|
this.migrations = [];
|
|
21
21
|
this.omitables = ['title', 'description', 'enabled'];
|
|
@@ -89,6 +89,12 @@ class ConnectionManager {
|
|
|
89
89
|
getStoreRepository() {
|
|
90
90
|
return this.getStore().extend(repository_1.StoreRepository);
|
|
91
91
|
}
|
|
92
|
+
getSmartCollection() {
|
|
93
|
+
return this.dataSource.getRepository(entity_1.SmartCollection);
|
|
94
|
+
}
|
|
95
|
+
getSmartCollectionRepository() {
|
|
96
|
+
return this.getSmartCollection().extend(repository_1.SmartCollectionRepository);
|
|
97
|
+
}
|
|
92
98
|
}
|
|
93
99
|
exports.default = ConnectionManager;
|
|
94
100
|
//# sourceMappingURL=ConnectionManager.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DataSource, DataSourceOptions } from 'typeorm';
|
|
2
|
-
import { Collection, Store, Logger } from '../database/entity';
|
|
3
|
-
import { CollectionRepository, LoggerRepository, StoreRepository } from '../database/repository';
|
|
2
|
+
import { Collection, Store, Logger, SmartCollection } from '../database/entity';
|
|
3
|
+
import { CollectionRepository, LoggerRepository, SmartCollectionRepository, StoreRepository } from '../database/repository';
|
|
4
4
|
import ConfigManager from './ConfigManager';
|
|
5
5
|
import { StorageType } from '../enums/StorageType';
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ export default class ConnectionManager {
|
|
|
10
10
|
|
|
11
11
|
dataSource: DataSource;
|
|
12
12
|
|
|
13
|
-
schemas: any[] = [Collection, Store, Logger];
|
|
13
|
+
schemas: any[] = [Collection, Store, Logger, SmartCollection];
|
|
14
14
|
subscribers: any[] = [];
|
|
15
15
|
migrations: any[] = [];
|
|
16
16
|
|
|
@@ -104,4 +104,12 @@ export default class ConnectionManager {
|
|
|
104
104
|
getStoreRepository() {
|
|
105
105
|
return this.getStore().extend(StoreRepository);
|
|
106
106
|
}
|
|
107
|
+
|
|
108
|
+
getSmartCollection() {
|
|
109
|
+
return this.dataSource.getRepository(SmartCollection);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
getSmartCollectionRepository() {
|
|
113
|
+
return this.getSmartCollection().extend(SmartCollectionRepository);
|
|
114
|
+
}
|
|
107
115
|
}
|
|
@@ -141,6 +141,30 @@ class MessageHandler {
|
|
|
141
141
|
yield this.connectionManager.getCollectionRepository().updateCollectionCounts(items);
|
|
142
142
|
return yield this.fetchCollectionsWithCounts({});
|
|
143
143
|
}));
|
|
144
|
+
// Smart Collection
|
|
145
|
+
this.handle(ChannelType_1.ChannelType.IPC_SMART_COLLECTION_FIND, (_event) => __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
return yield this.connectionManager.getSmartCollectionRepository().fetchAll();
|
|
147
|
+
}));
|
|
148
|
+
this.handle(ChannelType_1.ChannelType.IPC_SMART_COLLECTION_CREATE, (_event, args) => __awaiter(this, void 0, void 0, function* () {
|
|
149
|
+
return yield this.connectionManager.getSmartCollectionRepository().createSmartCollection(args);
|
|
150
|
+
}));
|
|
151
|
+
this.handle(ChannelType_1.ChannelType.IPC_SMART_COLLECTION_UPDATE, (_event, args) => __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
return yield this.connectionManager.getSmartCollectionRepository().updateSmartCollection(args.id, args.data);
|
|
153
|
+
}));
|
|
154
|
+
this.handle(ChannelType_1.ChannelType.IPC_SMART_COLLECTION_DELETE, (_event, args) => __awaiter(this, void 0, void 0, function* () {
|
|
155
|
+
return yield this.connectionManager.getSmartCollectionRepository().deleteSmartCollection(args.id);
|
|
156
|
+
}));
|
|
157
|
+
this.handle(ChannelType_1.ChannelType.IPC_SMART_COLLECTION_EVALUATE, (_event, args) => __awaiter(this, void 0, void 0, function* () {
|
|
158
|
+
const sc = yield this.connectionManager.getSmartCollectionRepository().findOneBy({ id: args.id });
|
|
159
|
+
if (!sc)
|
|
160
|
+
return [[], 0];
|
|
161
|
+
const rules = JSON.parse(sc.rules);
|
|
162
|
+
return yield this.connectionManager.getStoreRepository().evaluateSmartRules(rules, sc.match_type, {
|
|
163
|
+
skip: args.skip,
|
|
164
|
+
take: args.take,
|
|
165
|
+
order: args.order,
|
|
166
|
+
});
|
|
167
|
+
}));
|
|
144
168
|
// Store
|
|
145
169
|
this.handle(ChannelType_1.ChannelType.IPC_STORE_FIND, (_event, args) => __awaiter(this, void 0, void 0, function* () {
|
|
146
170
|
return yield this.connectionManager.getStore().find(args);
|
|
@@ -184,6 +184,35 @@ export default class MessageHandler {
|
|
|
184
184
|
return await this.fetchCollectionsWithCounts({});
|
|
185
185
|
});
|
|
186
186
|
|
|
187
|
+
// Smart Collection
|
|
188
|
+
|
|
189
|
+
this.handle(ChannelType.IPC_SMART_COLLECTION_FIND, async (_event: IpcMainEvent) => {
|
|
190
|
+
return await this.connectionManager.getSmartCollectionRepository().fetchAll();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
this.handle(ChannelType.IPC_SMART_COLLECTION_CREATE, async (_event: IpcMainEvent, args: any) => {
|
|
194
|
+
return await this.connectionManager.getSmartCollectionRepository().createSmartCollection(args);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
this.handle(ChannelType.IPC_SMART_COLLECTION_UPDATE, async (_event: IpcMainEvent, args: any) => {
|
|
198
|
+
return await this.connectionManager.getSmartCollectionRepository().updateSmartCollection(args.id, args.data);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
this.handle(ChannelType.IPC_SMART_COLLECTION_DELETE, async (_event: IpcMainEvent, args: any) => {
|
|
202
|
+
return await this.connectionManager.getSmartCollectionRepository().deleteSmartCollection(args.id);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
this.handle(ChannelType.IPC_SMART_COLLECTION_EVALUATE, async (_event: IpcMainEvent, args: any) => {
|
|
206
|
+
const sc = await this.connectionManager.getSmartCollectionRepository().findOneBy({ id: args.id });
|
|
207
|
+
if (!sc) return [[], 0];
|
|
208
|
+
const rules = JSON.parse(sc.rules);
|
|
209
|
+
return await this.connectionManager.getStoreRepository().evaluateSmartRules(rules, sc.match_type, {
|
|
210
|
+
skip: args.skip,
|
|
211
|
+
take: args.take,
|
|
212
|
+
order: args.order,
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
187
216
|
// Store
|
|
188
217
|
|
|
189
218
|
this.handle(ChannelType.IPC_STORE_FIND, async (_event: IpcMainEvent, args: any) => {
|
|
@@ -68,6 +68,21 @@ class DarwinTemplate {
|
|
|
68
68
|
this.mainWindow.setFullScreen(!this.mainWindow.isFullScreen());
|
|
69
69
|
},
|
|
70
70
|
},
|
|
71
|
+
{ type: 'separator' },
|
|
72
|
+
{
|
|
73
|
+
label: 'Expand Collections',
|
|
74
|
+
accelerator: 'Alt+Command+E',
|
|
75
|
+
click: () => {
|
|
76
|
+
this.mainWindow.webContents.send(enums_1.ChannelType.IPC_TOGGLE_PANEL, 'expand-collections');
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
label: 'Collapse Collections',
|
|
81
|
+
accelerator: 'Alt+Command+Shift+E',
|
|
82
|
+
click: () => {
|
|
83
|
+
this.mainWindow.webContents.send(enums_1.ChannelType.IPC_TOGGLE_PANEL, 'collapse-collections');
|
|
84
|
+
},
|
|
85
|
+
},
|
|
71
86
|
];
|
|
72
87
|
if (!this.isProduction) {
|
|
73
88
|
items.push({ type: 'separator' }, {
|
|
@@ -107,7 +122,7 @@ class DarwinTemplate {
|
|
|
107
122
|
{ label: 'Toggle Navigation', panel: 'navigation', accelerator: 'Alt+Command+1' },
|
|
108
123
|
{ label: 'Toggle Aside', panel: 'aside', accelerator: 'Alt+Command+2' },
|
|
109
124
|
{ label: 'Toggle Preview', panel: 'preview', accelerator: 'Alt+Command+3' },
|
|
110
|
-
{ label: 'Toggle
|
|
125
|
+
{ label: 'Toggle Glyphs', panel: 'glyphs', accelerator: 'Alt+Command+4' },
|
|
111
126
|
{ label: 'Toggle Toolbar', panel: 'toolbar', accelerator: 'Alt+Command+5' },
|
|
112
127
|
{ label: 'Toggle Grid', panel: 'grid', accelerator: 'Alt+Command+6' },
|
|
113
128
|
{ label: 'Toggle Waterfall', panel: 'waterfall', accelerator: 'Alt+Command+7' },
|
|
@@ -80,6 +80,21 @@ export default class DarwinTemplate {
|
|
|
80
80
|
this.mainWindow.setFullScreen(!this.mainWindow.isFullScreen());
|
|
81
81
|
},
|
|
82
82
|
},
|
|
83
|
+
{ type: 'separator' },
|
|
84
|
+
{
|
|
85
|
+
label: 'Expand Collections',
|
|
86
|
+
accelerator: 'Alt+Command+E',
|
|
87
|
+
click: () => {
|
|
88
|
+
this.mainWindow.webContents.send(ChannelType.IPC_TOGGLE_PANEL, 'expand-collections');
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
label: 'Collapse Collections',
|
|
93
|
+
accelerator: 'Alt+Command+Shift+E',
|
|
94
|
+
click: () => {
|
|
95
|
+
this.mainWindow.webContents.send(ChannelType.IPC_TOGGLE_PANEL, 'collapse-collections');
|
|
96
|
+
},
|
|
97
|
+
},
|
|
83
98
|
];
|
|
84
99
|
|
|
85
100
|
if (!this.isProduction) {
|
|
@@ -127,7 +142,7 @@ export default class DarwinTemplate {
|
|
|
127
142
|
{ label: 'Toggle Navigation', panel: 'navigation', accelerator: 'Alt+Command+1' },
|
|
128
143
|
{ label: 'Toggle Aside', panel: 'aside', accelerator: 'Alt+Command+2' },
|
|
129
144
|
{ label: 'Toggle Preview', panel: 'preview', accelerator: 'Alt+Command+3' },
|
|
130
|
-
{ label: 'Toggle
|
|
145
|
+
{ label: 'Toggle Glyphs', panel: 'glyphs', accelerator: 'Alt+Command+4' },
|
|
131
146
|
{ label: 'Toggle Toolbar', panel: 'toolbar', accelerator: 'Alt+Command+5' },
|
|
132
147
|
{ label: 'Toggle Grid', panel: 'grid', accelerator: 'Alt+Command+6' },
|
|
133
148
|
{ label: 'Toggle Waterfall', panel: 'waterfall', accelerator: 'Alt+Command+7' },
|
|
@@ -65,6 +65,21 @@ class SystemTemplate {
|
|
|
65
65
|
this.mainWindow.setFullScreen(!this.mainWindow.isFullScreen());
|
|
66
66
|
},
|
|
67
67
|
},
|
|
68
|
+
{ type: 'separator' },
|
|
69
|
+
{
|
|
70
|
+
label: 'Expand Collections',
|
|
71
|
+
accelerator: 'Alt+Ctrl+E',
|
|
72
|
+
click: () => {
|
|
73
|
+
this.mainWindow.webContents.send(enums_1.ChannelType.IPC_TOGGLE_PANEL, 'expand-collections');
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
label: 'Collapse Collections',
|
|
78
|
+
accelerator: 'Alt+Ctrl+Shift+E',
|
|
79
|
+
click: () => {
|
|
80
|
+
this.mainWindow.webContents.send(enums_1.ChannelType.IPC_TOGGLE_PANEL, 'collapse-collections');
|
|
81
|
+
},
|
|
82
|
+
},
|
|
68
83
|
];
|
|
69
84
|
if (!this.isProduction) {
|
|
70
85
|
items.push({ type: 'separator' }, {
|
|
@@ -104,7 +119,7 @@ class SystemTemplate {
|
|
|
104
119
|
{ label: 'Toggle Navigation', panel: 'navigation', accelerator: 'Alt+Ctrl+1' },
|
|
105
120
|
{ label: 'Toggle Aside', panel: 'aside', accelerator: 'Alt+Ctrl+2' },
|
|
106
121
|
{ label: 'Toggle Preview', panel: 'preview', accelerator: 'Alt+Ctrl+3' },
|
|
107
|
-
{ label: 'Toggle
|
|
122
|
+
{ label: 'Toggle Glyphs', panel: 'glyphs', accelerator: 'Alt+Ctrl+4' },
|
|
108
123
|
{ label: 'Toggle Toolbar', panel: 'toolbar', accelerator: 'Alt+Ctrl+5' },
|
|
109
124
|
{ label: 'Toggle Grid', panel: 'grid', accelerator: 'Alt+Ctrl+6' },
|
|
110
125
|
{ label: 'Toggle Waterfall', panel: 'waterfall', accelerator: 'Alt+Ctrl+7' },
|
|
@@ -72,6 +72,21 @@ export default class SystemTemplate {
|
|
|
72
72
|
this.mainWindow.setFullScreen(!this.mainWindow.isFullScreen());
|
|
73
73
|
},
|
|
74
74
|
},
|
|
75
|
+
{ type: 'separator' },
|
|
76
|
+
{
|
|
77
|
+
label: 'Expand Collections',
|
|
78
|
+
accelerator: 'Alt+Ctrl+E',
|
|
79
|
+
click: () => {
|
|
80
|
+
this.mainWindow.webContents.send(ChannelType.IPC_TOGGLE_PANEL, 'expand-collections');
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
label: 'Collapse Collections',
|
|
85
|
+
accelerator: 'Alt+Ctrl+Shift+E',
|
|
86
|
+
click: () => {
|
|
87
|
+
this.mainWindow.webContents.send(ChannelType.IPC_TOGGLE_PANEL, 'collapse-collections');
|
|
88
|
+
},
|
|
89
|
+
},
|
|
75
90
|
];
|
|
76
91
|
|
|
77
92
|
if (!this.isProduction) {
|
|
@@ -119,7 +134,7 @@ export default class SystemTemplate {
|
|
|
119
134
|
{ label: 'Toggle Navigation', panel: 'navigation', accelerator: 'Alt+Ctrl+1' },
|
|
120
135
|
{ label: 'Toggle Aside', panel: 'aside', accelerator: 'Alt+Ctrl+2' },
|
|
121
136
|
{ label: 'Toggle Preview', panel: 'preview', accelerator: 'Alt+Ctrl+3' },
|
|
122
|
-
{ label: 'Toggle
|
|
137
|
+
{ label: 'Toggle Glyphs', panel: 'glyphs', accelerator: 'Alt+Ctrl+4' },
|
|
123
138
|
{ label: 'Toggle Toolbar', panel: 'toolbar', accelerator: 'Alt+Ctrl+5' },
|
|
124
139
|
{ label: 'Toggle Grid', panel: 'grid', accelerator: 'Alt+Ctrl+6' },
|
|
125
140
|
{ label: 'Toggle Waterfall', panel: 'waterfall', accelerator: 'Alt+Ctrl+7' },
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SmartCollection = void 0;
|
|
13
|
+
const typeorm_1 = require("typeorm");
|
|
14
|
+
let SmartCollection = class SmartCollection {
|
|
15
|
+
};
|
|
16
|
+
exports.SmartCollection = SmartCollection;
|
|
17
|
+
__decorate([
|
|
18
|
+
(0, typeorm_1.PrimaryGeneratedColumn)(),
|
|
19
|
+
__metadata("design:type", Number)
|
|
20
|
+
], SmartCollection.prototype, "id", void 0);
|
|
21
|
+
__decorate([
|
|
22
|
+
(0, typeorm_1.Column)({
|
|
23
|
+
length: 100,
|
|
24
|
+
}),
|
|
25
|
+
__metadata("design:type", String)
|
|
26
|
+
], SmartCollection.prototype, "title", void 0);
|
|
27
|
+
__decorate([
|
|
28
|
+
(0, typeorm_1.Column)({
|
|
29
|
+
type: 'text',
|
|
30
|
+
}),
|
|
31
|
+
__metadata("design:type", String)
|
|
32
|
+
], SmartCollection.prototype, "rules", void 0);
|
|
33
|
+
__decorate([
|
|
34
|
+
(0, typeorm_1.Column)({
|
|
35
|
+
type: 'varchar',
|
|
36
|
+
length: 3,
|
|
37
|
+
default: 'AND',
|
|
38
|
+
}),
|
|
39
|
+
__metadata("design:type", String)
|
|
40
|
+
], SmartCollection.prototype, "match_type", void 0);
|
|
41
|
+
__decorate([
|
|
42
|
+
(0, typeorm_1.Column)({
|
|
43
|
+
type: 'smallint',
|
|
44
|
+
default: 0,
|
|
45
|
+
}),
|
|
46
|
+
__metadata("design:type", Number)
|
|
47
|
+
], SmartCollection.prototype, "orderby", void 0);
|
|
48
|
+
__decorate([
|
|
49
|
+
(0, typeorm_1.Column)({
|
|
50
|
+
type: 'smallint',
|
|
51
|
+
default: 0,
|
|
52
|
+
}),
|
|
53
|
+
__metadata("design:type", Number)
|
|
54
|
+
], SmartCollection.prototype, "enabled", void 0);
|
|
55
|
+
__decorate([
|
|
56
|
+
(0, typeorm_1.CreateDateColumn)(),
|
|
57
|
+
__metadata("design:type", Date)
|
|
58
|
+
], SmartCollection.prototype, "created", void 0);
|
|
59
|
+
__decorate([
|
|
60
|
+
(0, typeorm_1.UpdateDateColumn)(),
|
|
61
|
+
__metadata("design:type", Date)
|
|
62
|
+
], SmartCollection.prototype, "updated", void 0);
|
|
63
|
+
exports.SmartCollection = SmartCollection = __decorate([
|
|
64
|
+
(0, typeorm_1.Entity)()
|
|
65
|
+
], SmartCollection);
|
|
66
|
+
//# sourceMappingURL=SmartCollection.schema.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm';
|
|
2
|
+
|
|
3
|
+
@Entity()
|
|
4
|
+
export class SmartCollection {
|
|
5
|
+
@PrimaryGeneratedColumn()
|
|
6
|
+
id: number;
|
|
7
|
+
|
|
8
|
+
@Column({
|
|
9
|
+
length: 100,
|
|
10
|
+
})
|
|
11
|
+
title: string;
|
|
12
|
+
|
|
13
|
+
@Column({
|
|
14
|
+
type: 'text',
|
|
15
|
+
})
|
|
16
|
+
rules: string;
|
|
17
|
+
|
|
18
|
+
@Column({
|
|
19
|
+
type: 'varchar',
|
|
20
|
+
length: 3,
|
|
21
|
+
default: 'AND',
|
|
22
|
+
})
|
|
23
|
+
match_type: string;
|
|
24
|
+
|
|
25
|
+
@Column({
|
|
26
|
+
type: 'smallint',
|
|
27
|
+
default: 0,
|
|
28
|
+
})
|
|
29
|
+
orderby: number;
|
|
30
|
+
|
|
31
|
+
@Column({
|
|
32
|
+
type: 'smallint',
|
|
33
|
+
default: 0,
|
|
34
|
+
})
|
|
35
|
+
enabled: number;
|
|
36
|
+
|
|
37
|
+
@CreateDateColumn() public created: Date;
|
|
38
|
+
@UpdateDateColumn() public updated: Date;
|
|
39
|
+
}
|
|
@@ -16,5 +16,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./Collection.schema"), exports);
|
|
18
18
|
__exportStar(require("./Logger.schema"), exports);
|
|
19
|
+
__exportStar(require("./SmartCollection.schema"), exports);
|
|
19
20
|
__exportStar(require("./Store.schema"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SmartCollectionRepository = void 0;
|
|
13
|
+
const entity_1 = require("../entity");
|
|
14
|
+
exports.SmartCollectionRepository = {
|
|
15
|
+
fetchAll() {
|
|
16
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
return this.createQueryBuilder('sc').orderBy('sc.orderby', 'ASC').addOrderBy('LOWER(sc.title)', 'ASC').getMany();
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
createSmartCollection(args) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
yield this.createQueryBuilder()
|
|
23
|
+
.insert()
|
|
24
|
+
.into(entity_1.SmartCollection)
|
|
25
|
+
.values({
|
|
26
|
+
title: args.title,
|
|
27
|
+
rules: args.rules,
|
|
28
|
+
match_type: args.match_type,
|
|
29
|
+
})
|
|
30
|
+
.execute();
|
|
31
|
+
return this.fetchAll();
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
updateSmartCollection(id, data) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
yield this.createQueryBuilder().update(entity_1.SmartCollection).set(data).where('id = :id', { id }).execute();
|
|
37
|
+
return this.fetchAll();
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
deleteSmartCollection(id) {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
yield this.createQueryBuilder().delete().from(entity_1.SmartCollection).where('id = :id', { id }).execute();
|
|
43
|
+
return this.fetchAll();
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=SmartCollection.repository.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SmartCollection } from '../entity';
|
|
2
|
+
|
|
3
|
+
export const SmartCollectionRepository = {
|
|
4
|
+
async fetchAll(): Promise<SmartCollection[]> {
|
|
5
|
+
return this.createQueryBuilder('sc').orderBy('sc.orderby', 'ASC').addOrderBy('LOWER(sc.title)', 'ASC').getMany();
|
|
6
|
+
},
|
|
7
|
+
|
|
8
|
+
async createSmartCollection(args: { title: string; rules: string; match_type: string }) {
|
|
9
|
+
await this.createQueryBuilder()
|
|
10
|
+
.insert()
|
|
11
|
+
.into(SmartCollection)
|
|
12
|
+
.values({
|
|
13
|
+
title: args.title,
|
|
14
|
+
rules: args.rules,
|
|
15
|
+
match_type: args.match_type,
|
|
16
|
+
})
|
|
17
|
+
.execute();
|
|
18
|
+
return this.fetchAll();
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
async updateSmartCollection(id: number, data: Partial<SmartCollection>) {
|
|
22
|
+
await this.createQueryBuilder().update(SmartCollection).set(data).where('id = :id', { id }).execute();
|
|
23
|
+
return this.fetchAll();
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
async deleteSmartCollection(id: number) {
|
|
27
|
+
await this.createQueryBuilder().delete().from(SmartCollection).where('id = :id', { id }).execute();
|
|
28
|
+
return this.fetchAll();
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -307,6 +307,113 @@ exports.StoreRepository = {
|
|
|
307
307
|
.catch((err) => console.log('insert-error', err));
|
|
308
308
|
});
|
|
309
309
|
},
|
|
310
|
+
evaluateSmartRules(rules_1, matchType_1) {
|
|
311
|
+
return __awaiter(this, arguments, void 0, function* (rules, matchType, options = {}) {
|
|
312
|
+
const db = this.createQueryBuilder();
|
|
313
|
+
const textFields = [
|
|
314
|
+
'file_name',
|
|
315
|
+
'file_path',
|
|
316
|
+
'compatible_full_name',
|
|
317
|
+
'copyright',
|
|
318
|
+
'description',
|
|
319
|
+
'designer',
|
|
320
|
+
'designer_url',
|
|
321
|
+
'font_family',
|
|
322
|
+
'font_subfamily',
|
|
323
|
+
'full_name',
|
|
324
|
+
'license',
|
|
325
|
+
'license_url',
|
|
326
|
+
'manufacturer',
|
|
327
|
+
'manufacturer_url',
|
|
328
|
+
'post_script_name',
|
|
329
|
+
'preferred_family',
|
|
330
|
+
'preferred_sub_family',
|
|
331
|
+
'sample_text',
|
|
332
|
+
'trademark',
|
|
333
|
+
'unique_id',
|
|
334
|
+
'version',
|
|
335
|
+
];
|
|
336
|
+
const booleanFields = ['favorite', 'system', 'installable', 'temporary'];
|
|
337
|
+
const numericFields = ['file_size'];
|
|
338
|
+
const dateFields = ['created'];
|
|
339
|
+
if (rules.length > 0) {
|
|
340
|
+
const conditions = rules.map((rule, idx) => {
|
|
341
|
+
const field = `store.${rule.field}`;
|
|
342
|
+
const paramName = `p${idx}`;
|
|
343
|
+
return (qb) => {
|
|
344
|
+
if (textFields.includes(rule.field)) {
|
|
345
|
+
const val = String(rule.value).toLowerCase();
|
|
346
|
+
switch (rule.operator) {
|
|
347
|
+
case 'contains':
|
|
348
|
+
qb.where(`LOWER(${field}) LIKE :${paramName}`, { [paramName]: `%${val}%` });
|
|
349
|
+
break;
|
|
350
|
+
case 'equals':
|
|
351
|
+
qb.where(`LOWER(${field}) = :${paramName}`, { [paramName]: val });
|
|
352
|
+
break;
|
|
353
|
+
case 'starts_with':
|
|
354
|
+
qb.where(`LOWER(${field}) LIKE :${paramName}`, { [paramName]: `${val}%` });
|
|
355
|
+
break;
|
|
356
|
+
case 'ends_with':
|
|
357
|
+
qb.where(`LOWER(${field}) LIKE :${paramName}`, { [paramName]: `%${val}` });
|
|
358
|
+
break;
|
|
359
|
+
default:
|
|
360
|
+
qb.where(`LOWER(${field}) LIKE :${paramName}`, { [paramName]: `%${val}%` });
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
else if (rule.field === 'file_type') {
|
|
364
|
+
qb.where(`${field} = :${paramName}`, { [paramName]: rule.value });
|
|
365
|
+
}
|
|
366
|
+
else if (booleanFields.includes(rule.field)) {
|
|
367
|
+
const boolVal = rule.operator === 'is_not' ? 0 : 1;
|
|
368
|
+
qb.where(`${field} = :${paramName}`, { [paramName]: boolVal });
|
|
369
|
+
}
|
|
370
|
+
else if (numericFields.includes(rule.field)) {
|
|
371
|
+
if (rule.operator === 'greater_than') {
|
|
372
|
+
qb.where(`${field} > :${paramName}`, { [paramName]: rule.value });
|
|
373
|
+
}
|
|
374
|
+
else if (rule.operator === 'less_than') {
|
|
375
|
+
qb.where(`${field} < :${paramName}`, { [paramName]: rule.value });
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
qb.where(`${field} = :${paramName}`, { [paramName]: rule.value });
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
else if (dateFields.includes(rule.field)) {
|
|
382
|
+
if (rule.operator === 'greater_than') {
|
|
383
|
+
qb.where(`${field} >= :${paramName}`, { [paramName]: rule.value });
|
|
384
|
+
}
|
|
385
|
+
else if (rule.operator === 'less_than') {
|
|
386
|
+
qb.where(`${field} <= :${paramName}`, { [paramName]: rule.value });
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
qb.where(`${field} = :${paramName}`, { [paramName]: rule.value });
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
});
|
|
394
|
+
const joiner = matchType === 'OR' ? 'orWhere' : 'andWhere';
|
|
395
|
+
conditions.forEach((condition, i) => {
|
|
396
|
+
if (i === 0) {
|
|
397
|
+
db.where(new typeorm_1.Brackets(condition));
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
db[joiner](new typeorm_1.Brackets(condition));
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
if (options.take) {
|
|
405
|
+
db.limit(options.take);
|
|
406
|
+
}
|
|
407
|
+
if (options.skip) {
|
|
408
|
+
db.offset(options.skip);
|
|
409
|
+
}
|
|
410
|
+
if (options.order && options.order.column) {
|
|
411
|
+
const direction = options.order.direction === 'DESC' ? 'DESC' : 'ASC';
|
|
412
|
+
db.orderBy(`store.${options.order.column}`, direction);
|
|
413
|
+
}
|
|
414
|
+
return yield db.getManyAndCount();
|
|
415
|
+
});
|
|
416
|
+
},
|
|
310
417
|
fetchSystemStats() {
|
|
311
418
|
return __awaiter(this, void 0, void 0, function* () {
|
|
312
419
|
const rowCount = yield this.createQueryBuilder().select('COUNT(*)', 'total').getRawOne();
|