@things-factory/dataset 7.0.0-alpha.5 → 7.0.0-alpha.6

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.
Files changed (58) hide show
  1. package/client/pages/data-entry/data-entry-list-page.ts +8 -23
  2. package/client/pages/data-ooc/data-ooc-list-page.ts +26 -11
  3. package/client/pages/data-ooc/{data-ooc-view-page.ts → data-ooc-page.ts} +1 -1
  4. package/client/pages/data-ooc/data-ooc-view.ts +53 -35
  5. package/client/pages/data-ooc/data-oocs-page.ts +132 -0
  6. package/client/pages/data-sample/data-sample-list-page.ts +25 -20
  7. package/client/pages/data-sample/{data-sample-view-page.ts → data-sample-page.ts} +1 -1
  8. package/client/pages/data-sample/data-sample-search-page.ts +25 -20
  9. package/client/pages/data-sample/data-sample-view.ts +60 -12
  10. package/client/pages/data-sample/data-samples-page.ts +121 -0
  11. package/client/route.ts +10 -2
  12. package/dist-client/pages/data-entry/data-entry-list-page.js +3 -15
  13. package/dist-client/pages/data-entry/data-entry-list-page.js.map +1 -1
  14. package/dist-client/pages/data-ooc/data-ooc-list-page.d.ts +6 -0
  15. package/dist-client/pages/data-ooc/data-ooc-list-page.js +17 -3
  16. package/dist-client/pages/data-ooc/data-ooc-list-page.js.map +1 -1
  17. package/dist-client/pages/data-ooc/{data-ooc-view-page.js → data-ooc-page.js} +2 -2
  18. package/dist-client/pages/data-ooc/data-ooc-page.js.map +1 -0
  19. package/dist-client/pages/data-ooc/data-ooc-view.d.ts +5 -1
  20. package/dist-client/pages/data-ooc/data-ooc-view.js +50 -38
  21. package/dist-client/pages/data-ooc/data-ooc-view.js.map +1 -1
  22. package/dist-client/pages/data-ooc/data-oocs-page.d.ts +17 -0
  23. package/dist-client/pages/data-ooc/data-oocs-page.js +132 -0
  24. package/dist-client/pages/data-ooc/data-oocs-page.js.map +1 -0
  25. package/dist-client/pages/data-sample/data-sample-list-page.d.ts +6 -1
  26. package/dist-client/pages/data-sample/data-sample-list-page.js +19 -13
  27. package/dist-client/pages/data-sample/data-sample-list-page.js.map +1 -1
  28. package/dist-client/pages/data-sample/{data-sample-view-page.js → data-sample-page.js} +2 -2
  29. package/dist-client/pages/data-sample/data-sample-page.js.map +1 -0
  30. package/dist-client/pages/data-sample/data-sample-search-page.d.ts +6 -1
  31. package/dist-client/pages/data-sample/data-sample-search-page.js +19 -13
  32. package/dist-client/pages/data-sample/data-sample-search-page.js.map +1 -1
  33. package/dist-client/pages/data-sample/data-sample-view.js +55 -11
  34. package/dist-client/pages/data-sample/data-sample-view.js.map +1 -1
  35. package/dist-client/pages/data-sample/data-samples-page.d.ts +19 -0
  36. package/dist-client/pages/data-sample/data-samples-page.js +120 -0
  37. package/dist-client/pages/data-sample/data-samples-page.js.map +1 -0
  38. package/dist-client/route.js +8 -2
  39. package/dist-client/route.js.map +1 -1
  40. package/dist-client/tsconfig.tsbuildinfo +1 -1
  41. package/dist-server/service/data-ooc/data-ooc.js +33 -15
  42. package/dist-server/service/data-ooc/data-ooc.js.map +1 -1
  43. package/dist-server/service/data-sample/data-sample.js +15 -12
  44. package/dist-server/service/data-sample/data-sample.js.map +1 -1
  45. package/dist-server/tsconfig.tsbuildinfo +1 -1
  46. package/package.json +14 -11
  47. package/server/service/data-ooc/data-ooc.ts +27 -28
  48. package/server/service/data-sample/data-sample.ts +14 -32
  49. package/things-factory.config.js +10 -2
  50. package/translations/en.json +1 -0
  51. package/translations/ja.json +1 -0
  52. package/translations/ko.json +1 -0
  53. package/translations/ms.json +1 -0
  54. package/translations/zh.json +1 -0
  55. package/dist-client/pages/data-ooc/data-ooc-view-page.js.map +0 -1
  56. package/dist-client/pages/data-sample/data-sample-view-page.js.map +0 -1
  57. /package/dist-client/pages/data-ooc/{data-ooc-view-page.d.ts → data-ooc-page.d.ts} +0 -0
  58. /package/dist-client/pages/data-sample/{data-sample-view-page.d.ts → data-sample-page.d.ts} +0 -0
