カミナシ エンジニアブログ

株式会社カミナシのエンジニアが色々書くブログです

Goでの自動化が唸るカッコいいworkflow画面を作りたい

f:id:kaminashi-developer:20201218053700p:plain

これはGo 4 Advent Calendar 2020 18日目の記事です

こんにちは株式会社カミナシのエンジニアの浦岡です。

個人的に、Goが一番輝きを放つのはworkflowの自動化だと思っています。 k8sなど自動化分野でGoはなくてはならない存在ですよね!

ただ、そのworkflow、テキストで記述するか、画面があってもフローチャートのような物が多く、どこか味けなくないでしょうか?

f:id:kaminashi-developer:20201218061918p:plain

見た目大事!!

少しジャンルは違いますが、こちらIntegromatというiPaaSのworkflow画面です。なんとも個性的じゃないですか?幾何学的なデザインが自動化魂に火をつけてくれます🔥🔥

f:id:kaminashi-developer:20201218053945p:plain

「よし、Workflow作るぞ!」と思い立ったユーザーを盛り立ててくれる演出があってもいいのではないでしょうか? 今回モックレベル(見た目だけ)ですが、それっぽい物ができるかチャレンジします!

※GoのAdvent Calendarですが、Goのソースは一切出てきません🙏

チャレンジ

workflowはブラウザ上で扱えるように、webアプリとして作成します。 フレームワークには、Goと同じくgoogle製のAngularを使ってみます。

具体的には以下のworkflowの構成要素を作ります。

f:id:kaminashi-developer:20201218054419p:plain
言葉の定義

ノードの作成

まず、以下の構成でノードとソケットを作ります。

f:id:kaminashi-developer:20201218054724p:plain

ノードはドラッグ操作で移動できるように、Angular CDKのDrag and Dropを使用。

<div class="node" cdkDrag (cdkDragMoved)="handleDragMoved($event)" [cdkDragFreeDragPosition]="node.initialPosition"
 (cdkDragMoved)="handleDragMoved($event)">
   <input-socket *ngIf="node.inputSocket"></input-socket>
   <div class="circle">
     {{node.icon}}
   </div>
   <div class="title">{{node.title}}</div>
   <output-socket *ngIf="node.outputSocket"></output-socket>
</div>

下のようなjsonを基にノードが描画されます。

f:id:kaminashi-developer:20201218055249p:plain

パスの作成

次にノード間を連結するパスで、これはCSSではなくSVGでレイアウトするようにしました。 SVG要素として表現することで、後々アニメーションなども仕込みやすくなるはずです。

<div class="svg-area">
 <svg class="full-screen">
   <path *ngFor="let path of paths" class="svg-path" stroke-dasharray="7, 5" [attr.d]="getD(path)" />
 </svg>
</div>

<node *ngFor="let node of nodes" [node]="node" (changePosition)="handleChangeNodePosition($event)"></node>

SVGのpathタグでベジェ曲線も表現することができます。

public static getD(startPosition: Position, endPosition: Position): string {
   const hx1 =
     startPosition.x + Math.abs(endPosition.x - startPosition.x) * 0.8;
   const hx2 = endPosition.x - Math.abs(endPosition.x - startPosition.x) * 0.8;

   return `M ${startPosition.x} ${startPosition.y} C ${hx1} ${
     startPosition.y
   } ${hx2} ${endPosition.y} ${endPosition.x} ${endPosition.y}`;
 }

パスは下のようなfrom, toのノードのidだけ持たせたjsonです。

f:id:kaminashi-developer:20201218055726p:plain

と、かなり中途半端なところでタイムアップしてしまいました、今回作ったソースはこちら stackblitz.com

今後について

  • データ構造は見直す必要ありそうです(AWS Step Functionsあたりが参考になるかもしれません)
  • monacoエディター組み込んでソース記述できるようになると便利そう

などなど

完成までの道のりは遠そうですが、まずはworkflowの定義情報をjsonファイルなりでインポート/エクスポートできるところを目指したいところです。(需要ありそうであれば、続き書きます)