Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

사용자 위젯의 매개변수와 이벤트

매개변수는 호스트에서 위젯으로 값을 전달하고 이벤트는 위젯에서 호스트로 변경이나 동작을 알립니다. 구성 파일 하나에는 최대 50개 매개변수와 50개 이벤트를 정의할 수 있습니다. 두 종류의 ID는 camelCase를 사용합니다.

자료형

type의미와 표현예
booleanBooleantrue, false
dateISO 8601 날짜2023-12-31
number숫자42, 3.14159
string문자열Hello World
timestamp시간대를 포함한 ISO 86012023-12-31T23:59:59.999Z
objectSet객체 집합 RIDri.object-set.main.temporary-object-set.2af08bf0-3feb-416e-9e34-ad604940581b
scenario온톨로지 시나리오 RIDri.actions..scenario.2af08bf0-3feb-416e-9e34-ad604940581b

배열은 type을 array로 두고 subType으로 기본형을 지정합니다. 객체 집합은 0개 이상의 객체를 나타낼 수 있으며 고정 목록 또는 객체 유형/인터페이스의 필터로 정의할 수 있습니다. allowedType에는 생성 OSDK의 객체 유형이나 인터페이스를 사용합니다.

scenario는 온톨로지 시나리오에만 사용할 수 있습니다. RID를 OSDK에 전달하여 격리된 시나리오의 조회와 액션을 수행합니다. Legacy Workshop 시나리오와 구분합니다.

Object set filter와 Struct는 일급 매개변수 유형으로 지원하지 않습니다.

구성과 호스트 바인딩

parameters는 ID를 키로 하는 객체입니다. 예를 들어 날짜는 {type:"date", displayName:"Start Date"}, 문자열 배열은 {type:"array", subType:"string", displayName:"Tags"}로 정의합니다.

events도 ID를 키로 합니다. 각 이벤트의 displayName과 parameterUpdateIds를 지정하며 parameterUpdateIds는 그 이벤트가 갱신할 수 있는 매개변수 ID 목록입니다.

Workshop의 Widget setup에서 매개변수를 변수에, 위젯 이벤트를 Workshop 이벤트에 연결합니다. 이벤트 하나로 매개변수 변경과 호스트 동작을 함께 구성할 수 있습니다.

문자열과 숫자 예

simpleCounter.config.ts입니다.

import { defineConfig } from "@osdk/widget.client";

export default defineConfig({
  id: "simpleCounter",
  name: "Simple Counter",
  description: "A minimal counter example",
  type: "workshop",
  parameters: {
    name: { displayName: "Name", type: "string" },
    count: { displayName: "Count", type: "number" },
  },
  events: {
    updateCount: { displayName: "Update Count", parameterUpdateIds: ["count"] },
  },
});

템플릿 진입점의 FoundryWidget에 이 config를 지정합니다. Widget.tsx는 다음과 같이 읽고 갱신합니다. 미지정 name과 count의 표시 기본값은 World와 0입니다.

import { useFoundryWidgetContext } from "@osdk/widget.client-react";
import { useCallback } from "react";
import type SimpleCounterConfig from "./simpleCounter.config.js";

const useWidgetContext = useFoundryWidgetContext.withTypes<typeof SimpleCounterConfig>();