@@ -46,23 +46,12 @@ const showEntryView = async (columns, data, column, record, rowIndex) => {
46
46
  const board = {
47
47
  id: entryView
48
48
  }
49
- openPopup(
50
- html`
51
- <ox-board-viewer
52
- style="background-color: white;"
53
- .board=${board}
54
- .provider=${provider}
55
- hide-fullscreen
56
- hide-navigation
57
- ></ox-board-viewer>
58
- `,
59
- {
60
- closable: true,
61
- backdrop: true,
62
- size: 'large',
63
- title
64
- }
65
- )
49
+ openPopup(html` <ox-board-viewer style="background-color: white;" .board=${board} .provider=${provider} hide-fullscreen hide-navigation></ox-board-viewer> `, {
50
+ closable: true,
51
+ backdrop: true,
52
+ size: 'large',
53
+ title
54
+ })
66
55
 
67
56
  // navigate(`board-viewer/${entryView}?interactive=true&title=${title}`)
68
57
  break
@@ -129,12 +118,7 @@ export class DataEntryListPage extends connect(store)(localize(i18next)(PageView
129
118
  const mode = 'CARD'
130
119
 
131
120
  return html`
132
- <ox-grist
133
- .mode=${mode}
134
- .config=${this.gristConfig}
135
- .fetchHandler=${this.fetchHandler.bind(this)}
136
- ?url-params-sensitive=${this.active}
137
- >
121
+ <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)} ?url-params-sensitive=${this.active}>
138
122
  <div slot="headroom" class="header">
139
123
  <div class="title">
140
124
  <mwc-icon>summarize</mwc-icon>
@@ -300,6 +284,7 @@ export class DataEntryListPage extends connect(store)(localize(i18next)(PageView
300
284
  ],
301
285
  rows: {
302
286
  appendable: false,
287
+ editable: false,
303
288
  selectable: {
304
289
  multiple: false
305
290
  },
@@ -1,6 +1,7 @@
1
1
  import '@operato/data-grist'
2
2
  import '@operato/context/ox-context-page-toolbar.js'
3
3
  import '@operato/input/ox-input-select-buttons.js'
4
+
4
5
  import './data-ooc-view.js'
5
6
 
6
7
  import gql from 'graphql-tag'
@@ -8,6 +9,8 @@ import { css, html } from 'lit'
8
9
  import { customElement, property, query, state } from 'lit/decorators.js'
9
10
  import { connect } from 'pwa-helpers/connect-mixin'
10
11
 
12
+ import { GhostPrint } from '@operato/ghost-print'
13
+
11
14
  function getOocStatus() {
12
15
  return [
13
16
  {
@@ -74,6 +77,13 @@ export class DataOocListPage extends connect(store)(localize(i18next)(PageView))
74
77
  }
75
78
  },
76
79
  help: 'dataset/data-ooc',
80
+ actions: [
81
+ {
82
+ title: i18next.t('button.print'),
83
+ action: this.printOocs.bind(this),
84
+ icon: 'print'
85
+ }
86
+ ],
77
87
  exportable: {
78
88
  name: i18next.t('title.data-ooc list'),
79
89
  data: this._exportableData.bind(this)
@@ -126,14 +136,11 @@ export class DataOocListPage extends connect(store)(localize(i18next)(PageView))
126
136
  title: i18next.t('title.view detail ooc data'),
127
137
  handlers: {
128
138
  click: (columns, data, column, record, rowIndex) => {
129
- const popup = openPopup(
130
- html` <data-ooc-view .dataOoc=${record} style="background-color: white;"></data-ooc-view> `,
131
- {
132
- backdrop: true,
133
- size: 'large',
134
- title: i18next.t('title.data-ooc view')
135
- }
136
- )
139
+ const popup = openPopup(html` <data-ooc-view .dataOoc=${record} style="background-color: white;"></data-ooc-view> `, {
140
+ backdrop: true,
141
+ size: 'large',
142
+ title: i18next.t('title.data-ooc view')
143
+ })
137
144
  popup.onclosed = () => {
138
145
  this.grist.fetch()
139
146
  }
@@ -479,9 +486,7 @@ export class DataOocListPage extends connect(store)(localize(i18next)(PageView))
479
486
  .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
480
487
  .reduce((record, column) => {
481
488
  const key = column.imex === true ? column.name : column.imex.key
482
- record[key] = key
483
- .split('.')
484
- .reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
489
+ record[key] = key.split('.').reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
485
490
  return record
486
491
  }, {})
487
492
  }
@@ -489,4 +494,14 @@ export class DataOocListPage extends connect(store)(localize(i18next)(PageView))
489
494
 
490
495
  return { header: headerSetting, data: data }
491
496
  }
497
+
498
+ printOocs() {
499
+ const selected = this.grist.selected
500
+ const ids = selected.map(record => record.id).join('|')
501
+
502
+ GhostPrint.print({
503
+ src: `./data-oocs?ids=${ids}`
504
+ // pending: 200 * selected.length
505
+ })
506
+ }
492
507
  }
@@ -8,7 +8,7 @@ import { client } from '@operato/graphql'
8
8
 
9
9
  import './data-ooc-view.js'
10
10
 
11
- @customElement('data-ooc-view-page')
11
+ @customElement('data-ooc-page')
12
12
  export class DataOocViewPage extends localize(i18next)(PageView) {
13
13
  static styles = [
14
14
  css`
@@ -1,10 +1,12 @@
1
1
  import '@operato/dataset/ox-data-ooc-brief-view.js'
2
+ import '@material/mwc-fab'
2
3
 
3
4
  import { css, html, LitElement } from 'lit'
4
5
  import { customElement, property, query } from 'lit/decorators.js'
5
6
 
6
7
  import { i18next, localize } from '@operato/i18n'
7
8
  import { ScrollbarStyles } from '@operato/styles'
9
+ import { GhostPrint } from '@operato/ghost-print'
8
10
 
9
11
  @customElement('data-ooc-view')
10
12
  export class DataOocView extends localize(i18next)(LitElement) {
@@ -14,65 +16,81 @@ export class DataOocView extends localize(i18next)(LitElement) {
14
16
  :host {
15
17
  display: flex;
16
18
  flex-direction: column;
19
+ position: relative;
17
20
 
18
21
  background-color: #fff;
19
22
  }
20
23
 
21
- div[content] {
22
- flex: 1;
23
-
24
- display: flex;
25
- overflow: auto;
26
- }
27
-
28
24
  ox-data-ooc-brief-view {
29
25
  flex: 1;
30
26
  padding: var(--padding-wide);
31
27
  overflow: auto;
32
28
  }
33
29
 
34
- label[comment] {
35
- display: flex;
36
- flex-direction: column;
37
-
38
- padding: var(--padding-wide);
30
+ mwc-fab {
31
+ position: absolute;
32
+ bottom: 15px;
33
+ right: 16px;
34
+ text-decoration: auto;
35
+ opacity: 0.5;
39
36
  }
40
37
 
41
- label[comment] div {
42
- display: flex;
43
- }
38
+ @media print {
39
+ :host {
40
+ display: block;
41
+ }
44
42
 
45
- mwc-icon {
46
- color: var(--status-danger-color);
47
- }
43
+ ox-data-ooc-brief-view {
44
+ flex: unset;
45
+ overflow: visible;
46
+ }
48
47
 
49
- textarea {
50
- border: var(--input-field-border);
51
- border-radius: var(--input-border-radius);
52
- padding: var(--input-field-padding);
53
- font: var(--input-field-font);
54
- }
55
-
56
- .button-container {
57
- display: flex;
58
- margin-left: auto;
59
- padding: var(--padding-default);
48
+ mwc-fab {
49
+ display: none;
50
+ }
60
51
  }
61
52
  `
62
53
  ]
63
54
 
64
55
  @property({ type: Object }) dataOoc?: any
65
56
 
66
- @query('textarea') commentTextArea!: HTMLTextAreaElement
67
57
  @query('ox-data-ooc-brief-view') sampleView!: HTMLTextAreaElement
68
58
 
69
- render() {
70
- const state = this.dataOoc?.state
59
+ private printHandler = this.handlePrint.bind(this)
71
60
 
61
+ render() {
72
62
  return html`
73
- <div content>
74
- <ox-data-ooc-brief-view .dataOoc=${this.dataOoc}></ox-data-ooc-brief-view>
75
- </div>
63
+ <ox-data-ooc-brief-view .dataOoc=${this.dataOoc}></ox-data-ooc-brief-view>
64
+
65
+ <mwc-fab
66
+ icon="print"
67
+ title="print"
68
+ @click=${() =>
69
+ GhostPrint.print({
70
+ src: `./data-ooc/${this.dataOoc.id}`
71
+ })}
72
+ >print</mwc-fab
73
+ >
76
74
  `
77
75
  }
76
+
77
+ handlePrint(event) {
78
+ if ((event.ctrlKey || event.metaKey) && event.key === 'p') {
79
+ event.preventDefault()
80
+
81
+ GhostPrint.print({
82
+ src: `./data-ooc/${this.dataOoc.id}`
83
+ })
84
+ }
85
+ }
86
+
87
+ connectedCallback(): void {
88
+ super.connectedCallback()
89
+ window.addEventListener('keydown', this.printHandler)
90
+ }
91
+
92
+ disconnectedCallback(): void {
93
+ super.disconnectedCallback()
94
+ window.removeEventListener('keydown', this.printHandler)
95
+ }
78
96
  }
@@ -0,0 +1,132 @@
1
+ import '@operato/dataset/ox-data-ooc-brief-view.js'
2
+
3
+ import gql from 'graphql-tag'
4
+ import { PropertyValues, html, css } from 'lit'
5
+ import { customElement, state } from 'lit/decorators.js'
6
+ import { PageView } from '@operato/shell'
7
+ import { i18next, localize } from '@operato/i18n'
8
+ import { client } from '@operato/graphql'
9
+
10
+ /**
11
+ * 이 페이지는 여러개의 Data OOC를 한번에 프린트하기 위한 용도로 사용되는 페이지이다.
12
+ */
13
+ @customElement('data-oocs-page')
14
+ export class DataOocsPage extends localize(i18next)(PageView) {
15
+ static styles = [
16
+ css`
17
+ :host {
18
+ display: block;
19
+ overflow: auto;
20
+ }
21
+
22
+ ox-data-ooc-brief-view {
23
+ page-break-after: always;
24
+ break-after: always;
25
+ }
26
+ `
27
+ ]
28
+
29
+ @state() dataOocs?: any[]
30
+
31
+ get context() {
32
+ return {
33
+ title: i18next.t('title.data-ooc view')
34
+ }
35
+ }
36
+
37
+ render() {
38
+ return this.dataOocs?.map(dataOoc => html` <ox-data-ooc-brief-view .dataOoc=${dataOoc}></ox-data-ooc-brief-view> `)
39
+ }
40
+
41
+ pageUpdated(changes: any, lifecycle: any, before: any) {
42
+ if (this.active) {
43
+ /*
44
+ * this page is activated
45
+ */
46
+ const { ids = '' } = lifecycle.params
47
+
48
+ this.fetchOocs(ids.split('|').map(id => id.trim()))
49
+ } else {
50
+ /* this page is deactivated */
51
+ }
52
+ }
53
+
54
+ async fetchOocs(ids: string[]) {
55
+ const filters = [
56
+ {
57
+ name: 'id',
58
+ operator: 'in',
59
+ value: ids
60
+ }
61
+ ]
62
+
63
+ const response = await client.query({
64
+ query: gql`
65
+ query ($filters: [Filter!]) {
66
+ dataOocs(filters: $filters) {
67
+ items {
68
+ id
69
+ name
70
+ description
71
+ useCase
72
+ dataSet {
73
+ id
74
+ name
75
+ }
76
+ key01
77
+ key02
78
+ key03
79
+ key04
80
+ key05
81
+ partitionKeys
82
+ dataItems {
83
+ name
84
+ description
85
+ active
86
+ tag
87
+ group
88
+ type
89
+ unit
90
+ options
91
+ quota
92
+ spec
93
+ }
94
+ data
95
+ rawData
96
+ judgment
97
+ ooc
98
+ oos
99
+ state
100
+ history
101
+ workDate
102
+ workShift
103
+ correctiveInstruction
104
+ correctiveAction
105
+ reviewedAt
106
+ reviewer {
107
+ id
108
+ name
109
+ }
110
+ correctedAt
111
+ corrector {
112
+ id
113
+ name
114
+ }
115
+ updater {
116
+ id
117
+ name
118
+ }
119
+ updatedAt
120
+ collectedAt
121
+ }
122
+ }
123
+ }
124
+ `,
125
+ variables: {
126
+ filters
127
+ }
128
+ })
129
+
130
+ this.dataOocs = response.data.dataOocs.items
131
+ }
132
+ }
@@ -15,6 +15,7 @@ import { openPopup } from '@operato/layout'
15
15
  import { PageView, store } from '@operato/shell'
16
16
  import { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles'
17
17
  import { isMobileDevice } from '@operato/utils'
18
+ import { GhostPrint } from '@operato/ghost-print'
18
19
 
19
20
  @customElement('data-sample-list-page')
20
21
  export class DataSampleListPage extends connect(store)(localize(i18next)(PageView)) {
@@ -56,7 +57,13 @@ export class DataSampleListPage extends connect(store)(localize(i18next)(PageVie
56
57
  }
57
58
  },
58
59
  help: 'dataset/data-sample',
59
- actions: [],
60
+ actions: [
61
+ {
62
+ title: i18next.t('button.print'),
63
+ action: this.printSamples.bind(this),
64
+ icon: 'print'
65
+ }
66
+ ],
60
67
  exportable: {
61
68
  name: i18next.t('title.data-sample list'),
62
69
  data: this._exportableData.bind(this)
@@ -69,12 +76,7 @@ export class DataSampleListPage extends connect(store)(localize(i18next)(PageVie
69
76
  const mode = this.mode || (isMobileDevice() ? 'LIST' : 'GRID')
70
77
 
71
78
  return html`
72
- <ox-grist
73
- .mode=${mode}
74
- .config=${this.gristConfig}
75
- .fetchHandler=${this.fetchHandler.bind(this)}
76
- ?url-params-sensitive=${false /* this.active */}
77
- >
79
+ <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)} ?url-params-sensitive=${false /* this.active */}>
78
80
  <div slot="headroom" class="header">
79
81
  <div class="title">
80
82
  <mwc-icon>summarize</mwc-icon>
@@ -108,16 +110,11 @@ export class DataSampleListPage extends connect(store)(localize(i18next)(PageVie
108
110
  title: i18next.t('title.open data sample view'),
109
111
  handlers: {
110
112
  click: (columns, data, column, record, rowIndex) => {
111
- openPopup(
112
- html`
113
- <data-sample-view data-sample-id=${record.id} style="background-color: white;"></data-sample-view>
114
- `,
115
- {
116
- backdrop: true,
117
- size: 'large',
118
- title: i18next.t('title.data-sample view')
119
- }
120
- )
113
+ openPopup(html` <data-sample-view data-sample-id=${record.id} style="background-color: white;"></data-sample-view> `, {
114
+ backdrop: true,
115
+ size: 'large',
116
+ title: i18next.t('title.data-sample view')
117
+ })
121
118
  }
122
119
  }
123
120
  },
@@ -387,9 +384,7 @@ export class DataSampleListPage extends connect(store)(localize(i18next)(PageVie
387
384
  .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
388
385
  .reduce((record, column) => {
389
386
  const key = column.imex === true ? column.name : column.imex.key
390
- record[key] = key
391
- .split('.')
392
- .reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
387
+ record[key] = key.split('.').reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
393
388
  return record
394
389
  }, {})
395
390
  }
@@ -397,4 +392,14 @@ export class DataSampleListPage extends connect(store)(localize(i18next)(PageVie
397
392
 
398
393
  return { header: headerSetting, data: data }
399
394
  }
395
+
396
+ printSamples() {
397
+ const selected = this.grist.selected
398
+ const ids = selected.map(record => record.id).join('|')
399
+
400
+ GhostPrint.print({
401
+ src: `./data-samples?ids=${ids}`
402
+ // pending: 200 * selected.length
403
+ })
404
+ }
400
405
  }
@@ -5,7 +5,7 @@ import { i18next, localize } from '@operato/i18n'
5
5
 
6
6
  import './data-sample-view.js'
7
7
 
8
- @customElement('data-sample-view-page')
8
+ @customElement('data-sample-page')
9
9
  export class DataSampleViewPage extends localize(i18next)(PageView) {
10
10
  static styles = [
11
11
  css`
@@ -15,6 +15,7 @@ import { openPopup } from '@operato/layout'
15
15
  import { PageView, store } from '@operato/shell'
16
16
  import { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles'
17
17
  import { isMobileDevice } from '@operato/utils'
18
+ import { GhostPrint } from '@operato/ghost-print'
18
19
 
19
20
  @customElement('data-sample-search-page')
20
21
  export class DataSampleSearchPage extends connect(store)(localize(i18next)(PageView)) {
@@ -60,7 +61,13 @@ export class DataSampleSearchPage extends connect(store)(localize(i18next)(PageV
60
61
  }
61
62
  },
62
63
  help: 'dataset/data-sample-search',
63
- actions: [],
64
+ actions: [
65
+ {
66
+ title: i18next.t('button.print'),
67
+ action: this.printSamples.bind(this),
68
+ icon: 'print'
69
+ }
70
+ ],
64
71
  exportable: {
65
72
  name: i18next.t('title.data-sample search'),
66
73
  data: this._exportableData.bind(this)
@@ -170,16 +177,11 @@ export class DataSampleSearchPage extends connect(store)(localize(i18next)(PageV
170
177
  title: i18next.t('title.open data sample view'),
171
178
  handlers: {
172
179
  click: (columns, data, column, record, rowIndex) => {
173
- openPopup(
174
- html`
175
- <data-sample-view data-sample-id=${record.id} style="background-color: white;"></data-sample-view>
176
- `,
177
- {
178
- backdrop: true,
179
- size: 'large',
180
- title: i18next.t('title.data-sample view')
181
- }
182
- )
180
+ openPopup(html` <data-sample-view data-sample-id=${record.id} style="background-color: white;"></data-sample-view> `, {
181
+ backdrop: true,
182
+ size: 'large',
183
+ title: i18next.t('title.data-sample view')
184
+ })
183
185
  }
184
186
  }
185
187
  },
@@ -319,12 +321,7 @@ export class DataSampleSearchPage extends connect(store)(localize(i18next)(PageV
319
321
  const response = await client.query({
320
322
  query: gql`
321
323
  query ($dataSetId: String!, $filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
322
- responses: dataSamplesByDataSet(
323
- dataSetId: $dataSetId
324
- filters: $filters
325
- pagination: $pagination
326
- sortings: $sortings
327
- ) {
324
+ responses: dataSamplesByDataSet(dataSetId: $dataSetId, filters: $filters, pagination: $pagination, sortings: $sortings) {
328
325
  items {
329
326
  id
330
327
  name
@@ -394,9 +391,7 @@ export class DataSampleSearchPage extends connect(store)(localize(i18next)(PageV
394
391
  .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
395
392
  .reduce((record, column) => {
396
393
  const key = column.imex === true ? column.name : column.imex.key
397
- record[key] = key
398
- .split('.')
399
- .reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
394
+ record[key] = key.split('.').reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
400
395
  return record
401
396
  }, {})
402
397
  }
@@ -404,4 +399,14 @@ export class DataSampleSearchPage extends connect(store)(localize(i18next)(PageV
404
399
 
405
400
  return { header: headerSetting, data: data }
406
401
  }
402
+
403
+ printSamples() {
404
+ const selected = this.grist.selected
405
+ const ids = selected.map(record => record.id).join('|')
406
+
407
+ GhostPrint.print({
408
+ src: `./data-samples?ids=${ids}`,
409
+ pending: 300 * selected.length
410
+ })
411
+ }
407
412
  }
@@ -1,13 +1,14 @@
1
1
  import '@operato/dataset/ox-data-sample-view.js'
2
2
 
3
3
  import gql from 'graphql-tag'
4
- import { css, html, LitElement } from 'lit'
5
- import { customElement, property, query, state } from 'lit/decorators.js'
4
+ import { css, html, LitElement, nothing } from 'lit'
5
+ import { customElement, property, state } from 'lit/decorators.js'
6
6
 
7
7
  import { client } from '@operato/graphql'
8
8
  import { i18next, localize } from '@operato/i18n'
9
9
  import { ScrollbarStyles } from '@operato/styles'
10
10
  import { DataSample } from '@operato/dataset'
11
+ import { GhostPrint } from '@operato/ghost-print'
11
12
 
12
13
  @customElement('data-sample-view')
13
14
  class DataSampleView extends localize(i18next)(LitElement) {
@@ -21,18 +22,34 @@ class DataSampleView extends localize(i18next)(LitElement) {
21
22
  background-color: #fff;
22
23
  }
23
24
 
24
- div[content] {
25
- flex: 1;
26
-
27
- display: flex;
28
- overflow: auto;
29
- }
30
-
31
25
  ox-data-sample-view {
32
26
  flex: 1;
33
27
  padding: var(--padding-wide);
34
28
  overflow: auto;
35
29
  }
30
+
31
+ mwc-fab {
32
+ position: absolute;
33
+ bottom: 15px;
34
+ right: 16px;
35
+ text-decoration: auto;
36
+ opacity: 0.5;
37
+ }
38
+
39
+ @media print {
40
+ :host {
41
+ display: block;
42
+ }
43
+
44
+ ox-data-sample-view {
45
+ flex: unset;
46
+ overflow: visible;
47
+ }
48
+
49
+ mwc-fab {
50
+ display: none;
51
+ }
52
+ }
36
53
  `
37
54
  ]
38
55
 
@@ -41,13 +58,24 @@ class DataSampleView extends localize(i18next)(LitElement) {
41
58
  attribute: 'data-sample-id'
42
59
  })
43
60
  dataSampleId?: string
61
+
44
62
  @state() dataSample?: DataSample
45
63
 
64
+ private printHandler = this.handlePrint.bind(this)
65
+
46
66
  render() {
47
67
  return html`
48
- <div content>
49
- ${this.dataSample ? html`<ox-data-sample-view .dataSample=${this.dataSample}></ox-data-sample-view>` : html``}
50
- </div>
68
+ ${this.dataSample ? html`<ox-data-sample-view .dataSample=${this.dataSample}></ox-data-sample-view>` : nothing}
69
+
70
+ <mwc-fab
71
+ icon="print"
72
+ title="print"
73
+ @click=${() =>
74
+ GhostPrint.print({
75
+ src: `./data-sample/${this.dataSampleId}`
76
+ })}
77
+ >print</mwc-fab
78
+ >
51
79
  `
52
80
  }
53
81
 
@@ -114,4 +142,24 @@ class DataSampleView extends localize(i18next)(LitElement) {
114
142
 
115
143
  this.dataSample = response.data.dataSample
116
144
  }
145
+
146
+ handlePrint(event) {
147
+ if ((event.ctrlKey || event.metaKey) && event.key === 'p') {
148
+ event.preventDefault()
149
+
150
+ GhostPrint.print({
151
+ src: `./data-sample/${this.dataSampleId}`
152
+ })
153
+ }
154
+ }
155
+
156
+ connectedCallback(): void {
157
+ super.connectedCallback()
158
+ window.addEventListener('keydown', this.printHandler)
159
+ }
160
+
161
+ disconnectedCallback(): void {
162
+ super.disconnectedCallback()
163
+ window.removeEventListener('keydown', this.printHandler)
164
+ }
117
165
  }