terrier-engine 4.7.5 → 4.7.7

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.
@@ -12,6 +12,8 @@ import {DiveSettingsModal} from "./dive-settings"
12
12
  import DdSession from "../dd-session"
13
13
  import Messages from "tuff-core/messages"
14
14
  import Arrays from "tuff-core/arrays"
15
+ import TerrierPart from "../../terrier/parts/terrier-part"
16
+ import {DiveRunModal} from "./dive-runs"
15
17
 
16
18
  const log = new Logger("DiveList")
17
19
 
@@ -20,43 +22,32 @@ const log = new Logger("DiveList")
20
22
  // List
21
23
  ////////////////////////////////////////////////////////////////////////////////
22
24
 
23
- export class DiveListPage extends PagePart<{}> {
25
+ export type DiveListState = {
26
+ mode: 'editor' | 'readonly' // whether or not to allow editing or simply viewing dives
27
+ }
24
28
 
25
- newGroupKey = Messages.untypedKey()
26
- editGroupKey = Messages.typedKey<{id: string}>()
27
- newDiveKey = Messages.typedKey<{group_id: string}>()
28
- editDiveKey = Messages.typedKey<{id: string}>()
29
+ /**
30
+ * Show a list of all dive groups and dives that match the given state.
31
+ */
32
+ export class DiveListPart extends TerrierPart<DiveListState> {
33
+
34
+ editGroupKey = Messages.typedKey<{ id: string }>()
35
+ newDiveKey = Messages.typedKey<{ group_id: string }>()
36
+ editDiveKey = Messages.typedKey<{ id: string }>()
37
+ runDiveKey = Messages.typedKey<{ id: string }>()
29
38
 
30
39
  session!: DdSession
31
40
  result!: DiveListResult
32
41
  schema!: SchemaDef
33
42
  groupMap: Record<string, DdDiveGroup> = {}
34
- diveMap: Record<string,DdDive> = {}
43
+ diveMap: Record<string, DdDive> = {}
44
+
35
45
 
36
46
  async init() {
37
- this.setTitle("Data Dive")
38
- this.setIcon('glyp-data_dives')
39
47
 
40
48
  this.schema = await Schema.get()
41
49
  this.session = await DdSession.get()
42
50
 
43
- this.mainContentWidth = 'wide'
44
-
45
- this.addAction({
46
- title: "New Group",
47
- icon: 'glyp-plus_outline',
48
- click: {key: this.newGroupKey}
49
- }, 'tertiary')
50
-
51
- this.onClick(this.newGroupKey, _ => {
52
- log.info("Showing new dive group model")
53
- const newGroup = {name: '', group_types: []}
54
- this.app.showModal(GroupEditorModal, {session: this.session,
55
- group: newGroup,
56
- callback: _ => this.reload()
57
- })
58
- })
59
-
60
51
  this.onClick(this.editGroupKey, m => {
61
52
  log.info(`Edit group ${m.data.id}`)
62
53
  const group = this.groupMap[m.data.id]
@@ -66,8 +57,7 @@ export class DiveListPage extends PagePart<{}> {
66
57
  group: group as UnpersistedDdDiveGroup,
67
58
  callback: _ => this.reload()
68
59
  })
69
- }
70
- else {
60
+ } else {
71
61
  this.alertToast(`No group with id ${m.data.id}`)
72
62
  }
73
63
  })
@@ -91,13 +81,22 @@ export class DiveListPage extends PagePart<{}> {
91
81
  if (dive) {
92
82
  log.info(`Editing settings for dive: ${dive.name}`)
93
83
  this.app.showModal(DiveSettingsModal, {schema: this.schema, dive, session: this.session})
84
+ } else {
85
+ log.warn(`No dive with id ${m.data.id}`)
94
86
  }
95
- else {
87
+ })
88
+
89
+ this.onClick(this.runDiveKey, m => {
90
+ const dive = this.diveMap[m.data.id] as DdDive
91
+ if (dive) {
92
+ log.info(`Running dive ${dive.name}`)
93
+ this.app.showModal(DiveRunModal, {dive})
94
+ } else {
96
95
  log.warn(`No dive with id ${m.data.id}`)
97
96
  }
98
97
  })
99
98
 
100
- await this.reload()
99
+ this.reload().then()
101
100
  }
102
101
 
