2023年12月31日日曜日

Cozy Web/グリッド内カードのカスタマイズ

モデル駆動開発のエコシステムのキーパーツとして、Webアプリケーション・フレームワークのCozy Webを紹介しています。

前回はWebフロントエンド・フレームワークBootstrapの上でグリッド表示を行いました。

今回はグリッド内に配置されるカードをカスタマイズする方法について説明します。

HelloGrid

前回作成したリソースのグリッド表示を行うHelloGridを使用します。

HelloGridはBootstrap 5を使ってグリッド表示を行います。

Cozy Web/Webライブラリで紹介したWebライブラリ機能を使用してBootstrap 5をサポートするBootstrap5ライブラリを使用しています。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloGridを作成します。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義します。これはHelloResourceと同じ設定です。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しており、Webのリソースproductとなります。

webapp.conf

ホームディレクトリのWEB-INFディレクトリ配下にwebapp.confを配置し、Bootstrap5ライブラリの名前である「bootstrap5」をextend属性に設定します。この設定を行うことで、Bootstrap5ライブラリがWebアプリケーションのベースとして設定されます。

またthemeにbootstrap-gridを設定します。この設定により一覧表示がグリッドで表示されます。

ここまでが前回の設定です。

extend: bootstrap5
theme: bootstrap-grid

今回はグリッドの表示方法をカスタマイズします。

このためにwebapp.confに以下のようにrender.card_kind_in_gridを設定します。

render.card_kind_in_gridに"grid"を指定しているので、card__gridという名前のウィジェットがグリッド内のカードの表示に使用されます。

extend: bootstrap5
theme: bootstrap-grid
render.card_kind_in_grid: "grid"

カードの表示内容の設定

グリッド内にカードを表示するときに使用するウィジェットcard_gridを作成します。

以下のJade形式の card__grid.jade 作成し、WEB-INF/widgets配下に配置します。

-@val card: ViewCard
div.card
  div.card-header
    h4.card-title
      =card.header

ファイル名card__grid.jadeの「card」はウィジェット種別を表しこの場合はカードを示します。「__」の後のgridはウィジェットの名前を表します。

カードを記述するDIV要素以下をカードの部品として定義しています。部品内ではHTMLの要素を自由に使うことができます。

部品内のHTML要素ではBootstrapで定義されているcard, card-header, card-titleといったクラス属性を指定しているので、Bootstrapによって適切な表示が行われます。

また、カードの表示に必要な情報はViewCardオブジェクトとして渡されてくるので、ここから必要な情報を取り出してウィジェット内のHTML要素に埋め込んでいきます。ここではカードのヘッダ情報をH4要素に入れています。

グリッド表示

それでは、グリッド表示を行います。

Webブラウザ

productリソースに対するアクセスを行います。

http://localhost:8080/web/HelloGrid/product

webページの表示のために出力されたHTML文書は以下になります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8"/>
    <meta content="width=device-width, initial-scale=1" name="viewport"/>
    <link crossorigin="anonymous" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"/>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css"/>
    <style>
      .card a {
      color: inherit;
      text-decoration: none;
      }
      .card:hover {
      background-color: #f8f9fa;
      border-color: #007bff;
      }
    </style>
  </head>
  <body>
    <script crossorigin="anonymous" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"/>
    <nav class="navbar navbar-light bg-primary">
      <div class="container-fluid">
        <span class="navbar-brand mb-0 h1">Cozy Web</span>
      </div>
    </nav>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
      <div class="container-fluid">
        <a class="navbar-brand" href="#">Navbar</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"/>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
          <ul class="navbar-nav">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Features</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Pricing</a>
            </li>
            <li class="nav-item">
              <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
            </li>
          </ul>
        </div>
      </div>
    </nav>
    <div class="container">
      <div class="row">
        <div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
          <div class="card">
            <div class="card-header">
              <h4 class="card-title">
          Apple
        </h4>
            </div>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
          <div class="card">
            <div class="card-header">
              <h4 class="card-title">
          Orange
        </h4>
            </div>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
          <div class="card">
            <div class="card-header">
              <h4 class="card-title">
          Peach
        </h4>
            </div>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
          <div class="card">
            <div class="card-header">
              <h4 class="card-title">
          Berry
        </h4>
            </div>
          </div>
        </div>
      </div>
    </div>
    <nav class="navbar navbar-light bg-secondary">
      <span>Cozy Web</span>
    </nav>
  </body>
</html>

前回のグリッド表示ではカード部分は以下のHTML断片になっていました。

          <div class="card">
            <a href="product/1.html" class="">
              <img src="assets/img/no-image-icon.png" class="card-img-top"/>
              <div class="card-header">
                <h4 class="card-title">Apple</h4>
              </div>
            </a>
          </div>

今回は、以下のHTML断片になっており、グリッド内のカードはcard__grid.jadeで定義したものが使用されています。

          <div class="card">
            <div class="card-header">
              <h4 class="card-title">
          Apple
        </h4>
            </div>
          </div>

まとめ

Cozy Webでリソースの定義をすることで、Webアプリケーションが簡単に作成できることを確認してきました。

今回はBootstrapによるレスポンシブル・デザインによるグリッド表示のカードをカスタマイズする方法について説明しました。

モデルの定義とカスタマイズしたカードの定義以外はほとんどノープログラミングでレスポンシブルなWebアプリケーションの作成ができることを確認することができました。

諸元

Cozy
0.0.16

2023年11月30日木曜日

Cozy Web/グリッド

モデル駆動開発のエコシステムのキーパーツとして、Webアプリケーション・フレームワークのCozy Webを紹介しています。

数回に渡りリソースの一覧表示の方法について見てきました。その一環でグリッドとカードによる一覧表示を取り上げます。グリッドとカードによる覧表表示はHTMLの標準機能では用意されていないので、この機能をサポートしているWebフロントエンド・フレームワークBootstrapを導入し、その上でグリッドとカードによるリソースの一覧表示を行うことにします。

