mcpField
I
integrate-file-viewer

integrate-file-viewer

github.com/cognitedataドキュメント61.9k 回インストール1 日前に更新
リポジトリ

integrate-file-viewer について

Cognite Flows アプリに CogniteFileViewer を組み込み、CDF ファイルをプレビューするためのスキルです。コンポーネントの配置、依存関係と Vite の設定に加え、対応形式や注釈、操作方法を説明します。

主な機能

  1. 01PDF、Office 文書、画像、テキストのプレビュー
  2. 02PDF のページ移動とズーム
  3. 03画像のズーム、パン、回転
  4. 04関連する図面注釈の表示
  5. 05タッチ操作とカーソル位置へのズーム

活用シーン

  1. 01Flows アプリに CDF ファイルのプレビューを追加
  2. 02PDF の図面注釈を確認し、リンク先ファイルを開く
  3. 03タッチデバイスで文書をパン、ズーム
  4. 04テキスト、画像、Office ファイルを表示

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/cognitedata/builder-skills --skill integrate-file-viewer

インストール後、Claude Code で/integrate-file-viewerを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

code/
CogniteFileViewer.tsx
DocumentAnnotationOverlay.tsx
fileResolution.ts
index.ts
mimeTypes.ts
types.ts
useDocumentAnnotations.ts
useFileResolver.ts
useViewport.ts

詳細

CogniteFileViewer を統合する

この Flows アプリに CogniteFileViewer を追加し、CDF ファイル(PDF、画像、テキスト)をプレビューできるようにします。

依存関係

ファイルビューアーのライブラリファイル(ステップ 2 でコピー)は、次の npm パッケージを必要とします。

パッケージバージョン
react-pdf^9.1.1

pdfjs-dist は適切なバージョンの react-pdf の依存関係として含まれています。別途インストールしないでください。 react と @cognite/sdk は、Flows アプリにすでに含まれていることを前提としています。


作業内容

以下の手順を順番に完了してください。変更する前に各ファイルを読んでください。


ステップ 1 — アプリを理解する

作業を始める前に、次のファイルを読んでください。

  • package.json — パッケージマネージャー(packageManager フィールドまたはロックファイル)と既存の依存関係を確認します
  • vite.config.ts — 現在の Vite 設定を確認します
  • ビューアーを追加するコンポーネント

ステップ 2 — ファイルビューアーのソースファイルをコピーする

ファイルビューアーのライブラリは、このスキルファイルと同じ階層の code/ ディレクトリにあります。そこにあるすべてのファイルを読み、アプリ内の src/cognite-file-viewer/ にコピーしてください。

  • code/types.ts
  • code/mimeTypes.ts
  • code/fileResolution.ts
  • code/useViewport.ts
  • code/useFileResolver.ts
  • code/useDocumentAnnotations.ts
  • code/DocumentAnnotationOverlay.tsx
  • code/CogniteFileViewer.tsx
  • code/index.ts

PDF.js ワーカーは CogniteFileViewer.tsx 内で設定されるため、利用側で別途設定する必要はありません。


ステップ 3 — 依存関係をインストールする

アプリのパッケージマネージャーを使って、上記の依存関係に記載されている react-pdf をインストールしてください。

  • pnpm → pnpm add react-pdf@^9.1.1
  • npm → npm install react-pdf@^9.1.1
  • yarn → yarn add react-pdf@^9.1.1

pnpm をお使いの場合: pnpm の厳密なリンク設定により、ブラウザーが pdfjs-dist を解決できないことがあります。pdfjs-dist を直接の依存関係として追加する(pnpm add pdfjs-dist)か、.npmrc に public-hoist-pattern[]=pdfjs-dist を追加してください。


ステップ 4 — Vite を設定する

Vite が pdfjs-dist を事前バンドルしないように(事前バンドルするとワーカーが動作しなくなります)、vite.config.ts に optimizeDeps.exclude: ['pdfjs-dist'] を追加してください。