export const Widget = () => {
  const { parameters, emitEvent } = useWidgetContext();
  const name = parameters.values.name ?? "World";
  const count = parameters.values.count ?? 0;
  const increment = useCallback(() => {
    emitEvent("updateCount", { parameterUpdates: { count: count + 1 } });
  }, [emitEvent, count]);

  return (
    <div>
      <h1>Hello, {name}!</h1>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

객체 집합 예

다음 예는 @osdk/react 2.83.0의 공개 OsdkProvider와 useObjectSet을 사용합니다. @osdk/api와 @osdk/client도 호환되는 2.83.0 구성을 기준으로 하며 생성 SDK에 Flight가 포함되어 있어야 합니다. client.ts는 위젯 런타임 클라이언트를 사용합니다.

flights.config.ts입니다.

import { Flight } from "@custom-widget/sdk";
import { defineConfig } from "@osdk/widget.client";

export default defineConfig({
  id: "flights",
  name: "Flights Example",
  description: "An example with flights",
  type: "workshop",
  parameters: {
    flights: { displayName: "Flights", allowedType: Flight, type: "objectSet" },
  },
  events: {},
});

Object set 매개변수를 쓰려면 FoundryWidget에 client를 전달합니다. React hook을 쓰는 자식은 같은 client를 받은 OsdkProvider 안에 둡니다. HTML에는 root 요소가 있어야 합니다.

import { FoundryWidget } from "@osdk/widget.client-react";
import { OsdkProvider } from "@osdk/react";
import { createRoot } from "react-dom/client";
import FlightsConfig from "./flights.config.js";
import { client } from "./client.js";
import { Widget } from "./Widget.js";

createRoot(document.getElementById("root")!).render(
  <FoundryWidget config={FlightsConfig} client={client}>
    <OsdkProvider client={client}>
      <Widget />
    </OsdkProvider>
  </FoundryWidget>,
);

매개변수를 아직 고르지 않은 화면과 조회 화면을 나누는 예입니다. 유효한 빈 객체 집합과 미설정 매개변수는 구분합니다.

import { Flight } from "@custom-widget/sdk";
import type { ObjectSet } from "@osdk/api";
import { useObjectSet } from "@osdk/react";
import { useFoundryWidgetContext } from "@osdk/widget.client-react";
import type FlightsConfig from "./flights.config.js";

const useWidgetContext = useFoundryWidgetContext.withTypes<typeof FlightsConfig>();

export const Widget = () => {
  const { parameters } = useWidgetContext();
  const flightsParam = parameters.values.flights;
  if (flightsParam == null) return <div>Select an object set</div>;
  return <FlightsView objectSet={flightsParam.objectSet} />;
};

const FlightsView = ({ objectSet }: { objectSet: ObjectSet<Flight> }) => {
  const { data: flights, isLoading, error } = useObjectSet(objectSet, { streamUpdates: false });
  if (isLoading) return <div>Loading flights...</div>;
  if (error) return <div role="alert">Error loading flights: {error.message}</div>;
  return (
    <ul>
      {flights?.map(flight => (
        <li key={String(flight.$primaryKey)}>{String(flight.$primaryKey)}</li>
      ))}
    </ul>
  );
};

useObjectSet의 data는 조회한 객체 배열 또는 undefined이고 isLoading과 error를 함께 사용합니다. 기본으로 첫 페이지를 읽으며, 추가 페이지는 hook의 fetchMore/hasMore 계약을 사용합니다. 위 예는 현재 읽은 항목을 표시합니다.

현재 hook은 undefined 입력도 받을 수 있지만 위 예는 미설정 안내를 별도 컴포넌트로 구분합니다. 사용자 위젯 런타임은 객체 집합 구독을 지원하지 않으므로 streamUpdates를 켜지 않습니다.

매개변수값에는 객체 집합 RID와 편의를 위한 OSDK objectSet이 포함됩니다. 집합 정의가 바뀌거나 호스트가 데이터를 무효화하면 RID와 인스턴스도 갱신됩니다.

객체 집합 갱신

갱신 기능을 추가한 flights.config.ts의 전체 구성입니다.

import { Flight } from "@custom-widget/sdk";
import { defineConfig } from "@osdk/widget.client";

export default defineConfig({
  id: "flights",
  name: "Flights Example",
  description: "An example with flights",
  type: "workshop",
  parameters: {
    flights: { displayName: "Flights", allowedType: Flight, type: "objectSet" },
  },
  events: {
    updateFlights: {
      displayName: "Update Flights",
      parameterUpdateIds: ["flights"],
    },
  },
});

다음 컴포넌트는 숫자 duration 속성이 있는 Flight를 전제로 전체 Flight 집합에서 duration이 500보다 큰 새 집합을 정의합니다. 단위는 실제 객체 속성의 계약을 따릅니다.

import { Flight } from "@custom-widget/sdk";
import { useFoundryWidgetContext } from "@osdk/widget.client-react";
import { useCallback } from "react";
import { client } from "./client.js";
import type FlightsConfig from "./flights.config.js";

const useWidgetContext = useFoundryWidgetContext.withTypes<typeof FlightsConfig>();

export const Widget = () => {
  const { emitEvent } = useWidgetContext();
  const filterToLongFlights = useCallback(() => {
    const longFlights = client(Flight).where({ duration: { $gt: 500 } });
    emitEvent("updateFlights", { parameterUpdates: { flights: longFlights } });
  }, [emitEvent]);
  return <button onClick={filterToLongFlights}>Show Long Flights</button>;
};

SDK는 ObjectSet 정의로 임시 집합을 만들고 그 RID를 호스트에 전달합니다. 같은 이벤트를 빠르게 여러 번 발생시키면 마지막 호출만 전달하고 이전 호출은 버립니다. 임시 집합을 만드는 도중의 네트워크 오류 등은 호출자에게 노출되지 않습니다.

OSDK 액션으로 집합의 데이터를 편집하는 경우에는 refreshHostDataOnAction을 사용할 수 있습니다.

호스트 화면에 맞추기

같은 저장소에서 기능을 나누려면 위젯을 추가합니다. 표시에는 부모 테마와 자동 크기를 적용할 수 있습니다. 외부 화면으로 이동하는 동작은 Workshop의 URL 열기에 연결합니다.