HelloGrid

リソースのグリッド表示を行うHelloGridを作成します。

HelloGridはBootstrap 5を使ってグリッド表示を行います。

Cozy Web/Webライブラリで紹介したWebライブラリ機能を使用してBootstrap 5をサポートするBootstrap5ライブラリを使用します。Cozy Web/Webライブラリで紹介したWebライブラリ機能を使用してBootstrap 5をサポートするBootstrap5ライブラリを使用します。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloGridを作成します。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義します。これは前回まで使用していたHelloResourceと同じ設定です。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しており、Webのリソースproductとなります。

webapp.conf

ホームディレクトリのWEB-INFディレクトリ配下にwebapp.confを配置し、Bootstrap5ライブラリの名前である「bootstrap5」をextend属性に設定します。この設定を行うことで、Bootstrap5ライブラリがWebアプリケーションのベースとして設定されます。

extend: bootstrap5

一覧表示

CozyのWebライブラリBootstrap5はデフォルトでは、tableタグを使った一覧表示を行います。

Webブラウザ

前回と同様にproductリソースに対するアクセスを行います。

http://localhost:8080/web/HelloGrid/product

Cozy Web/Webライブラリで説明したとおり、WebライブラリBootstrapでは、ナビゲーションバーやヘッダー、フッターを使用した画面レイアウトになります。Cozy Web/Webライブラリで説明したとおり、WebライブラリBootstrapでは、ナビゲーションバーやヘッダー、フッターを使用した画面レイアウトになります。

画面内のコンテンツの部分にBootstrapによって綺麗にレイアウトされた表が表示されました。

HTML

webページの表示のために出力されたHTMLは以下になります。

tableタグにはBootstrap用のclass属性が設定されているため、Bootstrap標準の綺麗な表が出力されます。

<?xml version="1.0"?>
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8"/>
    <meta content="width=device-width, initial-scale=1" name="viewport"/>
    <link crossorigin="anonymous" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"/>
    <style>
      .card a {
      color: inherit;
      text-decoration: none;
      }
      .card:hover {
      background-color: #f8f9fa;
      border-color: #007bff;
      }
    </style>
  </head>
  <body>
    <script crossorigin="anonymous" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"/>
    <nav class="navbar navbar-light bg-primary">
      <div class="container-fluid">
        <span class="navbar-brand mb-0 h1">Cozy Web</span>
      </div>
    </nav>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
      <div class="container-fluid">
        <a class="navbar-brand" href="#">Navbar</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"/>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
          <ul class="navbar-nav">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Features</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Pricing</a>
            </li>
            <li class="nav-item">
              <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
            </li>
          </ul>
        </div>
      </div>
    </nav>
    <div class="table-responsive">
      <table class="table">
        <caption class="">product</caption>
        <thead class="">
          <tr class="">
            <th class="" scope="col">Id</th>
            <th class="" scope="col">Name</th>
            <th class="" scope="col">Price</th>
          </tr>
        </thead>
        <tbody class="">
          <tr data-href="product/1.html">
            <td class="">1</td>
            <td class="">Apple</td>
            <td class="">300</td>
          </tr>
          <tr data-href="product/2.html">
            <td class="">2</td>
            <td class="">Orange</td>
            <td class="">350</td>
          </tr>
          <tr data-href="product/3.html">
            <td class="">3</td>
            <td class="">Peach</td>
            <td class="">400</td>
          </tr>
          <tr data-href="product/4.html">
            <td class="">4</td>
            <td class="">Berry</td>
            <td class="">450</td>
          </tr>
        </tbody>
      </table>
    </div>
    <nav class="navbar navbar-light bg-secondary">
      <span>Cozy Web</span>
    </nav>
  </body>
</html>

グリッド

それでは、グリッド表示を行います。

webapp.conf

Bootstrapアプリケーションの一覧表示のデフォルト設定をwebapp.confに設定することができます。

webapp.confのthemeにテーマbootstrap-gridを設定します。

テーマbootstrap-gridは一覧表示のデフォルト設定をグリッドにしたテーマです。

extend: bootstrap5
theme: bootstrap-grid

Webブラウザ

productリソースに対するアクセスを行います。

http://localhost:8080/web/HelloGrid/product

表示結果は以下になります。

無事Bootstrapのグリッド表示になります。グリッド内にはリソースの内容を記述するカードが表示されています。

デフォルトでは、カード内にはリソースの内容を表す画像どリソースの名前が表示されます。productでは画像の情報は持っていないので、画像なしを示す画像が表示されています。

Bootstrapのグリッドは画面サイズを変えても適切にレイアウトが行われます。先ほどのWebページの横幅を小さく縮めたWebページが以下になります。

HTML

webページの表示のために出力されたHTMLは以下になります。

グリッド内のカードはclass属性にcardが設定されたdevタグで記述されています。

