@things-factory/integration-label-studio 9.1.19

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 (152) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/EXTERNAL_DATA_SOURCING.md +484 -0
  3. package/IMPLEMENTATION_GUIDE.md +469 -0
  4. package/INTEGRATION.md +279 -0
  5. package/README.md +1014 -0
  6. package/SETUP_GUIDE.md +577 -0
  7. package/TEST_GUIDE.md +387 -0
  8. package/UI_CUSTOMIZATION.md +395 -0
  9. package/USER_SYNC_GUIDE.md +514 -0
  10. package/client/bootstrap.ts +1 -0
  11. package/client/index.ts +1 -0
  12. package/client/label-studio-label-page.ts +52 -0
  13. package/client/label-studio-project-create.ts +216 -0
  14. package/client/label-studio-project-list.ts +214 -0
  15. package/client/label-studio-wrapper.ts +294 -0
  16. package/client/route.ts +15 -0
  17. package/client/tsconfig.json +13 -0
  18. package/config/config.development.js +124 -0
  19. package/config/config.production.js +182 -0
  20. package/dist-client/bootstrap.d.ts +1 -0
  21. package/dist-client/bootstrap.js +2 -0
  22. package/dist-client/bootstrap.js.map +1 -0
  23. package/dist-client/index.d.ts +1 -0
  24. package/dist-client/index.js +2 -0
  25. package/dist-client/index.js.map +1 -0
  26. package/dist-client/label-studio-label-page.d.ts +8 -0
  27. package/dist-client/label-studio-label-page.js +54 -0
  28. package/dist-client/label-studio-label-page.js.map +1 -0
  29. package/dist-client/label-studio-project-create.d.ts +16 -0
  30. package/dist-client/label-studio-project-create.js +235 -0
  31. package/dist-client/label-studio-project-create.js.map +1 -0
  32. package/dist-client/label-studio-project-list.d.ts +16 -0
  33. package/dist-client/label-studio-project-list.js +222 -0
  34. package/dist-client/label-studio-project-list.js.map +1 -0
  35. package/dist-client/label-studio-wrapper.d.ts +57 -0
  36. package/dist-client/label-studio-wrapper.js +304 -0
  37. package/dist-client/label-studio-wrapper.js.map +1 -0
  38. package/dist-client/route.d.ts +1 -0
  39. package/dist-client/route.js +14 -0
  40. package/dist-client/route.js.map +1 -0
  41. package/dist-client/tsconfig.tsbuildinfo +1 -0
  42. package/dist-server/controller/label-studio-role-mapper.d.ts +35 -0
  43. package/dist-server/controller/label-studio-role-mapper.js +65 -0
  44. package/dist-server/controller/label-studio-role-mapper.js.map +1 -0
  45. package/dist-server/controller/user-provisioning-service.d.ts +66 -0
  46. package/dist-server/controller/user-provisioning-service.js +264 -0
  47. package/dist-server/controller/user-provisioning-service.js.map +1 -0
  48. package/dist-server/index.d.ts +7 -0
  49. package/dist-server/index.js +19 -0
  50. package/dist-server/index.js.map +1 -0
  51. package/dist-server/route/label-studio-sso.d.ts +2 -0
  52. package/dist-server/route/label-studio-sso.js +156 -0
  53. package/dist-server/route/label-studio-sso.js.map +1 -0
  54. package/dist-server/route/webhook.d.ts +65 -0
  55. package/dist-server/route/webhook.js +248 -0
  56. package/dist-server/route/webhook.js.map +1 -0
  57. package/dist-server/route.d.ts +1 -0
  58. package/dist-server/route.js +21 -0
  59. package/dist-server/route.js.map +1 -0
  60. package/dist-server/service/ai-prediction-service.d.ts +27 -0
  61. package/dist-server/service/ai-prediction-service.js +222 -0
  62. package/dist-server/service/ai-prediction-service.js.map +1 -0
  63. package/dist-server/service/dataset-labeling-integration.d.ts +44 -0
  64. package/dist-server/service/dataset-labeling-integration.js +512 -0
  65. package/dist-server/service/dataset-labeling-integration.js.map +1 -0
  66. package/dist-server/service/external-data-source-service.d.ts +78 -0
  67. package/dist-server/service/external-data-source-service.js +415 -0
  68. package/dist-server/service/external-data-source-service.js.map +1 -0
  69. package/dist-server/service/index.d.ts +12 -0
  70. package/dist-server/service/index.js +27 -0
  71. package/dist-server/service/index.js.map +1 -0
  72. package/dist-server/service/label-studio-sso-service.d.ts +38 -0
  73. package/dist-server/service/label-studio-sso-service.js +98 -0
  74. package/dist-server/service/label-studio-sso-service.js.map +1 -0
  75. package/dist-server/service/ml/ml-backend-service.d.ts +23 -0
  76. package/dist-server/service/ml/ml-backend-service.js +153 -0
  77. package/dist-server/service/ml/ml-backend-service.js.map +1 -0
  78. package/dist-server/service/prediction/prediction-management.d.ts +32 -0
  79. package/dist-server/service/prediction/prediction-management.js +299 -0
  80. package/dist-server/service/prediction/prediction-management.js.map +1 -0
  81. package/dist-server/service/project/project-management.d.ts +36 -0
  82. package/dist-server/service/project/project-management.js +309 -0
  83. package/dist-server/service/project/project-management.js.map +1 -0
  84. package/dist-server/service/task/task-management.d.ts +42 -0
  85. package/dist-server/service/task/task-management.js +372 -0
  86. package/dist-server/service/task/task-management.js.map +1 -0
  87. package/dist-server/service/user-provisioning/user-sync-mutation.d.ts +28 -0
  88. package/dist-server/service/user-provisioning/user-sync-mutation.js +111 -0
  89. package/dist-server/service/user-provisioning/user-sync-mutation.js.map +1 -0
  90. package/dist-server/service/webhook/webhook-management.d.ts +21 -0
  91. package/dist-server/service/webhook/webhook-management.js +134 -0
  92. package/dist-server/service/webhook/webhook-management.js.map +1 -0
  93. package/dist-server/tsconfig.tsbuildinfo +1 -0
  94. package/dist-server/types/dataset-labeling-types.d.ts +71 -0
  95. package/dist-server/types/dataset-labeling-types.js +259 -0
  96. package/dist-server/types/dataset-labeling-types.js.map +1 -0
  97. package/dist-server/types/label-studio-types.d.ts +128 -0
  98. package/dist-server/types/label-studio-types.js +494 -0
  99. package/dist-server/types/label-studio-types.js.map +1 -0
  100. package/dist-server/types/prediction-types.d.ts +39 -0
  101. package/dist-server/types/prediction-types.js +121 -0
  102. package/dist-server/types/prediction-types.js.map +1 -0
  103. package/dist-server/utils/annotation-exporter.d.ts +104 -0
  104. package/dist-server/utils/annotation-exporter.js +261 -0
  105. package/dist-server/utils/annotation-exporter.js.map +1 -0
  106. package/dist-server/utils/label-config-builder.d.ts +117 -0
  107. package/dist-server/utils/label-config-builder.js +286 -0
  108. package/dist-server/utils/label-config-builder.js.map +1 -0
  109. package/dist-server/utils/label-studio-api-client.d.ts +180 -0
  110. package/dist-server/utils/label-studio-api-client.js +401 -0
  111. package/dist-server/utils/label-studio-api-client.js.map +1 -0
  112. package/dist-server/utils/media-url-extractor.d.ts +45 -0
  113. package/dist-server/utils/media-url-extractor.js +152 -0
  114. package/dist-server/utils/media-url-extractor.js.map +1 -0
  115. package/dist-server/utils/task-transformer.d.ts +108 -0
  116. package/dist-server/utils/task-transformer.js +260 -0
  117. package/dist-server/utils/task-transformer.js.map +1 -0
  118. package/package.json +47 -0
  119. package/server/SERVER_STRUCTURE.md +351 -0
  120. package/server/controller/label-studio-role-mapper.ts +76 -0
  121. package/server/controller/user-provisioning-service.ts +340 -0
  122. package/server/index.ts +19 -0
  123. package/server/route/label-studio-sso.ts +194 -0
  124. package/server/route/webhook.ts +304 -0
  125. package/server/route.ts +35 -0
  126. package/server/service/ai-prediction-service.ts +239 -0
  127. package/server/service/dataset-labeling-integration.ts +590 -0
  128. package/server/service/external-data-source-service.ts +438 -0
  129. package/server/service/index.ts +24 -0
  130. package/server/service/label-studio-sso-service.ts +108 -0
  131. package/server/service/labeling-scenario-service.ts.deprecated +566 -0
  132. package/server/service/ml/ml-backend-service.ts +127 -0
  133. package/server/service/prediction/prediction-management.ts +281 -0
  134. package/server/service/project/project-management.ts +284 -0
  135. package/server/service/task/task-management.ts +363 -0
  136. package/server/service/user-provisioning/user-sync-mutation.ts +80 -0
  137. package/server/service/webhook/webhook-management.ts +109 -0
  138. package/server/tsconfig.json +11 -0
  139. package/server/types/dataset-labeling-types.ts +181 -0
  140. package/server/types/global.d.ts +23 -0
  141. package/server/types/label-studio-types.ts +346 -0
  142. package/server/types/prediction-types.ts +86 -0
  143. package/server/types/scenario-types.ts.deprecated +362 -0
  144. package/server/utils/annotation-exporter.ts +340 -0
  145. package/server/utils/label-config-builder.ts +340 -0
  146. package/server/utils/label-studio-api-client.ts +487 -0
  147. package/server/utils/media-url-extractor.ts +193 -0
  148. package/server/utils/task-transformer.ts +342 -0
  149. package/test-ai-prediction.js +268 -0
  150. package/test-dataset-integration.js +449 -0
  151. package/test-simple.js +89 -0
  152. package/things-factory.config.js +12 -0