export default defineConfig({
  // ... existing config ...
  optimizeDeps: {
    exclude: ['pdfjs-dist'],
  },
});

ステップ 5 — コンポーネントを使用する

ローカルにコピーしたファイルから CogniteFileViewer をインポートして、レンダリングしてください。

import { CogniteFileViewer } from './cognite-file-viewer';

useDune() フックから sdk を取得してください(すべての Flows アプリで利用できます)。

import { useDune } from '@cognite/dune';
const { sdk } = useDune();
対応ファイル形式
種類形式
PDF.pdf — ページ移動、ズーム、パン、図面の注釈オーバーレイ
Office ドキュメントWord、PowerPoint、Excel、ODS、ODP、ODT、RTF、TSV — CDF Document Preview API で PDF に変換してから、PDF と同様にレンダリング
画像JPEG、PNG、WebP、SVG、TIFF — ズーム、パン、回転
テキスト.txt、.csv、.json — 書式付きテキストとしてレンダリング
その他renderUnsupported にフォールバック
最小限の使用例

必要な設定はこれだけです。ズーム、パン、タッチ操作は内部で処理されます。

<CogniteFileViewer
  source={{ type: 'internalId', id: file.id }}
  client={sdk}
  style={{ width: '100%', height: '600px' }}
/>

コンポーネントには高さの指定が必要です。 親要素に明示的な高さがない場合、ビューアーの高さは 0 になります。style、className、または親コンテナーを使って、必ず height を設定してください。

ファイルソース

次の 3 種類のソースのうち、いずれかを渡してください。

// By instance ID (data-modelled file — enables annotations)
<CogniteFileViewer
  source={{ type: 'instanceId', space: 'my-space', externalId: 'my-file' }}
  client={sdk}
/>

// By CDF internal ID
<CogniteFileViewer
  source={{ type: 'internalId', id: 12345 }}
  client={sdk}
/>

// By direct URL
<CogniteFileViewer
  source={{ type: 'url', url: 'https://...', mimeType: 'application/pdf' }}
/>

利用可能な場合は instanceId を優先してください。 図面の注釈オーバーレイを有効にできるのは、このソース形式だけです。sdk.files.list() でファイルを一覧表示する際は、まず file.instanceId を確認してください。

source={
  file.instanceId
    ? { type: 'instanceId', space: file.instanceId.space, externalId: file.instanceId.externalId }
    : { type: 'internalId', id: file.id }
}
props の全リファレンス
<CogniteFileViewer
  // Required
  source={source}
  client={sdk}              // required for instanceId and internalId sources

  // PDF pagination
  page={page}               // controlled current page (1-indexed)
  onPageChange={setPage}
  onDocumentLoad={({ numPages }) => setNumPages(numPages)}

  // Zoom & pan (works on PDF and images)
  zoom={zoom}               // 1 = 100%; Ctrl/Cmd+wheel, pinch-to-zoom, and middle-click drag built in
  onZoomChange={setZoom}
  minZoom={0.25}            // default
  maxZoom={5}               // default
  panOffset={pan}           // controlled pan offset; resets on page change
  onPanChange={setPan}

  // Fit mode
  fitMode="width"           // 'width' fits to container width; 'page' fits entire page in container

  // Rotation (PDFs and images)
  rotation={rotation}       // 0 | 90 | 180 | 270

  // Diagram annotations (instanceId sources only)
  showAnnotations={true}    // default
  onAnnotationClick={(annotation) => { /* annotation.linkedResource has space + externalId */ }}
  onAnnotationHover={(annotation) => {}}

  // Custom annotation tooltip (replaces native <title> tooltip)
  renderAnnotationTooltip={(annotation, rect) => (
    <div style={{
      position: 'absolute',
      left: rect.x + rect.width,
      top: rect.y,
      zIndex: 11,
    }}>
      {annotation.text}
    </div>
  )}

  // Custom overlay (SVG paths, highlights, drawings — works on PDF and images)
  renderOverlay={({ width, height, originalWidth, originalHeight, pageNumber, rotation }) => (
    <svg
      width={width}
      height={height}
      viewBox={`0 0 ${originalWidth} ${originalHeight}`}
      preserveAspectRatio="none"
      style={{ position: 'absolute', top: 0, left: 0, pointerEvents: 'all' }}
    >
      <path d="..." stroke="cyan" fill="none" />
    </svg>
  )}

  // Custom renderers (all optional)
  renderLoading={() => <MySpinner />}
  renderError={(error) => <MyError message={error.message} />}
  renderUnsupported={(mimeType) => <div>Cannot preview {mimeType}</div>}

  // Layout
  className="..."
  style={{ width: '100%', height: '100%' }}