<?xml version="1.0"?>
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8"/>
    <meta content="width=device-width, initial-scale=1" name="viewport"/>
    <link crossorigin="anonymous" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"/>
    <style>
      .card a {
      color: inherit;
      text-decoration: none;
      }
      .card:hover {
      background-color: #f8f9fa;
      border-color: #007bff;
      }
    </style>
  </head>
  <body>
    <script crossorigin="anonymous" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"/>
    <nav class="navbar navbar-light bg-primary">
      <div class="container-fluid">
        <span class="navbar-brand mb-0 h1">Cozy Web</span>
      </div>
    </nav>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
      <div class="container-fluid">
        <a class="navbar-brand" href="#">Navbar</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"/>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
          <ul class="navbar-nav">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Features</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Pricing</a>
            </li>
            <li class="nav-item">
              <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
            </li>
          </ul>
        </div>
      </div>
    </nav>
    <div class="container">
      <div class="row">
        <div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
          <div class="card">
            <a href="product/1.html" class="">
              <img src="assets/img/no-image-icon.png" class="card-img-top"/>
              <div class="card-header">
                <h4 class="card-title">Apple</h4>
              </div>
            </a>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
          <div class="card">
            <a href="product/2.html" class="">
              <img src="assets/img/no-image-icon.png" class="card-img-top"/>
              <div class="card-header">
                <h4 class="card-title">Orange</h4>
              </div>
            </a>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
          <div class="card">
            <a href="product/3.html" class="">
              <img src="assets/img/no-image-icon.png" class="card-img-top"/>
              <div class="card-header">
                <h4 class="card-title">Peach</h4>
              </div>
            </a>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
          <div class="card">
            <a href="product/4.html" class="">
              <img src="assets/img/no-image-icon.png" class="card-img-top"/>
              <div class="card-header">
                <h4 class="card-title">Berry</h4>
              </div>
            </a>
          </div>
        </div>
      </div>
    </div>
    <nav class="navbar navbar-light bg-secondary">
      <span>Cozy Web</span>
    </nav>
  </body>
</html>

まとめ

前回まではCozy Webでリソースの定義をすることで、Webアプリケーションが簡単に作成できることを説明しました。

今回は画面の表示方法のカスタマイズとして、グリッド表示を取り上げました。

テーマの設定のみで一覧表示をtableタグによる表からBootstrapならではのグリッド表示にすることができました。また、グリッド表示はBootstrapの機能により画面サイズに従って適切なレイアウトが行われることが確認できました。

モデルの定義以外はほとんどノープログラミングでWebアプリケーションの作成ができることが分かりました。

次回はグリッド表示のカスタマイズ方法について取り上げる予定です。

諸元

Cozy
0.0.15

2023年10月31日火曜日

Cozy Web上でエンティティのモデル定義によって設定されたリソースの一覧アクセスをノンプログラミングで行う方法についてみています。

前回はリソースの一覧表示の機能機能について説明します。

今回はページング機能について説明します。

HelloResource

リソースの作成・更新処理の題材としてHelloResourceを定義しました。

このHelloResourceを使用して、リソースの一覧表示の方法についてみています。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しています。

これがWebのリソースproductとなります。

トップページ

トップページとしてホームディレクトリに以下のindex.htmlを配備しています。これは前回と同様です。

<html>
    <head>
	<title>HelloResource</title>
    </head>
    <body>
	<ul>
	    <li><a href="product">List</a></li>
	    <li><a href="product/_create_">Create</a></li>
	    <li><a href="product/_update_">Update</a></li>
	    <li><a href="product/_delete_">Delete</a></li>
	</ul>
    </body>
</html>

一覧表示

まず、前回紹介したパラメタなしの場合です。

以下のようにリソース名を指定してアクセスします。

$ curl http://localhost:8080/web/HelloResource/product

その結果、以下のページが表示されます。(この結果はxmllintで整形しています。他のHTML出力も同様です。)

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
    <title>product</title>
  </head>
  <body>
    <div>
      <table class="">
        <caption class="">product</caption>
        <thead class="">
          <tr class="">
            <th scope="col" class="">Id</th>
            <th scope="col" class="">Name</th>
            <th scope="col" class="">Price</th>
          </tr>
        </thead>
        <tbody class="">
          <tr data-href="product/1.html">
            <td class="">1</td>
            <td class="">Apple</td>
            <td class="">300</td>
          </tr>
        </tbody>
      </table>
      <table>
        <tr>
          <td>Prev</td>
          <td>
            <a href="#?query.offset=0&amp;query.page.size=1">1</a>
          </td>
          <td>
            <a href="#?query.offset=1&amp;query.page.size=1">2</a>
          </td>
          <td>
            <a href="#?query.offset=2&amp;query.page.size=1">3</a>
          </td>
          <td>
            <a href="#?query.offset=3&amp;query.page.size=1">4</a>
          </td>
          <td>Next</td>
        </tr>
      </table>
    </div>
  </body>
</html>

ページング

次はページング機能を使用してみます。

ページング機能を使用する場合、query.page.sizeパラメタで1ページ数あたりの行数を指定します。

以下のようにリソース名のページを指定して、queyr.page.sizeに「1」を指定して実行してみます。

$ curl "http://localhost:8080/web/HelloResource/product?query.page.size=1"

この結果、以下のページが表示されました。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
    <title>product</title>
  </head>
  <body>
    <div>
      <table class="">
        <caption class="">product</caption>
        <thead class="">
          <tr class="">
            <th scope="col" class="">Id</th>
            <th scope="col" class="">Name</th>
            <th scope="col" class="">Price</th>
          </tr>
        </thead>
        <tbody class="">
          <tr data-href="product/1.html">
            <td class="">1</td>
            <td class="">Apple</td>
            <td class="">300</td>
          </tr>
        </tbody>
      </table>
      <table>
        <tr>
          <td>Prev</td>
          <td>
            <a href="#?query.offset=0&amp;query.page.size=1">1</a>
          </td>
          <td>
            <a href="#?query.offset=1&amp;query.page.size=1">2</a>
          </td>
          <td>
            <a href="#?query.offset=2&amp;query.page.size=1">3</a>
          </td>
          <td>
            <a href="#?query.offset=3&amp;query.page.size=1">4</a>
          </td>
          <td>Next</td>
        </tr>
      </table>
    </div>
  </body>
</html>

query.page.sizeに「1」を指定しているので1ページあたり1行表示のページングが行われています。データ表示のテーブルの下部にページング移動用のテーブルが表示されています。全レコード数が4なので、4ページの構成となっています。

まとめ

今回はリソースの一覧表示のページングについて説明しました。

