terrier-engine 4.6.2 → 4.7.3
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/data-dive/dd-session.ts +2 -2
- package/data-dive/dives/dive-editor.ts +12 -11
- package/data-dive/dives/dive-list.ts +10 -9
- package/data-dive/dives/dive-runs.ts +3 -3
- package/data-dive/dives/dive-settings.ts +4 -4
- package/data-dive/dives/group-editor.ts +3 -3
- package/data-dive/queries/columns.ts +11 -10
- package/data-dive/queries/dates.ts +2 -2
- package/data-dive/queries/filters.ts +15 -14
- package/data-dive/queries/queries.ts +8 -6
- package/data-dive/queries/query-editor.ts +4 -4
- package/data-dive/queries/query-form.ts +3 -3
- package/data-dive/queries/tables.ts +11 -10
- package/package.json +1 -1
- package/terrier/app.ts +5 -4
- package/terrier/dropdowns.ts +4 -4
- package/terrier/forms.ts +6 -4
- package/terrier/glyps.ts +3 -2
- package/terrier/lightbox.ts +2 -2
- package/terrier/modals.ts +2 -2
- package/terrier/overlays.ts +4 -4
- package/terrier/parts/glyp-picker.ts +5 -4
- package/terrier/parts/panel-part.ts +3 -3
- package/terrier/sheets.ts +2 -2
- package/terrier/tabs.ts +3 -3
- package/terrier/theme.ts +3 -3
package/data-dive/dd-session.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {DdUser} from "./dd-user"
|
|
2
2
|
import Api from "../terrier/api"
|
|
3
3
|
import {DdDiveGroup} from "./gen/models"
|
|
4
|
-
import
|
|
4
|
+
import Arrays from "tuff-core/arrays"
|
|
5
5
|
import {SelectOptions} from "tuff-core/forms"
|
|
6
6
|
import {Logger} from "tuff-core/logging"
|
|
7
7
|
|
|
@@ -76,7 +76,7 @@ export default class DdSession {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
groupsInOrder(): DdDiveGroup[] {
|
|
79
|
-
return
|
|
79
|
+
return Arrays.sortBy(Object.values(this.data.groupMap), 'name')
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
groupOptions(): SelectOptions {
|
|
@@ -5,7 +5,6 @@ import {Query, QueryModelPicker} from "../queries/queries"
|
|
|
5
5
|
import QueryEditor from "../queries/query-editor"
|
|
6
6
|
import {Logger} from "tuff-core/logging"
|
|
7
7
|
import QueryForm from "../queries/query-form"
|
|
8
|
-
import {arrays, messages} from "tuff-core"
|
|
9
8
|
import {TabContainerPart} from "../../terrier/tabs"
|
|
10
9
|
import PagePart from "../../terrier/parts/page-part"
|
|
11
10
|
import ContentPart from "../../terrier/parts/content-part"
|
|
@@ -15,7 +14,9 @@ import Ids from "../../terrier/ids"
|
|
|
15
14
|
import Db from "../dd-db"
|
|
16
15
|
import DdSession from "../dd-session"
|
|
17
16
|
import {DiveRunModal} from "./dive-runs"
|
|
18
|
-
import Nav from "tuff-core/nav"
|
|
17
|
+
import Nav from "tuff-core/nav"
|
|
18
|
+
import Messages from "tuff-core/messages"
|
|
19
|
+
import Arrays from "tuff-core/arrays"
|
|
19
20
|
|
|
20
21
|
const log = new Logger("DiveEditor")
|
|
21
22
|
|
|
@@ -34,9 +35,9 @@ export default class DiveEditor extends ContentPart<DiveEditorState> {
|
|
|
34
35
|
|
|
35
36
|
tabs!: TabContainerPart
|
|
36
37
|
|
|
37
|
-
newQueryKey =
|
|
38
|
+
newQueryKey = Messages.untypedKey()
|
|
38
39
|
|
|
39
|
-
static readonly diveChangedKey =
|
|
40
|
+
static readonly diveChangedKey = Messages.untypedKey()
|
|
40
41
|
|
|
41
42
|
queries = new Array<Query>()
|
|
42
43
|
|
|
@@ -88,7 +89,7 @@ export default class DiveEditor extends ContentPart<DiveEditorState> {
|
|
|
88
89
|
|
|
89
90
|
deleteQuery(id: string) {
|
|
90
91
|
log.info(`Deleting query ${id}`)
|
|
91
|
-
if (
|
|
92
|
+
if (Arrays.deleteIf(this.queries, q => q.id == id) > 0) {
|
|
92
93
|
this.tabs.removeTab(id)
|
|
93
94
|
this.dirty()
|
|
94
95
|
}
|
|
@@ -102,7 +103,7 @@ export default class DiveEditor extends ContentPart<DiveEditorState> {
|
|
|
102
103
|
parent.part(this.tabs)
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
static readonly deleteQueryKey =
|
|
106
|
+
static readonly deleteQueryKey = Messages.typedKey<{ id: string }>()
|
|
106
107
|
|
|
107
108
|
async serialize(): Promise<DdDive> {
|
|
108
109
|
const queries = this.queries
|
|
@@ -117,10 +118,10 @@ export class DiveEditorPage extends PagePart<{id: string}> {
|
|
|
117
118
|
editor!: DiveEditor
|
|
118
119
|
session!: DdSession
|
|
119
120
|
|
|
120
|
-
showHintsKey =
|
|
121
|
-
saveKey =
|
|
122
|
-
discardKey =
|
|
123
|
-
runKey =
|
|
121
|
+
showHintsKey = Messages.untypedKey()
|
|
122
|
+
saveKey = Messages.untypedKey()
|
|
123
|
+
discardKey = Messages.untypedKey()
|
|
124
|
+
runKey = Messages.untypedKey()
|
|
124
125
|
|
|
125
126
|
async init() {
|
|
126
127
|
log.info(`Loading dive ${this.state.id}`)
|
|
@@ -233,7 +234,7 @@ type NewQueryState = {
|
|
|
233
234
|
|
|
234
235
|
class NewQueryModal extends ModalPart<NewQueryState> {
|
|
235
236
|
|
|
236
|
-
addKey =
|
|
237
|
+
addKey = Messages.untypedKey()
|
|
237
238
|
settingsForm!: QueryForm
|
|
238
239
|
modelPicker!: QueryModelPicker
|
|
239
240
|
|
|
@@ -2,7 +2,6 @@ import {Logger} from "tuff-core/logging"
|
|
|
2
2
|
import PagePart from "../../terrier/parts/page-part"
|
|
3
3
|
import {PartTag} from "tuff-core/parts"
|
|
4
4
|
import Schema, {SchemaDef} from "../../terrier/schema"
|
|
5
|
-
import {arrays, messages} from "tuff-core"
|
|
6
5
|
import {DdDive, DdDiveGroup, UnpersistedDdDive, UnpersistedDdDiveGroup} from "../gen/models"
|
|
7
6
|
import Dives, {DiveListResult} from "./dives"
|
|
8
7
|
import {GroupEditorModal} from "./group-editor"
|
|
@@ -11,6 +10,8 @@ import {IconName} from "../../terrier/theme"
|
|
|
11
10
|
import {routes} from "../dd-routes"
|
|
12
11
|
import {DiveSettingsModal} from "./dive-settings"
|
|
13
12
|
import DdSession from "../dd-session"
|
|
13
|
+
import Messages from "tuff-core/messages"
|
|
14
|
+
import Arrays from "tuff-core/arrays"
|
|
14
15
|
|
|
15
16
|
const log = new Logger("DiveList")
|
|
16
17
|
|
|
@@ -21,10 +22,10 @@ const log = new Logger("DiveList")
|
|
|
21
22
|
|
|
22
23
|
export class DiveListPage extends PagePart<{}> {
|
|
23
24
|
|
|
24
|
-
newGroupKey =
|
|
25
|
-
editGroupKey =
|
|
26
|
-
newDiveKey =
|
|
27
|
-
editDiveKey =
|
|
25
|
+
newGroupKey = Messages.untypedKey()
|
|
26
|
+
editGroupKey = Messages.typedKey<{id: string}>()
|
|
27
|
+
newDiveKey = Messages.typedKey<{group_id: string}>()
|
|
28
|
+
editDiveKey = Messages.typedKey<{id: string}>()
|
|
28
29
|
|
|
29
30
|
session!: DdSession
|
|
30
31
|
result!: DiveListResult
|
|
@@ -104,16 +105,16 @@ export class DiveListPage extends PagePart<{}> {
|
|
|
104
105
|
this.result = await Dives.list()
|
|
105
106
|
log.info("Loading data dive list", this.result)
|
|
106
107
|
this.groupMap = this.session.data.groupMap
|
|
107
|
-
this.diveMap =
|
|
108
|
+
this.diveMap = Arrays.indexBy(this.result.dives, 'id')
|
|
108
109
|
this.dirty()
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
renderContent(parent: PartTag): void {
|
|
112
113
|
|
|
113
|
-
const groupedDives =
|
|
114
|
+
const groupedDives = Arrays.groupBy(this.result.dives, 'dd_dive_group_id')
|
|
114
115
|
|
|
115
116
|
parent.div('.dd-group-grid', grid => {
|
|
116
|
-
const groups =
|
|
117
|
+
const groups = Arrays.sortBy(Object.values(this.groupMap), 'name')
|
|
117
118
|
for (const group of groups) {
|
|
118
119
|
this.renderGroupPanel(grid, group, groupedDives[group.id] || [])
|
|
119
120
|
}
|
|
@@ -127,7 +128,7 @@ export class DiveListPage extends PagePart<{}> {
|
|
|
127
128
|
.classes('group')
|
|
128
129
|
.content(content => {
|
|
129
130
|
content.class('tt-list')
|
|
130
|
-
for (const dive of
|
|
131
|
+
for (const dive of Arrays.sortBy(dives, 'name')) {
|
|
131
132
|
this.renderDiveRow(content, dive)
|
|
132
133
|
}
|
|
133
134
|
})
|
|
@@ -5,7 +5,6 @@ import Db from "../dd-db"
|
|
|
5
5
|
import Api, {ErrorEvent} from "../../terrier/api"
|
|
6
6
|
import {Query} from "../queries/queries"
|
|
7
7
|
import {DivTag, HtmlParentTag} from "tuff-core/html"
|
|
8
|
-
import {messages} from "tuff-core"
|
|
9
8
|
import {IconName} from "../../terrier/theme"
|
|
10
9
|
import Filters, {DateRangeFilter, DirectFilter, FilterInput, InclusionFilter} from "../queries/filters"
|
|
11
10
|
import Dives from "./dives"
|
|
@@ -17,6 +16,7 @@ import Dates, {DateLiteral, DatePeriodPickerPart, DatePeriodPickerState, Literal
|
|
|
17
16
|
import dayjs from "dayjs"
|
|
18
17
|
import {ProgressBarPart} from "../../terrier/progress";
|
|
19
18
|
import {LogListPart} from "../../terrier/logging";
|
|
19
|
+
import Messages from "tuff-core/messages"
|
|
20
20
|
|
|
21
21
|
const log = new Logger("DiveRuns")
|
|
22
22
|
|
|
@@ -55,8 +55,8 @@ export class DiveRunModal extends ModalPart<{dive: DdDive }> {
|
|
|
55
55
|
progressBar!: ProgressBarPart
|
|
56
56
|
logList!: LogListPart
|
|
57
57
|
|
|
58
|
-
startKey =
|
|
59
|
-
pickDateKey =
|
|
58
|
+
startKey = Messages.untypedKey()
|
|
59
|
+
pickDateKey = Messages.typedKey<{ input_key: string }>()
|
|
60
60
|
|
|
61
61
|
async init() {
|
|
62
62
|
this.setTitle("Run Dive")
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import TerrierPart from "../../terrier/parts/terrier-part"
|
|
2
2
|
import {Logger} from "tuff-core/logging"
|
|
3
|
-
import {messages} from "tuff-core"
|
|
4
3
|
import {PartTag} from "tuff-core/parts"
|
|
5
4
|
import {DdDive, DdDiveEnumFields, UnpersistedDdDive} from "../gen/models"
|
|
6
5
|
import inflection from "inflection"
|
|
@@ -15,6 +14,7 @@ import {DbErrors} from "../../terrier/db-client"
|
|
|
15
14
|
import {TerrierFormFields} from "../../terrier/forms"
|
|
16
15
|
import DdSession from "../dd-session"
|
|
17
16
|
import Dives from "./dives";
|
|
17
|
+
import Messages from "tuff-core/messages"
|
|
18
18
|
|
|
19
19
|
const log = new Logger("DiveForm")
|
|
20
20
|
|
|
@@ -39,7 +39,7 @@ class DiveForm extends TerrierPart<{dive: DiveSettings, session: DdSession}> {
|
|
|
39
39
|
}, {attach: 'passive'})
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
static readonly settingsChangedKey =
|
|
42
|
+
static readonly settingsChangedKey = Messages.typedKey<DiveSettings>()
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
get parentClasses(): Array<string> {
|
|
@@ -109,8 +109,8 @@ export class DiveSettingsModal extends ModalPart<DiveSettingsState> {
|
|
|
109
109
|
|
|
110
110
|
settingsForm!: DiveForm
|
|
111
111
|
modelPicker!: QueryModelPicker
|
|
112
|
-
saveKey =
|
|
113
|
-
deleteKey =
|
|
112
|
+
saveKey = Messages.untypedKey()
|
|
113
|
+
deleteKey = Messages.untypedKey()
|
|
114
114
|
isNew = true
|
|
115
115
|
|
|
116
116
|
async init() {
|
|
@@ -3,12 +3,12 @@ import TerrierPart from "../../terrier/parts/terrier-part"
|
|
|
3
3
|
import {DdDiveGroup, UnpersistedDdDiveGroup} from "../gen/models"
|
|
4
4
|
import Db from "../dd-db"
|
|
5
5
|
import {PartTag} from "tuff-core/parts"
|
|
6
|
-
import {messages} from "tuff-core"
|
|
7
6
|
import {DbErrors} from "../../terrier/db-client"
|
|
8
7
|
import DdSession from "../dd-session"
|
|
9
8
|
import Nav from "tuff-core/nav"
|
|
10
9
|
import {routes} from "../dd-routes"
|
|
11
10
|
import {TerrierFormFields} from "../../terrier/forms"
|
|
11
|
+
import Messages from "tuff-core/messages"
|
|
12
12
|
|
|
13
13
|
class GroupForm extends TerrierPart<{ group: UnpersistedDdDiveGroup }> {
|
|
14
14
|
|
|
@@ -66,8 +66,8 @@ export type GroupModalState = {
|
|
|
66
66
|
export class GroupEditorModal extends ModalPart<GroupModalState> {
|
|
67
67
|
|
|
68
68
|
form!: GroupForm
|
|
69
|
-
saveKey =
|
|
70
|
-
deleteKey =
|
|
69
|
+
saveKey = Messages.untypedKey()
|
|
70
|
+
deleteKey = Messages.untypedKey()
|
|
71
71
|
|
|
72
72
|
async init() {
|
|
73
73
|
const group = this.state.group
|
|
@@ -4,12 +4,13 @@ import {TableRef, TableView} from "./tables"
|
|
|
4
4
|
import {Logger} from "tuff-core/logging"
|
|
5
5
|
import {FormFields, SelectOptions} from "tuff-core/forms"
|
|
6
6
|
import Forms from "../../terrier/forms"
|
|
7
|
-
import {arrays, messages} from "tuff-core"
|
|
8
7
|
import Objects from "tuff-core/objects"
|
|
9
8
|
import {ModalPart} from "../../terrier/modals";
|
|
10
9
|
import TerrierFormPart from "../../terrier/parts/terrier-form-part"
|
|
11
10
|
import {Dropdown} from "../../terrier/dropdowns"
|
|
12
11
|
import DiveEditor from "../dives/dive-editor"
|
|
12
|
+
import Messages from "tuff-core/messages"
|
|
13
|
+
import Arrays from "tuff-core/arrays"
|
|
13
14
|
|
|
14
15
|
const log = new Logger("Columns")
|
|
15
16
|
|
|
@@ -90,10 +91,10 @@ export type ColumnsEditorState = {
|
|
|
90
91
|
tableView: TableView<TableRef>
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
const saveKey =
|
|
94
|
-
const addKey =
|
|
95
|
-
const addSingleKey =
|
|
96
|
-
const removeKey =
|
|
94
|
+
const saveKey = Messages.untypedKey()
|
|
95
|
+
const addKey = Messages.untypedKey()
|
|
96
|
+
const addSingleKey = Messages.typedKey<{ name: string }>()
|
|
97
|
+
const removeKey = Messages.typedKey<{id: string}>()
|
|
97
98
|
|
|
98
99
|
/**
|
|
99
100
|
* A modal that lets the user edit the columns being referenced for a particular table.
|
|
@@ -235,9 +236,9 @@ export class ColumnsEditorModal extends ModalPart<ColumnsEditorState> {
|
|
|
235
236
|
}
|
|
236
237
|
|
|
237
238
|
removeColumn(id: string) {
|
|
238
|
-
const col =
|
|
239
|
+
const col = Arrays.find(this.columnStates, c => c.id == id)
|
|
239
240
|
if (col) {
|
|
240
|
-
this.columnStates =
|
|
241
|
+
this.columnStates = Arrays.without(this.columnStates, col)
|
|
241
242
|
this.updateColumnEditors()
|
|
242
243
|
}
|
|
243
244
|
}
|
|
@@ -315,9 +316,9 @@ class ColumnEditor extends TerrierFormPart<ColumnState> {
|
|
|
315
316
|
// Add Column Dropdown
|
|
316
317
|
////////////////////////////////////////////////////////////////////////////////
|
|
317
318
|
|
|
318
|
-
const checkAllKey =
|
|
319
|
-
const applySelectionKey =
|
|
320
|
-
const checkChangedKey =
|
|
319
|
+
const checkAllKey = Messages.untypedKey()
|
|
320
|
+
const applySelectionKey = Messages.untypedKey()
|
|
321
|
+
const checkChangedKey = Messages.typedKey<{column: string}>()
|
|
321
322
|
|
|
322
323
|
type SelectColumnsCallback = (columns: string[]) => any
|
|
323
324
|
|
|
@@ -2,8 +2,8 @@ import inflection from "inflection"
|
|
|
2
2
|
import dayjs from "dayjs"
|
|
3
3
|
import {Dropdown} from "../../terrier/dropdowns"
|
|
4
4
|
import {PartTag} from "tuff-core/parts"
|
|
5
|
-
import {messages} from "tuff-core"
|
|
6
5
|
import {Logger} from "tuff-core/logging"
|
|
6
|
+
import Messages from "tuff-core/messages"
|
|
7
7
|
|
|
8
8
|
const log = new Logger("Dates")
|
|
9
9
|
|
|
@@ -211,7 +211,7 @@ export type DatePeriodPickerState = {
|
|
|
211
211
|
*/
|
|
212
212
|
export class DatePeriodPickerPart extends Dropdown<DatePeriodPickerState> {
|
|
213
213
|
|
|
214
|
-
periodKey =
|
|
214
|
+
periodKey = Messages.typedKey<{period: string}>()
|
|
215
215
|
|
|
216
216
|
async init() {
|
|
217
217
|
await super.init()
|
|
@@ -2,16 +2,17 @@ import {Part, PartTag} from "tuff-core/parts"
|
|
|
2
2
|
import Dates, {DateLiteral, VirtualDatePeriod, VirtualDateRange} from "./dates"
|
|
3
3
|
import {ColumnDef, ModelDef, SchemaDef} from "../../terrier/schema"
|
|
4
4
|
import {TableRef, TableView} from "./tables"
|
|
5
|
-
import {arrays, messages} from "tuff-core"
|
|
6
5
|
import {Logger} from "tuff-core/logging"
|
|
7
6
|
import Objects from "tuff-core/objects"
|
|
8
7
|
import inflection from "inflection"
|
|
9
|
-
import {ModalPart} from "../../terrier/modals"
|
|
8
|
+
import {ModalPart} from "../../terrier/modals"
|
|
10
9
|
import TerrierFormPart from "../../terrier/parts/terrier-form-part"
|
|
11
10
|
import {Dropdown} from "../../terrier/dropdowns"
|
|
12
11
|
import dayjs from "dayjs"
|
|
13
12
|
import Format from "../../terrier/format"
|
|
14
13
|
import DiveEditor from "../dives/dive-editor"
|
|
14
|
+
import Messages from "tuff-core/messages"
|
|
15
|
+
import Arrays from "tuff-core/arrays"
|
|
15
16
|
|
|
16
17
|
const log = new Logger("Filters")
|
|
17
18
|
|
|
@@ -125,9 +126,9 @@ export type FiltersEditorState = {
|
|
|
125
126
|
tableView: TableView<TableRef>
|
|
126
127
|
}
|
|
127
128
|
|
|
128
|
-
const saveKey =
|
|
129
|
-
const addKey =
|
|
130
|
-
const removeKey =
|
|
129
|
+
const saveKey = Messages.untypedKey()
|
|
130
|
+
const addKey = Messages.untypedKey()
|
|
131
|
+
const removeKey = Messages.typedKey<{ id: string }>()
|
|
131
132
|
|
|
132
133
|
export class FiltersEditorModal extends ModalPart<FiltersEditorState> {
|
|
133
134
|
|
|
@@ -202,10 +203,10 @@ export class FiltersEditorModal extends ModalPart<FiltersEditorState> {
|
|
|
202
203
|
}
|
|
203
204
|
|
|
204
205
|
removeFilter(id: string) {
|
|
205
|
-
const filter =
|
|
206
|
+
const filter = Arrays.find(this.filterStates, f => f.id == id)
|
|
206
207
|
if (filter) {
|
|
207
208
|
log.info(`Removing filter ${id}`, filter)
|
|
208
|
-
this.filterStates =
|
|
209
|
+
this.filterStates = Arrays.without(this.filterStates, filter)
|
|
209
210
|
this.updateFilterEditors()
|
|
210
211
|
}
|
|
211
212
|
}
|
|
@@ -336,7 +337,7 @@ class FilterEditorContainer extends Part<FilterState> {
|
|
|
336
337
|
|
|
337
338
|
class DirectFilterEditor extends FilterEditor<DirectFilter> {
|
|
338
339
|
|
|
339
|
-
numericChangeKey =
|
|
340
|
+
numericChangeKey = Messages.untypedKey()
|
|
340
341
|
|
|
341
342
|
async init() {
|
|
342
343
|
await super.init()
|
|
@@ -399,7 +400,7 @@ class DirectFilterEditor extends FilterEditor<DirectFilter> {
|
|
|
399
400
|
// Inclusion Editor
|
|
400
401
|
////////////////////////////////////////////////////////////////////////////////
|
|
401
402
|
|
|
402
|
-
const inclusionChangedKey =
|
|
403
|
+
const inclusionChangedKey = Messages.typedKey<{value: string}>()
|
|
403
404
|
|
|
404
405
|
class InclusionFilterEditor extends FilterEditor<InclusionFilter> {
|
|
405
406
|
|
|
@@ -456,9 +457,9 @@ class InclusionFilterEditor extends FilterEditor<InclusionFilter> {
|
|
|
456
457
|
// Date Range Editor
|
|
457
458
|
////////////////////////////////////////////////////////////////////////////////
|
|
458
459
|
|
|
459
|
-
const dateRangeRelativeChangedKey =
|
|
460
|
-
const dateRangePeriodChangedKey =
|
|
461
|
-
const dateRangePreselectKey =
|
|
460
|
+
const dateRangeRelativeChangedKey = Messages.untypedKey()
|
|
461
|
+
const dateRangePeriodChangedKey = Messages.typedKey<{period: string}>()
|
|
462
|
+
const dateRangePreselectKey = Messages.typedKey<VirtualDateRange>()
|
|
462
463
|
|
|
463
464
|
class DateRangeFilterEditor extends FilterEditor<DateRangeFilter> {
|
|
464
465
|
|
|
@@ -550,7 +551,7 @@ class DateRangeFilterEditor extends FilterEditor<DateRangeFilter> {
|
|
|
550
551
|
|
|
551
552
|
type AddFilterCallback = (filter: Filter) => any
|
|
552
553
|
|
|
553
|
-
const columnSelectedKey =
|
|
554
|
+
const columnSelectedKey = Messages.typedKey<{column: string}>()
|
|
554
555
|
|
|
555
556
|
class AddFilterDropdown extends Dropdown<{modelDef: ModelDef, callback: AddFilterCallback}> {
|
|
556
557
|
columns!: ColumnDef[]
|
|
@@ -562,7 +563,7 @@ class AddFilterDropdown extends Dropdown<{modelDef: ModelDef, callback: AddFilte
|
|
|
562
563
|
async init() {
|
|
563
564
|
await super.init()
|
|
564
565
|
|
|
565
|
-
this.columns =
|
|
566
|
+
this.columns = Arrays.sortByFunction(Object.values(this.state.modelDef.columns), col => {
|
|
566
567
|
const visibility = col.metadata?.visibility
|
|
567
568
|
const sort = visibility == 'common' ? '0' : '1'
|
|
568
569
|
return `${sort}${col.name}`
|
|
@@ -6,9 +6,11 @@ import dayjs from "dayjs"
|
|
|
6
6
|
import QueryEditor from "./query-editor"
|
|
7
7
|
import TerrierPart from "../../terrier/parts/terrier-part"
|
|
8
8
|
import Schema, {ModelDef, SchemaDef} from "../../terrier/schema"
|
|
9
|
-
import {arrays, messages, strings} from "tuff-core"
|
|
10
9
|
import {Logger} from "tuff-core/logging"
|
|
11
|
-
import inflection from "inflection"
|
|
10
|
+
import inflection from "inflection"
|
|
11
|
+
import Messages from "tuff-core/messages"
|
|
12
|
+
import Strings from "tuff-core/strings"
|
|
13
|
+
import Arrays from "tuff-core/arrays"
|
|
12
14
|
|
|
13
15
|
const log = new Logger("Queries")
|
|
14
16
|
|
|
@@ -184,7 +186,7 @@ export type QueryModelPickerState = {
|
|
|
184
186
|
*/
|
|
185
187
|
export class QueryModelPicker extends TerrierPart<QueryModelPickerState> {
|
|
186
188
|
|
|
187
|
-
pickedKey =
|
|
189
|
+
pickedKey = Messages.typedKey<{ model: string }>()
|
|
188
190
|
model?: ModelDef
|
|
189
191
|
|
|
190
192
|
async init() {
|
|
@@ -205,7 +207,7 @@ export class QueryModelPicker extends TerrierPart<QueryModelPickerState> {
|
|
|
205
207
|
label.input({type: 'radio', name: `new-query-model-${this.id}`, value: model.name})
|
|
206
208
|
.emitChange(this.pickedKey, {model: model.name})
|
|
207
209
|
label.div(col => {
|
|
208
|
-
const name = inflection.pluralize(
|
|
210
|
+
const name = inflection.pluralize(Strings.titleize(model.name))
|
|
209
211
|
col.div('.name').text(name)
|
|
210
212
|
if (model.metadata?.description) {
|
|
211
213
|
col.div('.description').text(model.metadata.description)
|
|
@@ -228,7 +230,7 @@ export class QueryModelPicker extends TerrierPart<QueryModelPickerState> {
|
|
|
228
230
|
h3.i('.glyp-refresh')
|
|
229
231
|
h3.span().text("Common Tables")
|
|
230
232
|
})
|
|
231
|
-
for (const model of
|
|
233
|
+
for (const model of Arrays.sortBy(commonModels, 'name')) {
|
|
232
234
|
this.renderModelOption(col, model)
|
|
233
235
|
}
|
|
234
236
|
}
|
|
@@ -241,7 +243,7 @@ export class QueryModelPicker extends TerrierPart<QueryModelPickerState> {
|
|
|
241
243
|
h3.i('.glyp-pending')
|
|
242
244
|
h3.span().text("Other Tables")
|
|
243
245
|
})
|
|
244
|
-
for (const model of
|
|
246
|
+
for (const model of Arrays.sortBy(uncommonModels, 'name')) {
|
|
245
247
|
this.renderModelOption(col, model)
|
|
246
248
|
}
|
|
247
249
|
}
|
|
@@ -5,10 +5,10 @@ import {Logger} from "tuff-core/logging"
|
|
|
5
5
|
import QueryForm, {QuerySettings, QuerySettingsColumns} from "./query-form"
|
|
6
6
|
import DiveEditor, {DiveEditorState} from "../dives/dive-editor"
|
|
7
7
|
import Objects from "tuff-core/objects"
|
|
8
|
-
import {messages} from "tuff-core"
|
|
9
8
|
import Html from "tuff-core/html"
|
|
10
9
|
import ContentPart from "../../terrier/parts/content-part"
|
|
11
10
|
import {TabContainerPart} from "../../terrier/tabs"
|
|
11
|
+
import Messages from "tuff-core/messages"
|
|
12
12
|
|
|
13
13
|
const log = new Logger("QueryEditor")
|
|
14
14
|
|
|
@@ -17,7 +17,7 @@ const log = new Logger("QueryEditor")
|
|
|
17
17
|
// Keys
|
|
18
18
|
////////////////////////////////////////////////////////////////////////////////
|
|
19
19
|
|
|
20
|
-
const validationKey =
|
|
20
|
+
const validationKey = Messages.typedKey<QueryValidation>()
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -157,7 +157,7 @@ export default class QueryEditor extends ContentPart<QueryEditorState> {
|
|
|
157
157
|
sqlPart!: SqlPart
|
|
158
158
|
previewPart!: PreviewPart
|
|
159
159
|
|
|
160
|
-
updatePreviewKey =
|
|
160
|
+
updatePreviewKey = Messages.untypedKey()
|
|
161
161
|
|
|
162
162
|
async init() {
|
|
163
163
|
const query = this.state.query
|
|
@@ -231,5 +231,5 @@ export default class QueryEditor extends ContentPart<QueryEditorState> {
|
|
|
231
231
|
this.tabs.showTab('preview')
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
static readonly copyToClipboardKey =
|
|
234
|
+
static readonly copyToClipboardKey = Messages.typedKey<{ value: string }>()
|
|
235
235
|
}
|
|
@@ -2,8 +2,8 @@ import {Query} from "./queries"
|
|
|
2
2
|
import {PartTag} from "tuff-core/parts"
|
|
3
3
|
import {FormFields} from "tuff-core/forms"
|
|
4
4
|
import {Logger} from "tuff-core/logging"
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import ContentPart from "../../terrier/parts/content-part"
|
|
6
|
+
import Messages from "tuff-core/messages"
|
|
7
7
|
|
|
8
8
|
const log = new Logger("QueryForm")
|
|
9
9
|
|
|
@@ -46,6 +46,6 @@ export default class QueryForm extends ContentPart<{ query: QuerySettings }> {
|
|
|
46
46
|
})
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
static readonly settingsChangedKey =
|
|
49
|
+
static readonly settingsChangedKey = Messages.typedKey<QuerySettings>()
|
|
50
50
|
|
|
51
51
|
}
|
|
@@ -3,13 +3,14 @@ import Schema, {BelongsToDef, ModelDef, SchemaDef} from "../../terrier/schema"
|
|
|
3
3
|
import inflection from "inflection"
|
|
4
4
|
import Filters, {Filter, FilterInput, FiltersEditorModal} from "./filters"
|
|
5
5
|
import Columns, {ColumnRef, ColumnsEditorModal} from "./columns"
|
|
6
|
-
import {arrays, messages} from "tuff-core"
|
|
7
6
|
import {Logger} from "tuff-core/logging"
|
|
8
7
|
import ContentPart from "../../terrier/parts/content-part"
|
|
9
8
|
import {ActionsDropdown} from "../../terrier/dropdowns"
|
|
10
9
|
import {ModalPart} from "../../terrier/modals"
|
|
11
10
|
import TerrierFormPart from "../../terrier/parts/terrier-form-part"
|
|
12
|
-
import DiveEditor from "../dives/dive-editor"
|
|
11
|
+
import DiveEditor from "../dives/dive-editor"
|
|
12
|
+
import Messages from "tuff-core/messages"
|
|
13
|
+
import Arrays from "tuff-core/arrays"
|
|
13
14
|
|
|
14
15
|
const log = new Logger("Tables")
|
|
15
16
|
|
|
@@ -35,7 +36,7 @@ export type JoinedTableRef = TableRef & {
|
|
|
35
36
|
// Keys
|
|
36
37
|
////////////////////////////////////////////////////////////////////////////////
|
|
37
38
|
|
|
38
|
-
const updatedKey =
|
|
39
|
+
const updatedKey = Messages.typedKey<TableRef>()
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -75,11 +76,11 @@ export class TableView<T extends TableRef> extends ContentPart<{ schema: SchemaD
|
|
|
75
76
|
modelDef!: ModelDef
|
|
76
77
|
parentView?: TableView<any>
|
|
77
78
|
|
|
78
|
-
editTableKey =
|
|
79
|
-
editColumnsKey =
|
|
80
|
-
editFiltersKey =
|
|
81
|
-
newJoinedKey =
|
|
82
|
-
createJoinedKey =
|
|
79
|
+
editTableKey = Messages.untypedKey()
|
|
80
|
+
editColumnsKey = Messages.untypedKey()
|
|
81
|
+
editFiltersKey = Messages.untypedKey()
|
|
82
|
+
newJoinedKey = Messages.untypedKey()
|
|
83
|
+
createJoinedKey = Messages.typedKey<{name: string}>()
|
|
83
84
|
|
|
84
85
|
async init() {
|
|
85
86
|
this.schema = this.state.schema
|
|
@@ -111,7 +112,7 @@ export class TableView<T extends TableRef> extends ContentPart<{ schema: SchemaD
|
|
|
111
112
|
|
|
112
113
|
// show the common tables at the top
|
|
113
114
|
let showingCommon = true
|
|
114
|
-
const actions =
|
|
115
|
+
const actions = Arrays.sortByFunction(newJoins, bt => {
|
|
115
116
|
const model = this.schema.models[bt.model]
|
|
116
117
|
const common = model.metadata?.visibility == 'common' ? '0' : '1'
|
|
117
118
|
return `${common}${bt.name}`
|
|
@@ -394,7 +395,7 @@ class JoinedTableEditorForm extends TerrierFormPart<JoinedTableRef> {
|
|
|
394
395
|
class JoinedTableEditorModal extends ModalPart<JoinedTableEditorState> {
|
|
395
396
|
|
|
396
397
|
form!: JoinedTableEditorForm
|
|
397
|
-
applyKey =
|
|
398
|
+
applyKey = Messages.untypedKey()
|
|
398
399
|
|
|
399
400
|
async init() {
|
|
400
401
|
this.form = this.makePart(JoinedTableEditorForm, this.state.table)
|
package/package.json
CHANGED
package/terrier/app.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {Logger} from "tuff-core/logging"
|
|
2
2
|
import {Part, PartConstructor, PartParent} from "tuff-core/parts"
|
|
3
3
|
import TerrierPart from "./parts/terrier-part"
|
|
4
4
|
import Tooltips from "./tooltips"
|
|
@@ -6,11 +6,12 @@ import Lightbox from "./lightbox"
|
|
|
6
6
|
import Theme from "./theme"
|
|
7
7
|
import {ModalPart, ModalStackPart} from "./modals"
|
|
8
8
|
import {OverlayLayerType, OverlayPart} from "./overlays"
|
|
9
|
+
import Messages from "tuff-core/messages"
|
|
9
10
|
|
|
10
11
|
// @ts-ignore
|
|
11
12
|
import logoUrl from './images/optimized/terrier-hub-logo-light.svg'
|
|
12
|
-
import Sheets, {AlertSheetState, ConfirmSheetState, Sheet, SheetState} from "./sheets"
|
|
13
|
-
|
|
13
|
+
import Sheets, {AlertSheetState, ConfirmSheetState, Sheet, SheetState} from "./sheets"
|
|
14
|
+
|
|
14
15
|
|
|
15
16
|
const log = new Logger('App')
|
|
16
17
|
Logger.level = 'info'
|
|
@@ -103,7 +104,7 @@ export abstract class TerrierApp<TState> extends TerrierPart<TState> {
|
|
|
103
104
|
* @param callback gets called if the user hits "Confirm"
|
|
104
105
|
*/
|
|
105
106
|
confirm(options: ConfirmSheetState, callback: () => any) {
|
|
106
|
-
const key =
|
|
107
|
+
const key = Messages.untypedKey()
|
|
107
108
|
const state = {...options,
|
|
108
109
|
primaryActions: [
|
|
109
110
|
{
|
package/terrier/dropdowns.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {Logger} from "tuff-core/logging"
|
|
2
|
-
import
|
|
3
|
-
import {unique} from "tuff-core/arrays"
|
|
2
|
+
import Messages from "tuff-core/messages"
|
|
4
3
|
import {PartTag, StatelessPart} from "tuff-core/parts"
|
|
5
4
|
import Overlays from "./overlays"
|
|
6
5
|
import TerrierPart from "./parts/terrier-part"
|
|
7
6
|
import Objects from "tuff-core/objects"
|
|
8
7
|
import {Action} from "./theme"
|
|
8
|
+
import Arrays from "tuff-core/arrays"
|
|
9
9
|
|
|
10
10
|
const log = new Logger('Dropdowns')
|
|
11
11
|
|
|
12
|
-
const clearDropdownKey = untypedKey()
|
|
12
|
+
const clearDropdownKey = Messages.untypedKey()
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Abstract base class for dropdown parts.
|
|
@@ -109,7 +109,7 @@ export class ActionsDropdown extends Dropdown<Array<Action>> {
|
|
|
109
109
|
renderContent(parent: PartTag) {
|
|
110
110
|
// handle each key declared on the actions directly,
|
|
111
111
|
// then clear the dropdown and re-emit them on the parent part
|
|
112
|
-
const keys = unique(this.state.map(action => action.click?.key).filter(Objects.notNull))
|
|
112
|
+
const keys = Arrays.unique(this.state.map(action => action.click?.key).filter(Objects.notNull))
|
|
113
113
|
for (const key of keys) {
|
|
114
114
|
this.onClick(key, m => {
|
|
115
115
|
this.clear()
|
package/terrier/forms.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {Field, FormFields, FormPartData, InputType, KeyOfType, SelectOptions} from "tuff-core/forms"
|
|
2
|
-
import {logging, messages, strings} from "tuff-core"
|
|
3
2
|
import {DbErrors} from "./db-client"
|
|
4
3
|
import {PartTag} from "tuff-core/parts"
|
|
5
4
|
import {InputTag, InputTagAttrs} from "tuff-core/html"
|
|
6
5
|
import TerrierPart from "./parts/terrier-part"
|
|
7
6
|
import GlypPicker from "./parts/glyp-picker"
|
|
8
7
|
import Glyps from "./glyps"
|
|
8
|
+
import Messages from "tuff-core/messages"
|
|
9
|
+
import {Logger} from "tuff-core/logging"
|
|
10
|
+
import Strings from "tuff-core/strings"
|
|
9
11
|
|
|
10
|
-
const log = new
|
|
12
|
+
const log = new Logger("TerrierForms")
|
|
11
13
|
|
|
12
14
|
////////////////////////////////////////////////////////////////////////////////
|
|
13
15
|
// Options
|
|
@@ -19,7 +21,7 @@ const log = new logging.Logger("TerrierForms")
|
|
|
19
21
|
*/
|
|
20
22
|
function titleizeOptions(opts: string[], blank?: string): SelectOptions {
|
|
21
23
|
const out = opts.map(c => {
|
|
22
|
-
return {value: c, title:
|
|
24
|
+
return {value: c, title: Strings.titleize(c)}
|
|
23
25
|
})
|
|
24
26
|
if (blank != undefined) { // don't test length, allow it to be a blank string
|
|
25
27
|
out.unshift({title: blank, value: ''})
|
|
@@ -39,7 +41,7 @@ export class TerrierFormFields<T extends FormPartData> extends FormFields<T> {
|
|
|
39
41
|
|
|
40
42
|
errors?: DbErrors<T>
|
|
41
43
|
|
|
42
|
-
pickGlypKey =
|
|
44
|
+
pickGlypKey = Messages.typedKey<{ key: KeyOfType<T, string | undefined> & string }>()
|
|
43
45
|
|
|
44
46
|
/**
|
|
45
47
|
* You must pass a `TerrierPart` so that we can render the error bubble with it.
|
package/terrier/glyps.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// This file was automatically generated by glyps:compile on 08/19/23 9:07 AM, DO NOT MANUALLY EDIT!
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
import Strings from "tuff-core/strings"
|
|
4
5
|
|
|
5
6
|
const names = ['glyp-abacus', 'glyp-account', 'glyp-accounts_payable', 'glyp-accounts_receivable', 'glyp-action_log', 'glyp-activate', 'glyp-active', 'glyp-activity_high', 'glyp-activity_low', 'glyp-activity_medium', 'glyp-activity_none', 'glyp-address1', 'glyp-adjustment', 'glyp-admin', 'glyp-administration', 'glyp-air_freshener', 'glyp-alert', 'glyp-align_horizontal', 'glyp-align_vertical', 'glyp-anchor', 'glyp-announcement', 'glyp-app_update', 'glyp-append_selection', 'glyp-appointment', 'glyp-appointment_setup', 'glyp-archive', 'glyp-arrow_down', 'glyp-arrow_left', 'glyp-arrow_right', 'glyp-arrow_transfer', 'glyp-arrow_up', 'glyp-ascending', 'glyp-attachment', 'glyp-audit_analyzer', 'glyp-autopay', 'glyp-availability', 'glyp-background_batch', 'glyp-background_job', 'glyp-bait_for_demolition', 'glyp-bar_chart', 'glyp-barcode', 'glyp-bat_exclusion', 'glyp-bed_bug_fumigation', 'glyp-begin_service', 'glyp-belongs_to', 'glyp-billing', 'glyp-billing_office', 'glyp-billing_terms', 'glyp-billto', 'glyp-bioremediation', 'glyp-bird_exclusion', 'glyp-black_light', 'glyp-branch', 'glyp-branch_bats', 'glyp-branch_birds', 'glyp-branch_general', 'glyp-branch_irrigation', 'glyp-branch_landscape', 'glyp-branch_multi_housing', 'glyp-branch_office', 'glyp-branch_orders', 'glyp-branch_residential', 'glyp-branch_sales', 'glyp-branch_termites', 'glyp-branch_weeds', 'glyp-branch_wildlife', 'glyp-build', 'glyp-calculate', 'glyp-calendar', 'glyp-calendar_branch', 'glyp-calendar_map', 'glyp-calendar_rolling', 'glyp-calendar_share', 'glyp-calendar_snap', 'glyp-california', 'glyp-call', 'glyp-callback', 'glyp-camera', 'glyp-cancellation', 'glyp-cancelled', 'glyp-card_american_express', 'glyp-card_discover', 'glyp-card_mastercard', 'glyp-card_visa', 'glyp-catalog', 'glyp-caught', 'glyp-cert', 'glyp-check_all', 'glyp-check_in', 'glyp-check_in_service', 'glyp-checked', 'glyp-checked_empty', 'glyp-checkmark', 'glyp-checkmark_filled', 'glyp-checkout', 'glyp-chemical', 'glyp-chemical_authorization', 'glyp-chemical_backpack_sprayer', 'glyp-chemical_biological_controls', 'glyp-chemical_disinfectant', 'glyp-chemical_fertilizer', 'glyp-chemical_flying_insect_bait', 'glyp-chemical_fumigants', 'glyp-chemical_insect_aerosol', 'glyp-chemical_insect_bait', 'glyp-chemical_insect_dust', 'glyp-chemical_insect_granules', 'glyp-chemical_insect_spray', 'glyp-chemical_label', 'glyp-chemical_mole_bait', 'glyp-chemical_pest_bird_control', 'glyp-chemical_pheromone_products', 'glyp-chemical_power_sprayer', 'glyp-chemical_rodenticide_block', 'glyp-chemical_rodenticide_non_block', 'glyp-chemical_sds', 'glyp-chemical_tree_products', 'glyp-chemical_weed_control', 'glyp-chemical_wildlife_repellents', 'glyp-chemical_wildlife_toxicants', 'glyp-chevron_down', 'glyp-chevron_left', 'glyp-chevron_right', 'glyp-chevron_up', 'glyp-city', 'glyp-click', 'glyp-client_actions', 'glyp-client_pest_sightings', 'glyp-client_required', 'glyp-close', 'glyp-cloud', 'glyp-clypboard', 'glyp-clypedia', 'glyp-clypmart', 'glyp-code', 'glyp-code_details', 'glyp-collections', 'glyp-columns', 'glyp-comment', 'glyp-comment_filled', 'glyp-commission_origin', 'glyp-commissions', 'glyp-company_setup', 'glyp-compass', 'glyp-complete', 'glyp-complete_certificate', 'glyp-complete_enrollment', 'glyp-condition_appliance_machinery', 'glyp-condition_customer', 'glyp-condition_device', 'glyp-condition_door_window', 'glyp-condition_dumpster', 'glyp-condition_entry_point', 'glyp-condition_evidence', 'glyp-condition_exclusion', 'glyp-condition_exterior', 'glyp-condition_interior', 'glyp-condition_plumbing', 'glyp-condition_prep_storage', 'glyp-condition_rodent_evidence', 'glyp-condition_rodent_exclusion', 'glyp-condition_roof_ceiling', 'glyp-condition_structure', 'glyp-condition_supplies', 'glyp-condition_termites', 'glyp-condition_ventilation', 'glyp-condition_wall_floor', 'glyp-condition_wildlife', 'glyp-conditions', 'glyp-consolidate', 'glyp-construction', 'glyp-contract', 'glyp-contract_cancellation', 'glyp-contract_overview', 'glyp-conversation', 'glyp-copesan', 'glyp-copy', 'glyp-credit_memo', 'glyp-credit_non_revenue', 'glyp-credit_production', 'glyp-credit_prospect', 'glyp-credit_sales_bonus', 'glyp-crew', 'glyp-cumulative', 'glyp-cursor', 'glyp-custom_form', 'glyp-customer', 'glyp-customer_service', 'glyp-dashboard', 'glyp-data_dive', 'glyp-data_dive_query', 'glyp-data_dives', 'glyp-database', 'glyp-dead_animal_removal', 'glyp-default', 'glyp-delete', 'glyp-demo_mode', 'glyp-descending', 'glyp-design', 'glyp-desktop', 'glyp-detail_report', 'glyp-developer', 'glyp-device', 'glyp-device_sync', 'glyp-differential', 'glyp-disable', 'glyp-disabled_filled', 'glyp-distribute_horizontal', 'glyp-distribute_vertical', 'glyp-division', 'glyp-document', 'glyp-documentation', 'glyp-documents', 'glyp-download', 'glyp-driving', 'glyp-duplicate', 'glyp-duplicate_location', 'glyp-duration', 'glyp-edit', 'glyp-email', 'glyp-employment', 'glyp-entertainment_public_venues', 'glyp-equipment_bear_trap', 'glyp-equipment_flying_insect_bait_station', 'glyp-equipment_flying_insect_light_trap', 'glyp-equipment_insect_monitor', 'glyp-equipment_lethal_animal_trap', 'glyp-equipment_live_animal_trap', 'glyp-equipment_live_rodent_trap', 'glyp-equipment_maintenance', 'glyp-equipment_map_viewer', 'glyp-equipment_maps', 'glyp-equipment_mosquito_trap', 'glyp-equipment_other', 'glyp-equipment_pheromone_trap', 'glyp-equipment_pick_up', 'glyp-equipment_rodent_bait', 'glyp-equipment_rodent_trap', 'glyp-equipment_termite_bait_station', 'glyp-equipment_termite_monitor', 'glyp-exclusion', 'glyp-expand', 'glyp-expired', 'glyp-expiring', 'glyp-exterior', 'glyp-extras', 'glyp-facebook', 'glyp-farm', 'glyp-farm_grain_seed', 'glyp-fast_and_frequent', 'glyp-favorite', 'glyp-feedback', 'glyp-field_guide', 'glyp-field_training', 'glyp-file_blank', 'glyp-file_html', 'glyp-file_image', 'glyp-file_pdf', 'glyp-file_printable', 'glyp-file_spreadsheet', 'glyp-file_text', 'glyp-filter', 'glyp-finance', 'glyp-finding', 'glyp-folder', 'glyp-followup', 'glyp-food_bev_pharma', 'glyp-formula', 'glyp-fuel', 'glyp-fumigation', 'glyp-function', 'glyp-function_aggregate', 'glyp-function_time', 'glyp-gain_loss', 'glyp-generate_invoices', 'glyp-generate_orders', 'glyp-geo', 'glyp-geo_heat_map', 'glyp-google', 'glyp-google_calendar', 'glyp-government', 'glyp-grain_seed', 'glyp-grid', 'glyp-grouped', 'glyp-grouping_combine', 'glyp-grouping_separate', 'glyp-has_many', 'glyp-health_care', 'glyp-heat_map', 'glyp-heat_treatment', 'glyp-help', 'glyp-hidden', 'glyp-hint', 'glyp-honeybee_removal', 'glyp-housing', 'glyp-in_progress', 'glyp-inbox', 'glyp-incomplete_certificate', 'glyp-industrial', 'glyp-info', 'glyp-information_technology', 'glyp-inspect_map', 'glyp-inspections', 'glyp-insulation', 'glyp-interior', 'glyp-invoice', 'glyp-invoice_review', 'glyp-irrigation_install', 'glyp-irrigation_maintenance', 'glyp-items', 'glyp-job', 'glyp-join', 'glyp-join_inner', 'glyp-join_left', 'glyp-justice', 'glyp-k9_inspection', 'glyp-key', 'glyp-label_bottom', 'glyp-label_left', 'glyp-label_right', 'glyp-label_top', 'glyp-labor', 'glyp-landscape', 'glyp-landscape_maintenance', 'glyp-laptop', 'glyp-lead', 'glyp-lead_listing', 'glyp-lead_source', 'glyp-leads_report', 'glyp-learning_hub', 'glyp-ledger', 'glyp-legal', 'glyp-license', 'glyp-lifetime', 'glyp-line_cap_arrow', 'glyp-line_cap_bar', 'glyp-line_cap_circle', 'glyp-line_cap_none', 'glyp-line_caps', 'glyp-line_style', 'glyp-link', 'glyp-location', 'glyp-location_charge', 'glyp-location_credit', 'glyp-location_kind', 'glyp-location_message', 'glyp-location_origin', 'glyp-location_tags', 'glyp-locations', 'glyp-locked', 'glyp-lodging', 'glyp-log_in', 'glyp-log_out', 'glyp-log_report', 'glyp-logbook', 'glyp-logbook_documents', 'glyp-lot_number', 'glyp-manager', 'glyp-map', 'glyp-markdown', 'glyp-market', 'glyp-materials', 'glyp-mattress_encasement', 'glyp-merge', 'glyp-message_billing', 'glyp-message_collections', 'glyp-message_complaint', 'glyp-message_misc', 'glyp-message_technician', 'glyp-messages', 'glyp-misc', 'glyp-miscellaneous', 'glyp-move_order', 'glyp-mowing', 'glyp-multi_housing', 'glyp-mute', 'glyp-navicon', 'glyp-new_location', 'glyp-new_ticket', 'glyp-no_charge', 'glyp-no_service', 'glyp-note', 'glyp-note_access', 'glyp-note_billing', 'glyp-note_collection', 'glyp-note_complaint', 'glyp-note_directions', 'glyp-note_focused', 'glyp-note_office', 'glyp-note_preservice', 'glyp-note_sales', 'glyp-note_service', 'glyp-notification', 'glyp-number', 'glyp-office', 'glyp-office_government', 'glyp-office_training', 'glyp-on_demand', 'glyp-on_demand_order', 'glyp-open', 'glyp-open_invoice', 'glyp-operations', 'glyp-options', 'glyp-order_actions', 'glyp-order_approved', 'glyp-order_batch', 'glyp-order_editor', 'glyp-order_pending', 'glyp-order_series', 'glyp-order_unapproved', 'glyp-org_structure', 'glyp-org_unit', 'glyp-org_unit_settings', 'glyp-origin', 'glyp-origin_client', 'glyp-origin_tech', 'glyp-outbox', 'glyp-outlook', 'glyp-overlap', 'glyp-password', 'glyp-past_due', 'glyp-paused', 'glyp-pay_brackets', 'glyp-payment', 'glyp-payment_ach', 'glyp-payment_application_apply', 'glyp-payment_application_correction', 'glyp-payment_application_initial', 'glyp-payment_application_refund', 'glyp-payment_application_transfer', 'glyp-payment_application_unapply', 'glyp-payment_application_unapply_all', 'glyp-payment_applications', 'glyp-payment_batch', 'glyp-payment_cash', 'glyp-payment_check', 'glyp-payment_coupon', 'glyp-payment_credit', 'glyp-payment_discount', 'glyp-payment_eft', 'glyp-payment_finance_charge', 'glyp-payments', 'glyp-payroll', 'glyp-pdf', 'glyp-pending', 'glyp-periodic', 'glyp-periodic_assessment', 'glyp-permission', 'glyp-pest', 'glyp-pest_ants', 'glyp-pest_bats', 'glyp-pest_bed_bugs', 'glyp-pest_birds', 'glyp-pest_crawling_insects', 'glyp-pest_dermestids', 'glyp-pest_fall_invaders', 'glyp-pest_flying_insects', 'glyp-pest_moles', 'glyp-pest_mosquitoes', 'glyp-pest_nuisance_animals', 'glyp-pest_ornamental', 'glyp-pest_ornamental_diseases', 'glyp-pest_roaches', 'glyp-pest_rodents', 'glyp-pest_scorpions', 'glyp-pest_snakes', 'glyp-pest_spiders', 'glyp-pest_stinging_insects', 'glyp-pest_stored_product_pests', 'glyp-pest_ticks_and_fleas', 'glyp-pest_viruses_and_bacteria', 'glyp-pest_weeds', 'glyp-pest_wood_destroyers', 'glyp-phone', 'glyp-pick_date', 'glyp-pick_list', 'glyp-platform_android', 'glyp-platform_ios', 'glyp-platform_macos', 'glyp-platform_windows', 'glyp-play', 'glyp-plus', 'glyp-plus_filled', 'glyp-plus_outline', 'glyp-portal', 'glyp-price_increase', 'glyp-price_increase_alt', 'glyp-pricing_table', 'glyp-print', 'glyp-privacy', 'glyp-product_sale', 'glyp-production', 'glyp-professional_consultation', 'glyp-program', 'glyp-program_elements', 'glyp-program_initiation', 'glyp-program_order', 'glyp-program_review', 'glyp-promo', 'glyp-proposal', 'glyp-protection', 'glyp-purchase_order', 'glyp-quality', 'glyp-query', 'glyp-radio_checked', 'glyp-radio_empty', 'glyp-reassign', 'glyp-receipt', 'glyp-recent', 'glyp-recommendation', 'glyp-record_details', 'glyp-recurring_revenue', 'glyp-redo', 'glyp-refresh', 'glyp-refund', 'glyp-region', 'glyp-released', 'glyp-remove', 'glyp-renewal', 'glyp-report', 'glyp-required_input', 'glyp-reschedule', 'glyp-restaurant_bar', 'glyp-revenue', 'glyp-review', 'glyp-rfid', 'glyp-ride_along', 'glyp-rodent_exclusion', 'glyp-route_change', 'glyp-route_optimization', 'glyp-rows', 'glyp-ruler', 'glyp-sales', 'glyp-sales_contest', 'glyp-sales_pipeline', 'glyp-sales_tax', 'glyp-sales_tax_exemption', 'glyp-schedule_lock', 'glyp-schedule_lock_afternoon', 'glyp-schedule_lock_day', 'glyp-schedule_lock_exact', 'glyp-schedule_lock_four_hour', 'glyp-schedule_lock_morning', 'glyp-schedule_lock_none', 'glyp-schedule_lock_two_day', 'glyp-schedule_lock_two_hour', 'glyp-schedule_lock_week', 'glyp-schedule_tyoe_every', 'glyp-schedule_type_every', 'glyp-schedule_type_none', 'glyp-schedule_type_on_demand', 'glyp-schedule_type_schedule', 'glyp-scheduled', 'glyp-scheduling', 'glyp-school_church', 'glyp-script', 'glyp-search', 'glyp-seeding', 'glyp-segment', 'glyp-sent', 'glyp-sentricon', 'glyp-service_agreement', 'glyp-service_form', 'glyp-service_miscellaneous', 'glyp-service_reminder', 'glyp-service_report', 'glyp-service_request', 'glyp-services', 'glyp-settings', 'glyp-setup', 'glyp-signature', 'glyp-simulator', 'glyp-site_map', 'glyp-site_map_annotation', 'glyp-site_map_chemical', 'glyp-site_map_edit_details', 'glyp-site_map_edit_geo', 'glyp-site_map_equipment', 'glyp-site_map_exterior', 'glyp-site_map_foundation', 'glyp-site_map_icon', 'glyp-site_map_interior', 'glyp-site_map_label', 'glyp-site_map_perimeter', 'glyp-site_map_settings_left', 'glyp-site_map_settings_right', 'glyp-site_map_template', 'glyp-skip', 'glyp-smart_traps', 'glyp-sms', 'glyp-snow_removal', 'glyp-sort', 'glyp-special', 'glyp-split', 'glyp-spp_scorecard', 'glyp-square_edge', 'glyp-start_sheet', 'glyp-start_time', 'glyp-statement', 'glyp-states', 'glyp-sticky', 'glyp-stop_time', 'glyp-store_material', 'glyp-store_order', 'glyp-store_order_back_order', 'glyp-store_order_cancelled', 'glyp-store_order_complete', 'glyp-store_order_pending', 'glyp-store_order_pending_return', 'glyp-store_order_pre_order', 'glyp-store_order_returned', 'glyp-stores', 'glyp-styling', 'glyp-subscribe', 'glyp-supplemental', 'glyp-support', 'glyp-sync', 'glyp-table', 'glyp-tablet', 'glyp-tablets', 'glyp-tag_manager', 'glyp-tags', 'glyp-task_runs', 'glyp-tech_pest_sightings', 'glyp-technician', 'glyp-technician_approach', 'glyp-template', 'glyp-termite_fumigation', 'glyp-terrier', 'glyp-territory', 'glyp-text', 'glyp-thermometer', 'glyp-third_party_billing', 'glyp-ticket', 'glyp-ticket_type', 'glyp-tickets', 'glyp-tidy', 'glyp-time', 'glyp-time_entry', 'glyp-timeline', 'glyp-toolbox', 'glyp-tqi', 'glyp-tracker', 'glyp-tracking', 'glyp-training_course', 'glyp-treatment_split', 'glyp-trends', 'glyp-trip_charge', 'glyp-ui_type', 'glyp-unarchive', 'glyp-unchecked', 'glyp-undo', 'glyp-unfavorite', 'glyp-unit_sweep', 'glyp-unit_tag', 'glyp-university', 'glyp-unlocked', 'glyp-unmute', 'glyp-unscheduled', 'glyp-update_check_positions', 'glyp-upload', 'glyp-user', 'glyp-user_credit', 'glyp-user_tags', 'glyp-users', 'glyp-utility', 'glyp-vacation', 'glyp-vacuum', 'glyp-variant', 'glyp-vendor', 'glyp-versions', 'glyp-video', 'glyp-visible', 'glyp-warehouse', 'glyp-wdo', 'glyp-web_dusting', 'glyp-website', 'glyp-wildlife', 'glyp-wildlife_exclusion', 'glyp-winter_check', 'glyp-wizard', 'glyp-work', 'glyp-work_class', 'glyp-work_code', 'glyp-work_order', 'glyp-work_production', 'glyp-work_progress', 'glyp-work_yield', 'glyp-year', 'glyp-yield', 'glyp-zip_code', 'glyp-zone_adjacent', 'glyp-zone_check', 'glyp-zone_production', 'glyp-zone_remote', 'glyp-zoom_fit'] as const
|
|
6
7
|
|
|
@@ -9,7 +10,7 @@ const names = ['glyp-abacus', 'glyp-account', 'glyp-accounts_payable', 'glyp-acc
|
|
|
9
10
|
* @param glyp
|
|
10
11
|
*/
|
|
11
12
|
const displayName = (glyp: string): string => {
|
|
12
|
-
return
|
|
13
|
+
return Strings.titleize(glyp.replace('glyp-', ''))
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
const Glyps = {
|
package/terrier/lightbox.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {Logger} from "tuff-core/logging"
|
|
2
|
-
import
|
|
2
|
+
import Messages from "tuff-core/messages"
|
|
3
3
|
import {Part, PartTag} from "tuff-core/parts"
|
|
4
4
|
import {TerrierApp} from "./app"
|
|
5
5
|
|
|
@@ -52,7 +52,7 @@ function showPart(app: TerrierApp<any>, state: LightboxState) {
|
|
|
52
52
|
app.addOverlay(LightboxPart, state, 'lightbox')
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
const closeKey = untypedKey()
|
|
55
|
+
const closeKey = Messages.untypedKey()
|
|
56
56
|
|
|
57
57
|
class LightboxPart extends Part<LightboxState> {
|
|
58
58
|
|
package/terrier/modals.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {Logger} from "tuff-core/logging"
|
|
2
|
-
import {untypedKey} from "tuff-core/messages"
|
|
3
2
|
import TerrierPart from "./parts/terrier-part"
|
|
4
3
|
import {PartConstructor, PartTag} from "tuff-core/parts"
|
|
5
4
|
import ContentPart from "./parts/content-part"
|
|
5
|
+
import Messages from "tuff-core/messages"
|
|
6
6
|
|
|
7
7
|
const log = new Logger('Modals')
|
|
8
8
|
|
|
@@ -99,7 +99,7 @@ export abstract class ModalPart<TState> extends ContentPart<TState> {
|
|
|
99
99
|
/**
|
|
100
100
|
* Emit this key from anywhere inside a modal to pop it off the stack.
|
|
101
101
|
*/
|
|
102
|
-
export const modalPopKey = untypedKey()
|
|
102
|
+
export const modalPopKey = Messages.untypedKey()
|
|
103
103
|
|
|
104
104
|
export class ModalStackPart extends TerrierPart<{}> {
|
|
105
105
|
|
package/terrier/overlays.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {Part, PartTag, StatelessPart, NoState, PartConstructor} from "tuff-core/parts"
|
|
2
|
-
import { Size, Box, Side } from "tuff-core/
|
|
2
|
+
import { Size, Box, Side } from "tuff-core/boxes"
|
|
3
3
|
import { Logger } from "tuff-core/logging"
|
|
4
|
-
import
|
|
4
|
+
import Arrays from "tuff-core/arrays"
|
|
5
5
|
|
|
6
6
|
const log = new Logger('Overlays')
|
|
7
7
|
|
|
@@ -73,7 +73,7 @@ export class OverlayPart extends Part<NoState> {
|
|
|
73
73
|
for (let i = this.layerStates.length-1; i>=0; i--) {
|
|
74
74
|
if (this.layerStates[i].type == type) {
|
|
75
75
|
const part = oldParts[i]
|
|
76
|
-
this.layerStates =
|
|
76
|
+
this.layerStates = Arrays.without(this.layerStates, this.layerStates[i])
|
|
77
77
|
this.updateLayers()
|
|
78
78
|
return part
|
|
79
79
|
}
|
|
@@ -96,7 +96,7 @@ export class OverlayPart extends Part<NoState> {
|
|
|
96
96
|
removeLayer<StateType>(state: StateType): boolean {
|
|
97
97
|
for (const layerState of this.layerStates) {
|
|
98
98
|
if (layerState.partState == state) {
|
|
99
|
-
this.layerStates =
|
|
99
|
+
this.layerStates = Arrays.without(this.layerStates, layerState)
|
|
100
100
|
this.updateLayers()
|
|
101
101
|
return true
|
|
102
102
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {ModalPart} from "../modals"
|
|
2
2
|
import {Part, PartTag} from "tuff-core/parts"
|
|
3
|
-
import {messages, logging} from "tuff-core"
|
|
4
3
|
import Glyps from "../glyps"
|
|
4
|
+
import {Logger} from "tuff-core/logging"
|
|
5
|
+
import Messages from "tuff-core/messages"
|
|
5
6
|
|
|
6
|
-
const log = new
|
|
7
|
+
const log = new Logger("GlypPicker")
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
const pickKey =
|
|
10
|
+
const pickKey = Messages.typedKey<{ icon: string }>()
|
|
10
11
|
|
|
11
12
|
export type GlypPickerState = {
|
|
12
13
|
icon?: string
|
|
@@ -20,7 +21,7 @@ class GlypPickerModal extends ModalPart<GlypPickerState> {
|
|
|
20
21
|
|
|
21
22
|
grid!: GlypGrid
|
|
22
23
|
|
|
23
|
-
filterKey =
|
|
24
|
+
filterKey = Messages.untypedKey()
|
|
24
25
|
|
|
25
26
|
async init() {
|
|
26
27
|
await super.init()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ContentPart from "./content-part"
|
|
2
2
|
import {PartTag} from "tuff-core/parts"
|
|
3
3
|
import Fragments from "../fragments"
|
|
4
|
-
import
|
|
4
|
+
import Messages from "tuff-core/messages"
|
|
5
5
|
|
|
6
6
|
export type CollapsibleConfig = {
|
|
7
7
|
collapsed?: boolean
|
|
@@ -13,8 +13,8 @@ export type CollapsibleConfig = {
|
|
|
13
13
|
export default abstract class PanelPart<TState> extends ContentPart<TState & { collapsible?: CollapsibleConfig}> {
|
|
14
14
|
protected static readonly DEFAULT_CHEVRON_SIDE: 'left' | 'right' = 'left'
|
|
15
15
|
|
|
16
|
-
private _toggleCollapseKey = untypedKey()
|
|
17
|
-
private _transitionEndKey = untypedKey()
|
|
16
|
+
private _toggleCollapseKey = Messages.untypedKey()
|
|
17
|
+
private _transitionEndKey = Messages.untypedKey()
|
|
18
18
|
|
|
19
19
|
private _prevCollapsedState?: boolean
|
|
20
20
|
|
package/terrier/sheets.ts
CHANGED
|
@@ -2,8 +2,8 @@ import {Action, IconName} from "./theme"
|
|
|
2
2
|
import TerrierPart from "./parts/terrier-part"
|
|
3
3
|
import {PartTag} from "tuff-core/parts"
|
|
4
4
|
import Fragments from "./fragments"
|
|
5
|
-
import {messages} from "tuff-core"
|
|
6
5
|
import {Logger} from "tuff-core/logging"
|
|
6
|
+
import Messages from "tuff-core/messages"
|
|
7
7
|
|
|
8
8
|
const log = new Logger('Sheets')
|
|
9
9
|
|
|
@@ -20,7 +20,7 @@ export type SheetState = {
|
|
|
20
20
|
secondaryActions?: Action[]
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const clearKey =
|
|
23
|
+
const clearKey = Messages.untypedKey()
|
|
24
24
|
|
|
25
25
|
export class Sheet<TState extends SheetState> extends TerrierPart<TState> {
|
|
26
26
|
|
package/terrier/tabs.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {Logger} from "tuff-core/logging"
|
|
2
|
-
import
|
|
2
|
+
import Messages from "tuff-core/messages"
|
|
3
3
|
import {Part, PartParent, PartTag, StatelessPart} from "tuff-core/parts"
|
|
4
4
|
import TerrierPart from "./parts/terrier-part"
|
|
5
5
|
import {Action, IconName, Packet} from "./theme"
|
|
@@ -37,8 +37,8 @@ export type TabContainerState = {
|
|
|
37
37
|
export class TabContainerPart extends TerrierPart<TabContainerState> {
|
|
38
38
|
|
|
39
39
|
private tabs = {} as Record<string, TabDefinition>
|
|
40
|
-
changeTabKey = typedKey<{ tabKey: string }>()
|
|
41
|
-
changeSideKey = typedKey<{ side: TabSide }>()
|
|
40
|
+
changeTabKey = Messages.typedKey<{ tabKey: string }>()
|
|
41
|
+
changeSideKey = Messages.typedKey<{ side: TabSide }>()
|
|
42
42
|
|
|
43
43
|
async init() {
|
|
44
44
|
this.onClick(this.changeTabKey, m => {
|
package/terrier/theme.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {PartTag} from "tuff-core/parts"
|
|
2
|
-
import {messages} from "tuff-core"
|
|
3
2
|
import {GlypName} from "./glyps"
|
|
4
3
|
import HubIcons, {HubIconName} from "./gen/hub-icons"
|
|
4
|
+
import {Key} from "tuff-core/messages"
|
|
5
5
|
|
|
6
6
|
export interface ThemeType {
|
|
7
7
|
readonly icons: string
|
|
@@ -22,7 +22,7 @@ export type ColorName = typeof ColorNames[number]
|
|
|
22
22
|
* A combination of a message key and its associated data.
|
|
23
23
|
*/
|
|
24
24
|
export type Packet = {
|
|
25
|
-
key:
|
|
25
|
+
key: Key
|
|
26
26
|
data?: Record<string, unknown>
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -102,7 +102,7 @@ export default class Theme {
|
|
|
102
102
|
if (action.subtitle?.length) {
|
|
103
103
|
a.div('.subtitle', {text: action.subtitle})
|
|
104
104
|
}
|
|
105
|
-
|
|
105
|
+
if (!(action.title?.length || action.subtitle?.length)) {
|
|
106
106
|
a.class('icon-only')
|
|
107
107
|
}
|
|
108
108
|
if (action.href?.length) {
|