/>

ヒントとテクニック

ソースの変更時に、ページ、ズーム、回転をリセットします。 ファイルを切り替えても、コンポーネントはこれらを自動的にリセットしません。自分でリセットしてください。

const navigateToFile = (file: FileInfo) => {
  setSelectedFile(file);
  setPage(1);
  setZoom(1);
  setRotation(0);
};

ページネーション UI は numPages > 0 の場合にのみ表示します。 onDocumentLoad が呼び出されるのは PDF の場合のみです。ページ数がわかるまで、ページネーションコントロールを表示しないでください。

{numPages > 0 && (
  <>
    <button disabled={page <= 1} onClick={() => setPage(p => p - 1)}>‹</button>
    <span>{page} / {numPages}</span>
    <button disabled={page >= numPages} onClick={() => setPage(p => p + 1)}>›</button>
  </>
)}

注釈のクリック → リンク先ファイルへの移動。 annotation.linkedResource には、リンク先 CDF インスタンスの space と externalId が含まれています。これらを file.instanceId と照合して移動します。

onAnnotationClick={(annotation) => {
  if (!annotation.linkedResource) return;
  const { space, externalId } = annotation.linkedResource;
  const linked = files.find(
    f => f.instanceId?.space === space && f.instanceId?.externalId === externalId
  );
  if (linked) navigateToFile(linked);
}}

タッチ操作に標準対応しています。 タッチデバイスでは、2 本指のピンチでズームし、2 本指のドラッグでパンできます。設定は不要です。

デスクトップでは、中央クリックのドラッグでパンします(ズームイン時)。左クリックは注釈のクリックとテキスト選択に使用できます。

Ctrl/Cmd + ホイールでカーソル位置を中心にズームします。これも標準で利用できます。プログラムでズームボタンを操作したり、ズーム状態を保持したりする場合は、zoom/onZoomChange を接続してください。それ以外の場合は、完全に非制御で動作します。

renderOverlay には元のページ寸法(originalWidth、originalHeight)が渡されるため、元の座標空間で SVG の viewBox を設定できます。PDF ポイントまたは画像ピクセルの座標で描画したパスは、ズームレベルにかかわらず、レンダリングされたページに正しく対応します。


よくある問題

問題原因解決方法
Failed to resolve module specifier 'pdf.worker.mjs'pdfjs-dist が hoist されていない(pnpm).npmrc に public-hoist-pattern[]=pdfjs-dist を追加するか、pnpm add pdfjs-dist を直接実行します
API version does not match Worker versionアプリと react-pdf の間で pdfjs-dist のバージョンが一致していないpdfjs-dist を個別にインストールせず、react-pdf に提供させてください。すでにインストールされている場合は削除してください
注釈が表示されないinstanceId が undefined で、これがないと注釈オーバーレイが無効になるinstanceId ソースを使用するか、従来形式のファイルでは注釈が表示されないことを受け入れ、代替手段を使用します
注釈は表示されるが中身がないファイルに CDF の CogniteDiagramAnnotation エッジがない想定どおりです。アノテーションがあるのは、データモデルに同期された P&ID/図面ファイルのみです
ビューアーの高さがゼロになる親要素に明示的な高さが設定されていないstyle、className、または親要素の CSS で height を設定します

コメント