次回はカスタム画面などの機能について説明する予定です。

諸元

Cozy
0.0.15

2023年9月30日土曜日

Cozy Web/一覧表示

Cozy Web上でエンティティのモデル定義によって設定されたリソースの一覧アクセスをノンプログラミングで行う方法についてみていきます。

今回はリソースの一覧表示の機能機能について説明します。

HelloResource

リソースの作成・更新処理の題材としてHelloResourceを定義しました。

今回からこのHelloResourceを使用して、リソースの一覧表示の方法についてみていきます。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しています。

これがWebのリソースproductとなります。

トップページ

トップページとしてホームディレクトリに以下のindex.htmlを配備しています。

<html>
    <head>
	<title>HelloResource</title>
    </head>
    <body>
	<ul>
	    <li><a href="product">List</a></li>
	    <li><a href="product/_create_">Create</a></li>
	    <li><a href="product/_update_">Update</a></li>
	    <li><a href="product/_delete_">Delete</a></li>
	</ul>
    </body>
</html>

リソース一覧のシナリオ

リソースの作成・更新では入力フォームの入力から始まるシナリオによって、複数の画面によって作成・更新処理を実行しました。

一方、リソース一覧では一覧表示したいリソースの名前と表示方法を指定するパラメタを渡すことで、すぐに表示結果を得ることができます。

実行

それではリソース一覧の表示を行ってみましょう。

一覧表示

まず、パラメタなしの場合です。

以下のようにリソース名を指定してアクセスします。

$ curl http://localhost:8080/web/HelloResource/product

その結果、以下のページが表示されました。(この結果はxmllintで整形しています。他のHTML出力も同様です。)

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
    <title>product</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/1.html">
          <td class="">1</td>
          <td class="">Apple</td>
          <td class="">300</td>
        </tr>
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">3</td>
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

範囲指定

query.offsetパラメタで開始オフセットを、query.limitパラメタで表示の範囲を指定することができます。

以下の例ではquery.offsetに1、query.limitに1を指定しているので、2番目のレコードから1レコードを表示します。

$ curl "http://localhost:8080/web/HelloResource/product?query.offset=1&query.limit=1"

実行の結果、以下のようにレコード数1の表が表示されました。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
    <title>product</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

カラム指定

query.columnsパラメタで表示するカラムを指定することができます。

以下の例ではquery.columnsに「name,price」を指定しているのでnameとpriceの2カラムの表を表示します。

$ curl "http://localhost:8080/web/HelloResource/product?query.columns=name,price"

実行の結果、以下のように2カラムの表が表示されました。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
    <title>product</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/1.html">
          <td class="">Apple</td>
          <td class="">300</td>
        </tr>
        <tr data-href="product/2.html">
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

まとめ

今回はリソースの一覧表示の基本機能について説明しました。

次回はページングやカスタム画面などの機能について説明する予定です。

諸元

Cozy
0.0.14

2023年8月31日木曜日

Cozy Web/エンティティ削除

Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。

ここまでエンティティの作成、更新の方法について説明しました。

モデルを定義するだけで、エンティティの作成・更新画面が自動的に提供されることを確認しました。それぞれの画面ではエンティティ成・更新を入力、確認、表示の3画面を使って行うことができました。また、エンティティの作成・更新画面のカスタム画面を定義することも可能になっています。

今回はエンティティの削除について説明します。

HelloResource

ここまで作成したHelloResourceは、モデルの定義が行われており、エンティティの作成と更新を行うことができます。エンティティの作成では、アプリケーションが定義したビューを使用するようになっています。

今回は削除処理のアプリケーション定義ビューを追加します。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しています。

これがWebのリソースproductとなります。

トップページ

トップページとしてホームディレクトリに以下のindex.htmlを配備しています。

<html>
    <head>
	<title>HelloResource</title>
    </head>
    <body>
	<ul>
	    <li><a href="product">List</a></li>
	    <li><a href="product/_create_">Create</a></li>
	    <li><a href="product/_update_">Update</a></li>
	    <li><a href="product/_delete_">Delete</a></li>
	</ul>
    </body>
</html>

エンティティ操作シナリオ

エンティティのモデル定義を行うとエンティティ作成シナリオ、更新シナリオに加えて削除シナリオが自動的に作成されます。

エンティティの削除には以下の2種類があります。

  • 更新するエンティティのIDを削除画面から入力
  • 更新するエンティティのIDを削除開始時に指定

実行

それではエンティティの削除を実行してみましょう。まず削除するIDを削除画面から入力する方式です。

エンティティ削除ページ

以下のようにリソース名の後ろに「_delete_」をつけてアクセスします。

$ curl http://localhost:8080/web/HelloResource/product/_delete_

次のようにエンティティ削除に必要なIDを指定するためのFORMの画面が表示されました。

ビューの定義はしていないので、Cozy Webのデフォルト入力画面が表示されます。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">
              <input type="text" name="id" value=""/>
            </td>
          </tr>
        </tbody>
      </table>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Input"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{}}"/>
    </form>
  </body>
</html>

このページでは以下のボタンが表示されています。

Input
エンティティ削除
Cancel
キャンセル Inputボタンを押下するとエンティティ削除のための次の画面に遷移します。

Cancelボタンを押下するとトップページに戻ります。

削除確認ページ

エンティティ削除ページでInputボタンが押されたので、削除確認画面が表示されます。

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">1</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Apple</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">300</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="5"/>
      <input type="hidden" name="name" value="Banana"/>
      <input type="hidden" name="price" value="250"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Back"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Input&quot;}}"/>
    </form>
  </body>
</html>

画面に削除予定のエンティティのデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。

OK
確認OK
Back
入力画面にモデル
Cancel
キャンセル

Okボタンを押下するとエンティティの削除を行い、その結果を表示する画面に遷移します。

結果ページ

