やあ!今日は、コンテンツ管理エクスペリエンスを改善し、新しい種類の CMS である Flutter アプリケーション開発の世界に追加機能をもたらすために設計された、夜間と週末の数か月にわたる作業の成果を紹介したいと思います。
我々はナンクについて話している - ノーマルC MSではない.なぜそれが「普通ではない」のか、そしてそれに対して何ができるのかは、この記事を読めばわかります。
この記事には、理論だけでなく「実践」も含まれます - Nanc サンドボックスで遊ぶことができます。 Nanc の機能を一般に公開するために、2 つのデモ アプリケーションが作成されました。Flutter アプリケーションを模倣するクライアント アプリケーションと、Flutter ベースの Nanc アプリケーションで何ができるかを示す別のアプリケーション (ビルド済みの Nanc CMS) です。また、Nanc CMS アプリケーションは、クライアント アプリケーションを CMS と同期するために追加のロジック レイヤーが実装された構成済みの CMS です。
テキスト内のほとんどのロジック ブロックの最後に、Nanc のいくつかの側面の使用方法やデモンストレーション方法の例を含む YouTube ビデオがあります。
はじめに
CMSについて
モデルの種類
編集者
田畑
動的 Flutter アプリ
Nanc デモアプリ
次回は/あとがき
それで。 Nanc は、独自のバックエンドをプルしない、バックエンドに依存しない CMS です。それはどのように機能しますか? Nanc は、ネットワーク サービス インターフェイスの実装を提案しています。これには現在 6 つのメソッドがありますが、リリース時には約 10 になる予定です。これは多いですか、それとも少ないですか。たとえば、デモ アプリケーションの API を実装するには、170 行のコードが必要でした。これらのメソッドは、既存のバックエンドでの Nanc のすべての作業を担当します。実装は Dart (Flutter の開発言語でもあります) で記述する必要があります。将来、Nanc には、特定のバックエンド オプション (Firebase、Supabase、ローカル/ネットワーク SQLite、および REST と GraphQL の一般的な実装) 用のこれらのインターフェイスの実装が用意された状態で実装される予定です (おそらく他の何か?)。すべてまたはする必要がありますが、ほんの少しです。
Nanc のモデルは、 Nanc で制御するエンティティの構造記述です。モデルには、エンティティ名、さまざまなビジュアル パラメーター、およびフィールドの説明が含まれています。
コレクションは、多くのインスタンスを持つことができるエンティティです。ユーザーのリスト、書籍、およびレビューは、Nanc のコレクション型モデルの良い例です。
リレーショナル データベースに精通している場合、Nanc のコレクションの例は、データベース内のほぼすべてのテーブルになります。
ソロ (モデル) は、単一のインスタンスに存在するエンティティです。例 - 機能の切り替えまたは何かの構成、または... 「モバイル アプリケーションのメイン画面」。一般的に言えば、ソロモデルは使いやすさを向上させるように設計されており、データベースの投影にすぎません。また、Solo モデルは、データベース内のレコードが 1 つしかないテーブルであれば簡単に作成できます。しかし、現時点では、このクラスのモデルを実装するには、このモデルのレコード(データベース内の行)に、モデル自体のid
と同じid
が必要です。
final Model landingPage = Model( name: 'Landing page', /// ? id in format [toSnakeCase(name)] will be set automatically, if omitted // id: 'landing_page', isCollection: false, icon: IconPackNames.flu_document_page_break_regular, fields: [ ...
Nanc はいくつかの方法で構成できます。コード、Nanc インターフェイス自体、およびこれらのオプションの組み合わせによるものです。
「構成」とは、まず、モデルの構造を説明することです。製品の機能を記述するエンティティである機能モデルの簡単な例を見てみましょう。このエンティティには、次のフィールドが含まれています。
コードファースト構成としての実装は次のようになります。
import 'package:fields/fields.dart'; import 'package:icons/icons.dart'; import 'package:model/model.dart'; final Model feature = Model( name: 'Feature', icon: IconPackNames.flu_ribbon_star_filled, fields: [ [ IdField(width: 200), StringField(name: 'Title', maxLines: 1, isRequired: true, width: 400), ], [ IconField(name: 'Image', isRequired: true), ], [ StringField(name: 'Description', isRequired: true, showInList: true), ], ], );
このようなモデルを記述して Nanc CMS で使用することにより、そのモデルのすべての CRUD 操作が利用可能になります。
Nanc インターフェイスを介して、まったく同じ機能モデル (これを機能バリアントと呼びましょう) を作成できます。そして (Nanc を使用するためのすべての準備作業が完了していることを考慮して) - Nanc でモデルを作成すると、すぐにデータベースにテーブルが作成され、CRUD 全体もすぐに利用できるようになります。
また、Nanc インターフェースを介してモデルを作成するときに、データベースに何も作成しないというより安全な方法を取ることもできます。データベースに個別にテーブルを作成し、その下に Nanc にモデルを作成します。ちなみに、コードで構成を記述する場合、これはあなたがしなければならないことです-新しいテーブルはそれからデータベースに表示されません.
このオプションは、Code-first 構成があり、Nanc インターフェースを介して変更することにした場合に使用可能になります。この場合、このモデルへのそれ以降のすべての変更はインターフェイスを介してのみ可能であり、元のコード モデルに加えられた変更は無視されます。コード ファーストに戻る唯一の方法は、モデルを「リセット」することです。この場合、インターフェイスを介して行われたモデル構造へのすべての変更は消去され、コード ファーストの構成が再び使用されます。このリセットによるデータへの影響はありません。モデル構造にのみ影響します。
それでは、現在 Nanc がサポートしているフィールドのタイプを見てみましょう。
BoolField を使用すると、 bool
データ型を制御し、デフォルト値をカスタマイズできます。
ColorField は、Nanc ですぐに色を選択できる便利なカラー ピッカーを提供します。また、AHEX コードを編集して、手動で変更することもできます。 AHEX は従来の HEX-Color (たとえば、 #10A0CF
) ですが、追加の透過値が最初に指定されています。この場合、この色は#FF10A0CF
( FF
は 100% 不透明度 - 色は完全に不透明) に似ています。これは、同じ色が 50% の不透明度でどのように見えるかです: #7F10A0CF
.
DateField は、日付と時刻の制御を担当します (両方の値を一度に、日付と時刻の個別の値は後で実装されます)。 DateField には、エンティティ作成時のタイムスタンプと変更時のタイムスタンプにすることで、このフィールドの動作を変更できる 2 つのブール値パラメーターが含まれています。
一方では DynamicField は非常に単純なフィールドですが、他方では他のフィールドの完全な複雑さが含まれています。最初は、このフィールドの外観のみを構成できます (Nanc インターフェースでどのように表示されるか - 色と付随するアイコン)。その後、このフィールドには、それ自体を含め、Nanc で使用可能な任意の値を含めることができます。これは何を意味するのでしょうか?基本的に、DynamicField は型指定された JSON であり、それ自体でフィールドを順番に配置できます。
EnumField は、複数の値から値を選択するためのフィールドです。 EnumField を選択する際に従うべきルールは、別のデータベース テーブルに保存されていない値の最終リストを選択する場合は、Enum を選択することです。それ以外の場合は、以下で詳しく説明する SelectorField を選択します。 TODO: 現時点では、このフィールドは CodeConfig を介してのみ構成できます。インターフェイスを介した構成はうまくいきません。
HeaderField は、実際にはフィールドではありませんが、Nanc のモデルの視覚的なエンハンサーです。この非フィールドを使用して、関連するフィールドのグループに共通のヘッダーを設定したり、HeaderField を区切り文字として使用してモデル フィールドを互いに区別したりできます。
IconField を使用すると、定義済みのアイコン セットからアイコン ( IconData
クラス) を選択できます。現在、約 25,000 個のアイコンがあり、このセットには次のアイコンが含まれています。
必要に応じて、他のアイコンを基本配信セットに追加できます。そう遠くない将来に、独自のアイコンを使用するオプションも用意される予定です。
「アイコンも色もあるけど、フォントは?」と思う人もいるかもしれません。その場合は、 Textウィジェットのドキュメントで答えを見つけることができます。簡単に言うと、 Google Fontsのすべてのフォントが利用可能です。
IdField は非常に単純ですが、非常に重要なフィールドです。 Nanc によって管理されるすべてのモデルには、タイプ Id のフィールドが少なくとも 1 つ必要です。現在、文字列 ID タイプのみがサポートされています (1 つのエンティティ内の任意の一意の文字列にすることができます)。数値型のサポートも追加する予定ですが、API 実装でフィールド データを数値型にキャストするだけで、現在でも実装できます。
MultiSelectorField は、リレーショナルな多対多または多対 1 の関係を実装する役割を担うかなり複雑なフィールドです。このフィールドの使用には 3 つのモードがあります。それぞれについて詳しく見ていきましょう。 TODO: 現時点では、このフィールドは CodeConfig を介してのみ構成できます。インターフェイスを介した構成はうまくいきません。
このモードでは、関連するエンティティのid
を親エンティティに直接格納できます。たとえば、Reader と Book という 2 つのモデルがあります。このモードでは、リーダーが読んだ本は、リーダー モデル フィールドに格納された ID として考慮されます。たとえば、次のようにします。
/// user table { id: 'UUID', name: 'String', books: [ 'UUID', 'UUID' // ... ] }
上記は、JSON5 構文を使用して表現されたテーブル構造の例です。
このモードの欠点は、データの整合性が制限されることです。古い (削除された) ブック ID をbooks
リーダー フィールドから自動的に削除する機能を実装しないと、エラーが発生します。
SQL の世界からリレーションシップを提供する古典的なモード。このモードを使用する場合、エンティティ関係を別のテーブルに保存し、100% のデータ整合性を確保します。次の構造は、このモードの例です。
[ /// user table { id: 'UUID', name: 'String' }, /// book table { id: 'UUID', title: 'String' }, /// user_books_relations table { user_id: 'UUID', book_id: 'UUID' } ]
7 秒目にわずかな動きが見られます。よく見ると、ページの URL が変更されていることがわかります。これが、バグを隠そうとした方法です。3 番目のテーブル モードでは、データは親ページに保存されるすでに保存されています🤷🏼
親レコードが識別子を格納するのではなく、オブジェクト全体を格納することを除いて、通常は id の配列に似ています (ネストされたレコードの関連付けられたエンティティを持たないフラットな構造として)。これには Array of ids と同じ欠点がありますが、ストレージの使用量が増えるという追加の欠点があります。ただし、(少なくとも現時点では) このモードの適用分野があり、非常に重要です。しかし、これについては少し後で説明します。
私はスクリーンフィールドを示すビデオで自分自身を先取りしています。これについては後で説明します。
一般に、「非標準」モードを仮想化するという考えがあります。これにより、これらのモードは何らかの方法で 3 番目のテーブルを介して機能し、ページの編集時に必要なデータがロードされます (必要な場合)。
NumberField は数字を格納します - それは簡単です。
SelectorField は MultiSelectorField に似ていますが (名前から推測できるように)、少し単純です。ここでの関係は 1 対 1 または 1 対多であり、2 つのモードがあります。 TODO: 現時点では、このフィールドは CodeConfig を介してのみ構成できます。インターフェイスを介した構成はうまくいきません。
親レコード フィールドにリンクされたレコードの ID が格納される、SQL リンク プロビジョニングの一般的な形式。リーダーを例に取りましょう。どなた?まず第一にそれは人であり、人は何を持っていますか?それは正しい!生まれた都市(何らかの理由で私たちの図書館も知りたがっていました)。
/// user table { id: 'UUID', name: 'String', birth_place_id: 'UUID' }
MultiSelectorField のオブジェクトの配列に非常に似ていますが、親レコードのフィールドに関連付けられた単一の値を格納します。短所は同じですが、長所も以下で少し説明します。
StringField は文字列を格納します。このフィールドには、Nanc での編集の利便性を左右する個人設定が 1 つあります。これは、編集可能なフィールドの最大高さを制限するパラメーターです。テキストが大きくなる場合 - まったく指定しないのが理にかなっており、フィールドはテキストの高さに合わせて調整されます。大きく制限されている場合 - 明示的なフィールドの高さ (行単位) を指定すると、常にそのようになります。最後に、短い文字列の場合は、1 行に設定できます。その後、フィールドにいくら書き込んでも、フィールドは拡張されません。
StructureField を使用すると、型指定された構造体の配列をモデル レコードに格納できます。保存するデータの種類を指定して、簡単かつ簡単に管理できます。構造体フィールドで使用できる型は、絶対にすべてです。そのため、「動的構造フィールド リピート」を簡単に作成できます。 TODO: デモ内の StructureField に追加できるのは、「フラット」フィールドのみです。
ScreenField は、Flutter でアプリケーション全体を Nanc で直接作成できるフィールドです。 ScreenField を使用すると、単一の画面のインターフェイスを記述し、必要に応じて更新し、いつでも数分で実行できます。Apple や Google からのレビューを待つという面倒で神経質な作業は必要ありません。
このタイプのフィールド (そして実際には、Nanc の完全に別の機能的な分派) をもう少し詳しく分析してみましょう。
ScreenField を使用すると、ブラウザー (および IDE) でほぼすべての複雑なインターフェイスを実際に作成し、ストック パブリケーションを作成せずに、アプリケーションで対応する画面を更新できます。仮説をすばやく確認する必要がある場合、これは優れた機能です。この機能は、アプリ内の (ロジックに関しては) 比較的単純なページに最適ですが、頻繁に変更する必要があります。将来的には、この機能は拡張され、制限なく本当に何でも作成できる状態になります。
それでは、Nanc を使用して動的スクリーンを作成するすべての側面について説明しましょう。
Flutter にはたくさんのウィジェットがあります。それらの多く。ウィジェットとは?これは、アプリケーションを組み立てる機能のブリックです。視覚的なものだけにすることも、論理的なものにすることもできます-内部にいくつかの動作があります。 Nanc は、UI の構築に使用できる実装済みウィジェットの広範なリストを提供します。しかし、可能性が多ければ多いほど、それらについて学ぶのは難しくなります... したがって、Nanc のスクリーン エディターを使用すると、現在実装されているウィジェット、それらが持つパラメーターと構成可能なプロパティを確認できるインタラクティブなドキュメントにアクセスできます。ドキュメントで、作成するインターフェイスの外観にどのように影響するかを確認してください。
Nanc を使用すると、リアルタイムでインターフェイスを作成できますが、最も重要なことは、非常に簡単かつ迅速に作成できることです (デモ アプリケーションのインターフェイスに 2 時間強かかりました)。しかし、疑問が生じます - UI 自体を作成する方法は? Nanc で UI を記述するための風変わりな構文も、Nanc でインターフェイスを作成するのが嫌になるような長い JSON のような「あまりにも」単純なソリューションもありません。
最適なソリューションを見つけた結果、シンプルでわかりやすい XML 構文が得られます。すべての標準 Flutter ウィジェットの名前はまったく同じですが、XML 形式になっています。たとえば、Nanc のSizedBox
ウィジェットは<sizedBox>...</sizedBox>
となり、この規則は例外なくすべてのウィジェットに適用されます。ウィジェットに複雑なプロパティがある場合、XML と同じ (またはより単純な) 名前で、接頭辞prop
が付きます。たとえば、ウィジェットContainer
独自の内部プロパティを持つ複雑なプロパティboxDecoration
があります。したがって、Nanc のこのプロパティは次のようになります: <prop:decoration>...</prop:decoration>
。この規則は、すべての複雑なプロパティに適用されます。そして最後の側面は、比較的単純な引数が XML タグ パラメーターであることです。例として同じSizedBox
を見てみましょう:
<sizedBox width="50" height="50"> ... </sizedBox>
一部のウィジェットでは、コードの記述を簡素化するために追加の引数が実装されていますSizedBox
では、 width
とheight
の両方を設定するのはize
引数です。
ここに書かれていることはすべてオンライン ドキュメントに記載されているので、忘れたものや知りたいことがある場合は、オンライン ドキュメントを参照して、すべての質問に対する回答を見つけてください。
新しいウィジェットのサポートを実装します - 10 分から数時間程度です。この時点で、ほぼすべての基本的なウィジェットが実装されており、ロジックを使用して複雑なインターフェイスを作成できます。時間が経つにつれて、Flutter で利用可能なすべてのウィジェットが Nanc に実装され、実際にすべてのことができるようになります。しかし、それだけではありません。独自のウィジェットを簡単かつ簡単に実装し、1 行または 2 行の XML コードで Nanc で使用できます。たとえば、標準の Flutter ライブラリには、写真付きのカルーセル スライダーを簡単に表示できるウィジェットはありません。自分で実装を作成するか、そのようなオープン ソース ソリューションを使用する必要があります。そして、必要なものを実装したら、非常に簡単にウィジェットを Nanc に統合して使用することができます。
Nanc は、XML コードを Flutter のインターフェイスに変換する機能だけではありません。 Nanc は、テンプレート作成機能とロジック書き込み機能を提供します。条件付き要素のレンダリング、ループ描画、タップ処理 - これは現在の Nanc バージョン0.0.1
に既に含まれています。
これまでのところ、ロジック部分は非常に簡単です - 事前に書かれた `.dart' コードでタップとイベント処理を介した相互作用をサポートしています - しかし最終的には Nanc のこの部分が大幅に拡張され、ブラウザで直接 Dart にロジックを記述できるようになりますアプリケーションでも機能するようにします。
ユーザーのクリックを処理する方法は次のとおりです。ユーザーがアプリで実行できる「アクション」のリストを定義できます。たとえば、内部アプリケーション画面を開く、外部リンクをクリックする、SnackBar を表示する、モーダル ウィンドウをポップアップするなど、さまざまな操作を行うためのハンドラを事前に作成します。そして、そのアクションを Nanc で好きなように使用します。イベント処理の詳細については、Nanc のInkWell
ウィジェットのドキュメントを参照してください。
Nanc には XML エディターが組み込まれていますが、あまり便利ではありません。これは (まだ) 検索可能ではなく、多くのコードではあまり高速ではなく、オートコンプリート機能もありません。それと一緒に暮らす方法は?たとえば、ユーザーがお気に入りの IDE を使用して、リアルタイムで Nanc の変更を監視できるようにします。方法をお見せしましょう。
そして、これが Web です (これは、あなたが遊ばなければならないものです):
将来、オートコンプリートのサポートが追加される予定です。おそらく遠い将来に... XML スキーマを深く掘り下げようとしましたが、数日を費やしましたが、今のところできません🤷🏼
それとは別に、パフォーマンス (モバイル デバイスでの XML からのインターフェイスの描画) について言及したいと思います。つまり、オーバーヘッドなしで、Flutter 自体のパフォーマンスと同じです。現時点では、「画面」は遅延レンダリングされたウィジェットのリスト (SliverList) であり、非同期で作成されます。後で、この実装はウィジェットのレンダリングを非同期で開始するように改良されますが、コンテンツを表示するのに必要な時間は、XML で記述された最初のウィジェットをレンダリングするのにかかる時間と同じになります。
機能を実証するために、現在 Nanc で何が達成できるかを示すデモ アプリの公開セットが作成されています。これは Android と Web のクライアント アプリケーションです (後者は一時的に iOS アプリケーションの役割も果たします)。 Nanc CMSアプリと同様。それらの詳細については、以下をお読みください。
Client は、nanc エコシステムの単一のライブラリを使用するクライアント デモ アプリケーションです。このライブラリを使用すると、Flutter で XML をアプリケーション インターフェースに変換できます。このアプリケーションには、完全に Nanc で作成された 1 つの画面しかなく、必要に応じていつでも更新できます。右下には接続アイコンの付いたボタンがあります - これはdemo-CMSへの接続を担当します。この「接続」がどうなるかについては、以下で詳しく説明します。
Admin は Nanc-CMS デモ アプリケーションであり、ロジックのレイヤーが追加で実装されており、クライアントと同期する機能を提供します (接続については以下で詳しく説明します)。 Nanc-CMS デモ アプリケーションでは、ユーザーのブラウザ自体とその localStorage が「バックエンド」として機能します。追加または変更したものはすべて、ブラウザーにのみ保存されます。 Nanc-CMS では、既存のモデルに関連するデータを変更/作成/削除できます (それらが表示されます)。また、インターフェースを介して独自のモデルを作成し、それらで同じことを行うことができます。
このデモの作成に使用されたデータ モデルの SQL 表現として、次のスクリーンショットを参考にすることができます。
このセクションは、クライアントおよび CMS アプリケーションの「デモ」のロジックのみに関連しています。そして、Nanc と対話するエクスペリエンスとクライアントの更新プロセスをシミュレートするために実装されました。しかし、まず最初に。
実際の本番プロジェクトでは、次の方法で Nanc を使用できます。静的な Nanc CMS アプリケーションをどこかにデプロイし、API サービスを実装します。バックエンドと通信し、Nanc を好みに合わせて使用します。アプリケーションには、インターフェイスをレンダリングできる nanc エコシステムのライブラリが 1 つ含まれています。あなたは更新を行いました - アプリはあなたのバックエンドから新しいコードをロードし、更新しました - 誰もが幸せで満足しています.
このモデルの動作を示すために、同じことが実装されていますが、単純化された方法です。
Nanc CMS は github ページにある静的なものとして存在し、「実生活で」のように使用できますが、ブラウザはバックエンドとして機能します。つまり、API は、ブラウザの localStorage で「ネットワークに接続する」ように実装されています。この部分で完了ですが、「更新」のプロセスを何らかの方法で表示する必要があるモバイル アプリケーションがまだあります。
そこで「接続」の出番です。要するに、任意の Nanc クライアント デモ アプリと任意の Nanc CMS デモ アプリの間に直接接続を確立できます。これを行うには、CMS の QR コード アイコンで右下のボタンをクリックする必要があります。表示されるモーダル ウィンドウに、QR コードが表示されます。次に、椅子が 2 つあります。このコードをモバイル (またはブラウザー) クライアント アプリケーションで右下の同様のボタンを押してスキャンすると、接続が自動的に確立されます。または、QR コードをクリックすると、接続に必要なデータがクリップボードにコピーされます。次に、このデータをモバイル アプリケーションの入力フィールドに貼り付け、ボタンを押して接続する必要があります。接続が確立されると、あなたは自分自身を理解するでしょう。その後、既存のランディング ページで好きなように操作し、モバイル アプリで (保存後) リアルタイムで変更を確認できます。
ただし、ランディング ページに限定されるわけではありません。ブラウザーで新しいモデルを直接作成し、それらにコンテンツを入力できます。モデルにインターフェイスの説明用のフィールド (タイプ Screen) がある場合は、そのようなエンティティを保存すると、アプリケーションにも結果が表示されます。新しいモデルの画面は、既存のアプリケーション画面に置き換わります。唯一のポイントは、クライアント アプリケーションは、新しく作成されたレコードがどのタイプのフィールドであるかを認識していないため、可能性のある識別子が規定されていることです。これは、ScreenFields であると予想されます。
そのため、画面をまったくゼロから作成してアプリケーションで表示する場合は、次のリストのいずれかを IdField 値として使用します。
何かを壊した場合 - admin.nanc.ioデータをリセットするだけです (Chrome: F12 -> アプリケーション -> アプリケーション -> ストレージ -> サイト データの消去)。クライアント アプリケーションを再度開くと、作成された実際の画面コードが常に読み込まれます。このデモのために。 (ブラウザからのコードは、接続した場合にのみ読み込まれます)
最後に、ScreenField を含む新しいモデルの新しいページを作成し、アプリケーションでレンダリングする小さな例を示します。
公開デモの準備ができました。紹介記事を書いています。 Nanc の将来の計画 - モデル作成へのインターフェイス アプローチの機能的完全性を完成させ、すべてのフィールド (Enum、Selector、および MultiSelector) を構成できるようにします。 StructureField の要素の位置の変更など、既知のバグを修正します。それから「何とか何とか」、そして「まあまあ」。少なくとも次の半年間はバックログで十分ですが、機能をさらに拡張するモデルは顧客のニーズに基づいているため、アイデア/批評がある場合/バグを見つけた場合(そしてそれらはたくさんあります) /その他何でも-フォームに記入してください。このリンクは、クライアント デモ アプリケーションで利用できます。
Nanc の機能に興味があり、協力に興味がある場合は、フォームにも記入してください。