@things-factory/integration-ui 10.0.0-beta.95 → 10.0.0-beta.96

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.
@@ -1,7 +1,6 @@
1
1
  import '@material/web/button/filled-button.js'
2
2
  import '@material/web/button/outlined-button.js'
3
3
  import '@material/web/button/text-button.js'
4
- import '@material/web/textfield/outlined-text-field.js'
5
4
  import '@material/web/icon/icon.js'
6
5
 
7
6
  import gql from 'graphql-tag'
@@ -9,6 +8,7 @@ import { LitElement, css, html } from 'lit'
9
8
  import { customElement, property, state } from 'lit/decorators.js'
10
9
  import { client } from '@operato/graphql'
11
10
  import { notify } from '@operato/layout'
11
+ import { OxPropertyEditor } from '@operato/property-editor'
12
12
  import { i18next, localize } from '@operato/i18n'
13
13
 
14
14
  interface Resolution {
@@ -253,13 +253,7 @@ export class EnvVarQuickEditor extends localize(i18next)(LitElement) {
253
253
 
254
254
  ${this._renderScopePanel(isLocal, isInherited)}
255
255
 
256
- <md-outlined-text-field
257
- label=${i18next.t('field.value')}
258
- type=${this.isSecret ? 'password' : 'text'}
259
- .value=${this.editedValue}
260
- @input=${(e: any) => (this.editedValue = e.target.value)}
261
- ?disabled=${this.busy}
262
- ></md-outlined-text-field>
256
+ ${this._renderValueInput()}
263
257
  </div>
264
258
 
265
259
  <div class="actions">
@@ -278,6 +272,101 @@ export class EnvVarQuickEditor extends localize(i18next)(LitElement) {
278
272
  `
279
273
  }
280
274
 
275
+ /**
276
+ * 입력 control 은 플랫폼의 OxPropertyEditor 레지스트리에서 propSpec.type 에
277
+ * 등록된 element 를 그대로 사용. parameters builder 가 task params 화면에서
278
+ * 쓰는 것과 동일한 editor 를 EnvVar 편집기에도 노출 — 일관된 UX, 단일 진실 원천.
279
+ *
280
+ * EnvVar 저장 값은 항상 문자열. 비-string 값 (number/boolean/object) 은
281
+ * 직렬화/역직렬화. select 의 경우 option.value 가 string 이라 자연 동작.
282
+ */
283
+ private _renderValueInput() {
284
+ // host 만 lit-html 로 렌더. 실제 editor element 는 updated() 에서 imperative.
285
+ // secret 은 OxPropertyEditor 의 password editor 가 부족할 수 있어 별도 처리.
286
+ if (this.isSecret) {
287
+ return html`
288
+ <input
289
+ part="secret-input"
290
+ type="password"
291
+ .value=${this.editedValue}
292
+ @input=${(e: any) => (this.editedValue = e.target.value)}
293
+ ?disabled=${this.busy}
294
+ style="width:100%; padding:8px; box-sizing:border-box;"
295
+ />
296
+ `
297
+ }
298
+ return html`<div id="editor-host"></div>`
299
+ }
300
+
301
+ private _editorEl: HTMLElement | null = null
302
+ private _editorChangeBound: ((e: Event) => void) | null = null
303
+
304
+ protected updated(changed: Map<string, unknown>) {
305
+ super.updated?.(changed)
306
+ if (this.isSecret) return
307
+ if (changed.has('propSpec') || !this._editorEl) {
308
+ this._mountEditor()
309
+ } else if (changed.has('editedValue') && this._editorEl) {
310
+ // 외부에서 editedValue 변경 시 editor 도 동기화
311
+ const cur = (this._editorEl as any).value
312
+ if (cur !== this.editedValue) (this._editorEl as any).value = this.editedValue
313
+ }
314
+ }
315
+
316
+ private _mountEditor() {
317
+ const host = this.renderRoot.querySelector('#editor-host') as HTMLElement | null
318
+ if (!host) return
319
+ host.replaceChildren()
320
+ this._cleanupEditorListener()
321
+
322
+ const spec = this.propSpec || {}
323
+ const type = spec.type || 'string'
324
+ const elementType = OxPropertyEditor.getEditor(type)
325
+ if (!elementType) {
326
+ // 등록 editor 없음 — fallback 으로 단순 text input
327
+ const fallback = document.createElement('input')
328
+ fallback.type = 'text'
329
+ fallback.style.cssText = 'width:100%; padding:8px; box-sizing:border-box;'
330
+ fallback.value = this.editedValue || ''
331
+ fallback.addEventListener('input', () => (this.editedValue = fallback.value))
332
+ host.appendChild(fallback)
333
+ this._editorEl = fallback
334
+ return
335
+ }
336
+
337
+ const el = document.createElement(elementType) as any
338
+ el.label = spec.label || i18next.t('field.value')
339
+ el.type = type
340
+ el.placeholder = spec.placeholder || ''
341
+ el.property = spec.property
342
+ el.editor = spec.editor
343
+ el.value = this.editedValue || (type === 'checkbox' ? false : '')
344
+
345
+ // editor 의 change event 를 받아 editedValue 동기화. EnvVar 는 문자열 저장이라
346
+ // value 가 boolean/number 면 String() 변환.
347
+ const onChange = () => {
348
+ const v = el.value
349
+ this.editedValue = v == null ? '' : typeof v === 'string' ? v : String(v)
350
+ }
351
+ el.addEventListener('change', onChange)
352
+ this._editorChangeBound = onChange
353
+ host.appendChild(el)
354
+ this._editorEl = el
355
+ }
356
+
357
+ private _cleanupEditorListener() {
358
+ if (this._editorEl && this._editorChangeBound) {
359
+ this._editorEl.removeEventListener('change', this._editorChangeBound)
360
+ }
361
+ this._editorChangeBound = null
362
+ this._editorEl = null
363
+ }
364
+
365
+ disconnectedCallback() {
366
+ this._cleanupEditorListener()
367
+ super.disconnectedCallback()
368
+ }
369
+
281
370
  private _cancel() {
282
371
  this.dispatchEvent(new CustomEvent('cancel', { bubbles: true, composed: true }))
283
372
  }