削除確認画面でOKボタンが押されたので、エンティティの削除が行われ、削除されたエンティティの情報表示ページに移ります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">1</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Apple</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">100</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="1"/>
      <input type="hidden" name="name" value="Apple"/>
      <input type="hidden" name="price" value="100"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;a\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;update-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{}}\&quot;,\&quot;price\&quot;:\&quot;10\&quot;,\&quot;id\&quot;:\&quot;5\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Ok&quot;}}"/>
    </form>
  </body>
</html>

削除したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>HelloResource</title>
  </head>
  <body>
    <ul>
      <li>
        <a href="product">List</a>
      </li>
      <li>
        <a href="product/_create_">Create</a>
      </li>
      <li>
        <a href="product/_update_">Update</a>
      </li>
      <li>
        <a href="product/_delete_">Delete</a>
      </li>
    </ul>
  </body>
</html>

確認

確認のためにリソースproductの一覧を表示してみましょう。

$ curl http://localhost:8080/web/HelloResource/product

以下のようにオブジェクトID 1のAppleが削除されました。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>Product List</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">3</td>
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
        <tr data-href="product/4.html">
          <td class="">4</td>
          <td class="">Banana</td>
          <td class="">250</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

実行/ID指定

続けてIDを指定したエンティティの更新を実行してみましょう。

エンティティ更新ページ

IDを指定してリエンティティの更新を行ってみます。IDが1の場合は以下になります。

$ curl http://localhost:8080/web/HelloResource/product/1/_delete_

削除確認ページ

エンティティ削除ページでInputボタンが押されたので、削除確認画面が表示されます。

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">1</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Apple</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">300</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="5"/>
      <input type="hidden" name="name" value="Banana"/>
      <input type="hidden" name="price" value="250"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Back"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Input&quot;}}"/>
    </form>
  </body>
</html>

画面に削除予定のエンティティのデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。

OK
確認OK
Back
入力画面にモデル
Cancel
キャンセル

Okボタンを押下するとエンティティの削除を行い、その結果を表示する画面に遷移します。

結果ページ

削除確認画面でOKボタンが押されたので、エンティティの削除が行われ、削除されたエンティティの情報表示ページに移ります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">1</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Apple</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">100</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="1"/>
      <input type="hidden" name="name" value="Apple"/>
      <input type="hidden" name="price" value="100"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;a\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;update-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{}}\&quot;,\&quot;price\&quot;:\&quot;10\&quot;,\&quot;id\&quot;:\&quot;5\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Ok&quot;}}"/>
    </form>
  </body>
</html>

削除したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>HelloResource</title>
  </head>
  <body>
    <ul>
      <li>
        <a href="product">List</a>
      </li>
      <li>
        <a href="product/_create_">Create</a>
      </li>
      <li>
        <a href="product/_update_">Update</a>
      </li>
      <li>
        <a href="product/_delete_">Delete</a>
      </li>
    </ul>
  </body>
</html>

まとめ

Cozy Webでのエンティティの削除の方法について説明しました。モデルの定義のみでシナリオに沿ったエンティティの更新、作成、削除ができることが分かりました。

次回からエンティティの一覧表示について見ていきます。

諸元

Cozy
0.0.14

2023年7月31日月曜日

Cozy Web/エンティティ更新のカスタム画面

Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。

前回はエンティティ更新の方法について説明しました。

モデルを定義するだけで、エンティティの更新画面が自動的に提供されることを確認しました。エンティティ更新を入力、確認、表示の3画面を使って行うことができました。

前回は、画面そのものはCozyが作成したデフォルト画面です。今回はエンティティ更新のカスタム画面を設定する方法について説明します。

HelloResource

ここまで作成したHelloResourceは、モデルの定義が行われており、エンティティの作成と更新を行うことができます。エンティティの作成では、アプリケーションが定義したビューを使用するようになっています。

今回は更新処理のアプリケーション定義ビューを追加します。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しています。

これがWebのリソースproductとなります。

トップページ

トップページとしてホームディレクトリに以下のindex.htmlを配備しています。

<html>
    <head>
	<title>HelloResource</title>
    </head>
    <body>
	<ul>
	    <li><a href="product">List</a></li>
	    <li><a href="product/_create_">Create</a></li>
	    <li><a href="product/_update_">Update</a></li>
	</ul>
    </body>
</html>

エンティティ操作シナリオ

エンティティのモデル定義を行うとエンティティ作成シナリオが自動的に作成されます。

エンティティの更新には以下の2種類があります。

  • 更新するエンティティのIDを更新画面から入力
  • 更新するエンティティのIDを更新開始時に指定

アプリケーション定義ビュー

エンティティの更新シナリオの3つの処理、入力処理、確認処理、表示処理それぞれのアプリケーションのカスタム画面をみていきます。

入力画面

カスタムの入力画面として以下のupdate__input.htmlをproduct.entityディレクトリに配備します。

<html>
    <head>
	<title>Update Product/Input</title>
    </head>
    <body>
	<h1>Update Product/Input</h1>
	<c:detail />
    </body>
</html>

タグ c:detail の場所に入力処理用の入力フォームが出力されます。

デフォルト画面との変更点はヘッダと画面のタイトル部を追加している点です。ここではシンプルな追加のみにしていますが、必要に応じて画面のデザインを追加していく形になります。

確認画面

カスタムの入力画面として以下のupdate__confirm.htmlをproduct.entityディレクトリに配備します。

<html>
    <head>
	<title>Update Product/Confirm</title>
    </head>
    <body>
	<h1>Update Product/Confirm</h1>
	<c:detail />
    </body>
</html>

タグ c:detail の場所に確認処理用のフォームが出力されます。

入力画面と同様に、変更点はヘッダと画面のタイトル部を追加している点です。

表示画面