@@ -0,0 +1,216 @@
1
+ import '@material/web/button/filled-button.js'
2
+ import '@material/web/button/text-button.js'
3
+ import '@material/web/textfield/filled-text-field.js'
4
+ import { css, html } from 'lit'
5
+ import { customElement, state } from 'lit/decorators.js'
6
+ import { client, PageView, navigate } from '@things-factory/shell/client'
7
+ import gql from 'graphql-tag'
8
+
9
+ @customElement('label-studio-project-create')
10
+ export class LabelStudioProjectCreate extends PageView {
11
+ static styles = [
12
+ css`
13
+ :host {
14
+ display: flex;
15
+ flex-direction: column;
16
+ padding: 20px;
17
+ max-width: 800px;
18
+ margin: 0 auto;
19
+ }
20
+
21
+ h2 {
22
+ margin: 0 0 20px 0;
23
+ color: var(--md-sys-color-on-surface);
24
+ }
25
+
26
+ .form-field {
27
+ margin-bottom: 20px;
28
+ }
29
+
30
+ .form-field label {
31
+ display: block;
32
+ margin-bottom: 8px;
33
+ color: var(--md-sys-color-on-surface);
34
+ font-weight: 500;
35
+ }
36
+
37
+ md-filled-text-field {
38
+ width: 100%;
39
+ }
40
+
41
+ textarea {
42
+ width: 100%;
43
+ min-height: 200px;
44
+ padding: 12px;
45
+ border: 1px solid var(--md-sys-color-outline);
46
+ border-radius: 4px;
47
+ font-family: monospace;
48
+ font-size: 14px;
49
+ resize: vertical;
50
+ }
51
+
52
+ .actions {
53
+ display: flex;
54
+ gap: 10px;
55
+ justify-content: flex-end;
56
+ margin-top: 20px;
57
+ }
58
+
59
+ .template-examples {
60
+ margin-top: 20px;
61
+ padding: 15px;
62
+ background: var(--md-sys-color-surface-variant);
63
+ border-radius: 8px;
64
+ }
65
+
66
+ .template-examples h4 {
67
+ margin: 0 0 10px 0;
68
+ }
69
+
70
+ .template-btn {
71
+ margin: 5px;
72
+ }
73
+
74
+ .error {
75
+ color: var(--md-sys-color-error);
76
+ margin: 10px 0;
77
+ }
78
+ `
79
+ ]
80
+
81
+ @state() title: string = ''
82
+ @state() description: string = ''
83
+ @state() labelConfig: string = ''
84
+ @state() saving: boolean = false
85
+ @state() error: string = ''
86
+
87
+ render() {
88
+ return html`
89
+ <h2>Create Label Studio Project</h2>
90
+
91
+ <div class="form-field">
92
+ <label>Project Title *</label>
93
+ <md-filled-text-field
94
+ .value=${this.title}
95
+ @input=${(e: any) => (this.title = e.target.value)}
96
+ placeholder="Enter project title"
97
+ ></md-filled-text-field>
98
+ </div>
99
+
100
+ <div class="form-field">
101
+ <label>Description</label>
102
+ <md-filled-text-field
103
+ .value=${this.description}
104
+ @input=${(e: any) => (this.description = e.target.value)}
105
+ placeholder="Enter project description"
106
+ ></md-filled-text-field>
107
+ </div>
108
+
109
+ <div class="form-field">
110
+ <label>Label Configuration (XML) *</label>
111
+ <textarea
112
+ .value=${this.labelConfig}
113
+ @input=${(e: any) => (this.labelConfig = (e.target as HTMLTextAreaElement).value)}
114
+ placeholder='<View>&#10; <Text name="text" value="$text"/>&#10; <Choices name="label" toName="text">&#10; <Choice value="Positive"/>&#10; <Choice value="Negative"/>&#10; </Choices>&#10;</View>'
115
+ ></textarea>
116
+ </div>
117
+
118
+ <div class="template-examples">
119
+ <h4>Quick Templates</h4>
120
+ <md-filled-button class="template-btn" @click=${() => this.useTemplate('text-classification')}>
121
+ Text Classification
122
+ </md-filled-button>
123
+ <md-filled-button class="template-btn" @click=${() => this.useTemplate('image-classification')}>
124
+ Image Classification
125
+ </md-filled-button>
126
+ <md-filled-button class="template-btn" @click=${() => this.useTemplate('ner')}>
127
+ Named Entity Recognition
128
+ </md-filled-button>
129
+ </div>
130
+
131
+ ${this.error ? html`<div class="error">${this.error}</div>` : ''}
132
+
133
+ <div class="actions">
134
+ <md-text-button @click=${this.cancel}>Cancel</md-text-button>
135
+ <md-filled-button @click=${this.save} ?disabled=${this.saving}>
136
+ ${this.saving ? 'Creating...' : 'Create Project'}
137
+ </md-filled-button>
138
+ </div>
139
+ `
140
+ }
141
+
142
+ useTemplate(type: string) {
143
+ const templates = {
144
+ 'text-classification': `<View>
145
+ <Text name="text" value="$text"/>
146
+ <Choices name="sentiment" toName="text" choice="single">
147
+ <Choice value="Positive"/>
148
+ <Choice value="Negative"/>
149
+ <Choice value="Neutral"/>
150
+ </Choices>
151
+ </View>`,
152
+ 'image-classification': `<View>
153
+ <Image name="image" value="$image"/>
154
+ <Choices name="choice" toName="image" choice="single">
155
+ <Choice value="Cat"/>
156
+ <Choice value="Dog"/>
157
+ <Choice value="Bird"/>
158
+ </Choices>
159
+ </View>`,
160
+ ner: `<View>
161
+ <Text name="text" value="$text"/>
162
+ <Labels name="label" toName="text">
163
+ <Label value="Person" background="red"/>
164
+ <Label value="Organization" background="darkorange"/>
165
+ <Label value="Location" background="blue"/>
166
+ </Labels>
167
+ </View>`
168
+ }
169
+
170
+ this.labelConfig = templates[type] || ''
171
+ }
172
+
173
+ async save() {
174
+ if (!this.title || !this.labelConfig) {
175
+ this.error = 'Title and Label Configuration are required'
176
+ return
177
+ }
178
+
179
+ try {
180
+ this.saving = true
181
+ this.error = ''
182
+
183
+ const response = await client.mutate({
184
+ mutation: gql`
185
+ mutation CreateProject($input: CreateProjectInput!) {
186
+ createLabelStudioProject(input: $input) {
187
+ id
188
+ title
189
+ }
190
+ }
191
+ `,
192
+ variables: {
193
+ input: {
194
+ title: this.title,
195
+ description: this.description || undefined,
196
+ labelConfig: this.labelConfig
197
+ }
198
+ }
199
+ })
200
+
201
+ const project = response.data.createLabelStudioProject
202
+
203
+ // Navigate to project list
204
+ navigate('label-studio-project-list')
205
+ } catch (error: any) {
206
+ console.error('Failed to create project:', error)
207
+ this.error = error.message || 'Failed to create project'
208
+ } finally {
209
+ this.saving = false
210
+ }
211
+ }
212
+
213
+ cancel() {
214
+ navigate('label-studio-project-list')
215
+ }
216
+ }
@@ -0,0 +1,214 @@
1
+ import '@material/web/button/filled-button.js'
2
+ import '@material/web/button/outlined-button.js'
3
+ import '@material/web/icon/icon.js'
4
+ import '@material/web/iconbutton/icon-button.js'
5
+ import { css, html } from 'lit'
6
+ import { customElement, state } from 'lit/decorators.js'
7
+ import { client, PageView, navigate } from '@things-factory/shell/client'
8
+ import gql from 'graphql-tag'
9
+
10
+ @customElement('label-studio-project-list')
11
+ export class LabelStudioProjectList extends PageView {
12
+ static styles = [
13
+ css`
14
+ :host {
15
+ display: flex;
16
+ flex-direction: column;
17
+ height: 100%;
18
+ padding: 20px;
19
+ background-color: var(--md-sys-color-surface);
20
+ }
21
+
22
+ .header {
23
+ display: flex;
24
+ justify-content: space-between;
25
+ align-items: center;
26
+ margin-bottom: 20px;
27
+ }
28
+
29
+ .header h2 {
30
+ margin: 0;
31
+ color: var(--md-sys-color-on-surface);
32
+ }
33
+
34
+ .project-grid {
35
+ display: grid;
36
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
37
+ gap: 20px;
38
+ overflow-y: auto;
39
+ }
40
+
41
+ .project-card {
42
+ background: var(--md-sys-color-surface-container);
43
+ border-radius: 12px;
44
+ padding: 20px;
45
+ cursor: pointer;
46
+ transition: all 0.3s ease;
47
+ }
48
+
49
+ .project-card:hover {
50
+ background: var(--md-sys-color-surface-container-high);
51
+ transform: translateY(-2px);
52
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
53
+ }
54
+
55
+ .project-card h3 {
56
+ margin: 0 0 10px 0;
57
+ color: var(--md-sys-color-on-surface);
58
+ }
59
+
60
+ .project-card p {
61
+ margin: 5px 0;
62
+ color: var(--md-sys-color-on-surface-variant);
63
+ font-size: 14px;
64
+ }
65
+
66
+ .project-stats {
67
+ display: flex;
68
+ gap: 15px;
69
+ margin-top: 15px;
70
+ }
71
+
72
+ .stat-item {
73
+ display: flex;
74
+ flex-direction: column;
75
+ }
76
+
77
+ .stat-label {
78
+ font-size: 12px;
79
+ color: var(--md-sys-color-on-surface-variant);
80
+ }
81
+
82
+ .stat-value {
83
+ font-size: 20px;
84
+ font-weight: bold;
85
+ color: var(--md-sys-color-primary);
86
+ }
87
+
88
+ .progress-bar {
89
+ width: 100%;
90
+ height: 8px;
91
+ background: var(--md-sys-color-surface-variant);
92
+ border-radius: 4px;
93
+ margin-top: 10px;
94
+ overflow: hidden;
95
+ }
96
+
97
+ .progress-fill {
98
+ height: 100%;
99
+ background: var(--md-sys-color-primary);
100
+ transition: width 0.3s ease;
101
+ }
102
+
103
+ .loading {
104
+ display: flex;
105
+ justify-content: center;
106
+ align-items: center;
107
+ height: 100%;
108
+ font-size: 18px;
109
+ color: var(--md-sys-color-on-surface-variant);
110
+ }
111
+
112
+ .error {
113
+ color: var(--md-sys-color-error);
114
+ padding: 20px;
115
+ text-align: center;
116
+ }
117
+ `
118
+ ]
119
+
120
+ @state() projects: any[] = []
121
+ @state() loading: boolean = true
122
+ @state() error: string = ''
123
+
124
+ async pageUpdated(changes, lifecycle, changedBefore) {
125
+ if (this.active) {
126
+ this.loadProjects()
127
+ }
128
+ }
129
+
130
+ async loadProjects() {
131
+ try {
132
+ this.loading = true
133
+
134
+ const response = await client.query({
135
+ query: gql`
136
+ query {
137
+ labelStudioProjects {
138
+ id
139
+ title
140
+ description
141
+ taskCount
142
+ completedTaskCount
143
+ completionRate
144
+ createdAt
145
+ updatedAt
146
+ }
147
+ }
148
+ `
149
+ })
150
+
151
+ this.projects = response.data.labelStudioProjects
152
+ this.loading = false
153
+ } catch (error: any) {
154
+ console.error('Failed to load projects:', error)
155
+ this.error = error.message || 'Failed to load projects'
156
+ this.loading = false
157
+ }
158
+ }
159
+
160
+ createProject() {
161
+ navigate('label-studio-project-create')
162
+ }
163
+
164
+ openProject(projectId: number) {
165
+ // Open Label Studio viewer with project
166
+ navigate(`label-studio-label/${projectId}`)
167
+ }
168
+
169
+ render() {
170
+ if (this.loading) {
171
+ return html`<div class="loading">Loading projects...</div>`
172
+ }
173
+
174
+ if (this.error) {
175
+ return html`<div class="error">${this.error}</div>`
176
+ }
177
+
178
+ return html`
179
+ <div class="header">
180
+ <h2>Label Studio Projects</h2>
181
+ <md-filled-button @click=${this.createProject}>
182
+ <md-icon slot="icon">add</md-icon>
183
+ New Project
184
+ </md-filled-button>
185
+ </div>
186
+
187
+ <div class="project-grid">
188
+ ${this.projects.map(
189
+ project => html`
190
+ <div class="project-card" @click=${() => this.openProject(project.id)}>
191
+ <h3>${project.title}</h3>
192
+ <p>${project.description || 'No description'}</p>
193
+
194
+ <div class="project-stats">
195
+ <div class="stat-item">
196
+ <span class="stat-label">Tasks</span>
197
+ <span class="stat-value">${project.taskCount}</span>
198
+ </div>
199
+ <div class="stat-item">
200
+ <span class="stat-label">Completed</span>
201
+ <span class="stat-value">${project.completedTaskCount}</span>
202
+ </div>
203
+ </div>
204
+
205
+ <div class="progress-bar">
206
+ <div class="progress-fill" style="width: ${(project.completionRate * 100).toFixed(0)}%"></div>
207
+ </div>
208
+ </div>
209
+ `
210
+ )}
211
+ </div>
212
+ `
213
+ }
214
+ }