103
102
  async reload() {
@@ -109,7 +108,7 @@ export class DiveListPage extends PagePart<{}> {
109
108
  this.dirty()
110
109
  }
111
110
 
112
- renderContent(parent: PartTag): void {
111
+ render(parent: PartTag): any {
113
112
 
114
113
  const groupedDives = Arrays.groupBy(this.result.dives, 'dd_dive_group_id')
115
114
 
@@ -122,7 +121,7 @@ export class DiveListPage extends PagePart<{}> {
122
121
  }
123
122
 
124
123
  renderGroupPanel(parent: PartTag, group: DdDiveGroup, dives: DdDive[]) {
125
- Fragments.panel(this.theme)
124
+ const panel = Fragments.panel(this.theme)
126
125
  .title(group.name)
127
126
  .icon((group.icon || 'glyp-data_dives') as IconName)
128
127
  .classes('group')
@@ -132,36 +131,99 @@ export class DiveListPage extends PagePart<{}> {
132
131
  this.renderDiveRow(content, dive)
133
132
  }
134
133
  })
135
- .addAction({
134
+ if (this.state.mode == 'editor') {
135
+ panel.addAction({
136
136
  title: "New Dive",
137
137
  icon: 'glyp-data_dive',
138
138
  click: {key: this.newDiveKey, data: {group_id: group.id}}
139
139
  }, 'secondary')
140
- .addAction({
140
+ panel.addAction({
141
141
  icon: 'glyp-settings',
142
142
  click: {key: this.editGroupKey, data: {id: group.id}}
143
143
  }, 'tertiary')
144
- .render(parent)
144
+ }
145
+ panel.render(parent)
145
146
  }
146
147
 
147
148
  renderDiveRow(parent: PartTag, dive: DdDive) {
148
149
  parent.div('.dive', row => {
149
- row.a({href: routes.editor.path({id: dive.id})}, a => {
150
- if (dive.visibility == 'private') {
151
- a.i('.glyp-privacy')
152
- .data({tooltip: "Private Dive"})
153
- }
154
- else {
155
- a.i('.glyp-data_dive')
156
- }
157
- a.span().text(dive.name)
158
- }).data({tooltip: "Open Editor"})
159
- row.a('.icon-only', a => {
160
- a.i('.glyp-settings')
161
- }).data({tooltip: "Dive Settings"})
162
- .emitClick(this.editDiveKey, {id: dive.id})
150
+ if (this.state.mode == 'editor') {
151
+ row.a({href: routes.editor.path({id: dive.id})}, a => {
152
+ if (dive.visibility == 'private') {
153
+ a.i('.glyp-privacy')
154
+ .data({tooltip: "Private Dive"})
155
+ } else {
156
+ a.i('.glyp-data_dive')
157
+ .data({tooltip: "Public Dive"})
158
+ }
159
+ a.span().text(dive.name)
160
+ }).data({tooltip: "Open Editor"})
161
+ row.a('.icon-only', a => {
162
+ a.i('.glyp-settings')
163
+ }).data({tooltip: "Dive Settings"})
164
+ .emitClick(this.editDiveKey, {id: dive.id})
165
+ }
166
+ else {
167
+ // readonly mode
168
+ row.a(a => {
169
+ if (dive.visibility == 'private') {
170
+ a.i('.glyp-privacy')
171
+ .data({tooltip: "Private Dive"})
172
+ } else {
173
+ a.i('.glyp-data_dive')
174
+ .data({tooltip: "Public Dive"})
175
+ }
176
+ a.span().text(dive.name)
177
+ })
178
+ .data({tooltip: "Run Dive"})
179
+ .emitClick(this.runDiveKey, {id: dive.id})
180
+ }
163
181
  })
164
182
  }
165
183
 
166
184
  }
167
185
 
186
+
187
+ ////////////////////////////////////////////////////////////////////////////////
188
+ // Page
189
+ ////////////////////////////////////////////////////////////////////////////////
190
+
191
+ export class DiveListPage extends PagePart<{}> {
192
+
193
+ listPart!: DiveListPart
194
+ newGroupKey = Messages.untypedKey()
195
+
196
+ async init() {
197
+ this.setTitle("Data Dive")
198
+ this.setIcon('glyp-data_dives')
199
+ this.mainContentWidth = 'wide'
200
+
201
+ this.listPart = this.makePart(DiveListPart, {mode: 'editor'})
202
+
203
+ this.addAction({
204
+ title: "New Group",
205
+ icon: 'glyp-plus_outline',
206
+ click: {key: this.newGroupKey}
207
+ }, 'tertiary')
208
+
209
+ // we're handling this here instead of in the list part because, as of 9/15/23,
210
+ // attach: 'passive' doesn't seem to work for click handlers,
211
+ // so this handler never got called when it was inside the list part
212
+ this.onClick(this.newGroupKey, _ => {
213
+ log.info("Showing new dive group model")
214
+ const newGroup = {name: '', group_types: []}
215
+ this.app.showModal(GroupEditorModal, {
216
+ session: this.listPart.session,
217
+ group: newGroup,
218
+ callback: _ => this.listPart.reload()
219
+ })
220
+ })
221
+ }
222
+
223
+ renderContent(parent: PartTag): void {
224
+ parent.part(this.listPart)
225
+ }
226
+
227
+
228
+ }
229
+
@@ -120,9 +120,18 @@ class PreviewPart extends ContentPart<SubEditorState> {
120
120
 
121
121
  renderContent(parent: PartTag) {
122
122
  if (this.result) {
123
- parent.div('.table-container', col => {
124
- Queries.renderPreview(col, this.result!)
125
- })
123
+ if (this.result.columns?.length) {
124
+ parent.div('.table-container', col => {
125
+ Queries.renderPreview(col, this.result!)
126
+ })
127
+ }
128
+ else {
129
+ // empty query
130
+ parent.div('.dd-hint-container', hintContainer => {
131
+ hintContainer.div('.dd-hint.centered.glyp-columns')
132
+ .text("Select at least one column")
133
+ })
134
+ }
126
135
  }
127
136
  else {
128
137
  parent.a('.tt-button.stretch', a => {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "files": [
5
5
  "*"
6
6
  ],
7
- "version": "4.7.5",
7
+ "version": "4.7.7",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Terrier-Tech/terrier-engine"
@@ -90,11 +90,11 @@ export class PanelFragment extends ContentFragment {
90
90
  return parent.div(this.prefix, panel => {
91
91
  if (this._title?.length) {
92
92
  panel.div(`.${noTtPrefix}-header`, header => {
93
- header.h2(h2 => {
93
+ header.h3(h3 => {
94
94
  if (this._icon) {
95
- this.theme.renderIcon(h2, this._icon, 'link')
95
+ this.theme.renderIcon(h3, this._icon, 'link')
96
96
  }
97
- h2.div('.title', {text: this._title})
97
+ h3.div('.title', {text: this._title})
98
98
  })
99
99
  this.theme.renderActions(header, this.actions.tertiary)
100
100
  })