カスタムの入力画面として以下のupdate__show.htmlをproduct.entityディレクトリに配備します。

<html>
    <head>
	<title>Update Product/Show</title>
    </head>
    <body>
	<h1>Update Product/Show</h1>
	<c:detail />
    </body>
</html>

タグ c:detail の場所に結果確認処理用のフォームが出力されます。

入力画面や確認画面と同様に、変更点はヘッダと画面のタイトル部を追加している点です。

実行

それではIDを指定したエンティティの更新を実行してみましょう。

エンティティ更新ページ

IDを指定してリエンティティの更新を行ってみます。IDが1の場合は以下になります。

$ curl http://localhost:8080/web/HelloResource/product/1/_update_

次のようにエンティティ作成に必要なデータを登録するためのFORMの画面が表示されました。

update__input.htmlとして登録した入力ページが表示されました。

画面のタイトルとして、カスタム画面の定義が使用されていることが分かります。

<!DOCTYPE html>
<html><head>
	<title>Update Product/Input</title>
    </head><body>
	<h1>Update Product/Input</h1>
	<form action="" method="POST">
      <table class="">
      <tbody><tr class=""><th scope="row" class="">Id</th><td class=""><input type="text" name="id" value="1" /></td></tr><tr class=""><th scope="row" class="">Name</th><td class=""><input type="text" name="name" value="Apple" /></td></tr><tr class=""><th scope="row" class="">Price</th><td class=""><input type="text" name="price" value="300" /></td></tr></tbody>
      </table>
      <table>
        <tr><td><input type="submit" name="$submit" value="Input" /></td><td><input type="submit" name="$submit" value="Cancel" /></td></tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{},&quot;id&quot;:&quot;1&quot;}" />
    </form>
    
</body></html>

作成の場合と違って、FORMの中にID「1」の情報が動的的に設定されています。

このページでは以下のボタンが表示されています。

Input
データ登録
Cancel
キャンセル

ID 1のデータはAppleですが、値段を100円から150円に変更しましょう。

Inputボタンを押下するとエンティティ更新のための次の画面に遷移します。

Cancelボタンを押下するとトップページに戻ります。

登録データ確認ページ

データ登録画面でInputボタンを押すと、登録データ確認画面が表示されます。

update__confirm.htmlとして登録した入力ページが表示されました。

画面のタイトルとして、カスタム画面の定義が使用されていることが分かります。

<!DOCTYPE html>
<html><head>
	<title>Update Product/Confirm</title>
    </head><body>
	<h1>Update Product/Confirm</h1>
	<form action="" method="POST">
      <table class="">
      <tbody><tr class=""><th scope="row" class="">Id</th><td class="">1</td></tr><tr class=""><th scope="row" class="">Name</th><td class="">Apple</td></tr><tr class=""><th scope="row" class="">Price</th><td class="">150</td></tr></tbody>
      </table>
      <input type="hidden" name="id" value="1" /><input type="hidden" name="name" value="Apple" /><input type="hidden" name="price" value="150" />
      <table>
        <tr><td><input type="submit" name="$submit" value="Ok" /></td><td><input type="submit" name="$submit" value="Ok_show" /></td><td><input type="submit" name="$submit" value="Back" /></td><td><input type="submit" name="$submit" value="Cancel" /></td></tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Apple&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{},\&quot;id\&quot;:\&quot;1\&quot;}&quot;,&quot;price&quot;:&quot;150&quot;,&quot;id&quot;:&quot;1&quot;,&quot;$submit&quot;:&quot;Input&quot;},&quot;id&quot;:&quot;1&quot;}" />
    </form>
    
</body></html>

画面に入力したデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。

Ok
確認OK
Ok_show
確認OKで結果を表示
Back
入力画面にモデル
Cancel
キャンセル

Ok_showボタンを押下するとエンティティ更新が行われ、更新した情報の表示画面に遷移します。

Okの場合は、エンティティ更新後トップページに遷移します。

結果ページ

更新確認画面でOK_showボタンを押すと、エンティティの更新が行われ、作成されたエンティティの情報表示ページに移ります。

update__show.htmlとして登録した入力ページが表示されました。

画面のタイトルとして、カスタム画面の定義が使用されていることが分かります。

<!DOCTYPE html>
<html><head>
	<title>Update Product/Show</title>
    </head><body>
	<h1>Update Product/Show</h1>
	<form action="" method="POST">
      <table class="">
      <tbody><tr class=""><th scope="row" class="">Id</th><td class="">1</td></tr><tr class=""><th scope="row" class="">Name</th><td class="">Apple</td></tr><tr class=""><th scope="row" class="">Price</th><td class="">150</td></tr></tbody>
      </table>
      <input type="hidden" name="id" value="1" /><input type="hidden" name="name" value="Apple" /><input type="hidden" name="price" value="150" />
      <table>
        <tr><td><input type="submit" name="$submit" value="Ok" /></td></tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Apple&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;Apple\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;update-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}, {\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}, {\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{},\\\&quot;id\\\&quot;:\\\&quot;1\\\&quot;}\&quot;,\&quot;price\&quot;:\&quot;150\&quot;,\&quot;id\&quot;:\&quot;1\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;},\&quot;id\&quot;:\&quot;1\&quot;}&quot;,&quot;price&quot;:&quot;150&quot;,&quot;id&quot;:&quot;1&quot;,&quot;$submit&quot;:&quot;Ok_show&quot;},&quot;id&quot;:&quot;1&quot;}" />
    </form>
    
</body></html>

作成したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。

確認

確認のためにリソースproductの一覧を表示してみましょう。

$ curl http://localhost:8080/web/HelloResource/product

以下のようにオブジェクトID 1のAppleの値段が150に変更されました。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>Product List</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/1.html">
          <td class="">1</td>
          <td class="">Apple</td>
          <td class="">150</td>
        </tr>
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">3</td>
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

