@things-factory/reference-app 4.0.2 → 4.0.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.
- package/attachments/56a09233-daa3-4e11-90c6-a5f4861e433c.pdf +0 -0
- package/client/bootstrap.js +30 -0
- package/client/components/camera-capturer.js +29 -2
- package/client/components/ocr-viewpart.js +94 -0
- package/client/menu.js +1 -1
- package/client/pages/context-menu-page.js +91 -69
- package/client/pages/grist-mode-page.js +15 -15
- package/client/pages/label-scan-page.js +189 -0
- package/client/pages/ocr-page.js +4 -3
- package/client/route.js +4 -0
- package/config/config.development.js +5 -1
- package/db.sqlite +0 -0
- package/dist-server/service/reference/lambda-call.js +68 -0
- package/dist-server/service/reference/lambda-call.js.map +1 -0
- package/dist-server/service/reference/reference-query.js +26 -4
- package/dist-server/service/reference/reference-query.js.map +1 -1
- package/logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json +3 -8
- package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +3 -18
- package/logs/application-2021-09-30-15.log +14 -0
- package/logs/{connections-2021-11-02-11.log → connections-2021-09-30-15.log} +0 -0
- package/package.json +44 -43
- package/server/service/reference/lambda-call.ts +69 -0
- package/server/service/reference/reference-query.ts +35 -7
- package/things-factory.config.js +4 -0
- package/translations/en.json +3 -2
- package/translations/ko.json +3 -2
- package/translations/ms.json +3 -2
- package/translations/zh.json +3 -2
- package/views/auth-page.html +0 -1
- package/attachments/69808491-8e6b-45e2-9bf8-dccea1c5b52e.png +0 -0
- package/attachments/7927fe8e-2246-453d-9869-7072b983437c.png +0 -0
- package/attachments/7d150574-01b8-4439-96a0-d57299f3ffcf.png +0 -0
- package/attachments/a1cf142c-f3c2-442c-b8d5-a7f9cc6a59b3.png +0 -0
- package/attachments/cb3ac834-ece0-4802-bef0-dfdc0fcd93bd.png +0 -0
- package/logs/application-2021-11-04-14.log +0 -4
- package/logs/application-2021-11-05-18.log +0 -6
- package/logs/connections-2021-11-03-11.log +0 -0
- package/logs/connections-2021-11-04-14.log +0 -0
- package/logs/connections-2021-11-05-18.log +0 -0
|
Binary file
|
package/client/bootstrap.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import '@things-factory/auth-ui' /* for domain-switch */
|
|
2
2
|
import '@things-factory/barcode-base' /* for <default-label-printer-setting-let> */
|
|
3
3
|
import '@things-factory/notification' /* for notification-badge */
|
|
4
|
+
import './components/ocr-viewpart'
|
|
4
5
|
|
|
5
6
|
import { TOOL_POSITION, VIEWPART_POSITION, appendViewpart, toggleOverlay } from '@things-factory/layout-base'
|
|
6
7
|
import { getEditor, registerEditor, registerRenderer } from '@operato/data-grist'
|
|
@@ -134,6 +135,24 @@ export default function bootstrap() {
|
|
|
134
135
|
})
|
|
135
136
|
|
|
136
137
|
/* setting app-tools */
|
|
138
|
+
store.dispatch({
|
|
139
|
+
type: APPEND_APP_TOOL,
|
|
140
|
+
tool: {
|
|
141
|
+
name: 'ocr-toggler',
|
|
142
|
+
template: html`
|
|
143
|
+
<mwc-icon
|
|
144
|
+
@click=${e => {
|
|
145
|
+
toggleOverlay('ocr-viewpart', {
|
|
146
|
+
backdrop: false
|
|
147
|
+
})
|
|
148
|
+
}}
|
|
149
|
+
>camera_enhance
|
|
150
|
+
</mwc-icon>
|
|
151
|
+
`,
|
|
152
|
+
position: TOOL_POSITION.REAR
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
|
|
137
156
|
store.dispatch({
|
|
138
157
|
type: APPEND_APP_TOOL,
|
|
139
158
|
tool: {
|
|
@@ -162,6 +181,17 @@ export default function bootstrap() {
|
|
|
162
181
|
position: VIEWPART_POSITION.HEADERBAR
|
|
163
182
|
})
|
|
164
183
|
|
|
184
|
+
appendViewpart({
|
|
185
|
+
name: 'ocr-viewpart',
|
|
186
|
+
viewpart: {
|
|
187
|
+
show: false,
|
|
188
|
+
hovering: false,
|
|
189
|
+
resizable: true,
|
|
190
|
+
template: html` <ocr-viewpart style="min-width: 300px; height: 100%; width: 50vw;"></ocr-viewpart> `
|
|
191
|
+
},
|
|
192
|
+
position: VIEWPART_POSITION.ASIDEBAR
|
|
193
|
+
})
|
|
194
|
+
|
|
165
195
|
appendViewpart({
|
|
166
196
|
name: 'notification',
|
|
167
197
|
viewpart: {
|
|
@@ -119,8 +119,16 @@ export class CameraCapturer extends LitElement {
|
|
|
119
119
|
- ${file.name}
|
|
120
120
|
<mwc-icon
|
|
121
121
|
@click=${e => {
|
|
122
|
-
this._files.splice(this._files.indexOf(file), 1)
|
|
123
|
-
this.
|
|
122
|
+
this._files = [...this._files.splice(this._files.indexOf(file), 1)]
|
|
123
|
+
this.dispatchEvent(
|
|
124
|
+
new CustomEvent('files-change', {
|
|
125
|
+
bubbles: true,
|
|
126
|
+
composed: true,
|
|
127
|
+
detail: {
|
|
128
|
+
files: this._files
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
)
|
|
124
132
|
}}
|
|
125
133
|
>delete_outline</mwc-icon
|
|
126
134
|
>
|
|
@@ -137,6 +145,15 @@ export class CameraCapturer extends LitElement {
|
|
|
137
145
|
|
|
138
146
|
this.addEventListener('file-drop', e => {
|
|
139
147
|
this._files = this.multiple ? e.detail : e.detail[0] ? [e.detail[0]] : []
|
|
148
|
+
this.dispatchEvent(
|
|
149
|
+
new CustomEvent('files-change', {
|
|
150
|
+
bubbles: true,
|
|
151
|
+
composed: true,
|
|
152
|
+
detail: {
|
|
153
|
+
files: this._files
|
|
154
|
+
}
|
|
155
|
+
})
|
|
156
|
+
)
|
|
140
157
|
})
|
|
141
158
|
}
|
|
142
159
|
|
|
@@ -151,6 +168,16 @@ export class CameraCapturer extends LitElement {
|
|
|
151
168
|
reset() {
|
|
152
169
|
this.fileInput.value = ''
|
|
153
170
|
this._files = []
|
|
171
|
+
|
|
172
|
+
this.dispatchEvent(
|
|
173
|
+
new CustomEvent('files-change', {
|
|
174
|
+
bubbles: true,
|
|
175
|
+
composed: true,
|
|
176
|
+
detail: {
|
|
177
|
+
files: this._files
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
)
|
|
154
181
|
}
|
|
155
182
|
}
|
|
156
183
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import './camera-capturer'
|
|
2
|
+
import '@material/mwc-button'
|
|
3
|
+
import '@operato/ocr'
|
|
4
|
+
|
|
5
|
+
import { gql } from 'graphql-tag'
|
|
6
|
+
import { css, html, LitElement } from 'lit-element'
|
|
7
|
+
|
|
8
|
+
import { client } from '@things-factory/shell'
|
|
9
|
+
|
|
10
|
+
var FILES = []
|
|
11
|
+
var RESULT = []
|
|
12
|
+
|
|
13
|
+
class OCRViewPart extends LitElement {
|
|
14
|
+
static get styles() {
|
|
15
|
+
return [
|
|
16
|
+
css`
|
|
17
|
+
:host {
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
min-width: 240px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
ox-ocr-helper {
|
|
24
|
+
flex: 1;
|
|
25
|
+
}
|
|
26
|
+
`
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static get properties() {
|
|
31
|
+
return {
|
|
32
|
+
_result: Array,
|
|
33
|
+
_files: Array
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
connectedCallback() {
|
|
38
|
+
super.connectedCallback()
|
|
39
|
+
|
|
40
|
+
this._files = FILES
|
|
41
|
+
this._result = RESULT
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
render() {
|
|
45
|
+
const files = this._files || []
|
|
46
|
+
const index = this.index || 0
|
|
47
|
+
const file = files[index]
|
|
48
|
+
const image = file && URL.createObjectURL(file)
|
|
49
|
+
if (image) {
|
|
50
|
+
requestAnimationFrame(() => URL.revokeObjectURL(image))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return html`
|
|
54
|
+
<ox-ocr-helper @attached=${this.upload.bind(this)} .files=${this._files} .result=${this._result}> </ox-ocr-helper>
|
|
55
|
+
`
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async upload(e) {
|
|
59
|
+
FILES = this._files = e.detail
|
|
60
|
+
|
|
61
|
+
const response = await client.query({
|
|
62
|
+
query: gql`
|
|
63
|
+
query ocrRequest($images: [Upload!]!) {
|
|
64
|
+
ocrRequest(images: $images)
|
|
65
|
+
}
|
|
66
|
+
`,
|
|
67
|
+
variables: {
|
|
68
|
+
images: this._files
|
|
69
|
+
},
|
|
70
|
+
context: { hasUpload: true }
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
if (!response.errors) {
|
|
74
|
+
const helper = this.shadowRoot.querySelector('ox-ocr-helper')
|
|
75
|
+
RESULT = helper.result = response.data.ocrRequest.map(result => {
|
|
76
|
+
return {
|
|
77
|
+
...result,
|
|
78
|
+
boundaries: JSON.parse(result.boundaries)
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
} else {
|
|
82
|
+
document.dispatchEvent(
|
|
83
|
+
new CustomEvent('notify', {
|
|
84
|
+
detail: {
|
|
85
|
+
level: 'error',
|
|
86
|
+
message: response.errors
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
customElements.define('ocr-viewpart', OCRViewPart)
|
package/client/menu.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import '@material/mwc-icon'
|
|
2
|
-
import '@operato/
|
|
2
|
+
import '@operato/popup'
|
|
3
3
|
|
|
4
4
|
import { css, html } from 'lit-element'
|
|
5
5
|
import { connect } from 'pwa-helpers/connect-mixin.js'
|
|
6
6
|
|
|
7
|
+
import { PopupMenu } from '@operato/popup'
|
|
7
8
|
import { PageView, store } from '@things-factory/shell'
|
|
8
9
|
|
|
9
10
|
import { referencePageStyles } from './reference-page-styles'
|
|
@@ -39,93 +40,114 @@ class ContextMenuPage extends connect(store)(PageView) {
|
|
|
39
40
|
페이지내에 엘리먼트를 위치시키고 open method로 활성화 시키는 방법을 예시합니다. 데스크톱 브라우저 페이지 내 어느
|
|
40
41
|
위치에서든 마우스 우측버튼을 클릭하고, 모바일 디바이스에서는 탭을 오래누르면(longpress) 팝업메뉴가 동작합니다.
|
|
41
42
|
</p>
|
|
43
|
+
`
|
|
44
|
+
}
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
label="click me to toggle"
|
|
56
|
-
@click=${function (e) {
|
|
57
|
-
const target = e.currentTarget
|
|
58
|
-
const icon = target.querySelector('mwc-icon')
|
|
59
|
-
icon.innerHTML = icon.innerHTML == 'check' ? '' : 'check'
|
|
60
|
-
}}
|
|
61
|
-
>
|
|
62
|
-
<mwc-icon slot="icon" style="width: 20px;height: 20px;"></mwc-icon>
|
|
63
|
-
</popup-menuitem>
|
|
64
|
-
|
|
65
|
-
<popup-menuitem label="verified">
|
|
66
|
-
<mwc-icon slot="icon">verified</mwc-icon>
|
|
67
|
-
<popup-menu>
|
|
68
|
-
<popup-menuitem label="article">
|
|
46
|
+
firstUpdated() {
|
|
47
|
+
this.addEventListener('contextmenu', e => {
|
|
48
|
+
e.preventDefault()
|
|
49
|
+
|
|
50
|
+
PopupMenu.open({
|
|
51
|
+
template: html`
|
|
52
|
+
<ox-popup-menuitem
|
|
53
|
+
label="article - click me"
|
|
54
|
+
@selected=${function (e) {
|
|
55
|
+
console.log('first level article selected')
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
69
58
|
<mwc-icon slot="icon">article</mwc-icon>
|
|
70
|
-
</popup-menuitem>
|
|
59
|
+
</ox-popup-menuitem>
|
|
71
60
|
|
|
72
|
-
<popup-menuitem label="home">
|
|
61
|
+
<ox-popup-menuitem label="home">
|
|
73
62
|
<mwc-icon slot="icon">home</mwc-icon>
|
|
74
|
-
</popup-menuitem>
|
|
75
|
-
|
|
76
|
-
<popup-menuitem label="
|
|
63
|
+
</ox-popup-menuitem>
|
|
64
|
+
|
|
65
|
+
<ox-popup-menuitem label="empty"> </ox-popup-menuitem>
|
|
66
|
+
|
|
67
|
+
<ox-popup-menuitem
|
|
68
|
+
label="click me to toggle"
|
|
69
|
+
@selected=${function (e) {
|
|
70
|
+
const icon = this.querySelector('mwc-icon')
|
|
71
|
+
icon.innerHTML = icon.innerHTML == 'check' ? '' : 'check'
|
|
72
|
+
}}
|
|
73
|
+
alive-on-select
|
|
74
|
+
>
|
|
75
|
+
<mwc-icon slot="icon" style="width: 20px;height: 20px;"></mwc-icon>
|
|
76
|
+
</ox-popup-menuitem>
|
|
77
|
+
|
|
78
|
+
<ox-popup-menuitem label="verified" @selected=${e => console.log('selected verified')}>
|
|
77
79
|
<mwc-icon slot="icon">verified</mwc-icon>
|
|
78
|
-
<popup-menu>
|
|
79
|
-
<popup-menuitem
|
|
80
|
+
<ox-popup-menu>
|
|
81
|
+
<ox-popup-menuitem
|
|
82
|
+
label="article"
|
|
83
|
+
@selected=${function (e) {
|
|
84
|
+
console.log('article selected')
|
|
85
|
+
}}
|
|
86
|
+
alive-on-select
|
|
87
|
+
>
|
|
80
88
|
<mwc-icon slot="icon">article</mwc-icon>
|
|
81
|
-
</popup-menuitem>
|
|
89
|
+
</ox-popup-menuitem>
|
|
82
90
|
|
|
83
|
-
<popup-menuitem label="home">
|
|
91
|
+
<ox-popup-menuitem label="home">
|
|
84
92
|
<mwc-icon slot="icon">home</mwc-icon>
|
|
85
|
-
</popup-menuitem>
|
|
93
|
+
</ox-popup-menuitem>
|
|
86
94
|
|
|
87
|
-
<popup-menuitem label="verified">
|
|
95
|
+
<ox-popup-menuitem label="verified">
|
|
88
96
|
<mwc-icon slot="icon">verified</mwc-icon>
|
|
89
|
-
|
|
97
|
+
<ox-popup-menu>
|
|
98
|
+
<ox-popup-menuitem label="article">
|
|
99
|
+
<mwc-icon slot="icon">article</mwc-icon>
|
|
100
|
+
</ox-popup-menuitem>
|
|
90
101
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<div separator></div>
|
|
96
|
-
</popup-menu>
|
|
97
|
-
</popup-menuitem>
|
|
102
|
+
<ox-popup-menuitem label="home">
|
|
103
|
+
<mwc-icon slot="icon">home</mwc-icon>
|
|
104
|
+
</ox-popup-menuitem>
|
|
98
105
|
|
|
99
|
-
|
|
106
|
+
<ox-popup-menuitem label="verified">
|
|
107
|
+
<mwc-icon slot="icon">verified</mwc-icon>
|
|
108
|
+
</ox-popup-menuitem>
|
|
100
109
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
</popup-menu>
|
|
105
|
-
</popup-menuitem>
|
|
110
|
+
<ox-popup-menuitem label="checkbox">
|
|
111
|
+
<input type="checkbox" slot="icon" />
|
|
112
|
+
</ox-popup-menuitem>
|
|
106
113
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
114
|
+
<div separator></div>
|
|
115
|
+
</ox-popup-menu>
|
|
116
|
+
</ox-popup-menuitem>
|
|
110
117
|
|
|
111
|
-
|
|
118
|
+
<div separator></div>
|
|
112
119
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
120
|
+
<ox-popup-menuitem label="checkbox">
|
|
121
|
+
<input type="checkbox" slot="icon" />
|
|
122
|
+
</ox-popup-menuitem>
|
|
123
|
+
</ox-popup-menu>
|
|
124
|
+
</ox-popup-menuitem>
|
|
119
125
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
<ox-popup-menuitem label="checkbox in icon area" alive-on-select>
|
|
127
|
+
<input type="checkbox" slot="icon" />
|
|
128
|
+
</ox-popup-menuitem>
|
|
123
129
|
|
|
124
|
-
|
|
125
|
-
e.preventDefault()
|
|
130
|
+
<div separator></div>
|
|
126
131
|
|
|
127
|
-
|
|
128
|
-
|
|
132
|
+
<div menu>Plain Text</div>
|
|
133
|
+
|
|
134
|
+
<div menu alive-on-select>
|
|
135
|
+
<ox-checkbox label="checkbox" slot="icon" checked />checkbox</ox-checkbox>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<div menu alive-on-select>
|
|
139
|
+
<input id="checkbox-01" type="checkbox" />
|
|
140
|
+
<label for="checkbox-01">custom menu</label>
|
|
141
|
+
</div>
|
|
142
|
+
<div menu alive-on-select>
|
|
143
|
+
<label for="text-01">value</label>
|
|
144
|
+
<input id="text-01" type="text" value="Plain text input" />
|
|
145
|
+
</div>
|
|
146
|
+
`,
|
|
147
|
+
top: e.offsetY,
|
|
148
|
+
left: e.offsetX,
|
|
149
|
+
parent: this.renderRoot
|
|
150
|
+
})
|
|
129
151
|
})
|
|
130
152
|
}
|
|
131
153
|
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import '@operato/
|
|
1
|
+
import '@operato/popup'
|
|
2
2
|
import '@operato/data-grist'
|
|
3
3
|
|
|
4
4
|
import { css, html } from 'lit-element'
|
|
5
|
-
import { getEditor, getRenderer } from '@operato/data-grist'
|
|
6
|
-
import { i18next, localize } from '@things-factory/i18n-base'
|
|
7
5
|
|
|
6
|
+
import { i18next, localize } from '@things-factory/i18n-base'
|
|
8
7
|
import { PageView } from '@things-factory/shell'
|
|
9
|
-
import { isMobileDevice } from '@things-factory/utils'
|
|
10
8
|
|
|
11
9
|
class GristModePage extends localize(i18next)(PageView) {
|
|
12
10
|
static get styles() {
|
|
@@ -113,7 +111,7 @@ class GristModePage extends localize(i18next)(PageView) {
|
|
|
113
111
|
<mwc-icon
|
|
114
112
|
@click=${e => {
|
|
115
113
|
const target = e.currentTarget
|
|
116
|
-
this.renderRoot.querySelector('popup-
|
|
114
|
+
this.renderRoot.querySelector('ox-popup-list').open({
|
|
117
115
|
left: target.offsetLeft,
|
|
118
116
|
top: target.offsetTop + target.offsetHeight
|
|
119
117
|
})
|
|
@@ -123,7 +121,7 @@ class GristModePage extends localize(i18next)(PageView) {
|
|
|
123
121
|
<mwc-icon
|
|
124
122
|
@click=${e => {
|
|
125
123
|
const target = e.currentTarget
|
|
126
|
-
this.renderRoot.querySelector('popup-
|
|
124
|
+
this.renderRoot.querySelector('ox-popup-list').open({
|
|
127
125
|
left: target.offsetLeft,
|
|
128
126
|
top: target.offsetTop + target.offsetHeight
|
|
129
127
|
})
|
|
@@ -133,7 +131,7 @@ class GristModePage extends localize(i18next)(PageView) {
|
|
|
133
131
|
<mwc-icon
|
|
134
132
|
@click=${e => {
|
|
135
133
|
const target = e.currentTarget
|
|
136
|
-
this.renderRoot.querySelector('popup-
|
|
134
|
+
this.renderRoot.querySelector('ox-popup-list').open({
|
|
137
135
|
left: target.offsetLeft,
|
|
138
136
|
top: target.offsetTop + target.offsetHeight
|
|
139
137
|
})
|
|
@@ -141,26 +139,28 @@ class GristModePage extends localize(i18next)(PageView) {
|
|
|
141
139
|
>sort</mwc-icon
|
|
142
140
|
>
|
|
143
141
|
|
|
144
|
-
<popup-
|
|
145
|
-
<
|
|
146
|
-
|
|
142
|
+
<ox-popup-list alive-on-select>
|
|
143
|
+
<div
|
|
144
|
+
option
|
|
147
145
|
@click=${function (e) {
|
|
148
146
|
const icon = e.currentTarget.querySelector('mwc-icon')
|
|
149
147
|
icon.innerHTML = icon.innerHTML == 'check' ? '' : 'check'
|
|
150
148
|
}}
|
|
151
149
|
>
|
|
152
150
|
<mwc-icon slot="icon" style="width: 20px;height: 20px;"></mwc-icon>
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
<span>click me to toggle</span>
|
|
152
|
+
</div>
|
|
153
|
+
<div
|
|
154
|
+
option
|
|
156
155
|
@click=${function (e) {
|
|
157
156
|
const icon = e.currentTarget.querySelector('mwc-icon')
|
|
158
157
|
icon.innerHTML = icon.innerHTML == 'check' ? '' : 'check'
|
|
159
158
|
}}
|
|
160
159
|
>
|
|
161
160
|
<mwc-icon slot="icon" style="width: 20px;height: 20px;"></mwc-icon>
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
<span>click me to toggle</span>
|
|
162
|
+
</div>
|
|
163
|
+
</ox-popup-list>
|
|
164
164
|
</div>
|
|
165
165
|
</div>
|
|
166
166
|
</ox-grist>
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import '@things-factory/barcode-ui'
|
|
2
|
+
|
|
3
|
+
import { css, html } from 'lit-element'
|
|
4
|
+
import { connect } from 'pwa-helpers/connect-mixin.js'
|
|
5
|
+
|
|
6
|
+
import { PageView, store } from '@things-factory/shell'
|
|
7
|
+
|
|
8
|
+
import { referencePageStyles } from './reference-page-styles'
|
|
9
|
+
|
|
10
|
+
class LabelScanPage extends connect(store)(PageView) {
|
|
11
|
+
static get styles() {
|
|
12
|
+
return [
|
|
13
|
+
referencePageStyles,
|
|
14
|
+
css`
|
|
15
|
+
:host {
|
|
16
|
+
display: block;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
div {
|
|
20
|
+
overflow-wrap: anywhere;
|
|
21
|
+
}
|
|
22
|
+
`
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static get properties() {
|
|
27
|
+
return {
|
|
28
|
+
bcid: String,
|
|
29
|
+
value: String,
|
|
30
|
+
bcWidth: Number,
|
|
31
|
+
bcHeight: Number,
|
|
32
|
+
bcScale: Number,
|
|
33
|
+
padding: Number
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get context() {
|
|
38
|
+
return {
|
|
39
|
+
title: 'Barcode Scan Input and Tag Component'
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
render() {
|
|
44
|
+
const bcid = this.bcid || 'code128'
|
|
45
|
+
const value = this.value || '213439240572'
|
|
46
|
+
const bcWidth = this.bcWidth || 30
|
|
47
|
+
const bcHeight = this.bcHeight || 30
|
|
48
|
+
const bcScale = this.bcScale || 3
|
|
49
|
+
const padding = this.padding || 5
|
|
50
|
+
|
|
51
|
+
return html`
|
|
52
|
+
<section>
|
|
53
|
+
<h2>Barcode Scanable Input</h2>
|
|
54
|
+
<p>
|
|
55
|
+
barcode-scanable-input 컴포넌트는 카메라 입력을 통해서 바코드를 스캔하고, 스캔한 결과를 입력 필드에 적용한다.
|
|
56
|
+
</p>
|
|
57
|
+
<barcode-scanable-input
|
|
58
|
+
name="barcode-input"
|
|
59
|
+
custom-input
|
|
60
|
+
@keypress=${e => {
|
|
61
|
+
if (e.keyCode === 13) {
|
|
62
|
+
e.preventDefault()
|
|
63
|
+
this.value = e.target.shadowRoot.querySelector('input').value
|
|
64
|
+
console.log('input completed.', e.target.value)
|
|
65
|
+
}
|
|
66
|
+
}}
|
|
67
|
+
></barcode-scanable-input>
|
|
68
|
+
</section>
|
|
69
|
+
|
|
70
|
+
<section>
|
|
71
|
+
<h2>Input Field with Barcode Image</h2>
|
|
72
|
+
<p>barcode-input 컴포넌트는 입력필드에 입력된 결과를 바코드 이미지로도 보여준다.</p>
|
|
73
|
+
|
|
74
|
+
<label>bacode type</label>
|
|
75
|
+
<select
|
|
76
|
+
@change=${e => {
|
|
77
|
+
this.bcid = e.target.value
|
|
78
|
+
}}
|
|
79
|
+
.value=${bcid}
|
|
80
|
+
>
|
|
81
|
+
<option value="code39">code39</option>
|
|
82
|
+
<option value="code128" selected>code128</option>
|
|
83
|
+
<option value="qrcode">QR</option>
|
|
84
|
+
</select>
|
|
85
|
+
|
|
86
|
+
<label>bacode width</label>
|
|
87
|
+
<select
|
|
88
|
+
@change=${e => {
|
|
89
|
+
this.bcWidth = Number(e.target.value)
|
|
90
|
+
}}
|
|
91
|
+
.value=${bcWidth}
|
|
92
|
+
>
|
|
93
|
+
<option value="10">10</option>
|
|
94
|
+
<option value="30" selected>30</option>
|
|
95
|
+
<option value="50">50</option>
|
|
96
|
+
</select>
|
|
97
|
+
|
|
98
|
+
<label>bacode height</label>
|
|
99
|
+
<select
|
|
100
|
+
@change=${e => {
|
|
101
|
+
this.bcHeight = Number(e.target.value)
|
|
102
|
+
}}
|
|
103
|
+
.value=${bcHeight}
|
|
104
|
+
>
|
|
105
|
+
<option value="10">10</option>
|
|
106
|
+
<option value="30" selected>30</option>
|
|
107
|
+
<option value="50">50</option>
|
|
108
|
+
</select>
|
|
109
|
+
|
|
110
|
+
<label>bacode scale</label>
|
|
111
|
+
<select
|
|
112
|
+
@change=${e => {
|
|
113
|
+
this.bcScale = Number(e.target.value)
|
|
114
|
+
}}
|
|
115
|
+
.value=${bcScale}
|
|
116
|
+
>
|
|
117
|
+
<option value="2">2</option>
|
|
118
|
+
<option value="3" selected>3</option>
|
|
119
|
+
<option value="4">4</option>
|
|
120
|
+
</select>
|
|
121
|
+
|
|
122
|
+
<label>padding</label>
|
|
123
|
+
<select
|
|
124
|
+
@change=${e => {
|
|
125
|
+
this.padding = Number(e.target.value)
|
|
126
|
+
}}
|
|
127
|
+
.value=${padding}
|
|
128
|
+
>
|
|
129
|
+
<option value="3">3</option>
|
|
130
|
+
<option value="5" selected>5</option>
|
|
131
|
+
<option value="10">10</option>
|
|
132
|
+
</select>
|
|
133
|
+
|
|
134
|
+
<barcode-input
|
|
135
|
+
.bcid=${bcid}
|
|
136
|
+
.value=${value}
|
|
137
|
+
.bcWidth=${bcWidth}
|
|
138
|
+
.bcHeight=${bcHeight}
|
|
139
|
+
.bcScale=${bcScale}
|
|
140
|
+
@change=${e => {
|
|
141
|
+
this.value = e.target.value
|
|
142
|
+
}}
|
|
143
|
+
></barcode-input>
|
|
144
|
+
</section>
|
|
145
|
+
|
|
146
|
+
<section>
|
|
147
|
+
<h2>Barcode Image Component</h2>
|
|
148
|
+
<p>
|
|
149
|
+
barcode-tag 컴포넌트는 바코드 이미지를 보여준다. 바코드 이미지를 클릭하면 이미지 파일을 다운로드 받을 수 있다.
|
|
150
|
+
</p>
|
|
151
|
+
|
|
152
|
+
<barcode-tag
|
|
153
|
+
.bcid=${bcid}
|
|
154
|
+
.value=${value}
|
|
155
|
+
.bcWidth=${bcWidth}
|
|
156
|
+
.bcHeight=${bcHeight}
|
|
157
|
+
.bcScale=${bcScale}
|
|
158
|
+
.padding=${padding}
|
|
159
|
+
></barcode-tag>
|
|
160
|
+
</section>
|
|
161
|
+
`
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
updated(changes) {
|
|
165
|
+
/*
|
|
166
|
+
* If this page properties are changed, this callback will be invoked.
|
|
167
|
+
* This callback will be called back only when this page is activated.
|
|
168
|
+
*/
|
|
169
|
+
if (changes.has('itemId') || changes.has('params')) {
|
|
170
|
+
/* do something */
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
stateChanged(state) {
|
|
175
|
+
/*
|
|
176
|
+
* application wide state changed
|
|
177
|
+
*
|
|
178
|
+
*/
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
pageUpdated(changes, lifecycle, before) {
|
|
182
|
+
if (this.active) {
|
|
183
|
+
} else {
|
|
184
|
+
/* this page is deactivated */
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
customElements.define('label-scan-page', LabelScanPage)
|
package/client/pages/ocr-page.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import '@things-factory/form-ui'
|
|
2
2
|
import '../components/camera-capturer'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { gql } from 'graphql-tag'
|
|
5
5
|
import { css, html } from 'lit-element'
|
|
6
|
+
import { connect } from 'pwa-helpers/connect-mixin.js'
|
|
6
7
|
|
|
8
|
+
import { client, PageView, store } from '@things-factory/shell'
|
|
7
9
|
import { CommonButtonStyles } from '@things-factory/styles'
|
|
8
|
-
|
|
9
|
-
import { gql } from 'graphql-tag'
|
|
10
|
+
|
|
10
11
|
import { referencePageStyles } from './reference-page-styles'
|
|
11
12
|
|
|
12
13
|
class OCRPage extends connect(store)(PageView) {
|
package/client/route.js
CHANGED
package/db.sqlite
CHANGED
|
Binary file
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.interpretImages = void 0;
|
|
7
|
+
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
8
|
+
const env_1 = require("@things-factory/env");
|
|
9
|
+
const utils_1 = require("@things-factory/utils");
|
|
10
|
+
const appSyncConfig = env_1.config.get('awsAppSync');
|
|
11
|
+
async function interpretImages(images) {
|
|
12
|
+
const query = utils_1.gqlBuilder.jsonToGraphQLQuery({
|
|
13
|
+
mutation: {
|
|
14
|
+
upload: {
|
|
15
|
+
__args: {
|
|
16
|
+
images
|
|
17
|
+
},
|
|
18
|
+
success_count: true,
|
|
19
|
+
failure_count: true,
|
|
20
|
+
result: {
|
|
21
|
+
key_values: true,
|
|
22
|
+
boundaries: true,
|
|
23
|
+
texts: true
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
const body = JSON.stringify({ query });
|
|
29
|
+
const response = await (0, node_fetch_1.default)(appSyncConfig['apiUrl'], {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: {
|
|
32
|
+
'Content-Type': 'application/graphql',
|
|
33
|
+
'x-api-key': appSyncConfig['apiKey']
|
|
34
|
+
},
|
|
35
|
+
body
|
|
36
|
+
});
|
|
37
|
+
const jsonRes = await response.json();
|
|
38
|
+
return jsonRes;
|
|
39
|
+
}
|
|
40
|
+
exports.interpretImages = interpretImages;
|
|
41
|
+
// @deprecated
|
|
42
|
+
function getRequestBody(images) {
|
|
43
|
+
// @things-factory/utils gqlBuilder.buildArgs 와 유사
|
|
44
|
+
const imageArgs = images.map(obj => {
|
|
45
|
+
const args = [];
|
|
46
|
+
for (let key in obj) {
|
|
47
|
+
args.push(`${key}: \"${obj[key]}\"`);
|
|
48
|
+
}
|
|
49
|
+
return '{' + args.join(',') + '}';
|
|
50
|
+
});
|
|
51
|
+
// console.log(gqlBuilder.buildArgs(images))
|
|
52
|
+
// console.log(imageArgs)
|
|
53
|
+
const body = JSON.stringify({
|
|
54
|
+
query: `mutation {
|
|
55
|
+
upload(images: ${imageArgs}) {
|
|
56
|
+
success_count
|
|
57
|
+
failure_count
|
|
58
|
+
results {
|
|
59
|
+
key_values
|
|
60
|
+
boundaries
|
|
61
|
+
texts
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}`
|
|
65
|
+
});
|
|
66
|
+
return body;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=lambda-call.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lambda-call.js","sourceRoot":"","sources":["../../../server/service/reference/lambda-call.ts"],"names":[],"mappings":";;;;;;AAAA,4DAA8B;AAE9B,6CAA4C;AAC5C,iDAAkD;AAElD,MAAM,aAAa,GAAG,YAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;AAEvC,KAAK,UAAU,eAAe,CAAC,MAAM;IAC1C,MAAM,KAAK,GAAG,kBAAU,CAAC,kBAAkB,CAAC;QAC1C,QAAQ,EAAE;YACR,MAAM,EAAE;gBACN,MAAM,EAAE;oBACN,MAAM;iBACP;gBACD,aAAa,EAAE,IAAI;gBACnB,aAAa,EAAE,IAAI;gBACnB,MAAM,EAAE;oBACN,UAAU,EAAE,IAAI;oBAChB,UAAU,EAAE,IAAI;oBAChB,KAAK,EAAE,IAAI;iBACZ;aACF;SACF;KACF,CAAC,CAAA;IAEF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;IACtC,MAAM,QAAQ,GAAG,MAAM,IAAA,oBAAK,EAAC,aAAa,CAAC,QAAQ,CAAC,EAAE;QACpD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,qBAAqB;YACrC,WAAW,EAAE,aAAa,CAAC,QAAQ,CAAC;SACrC;QACD,IAAI;KACL,CAAC,CAAA;IAEF,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IACrC,OAAO,OAAO,CAAA;AAChB,CAAC;AA9BD,0CA8BC;AAED,cAAc;AACd,SAAS,cAAc,CAAC,MAAM;IAC5B,kDAAkD;IAClD,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;QACjC,MAAM,IAAI,GAAG,EAAE,CAAA;QACf,KAAK,IAAI,GAAG,IAAI,GAAG,EAAE;YACnB,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;SACrC;QACD,OAAO,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,4CAA4C;IAC5C,yBAAyB;IAEzB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;QAC1B,KAAK,EAAE;uBACY,SAAS;;;;;;;;;MAS1B;KACH,CAAC,CAAA;IAEF,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -13,13 +13,16 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.ReferenceQuery = void 0;
|
|
16
|
-
const type_graphql_1 = require("type-graphql");
|
|
17
16
|
const graphql_upload_1 = require("graphql-upload");
|
|
17
|
+
const type_graphql_1 = require("type-graphql");
|
|
18
|
+
const attachment_base_1 = require("@things-factory/attachment-base");
|
|
18
19
|
const shell_1 = require("@things-factory/shell");
|
|
19
20
|
const utils_1 = require("@things-factory/utils");
|
|
20
|
-
const
|
|
21
|
+
const lambda_call_1 = require("./lambda-call");
|
|
22
|
+
const debug = require('debug')('things-factory:reference-app');
|
|
21
23
|
let ReferenceQuery = class ReferenceQuery {
|
|
22
24
|
async ocrRequest(_, images, context) {
|
|
25
|
+
var _a, _b;
|
|
23
26
|
const { domain, user, tx } = context.state;
|
|
24
27
|
const all = Promise.all(images);
|
|
25
28
|
if ((images === null || images === void 0 ? void 0 : images.length) > 0) {
|
|
@@ -31,8 +34,27 @@ let ReferenceQuery = class ReferenceQuery {
|
|
|
31
34
|
};
|
|
32
35
|
});
|
|
33
36
|
await (0, attachment_base_1.createAttachments)(_, { attachments }, context);
|
|
37
|
+
const files = await Promise.all(images.map(async (file) => {
|
|
38
|
+
const { createReadStream, filename, mimetype } = await file;
|
|
39
|
+
const readStream = createReadStream();
|
|
40
|
+
const image = await this.streamToString(readStream);
|
|
41
|
+
// format is 'image/jpeg'
|
|
42
|
+
const formatArr = mimetype.split('/');
|
|
43
|
+
return { data: image, name: filename, format: formatArr[formatArr.length - 1] };
|
|
44
|
+
}));
|
|
45
|
+
const res = await (0, lambda_call_1.interpretImages)(files);
|
|
46
|
+
console.log('interpretImages response', JSON.stringify(res, null, ' '));
|
|
47
|
+
return (_b = (_a = res.data) === null || _a === void 0 ? void 0 : _a.upload) === null || _b === void 0 ? void 0 : _b.result;
|
|
34
48
|
}
|
|
35
|
-
return
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
streamToString(stream) {
|
|
52
|
+
const chunks = [];
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
|
|
55
|
+
stream.on('error', (err) => reject(err));
|
|
56
|
+
stream.on('end', () => resolve(Buffer.concat(chunks).toString('base64')));
|
|
57
|
+
});
|
|
36
58
|
}
|
|
37
59
|
async ocrPendingJob(_, tag, context) {
|
|
38
60
|
const { domain } = context.state;
|
|
@@ -49,7 +71,7 @@ let ReferenceQuery = class ReferenceQuery {
|
|
|
49
71
|
}
|
|
50
72
|
};
|
|
51
73
|
__decorate([
|
|
52
|
-
(0, type_graphql_1.Query)(returns =>
|
|
74
|
+
(0, type_graphql_1.Query)(returns => shell_1.ScalarAny, { description: 'To reference of ocr request' }),
|
|
53
75
|
__param(0, (0, type_graphql_1.Root)()),
|
|
54
76
|
__param(1, (0, type_graphql_1.Arg)('images', () => [graphql_upload_1.GraphQLUpload])),
|
|
55
77
|
__param(2, (0, type_graphql_1.Ctx)()),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reference-query.js","sourceRoot":"","sources":["../../../server/service/reference/reference-query.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA
|
|
1
|
+
{"version":3,"file":"reference-query.js","sourceRoot":"","sources":["../../../server/service/reference/reference-query.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,14 +6,9 @@
|
|
|
6
6
|
"auditLog": "logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json",
|
|
7
7
|
"files": [
|
|
8
8
|
{
|
|
9
|
-
"date":
|
|
10
|
-
"name": "logs/application-2021-
|
|
11
|
-
"hash": "
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
"date": 1636103946107,
|
|
15
|
-
"name": "logs/application-2021-11-05-18.log",
|
|
16
|
-
"hash": "dca379ac4e315b99f4a38f1350437523"
|
|
9
|
+
"date": 1632981885831,
|
|
10
|
+
"name": "logs/application-2021-09-30-15.log",
|
|
11
|
+
"hash": "515e7b9c4a0e33cfa4f1218a88c8f042"
|
|
17
12
|
}
|
|
18
13
|
]
|
|
19
14
|
}
|
|
@@ -6,24 +6,9 @@
|
|
|
6
6
|
"auditLog": "logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json",
|
|
7
7
|
"files": [
|
|
8
8
|
{
|
|
9
|
-
"date":
|
|
10
|
-
"name": "logs/connections-2021-
|
|
11
|
-
"hash": "
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
"date": 1635906208371,
|
|
15
|
-
"name": "logs/connections-2021-11-03-11.log",
|
|
16
|
-
"hash": "a1311491c36196b33b2dd55f164b95f7"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"date": 1636005260004,
|
|
20
|
-
"name": "logs/connections-2021-11-04-14.log",
|
|
21
|
-
"hash": "6d9ee9a4066c730e14f77f0396879d64"
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
"date": 1636103949582,
|
|
25
|
-
"name": "logs/connections-2021-11-05-18.log",
|
|
26
|
-
"hash": "f7593c79bc2d00a3832d894f74b529f8"
|
|
9
|
+
"date": 1632981891881,
|
|
10
|
+
"name": "logs/connections-2021-09-30-15.log",
|
|
11
|
+
"hash": "96dfe267599a1dba08dca294e7d8d0d1"
|
|
27
12
|
}
|
|
28
13
|
]
|
|
29
14
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
2021-09-30T06:04:49.542Z info: File Storage is Ready.
|
|
2
|
+
2021-09-30T06:04:56.532Z info: Database connection established
|
|
3
|
+
2021-09-30T06:04:57.913Z info: 🚀 Server ready at http://0.0.0.0:3000/graphql
|
|
4
|
+
2021-09-30T06:04:57.915Z info: 🚀 Subscriptions ready at ws://0.0.0.0:3000/subscriptions
|
|
5
|
+
2021-09-30T06:05:31.284Z info: File Storage is Ready.
|
|
6
|
+
2021-09-30T06:05:37.067Z info: Database connection established
|
|
7
|
+
2021-09-30T06:05:38.136Z info: 🚀 Server ready at http://0.0.0.0:3000/graphql
|
|
8
|
+
2021-09-30T06:05:38.148Z info: 🚀 Subscriptions ready at ws://0.0.0.0:3000/subscriptions
|
|
9
|
+
2021-09-30T06:07:44.914Z info: File Storage is Ready.
|
|
10
|
+
2021-09-30T06:08:06.103Z info: File Storage is Ready.
|
|
11
|
+
2021-09-30T06:08:29.712Z info: File Storage is Ready.
|
|
12
|
+
2021-09-30T06:08:32.447Z info: Database connection established
|
|
13
|
+
2021-09-30T06:08:33.349Z info: 🚀 Server ready at http://0.0.0.0:3000/graphql
|
|
14
|
+
2021-09-30T06:08:33.349Z info: 🚀 Subscriptions ready at ws://0.0.0.0:3000/subscriptions
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/reference-app",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.6",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -37,49 +37,50 @@
|
|
|
37
37
|
"docker:run": "docker run -it -p 4000:3000 hatiolab/reference-app:latest"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@hatiolab/things-scene": "^2.7.
|
|
41
|
-
"@material/mwc-checkbox": "^0.
|
|
42
|
-
"@operato/data-grist": "^0.2.
|
|
43
|
-
"@operato/ghost-print": "0.
|
|
44
|
-
"@operato/
|
|
45
|
-
"@operato/
|
|
46
|
-
"@
|
|
47
|
-
"@
|
|
48
|
-
"@things-factory/
|
|
49
|
-
"@things-factory/
|
|
50
|
-
"@things-factory/
|
|
51
|
-
"@things-factory/
|
|
52
|
-
"@things-factory/
|
|
53
|
-
"@things-factory/
|
|
54
|
-
"@things-factory/
|
|
55
|
-
"@things-factory/
|
|
56
|
-
"@things-factory/
|
|
57
|
-
"@things-factory/
|
|
58
|
-
"@things-factory/
|
|
59
|
-
"@things-factory/
|
|
60
|
-
"@things-factory/
|
|
61
|
-
"@things-factory/
|
|
62
|
-
"@things-factory/
|
|
63
|
-
"@things-factory/
|
|
64
|
-
"@things-factory/
|
|
65
|
-
"@things-factory/
|
|
66
|
-
"@things-factory/
|
|
67
|
-
"@things-factory/scene-
|
|
68
|
-
"@things-factory/scene-
|
|
69
|
-
"@things-factory/scene-
|
|
70
|
-
"@things-factory/scene-
|
|
71
|
-
"@things-factory/scene-
|
|
72
|
-
"@things-factory/scene-
|
|
73
|
-
"@things-factory/scene-
|
|
74
|
-
"@things-factory/scene-
|
|
75
|
-
"@things-factory/scene-
|
|
76
|
-
"@things-factory/
|
|
77
|
-
"@things-factory/setting-
|
|
78
|
-
"@things-factory/
|
|
79
|
-
"@things-factory/
|
|
40
|
+
"@hatiolab/things-scene": "^2.7.12",
|
|
41
|
+
"@material/mwc-checkbox": "^0.25.3",
|
|
42
|
+
"@operato/data-grist": "^0.2.28",
|
|
43
|
+
"@operato/ghost-print": "0.2.26",
|
|
44
|
+
"@operato/ocr": "^0.2.26",
|
|
45
|
+
"@operato/popup": "^0.2.26",
|
|
46
|
+
"@operato/pull-to-refresh": "^0.2.26",
|
|
47
|
+
"@operato/scene-switch": "^0.0.3",
|
|
48
|
+
"@things-factory/api": "^4.0.6",
|
|
49
|
+
"@things-factory/apptool-ui": "^4.0.6",
|
|
50
|
+
"@things-factory/auth-ui": "^4.0.6",
|
|
51
|
+
"@things-factory/board-service": "^4.0.6",
|
|
52
|
+
"@things-factory/board-ui": "^4.0.6",
|
|
53
|
+
"@things-factory/context-ui": "^4.0.6",
|
|
54
|
+
"@things-factory/dashboard": "^4.0.6",
|
|
55
|
+
"@things-factory/export-ui": "^4.0.6",
|
|
56
|
+
"@things-factory/export-ui-excel": "^4.0.6",
|
|
57
|
+
"@things-factory/grist-ui": "^4.0.6",
|
|
58
|
+
"@things-factory/help": "^4.0.6",
|
|
59
|
+
"@things-factory/i18n-ui": "^4.0.6",
|
|
60
|
+
"@things-factory/integration-ui": "^4.0.6",
|
|
61
|
+
"@things-factory/lite-menu": "^4.0.6",
|
|
62
|
+
"@things-factory/more-ui": "^4.0.6",
|
|
63
|
+
"@things-factory/notification": "^4.0.6",
|
|
64
|
+
"@things-factory/oauth2-client": "^4.0.6",
|
|
65
|
+
"@things-factory/print-ui": "^4.0.6",
|
|
66
|
+
"@things-factory/resource-ui": "^4.0.6",
|
|
67
|
+
"@things-factory/scene-chartjs": "^4.0.6",
|
|
68
|
+
"@things-factory/scene-clock": "^4.0.6",
|
|
69
|
+
"@things-factory/scene-form": "^4.0.6",
|
|
70
|
+
"@things-factory/scene-gauge": "^4.0.6",
|
|
71
|
+
"@things-factory/scene-half-roundrect": "^4.0.6",
|
|
72
|
+
"@things-factory/scene-indoor-map": "^4.0.6",
|
|
73
|
+
"@things-factory/scene-news-ticker": "^4.0.6",
|
|
74
|
+
"@things-factory/scene-progressbar": "^4.0.6",
|
|
75
|
+
"@things-factory/scene-random": "^4.0.6",
|
|
76
|
+
"@things-factory/scene-tab": "^4.0.6",
|
|
77
|
+
"@things-factory/setting-base": "^4.0.6",
|
|
78
|
+
"@things-factory/setting-ui": "^4.0.6",
|
|
79
|
+
"@things-factory/shell": "^4.0.6",
|
|
80
|
+
"@things-factory/system-ui": "^4.0.6"
|
|
80
81
|
},
|
|
81
82
|
"devDependencies": {
|
|
82
|
-
"@things-factory/builder": "^4.0.
|
|
83
|
+
"@things-factory/builder": "^4.0.6"
|
|
83
84
|
},
|
|
84
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "471247c3499ba439b074c7654ae8d8e9fc3972f0"
|
|
85
86
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import fetch from 'node-fetch'
|
|
2
|
+
|
|
3
|
+
import { config } from '@things-factory/env'
|
|
4
|
+
import { gqlBuilder } from '@things-factory/utils'
|
|
5
|
+
|
|
6
|
+
const appSyncConfig = config.get('awsAppSync')
|
|
7
|
+
|
|
8
|
+
export async function interpretImages(images) {
|
|
9
|
+
const query = gqlBuilder.jsonToGraphQLQuery({
|
|
10
|
+
mutation: {
|
|
11
|
+
upload: {
|
|
12
|
+
__args: {
|
|
13
|
+
images
|
|
14
|
+
},
|
|
15
|
+
success_count: true,
|
|
16
|
+
failure_count: true,
|
|
17
|
+
result: {
|
|
18
|
+
key_values: true,
|
|
19
|
+
boundaries: true,
|
|
20
|
+
texts: true
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const body = JSON.stringify({ query })
|
|
27
|
+
const response = await fetch(appSyncConfig['apiUrl'], {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers: {
|
|
30
|
+
'Content-Type': 'application/graphql',
|
|
31
|
+
'x-api-key': appSyncConfig['apiKey']
|
|
32
|
+
},
|
|
33
|
+
body
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const jsonRes = await response.json()
|
|
37
|
+
return jsonRes
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// @deprecated
|
|
41
|
+
function getRequestBody(images) {
|
|
42
|
+
// @things-factory/utils gqlBuilder.buildArgs 와 유사
|
|
43
|
+
const imageArgs = images.map(obj => {
|
|
44
|
+
const args = []
|
|
45
|
+
for (let key in obj) {
|
|
46
|
+
args.push(`${key}: \"${obj[key]}\"`)
|
|
47
|
+
}
|
|
48
|
+
return '{' + args.join(',') + '}'
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// console.log(gqlBuilder.buildArgs(images))
|
|
52
|
+
// console.log(imageArgs)
|
|
53
|
+
|
|
54
|
+
const body = JSON.stringify({
|
|
55
|
+
query: `mutation {
|
|
56
|
+
upload(images: ${imageArgs}) {
|
|
57
|
+
success_count
|
|
58
|
+
failure_count
|
|
59
|
+
results {
|
|
60
|
+
key_values
|
|
61
|
+
boundaries
|
|
62
|
+
texts
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}`
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
return body
|
|
69
|
+
}
|
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import { sleep } from '@things-factory/utils'
|
|
1
|
+
import { FileUpload, GraphQLUpload } from 'graphql-upload'
|
|
2
|
+
import { Arg, Ctx, Query, Resolver, Root } from 'type-graphql'
|
|
3
|
+
|
|
5
4
|
import { Attachment, createAttachments } from '@things-factory/attachment-base'
|
|
5
|
+
import { publishProgress, ScalarAny } from '@things-factory/shell'
|
|
6
|
+
import { sleep } from '@things-factory/utils'
|
|
7
|
+
|
|
8
|
+
import { interpretImages } from './lambda-call'
|
|
9
|
+
|
|
10
|
+
const debug = require('debug')('things-factory:reference-app')
|
|
6
11
|
|
|
7
12
|
@Resolver()
|
|
8
13
|
export class ReferenceQuery {
|
|
9
|
-
@Query(returns =>
|
|
14
|
+
@Query(returns => ScalarAny, { description: 'To reference of ocr request' })
|
|
10
15
|
async ocrRequest(
|
|
11
16
|
@Root() _,
|
|
12
17
|
@Arg('images', () => [GraphQLUpload])
|
|
13
18
|
images: FileUpload[],
|
|
14
19
|
@Ctx() context: any
|
|
15
|
-
): Promise<
|
|
20
|
+
): Promise<ScalarAny> {
|
|
16
21
|
const { domain, user, tx } = context.state
|
|
17
22
|
const all = Promise.all(images)
|
|
18
23
|
|
|
@@ -25,9 +30,32 @@ export class ReferenceQuery {
|
|
|
25
30
|
}
|
|
26
31
|
})
|
|
27
32
|
await createAttachments(_, { attachments }, context)
|
|
33
|
+
|
|
34
|
+
const files = await Promise.all(
|
|
35
|
+
images.map(async file => {
|
|
36
|
+
const { createReadStream, filename, mimetype } = await file
|
|
37
|
+
const readStream = createReadStream()
|
|
38
|
+
const image = await this.streamToString(readStream)
|
|
39
|
+
// format is 'image/jpeg'
|
|
40
|
+
const formatArr = mimetype.split('/')
|
|
41
|
+
return { data: image, name: filename, format: formatArr[formatArr.length - 1] }
|
|
42
|
+
})
|
|
43
|
+
)
|
|
44
|
+
const res = await interpretImages(files)
|
|
45
|
+
console.log('interpretImages response', JSON.stringify(res, null, ' '))
|
|
46
|
+
return res.data?.upload?.result
|
|
28
47
|
}
|
|
29
48
|
|
|
30
|
-
return
|
|
49
|
+
return []
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
streamToString (stream) {
|
|
53
|
+
const chunks = [];
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
|
|
56
|
+
stream.on('error', (err) => reject(err));
|
|
57
|
+
stream.on('end', () => resolve(Buffer.concat(chunks).toString('base64')));
|
|
58
|
+
})
|
|
31
59
|
}
|
|
32
60
|
|
|
33
61
|
@Query(returns => String, { description: 'To reference of pending job progress' })
|
package/things-factory.config.js
CHANGED
package/translations/en.json
CHANGED
package/translations/ko.json
CHANGED
package/translations/ms.json
CHANGED
package/translations/zh.json
CHANGED
package/views/auth-page.html
CHANGED
|
@@ -80,7 +80,6 @@
|
|
|
80
80
|
<!-- Load webcomponents-loader.js to check and load any polyfills your browser needs -->
|
|
81
81
|
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
|
|
82
82
|
<script src="node_modules/web-animations-js/web-animations-next.min.js"></script>
|
|
83
|
-
<script src="node_modules/@lottiefiles/lottie-player/dist/lottie-player.js"></script>
|
|
84
83
|
<!-- Built with love using PWA Starter Kit -->
|
|
85
84
|
|
|
86
85
|
<script src="<%- elementScript %>"></script>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
2021-11-04T05:54:18.294Z info: File Storage is Ready.
|
|
2
|
-
2021-11-04T05:54:26.107Z info: Database connection established
|
|
3
|
-
2021-11-04T05:54:30.807Z info: 🚀 Server ready at http://0.0.0.0:3000/graphql
|
|
4
|
-
2021-11-04T05:54:30.812Z info: 🚀 Subscriptions ready at ws://0.0.0.0:3000/subscriptions
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
2021-11-05T09:19:08.124Z info: File Storage is Ready.
|
|
2
|
-
2021-11-05T09:19:12.759Z info: Database connection established
|
|
3
|
-
2021-11-05T09:19:47.437Z info: File Storage is Ready.
|
|
4
|
-
2021-11-05T09:19:51.042Z info: Database connection established
|
|
5
|
-
2021-11-05T09:19:51.851Z info: 🚀 Server ready at http://0.0.0.0:3000/graphql
|
|
6
|
-
2021-11-05T09:19:51.851Z info: 🚀 Subscriptions ready at ws://0.0.0.0:3000/subscriptions
|
|
File without changes
|
|
File without changes
|
|
File without changes
|