まとめ

Cozy Webでのエンティティの作成、削除の方法について説明してきました。モデルの定義のみでシナリオに沿ったエンティティの作成、削除ができることが分かりました。またエンティティの作成、削除画面のカスタマイズも可能です。

次回はエンティティの削除について説明します。

諸元

Cozy
0.0.13

2023年6月30日金曜日

Cozy Web/エンティティ更新(2)

Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。

ここまで、エンティティの作成についてみてきました。

前回はエンティティの更新の基本形としてエンティティIDを指定しない形を説明しました。

今回はエンティティIDを指定してエンティティの更新をする方法について説明します。

HelloResource

ここまで作成したHelloResourceは、モデルの定義が行われており、エンティティの作成を行うことができます。エンティティの作成では、アプリケーションが定義したビューを使用するようになっています。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しています。

これがWebのリソースproductとなります。

トップページ

<html>
    <head>
	<title>HelloResource</title>
    </head>
    <body>
	<ul>
	    <li><a href="product">List</a></li>
	    <li><a href="product/_create_">Create</a></li>
	    <li><a href="product/_update_">Update</a></li>
	</ul>
    </body>
</html>

エンティティ操作シナリオ

エンティティのモデル定義を行うとエンティティ作成シナリオが自動的に作成されます。

エンティティの更新には以下の2種類があります。

  • 更新するエンティティのIDを更新画面から入力
  • 更新するエンティティのIDを更新開始時に指定

前回、前者の更新するエンティティのIDを更新画面から入力のシナリオを確認しました。

今回は後者の更新するエンティティのIDを更新開始時に指定を実行します。

実行

それではIDを指定したエンティティの更新を実行してみましょう。

エンティティ更新ページ

IDを指定してリエンティティの更新を行う場合には、リソース名の後ろに「ID/_update_」をつけてアクセスします。IDが1の場合は以下になります。

$ curl http://localhost:8080/web/HelloResource/product/1/_update_

次のようにエンティティ作成に必要なデータを登録するためのFORMの画面が表示されました。

まだビューの定義はされていないので、Cozy Webのデフォルト入力画面が表示されます。

<!DOCTYPE html>
<html><head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta name="keywords" content="TBD" />
  <meta name="description" content="TBD" />
  <meta name="robots" content="noindex,nofollow" />
  <meta name="author" content="TBD" />
  
  
  </head><body><form action="" method="POST">
      <table class="">
      <tbody><tr class=""><th scope="row" class="">Id</th><td class=""><input type="text" name="id" value="1" /></td></tr><tr class=""><th scope="row" class="">Name</th><td class=""><input type="text" name="name" value="Apple" /></td></tr><tr class=""><th scope="row" class="">Price</th><td class=""><input type="text" name="price" value="100" /></td></tr></tbody>
      </table>
      <table>
        <tr><td><input type="submit" name="$submit" value="Input" /></td><td><input type="submit" name="$submit" value="Cancel" /></td></tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{},&quot;id&quot;:&quot;1&quot;}" />
    </form></body></html>

作成の場合と違って、FORMの中にID「1」の情報が動的的に設定されています。

このページでは以下のボタンが表示されています。

Input
データ登録
Cancel
キャンセル

ID 1のデータはAppleですが、値段を100円から150円に変更しましょう。

Inputボタンを押下するとエンティティ更新のための次の画面に遷移します。

Cancelボタンを押下するとトップページに戻ります。

登録データ確認ページ

データ登録画面でInputボタンを押すと、登録データ確認画面が表示されます。

<!DOCTYPE html>
<html><head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta name="keywords" content="TBD" />
  <meta name="description" content="TBD" />
  <meta name="robots" content="noindex,nofollow" />
  <meta name="author" content="TBD" />
  
  
  </head><body><form action="" method="POST">
      <table class="">
      <tbody><tr class=""><th scope="row" class="">Id</th><td class="">1</td></tr><tr class=""><th scope="row" class="">Name</th><td class="">Apple</td></tr><tr class=""><th scope="row" class="">Price</th><td class="">150</td></tr></tbody>
      </table>
      <input type="hidden" name="id" value="1" /><input type="hidden" name="name" value="Apple" /><input type="hidden" name="price" value="150" />
      <table>
        <tr><td><input type="submit" name="$submit" value="Ok" /></td><td><input type="submit" name="$submit" value="Ok_show" /></td><td><input type="submit" name="$submit" value="Back" /></td><td><input type="submit" name="$submit" value="Cancel" /></td></tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Apple&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{},\&quot;id\&quot;:\&quot;1\&quot;}&quot;,&quot;price&quot;:&quot;150&quot;,&quot;id&quot;:&quot;1&quot;,&quot;$submit&quot;:&quot;Input&quot;},&quot;id&quot;:&quot;1&quot;}" />
    </form></body></html>

画面に入力したデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。

Ok
確認OK
Ok_show
確認OKで結果を表示
Back
入力画面にモデル
Cancel
キャンセル

Ok_showボタンを押下するとエンティティ更新が行われ、更新した情報の表示画面に遷移します。

Okの場合は、エンティティ更新後トップページに遷移します。

結果ページ

更新確認画面でOK_showボタンを押すと、エンティティの更新が行われ、作成されたエンティティの情報表示ページに移ります。

<!DOCTYPE html>
<html><head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta name="keywords" content="TBD" />
  <meta name="description" content="TBD" />
  <meta name="robots" content="noindex,nofollow" />
  <meta name="author" content="TBD" />
  
  
  </head><body><form action="" method="POST">
      <table class="">
      <tbody><tr class=""><th scope="row" class="">Id</th><td class="">1</td></tr><tr class=""><th scope="row" class="">Name</th><td class="">Apple</td></tr><tr class=""><th scope="row" class="">Price</th><td class="">150</td></tr></tbody>
      </table>
      <input type="hidden" name="id" value="1" /><input type="hidden" name="name" value="Apple" /><input type="hidden" name="price" value="150" />
      <table>
        <tr><td><input type="submit" name="$submit" value="Ok" /></td></tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Apple&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;Apple\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;update-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}, {\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}, {\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{},\\\&quot;id\\\&quot;:\\\&quot;1\\\&quot;}\&quot;,\&quot;price\&quot;:\&quot;150\&quot;,\&quot;id\&quot;:\&quot;1\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;},\&quot;id\&quot;:\&quot;1\&quot;}&quot;,&quot;price&quot;:&quot;150&quot;,&quot;id&quot;:&quot;1&quot;,&quot;$submit&quot;:&quot;Ok_show&quot;},&quot;id&quot;:&quot;1&quot;}" />
    </form></body></html>

作成したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。

確認

確認のためにリソースproductの一覧を表示してみましょう。

$ curl http://localhost:8080/web/HelloResource/product

以下のようにオブジェクトID 1のAppleの値段が150に変更されました。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>Product List</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/1.html">
          <td class="">1</td>
          <td class="">Apple</td>
          <td class="">150</td>
        </tr>
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">3</td>
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

まとめ

今回はエンティティ更新の方法について説明しました。

モデルを定義するだけで、エンティティの更新画面が自動的に提供されることを確認しました。エンティティ更新を入力、確認、表示の3画面を使って行うことができました。

今回は、画面そのものはCozyが作成したデフォルト画面です。次回はエンティティ更新のカスタム画面を設定する方法について説明します。

諸元

Cozy
0.0.13

2023年5月31日水曜日

Cozy Web/エンティティ更新

Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。

ここまで、エンティティの作成についてみてきました。

今回はエンティティの更新についてみていきます。

HelloResource

ここまで作成したHelloResourceは、モデルの定義が行われており、エンティティの作成を行うことができます。エンティティの作成では、アプリケーションが定義したビューを使用するようになっています。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しています。

これがWebのリソースproductとなります。

トップページ

<html>
    <head>
	<title>HelloResource</title>
    </head>
    <body>
	<ul>
	    <li><a href="product">List</a></li>
	    <li><a href="product/_create_">Create</a></li>
	    <li><a href="product/_update_">Update</a></li>
	</ul>
    </body>
</html>

エンティティ操作シナリオ

エンティティのモデル定義を行うとエンティティ作成シナリオが自動的に作成されます。

このエンティティ作成シナリオによって、エンティティの作成オペレーションが可能になったことを前々回、前回に確認しました。

エンティティの更新オペレーションも同様にエンティティ作成シナリオによって可能になります。

エンティティの更新には以下の2種類があります。

  • 更新するエンティティのIDを更新画面から入力
  • 更新するエンティティのIDを更新開始時に指定

今回は前者の更新エンティティIDを更新画面から入力するシナリオを実行します。

実行

それではエンティティの更新を実行してみましょう。

エンティティ更新ページ

以下のようにリソース名の後ろに「_update_」をつけてアクセスします。

$ curl http://localhost:8080/web/HelloResource/product/_update_

次のようにエンティティ作成に必要なデータを登録するためのFORMの画面が表示されました。

まだビューの定義はされていないので、Cozy Webのデフォルト入力画面が表示されます。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">
              <input type="text" name="id" value=""/>
            </td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">
              <input type="text" name="name" value=""/>
            </td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">
              <input type="text" name="price" value=""/>
            </td>
          </tr>
        </tbody>
      </table>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Input"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{}}"/>
    </form>
  </body>
</html>

このページでは以下のボタンが表示されています。

Input
データ登録
Cancel
キャンセル Inputボタンを押下するとエンティティ作成のための次の画面に遷移します。

Cancelボタンを押下するとトップページに戻ります。

登録データ確認ページ

データ登録画面でInputボタンが押されたので、登録データ確認画面が表示されます。

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">1</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Apple</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">300</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="5"/>
      <input type="hidden" name="name" value="Banana"/>
      <input type="hidden" name="price" value="250"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Back"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Input&quot;}}"/>
    </form>
  </body>
</html>

画面に入力したデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。

OK
確認OK
Back
入力画面にモデル
Cancel
キャンセル

Okボタンを押下するとエンティティ作成のための次の画面に遷移します。

結果ページ

登録データ確認画面でOKボタンが押されたので、エンティティの作成が行われ、作成されたエンティティの情報表示ページに移ります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">1</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Apple</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">100</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="1"/>
      <input type="hidden" name="name" value="Apple"/>
      <input type="hidden" name="price" value="100"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;a\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;update-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{}}\&quot;,\&quot;price\&quot;:\&quot;10\&quot;,\&quot;id\&quot;:\&quot;5\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Ok&quot;}}"/>
    </form>
  </body>
</html>

作成したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>HelloResource</title>
  </head>
  <body>
    <ul>
      <li>
        <a href="product">List</a>
      </li>
      <li>
        <a href="product/_create_">Create</a>
      </li>
      <li>
        <a href="product/_update_">Update</a>
      </li>
    </ul>
  </body>
</html>

確認

確認のためにリソースproductの一覧を表示してみましょう。

$ curl http://localhost:8080/web/HelloResource/product

以下のようにオブジェクトID 1のAppleの値段が100に変更されました。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>Product List</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/1.html">
          <td class="">1</td>
          <td class="">Apple</td>
          <td class="">100</td>
        </tr>
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">3</td>
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
        <tr data-href="product/4.html">
          <td class="">4</td>
          <td class="">Banana</td>
          <td class="">250</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

まとめ

Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。

リソースの作成に続いて、今回はリソースの更新の基本形について説明しました。

次回も引き続きリソースの更新について説明します。

諸元

Cozy
0.0.13