Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Framework for building CRUD UIs for Hasura GraphQL with models rather than code.

License

NotificationsYou must be signed in to change notification settings

evoluteur/evolutility-ui-react

Repository files navigation

Evolutility-UI-React is a set ofmodel-driven views toBrowse,Edit,List,Cards,Charts,Stats,Overview, andActivity.

With it you can easily build CRUD applications by writing models rather than code. It usesHasura GraphQL backend. No hand-coding is necessary!

Check out thelive demos.

Edit

Table of Contents

  1. Installation
  2. Configuration
  3. Views forOne,Many records, and forComfort
  4. Models
  5. Backend
  6. License

Installation

Download orclone fromGitHub.

# To get the latest stable version, use git from the command line.git clone https://github.com/evoluteur/evolutility-ui-react

or use thenpm package:

# To get the latest stable version, use npm from the command line.npm install evolutility-ui-react

In the Evolutility-UI-React directory, use the command line to type the following:

# Install dependenciesnpm install# Run the node.js servernpm start

In a web browser, go to the url [http://localhost:3000/ the REST endpoints, you also need to install and runEvolutility-Server-Node which provides the matching REST endpoints based on the same metadata.

Configuration

Configurations options are specified in the file/src/config.js. They apply to all apps (app specific options are specified in models).

OptionDescriptionExample
apiPathPath to GraphQL API."https://myapp.hasura.app/v1/graphql"
adminSecretToken for Hasura.
useCacheEnable/disable data caching.true
cacheDurationCache duration in seconds.120 (for 2 minutes)
filesUrlPath to upload files to."/pix/"
pageSizePage size in pagination.50
withActivityTracks and shows records activity (last visited and most visited). Currently implemented w/ the browser's localStorage, it will be moved to the server later.true
queryModelsGet models from JSON files or from the database through the API. (not implemented yet)
withTimestampTracks and shows timestamp for creation date and last update for every record. The DB tables need timestamp columns "updated_at" and "created_at" for the feature to work. (partial implementation)true

Views

For any object, a single model defines UI elements across views in a simple declarative way.

Evolutility-UI-React provides different types of view:

Evolutility uses GraphQL withHasura.

Notes: Views for actions (search, filter, export) will come later.

Views for One object

Browse -Edit

Browse

Shows all fields for viewing (read only). Fields are grouped in panels.

Browse

Code:/src/components/views/one/Browse/Browse.jsx

Route: "/{entity}/browse/{id}"

Edit

This view shows all fields for edition to create or update records.It automatically performs validation based on the model.Fields are grouped in panels and tabs.

Edit

Code:/src/components/views/one/Edit/Edit.jsx

Route: "/{entity}/edit/{id}"

Views for Many objects

List -Cards -Charts -Stats

List

Gives a tabular view of a collection.

List

Code:/src/components/views/many/List/List.jsx

Route: "/{entity}/list"

Cards

Shows records side by side as cards.

Cards

Code:/src/components/views/many/Cards/Cards.jsx

Route: "/{entity}/cards"

Charts

Draws charts about the collection. Currently bars and pie charts are implemented, a list with count and percentages is also available. Only provided for fields of types like boolean, lov, integer, decimal, date... (not text or textmultilines).

Charts

Code:/src/components/views/analytics/Charts/Charts.jsx

Route: "/{entity}/charts"

Note: The "Charts" view is currently only implemented for REST, not available with GraphQL yet.

Stats

Display last update, number of updates in the last week, and for numeric fields the min, max, count, average.

Stats

Code:/src/components/views/analytics/Stats/Stats.jsx

Route: "/{entity}/stats"

"Comfort" views

Display a summary of the object and the latest activity on it.

Overview

Display a summary of the object and the latest activity on it.

Overview

Code:/src/components/views/comfort/Overview/Overview.jsx

Route: "/{entity}/"

Activity

Show list of "last visited" and "most visited" records for the object (stored in the browser's localStorage).

Activity

Code:/src/components/views/comfort/Activity/Activity.jsx

Route: "/{entity}/activity"

Models

Each model describe an object and its list of fields. A single model is used for all views (Browse, Edit, List, Cards...).

For any object, all UI views (List, Cards, Edit, Charts...) share the same model.All Fields are present in the Edit and Browse views. Fields can be flagged with "inMany" to be included in the List and Cards views, or "noCharts" and "noStats" to be excluded from the Charts or Stats views.

Object

PropertyMeaning
idUnique key to identify the entity (used in route and as API parameter).
qidEntity ID used in GraphQL (may be different from id in route).
iconIcon file name for the entity (example: "cube.gif").
nameObject name (singular).
namePluralObject name (plural).
titleApplication name.
fieldsArray ofFields.
groupsArray ofGroups. If not provided a single group will be used.
collectionsArray ofCollections.
titleFieldId of the field which value is used as record title. titleField can also be a function.
titleFunctionFunction to calculate the record title based it's data. Example: titleFunction = (data, model) => data.firstname + " " + data.lastname;
defaultViewOneTo have List and Cards link to Edit instead of Browse, set defaultViewOne="edit".

Field

Objects have fields.

PropertyMeaning
idUnique key for the field (can be the same as column but doesn't have to be).
typeField type to show in the UI. Possible field types:
  • boolean (yes/no)
  • date
  • decimal
  • document
  • email
  • image
  • integer
  • json
  • lov (list of values)
  • money
  • text
  • textmultiline
  • time
  • url
labelField description (displayed with an asterisk for required fields).
labelShortOptional shorter version of the labels (used in List and Cards views).
requiredDetermines if the field is required for saving.
readOnlyIf set to true, the field value cannot be changed.
defaultValueDefault field value for new records.
formatField format (using moment for date values and numeral for numeric values).
max, minMaximum/Minimum value allowed (only applies to numeric fields).
maxLength, minLengthMaximum/Minimum length allowed (only applies to text fields).
regExpRegular expression used to validate the field value.
listList of items in the dropdown as an array of id-text objects (only for fields of "lov" type). If ommited, the list will be retrieved in the first query by id on that object.
lovIconSet to True to include icon with LOV items(only for fields of "lov" type).
objectModel id for the object to link to (only for fields of "lov" type).
chartObjectOptional overide for object name in charts (only for "lov" fields).
aggregateOptional overide for aggregation name in charts (only for "lov" fields).
inManyDetermines if the field is present (by default) in lists of records.
inSearchDetermine if the field is used in text searches.
heightFor fields of type "textmultiline", number of lines used in the field (in Browse and Edit views).
widthField width in Browse and Edit views (in percent of parent width).
helpOptional help on the field.
chartTypeDefault charts type used for the field ("Bars", "Pie", or "Table"). "Bars" is used if not specified.
noChartsExclude field from charts (only applies to fields of type integer, decimal, money, boolean, list of values which are "chartable").
noStatsExclude field from Stats.

Field Group

Field Groups are used to separate Fields into panels in the Edit and Browse views.

PropertyMeaning
idUnique key for the group. It is optional.
typeType of fields group. Only "panel" is currently supported (tab and other types of groups will be added later).
labelGroup title displayed in the group header.
fieldsArray of field ids.
widthWidth (in % of the container total width).
helpOptional help tooltip text.
headerOptional text displayed at the top of the group (just below the group title).
footerOptional text displayed below the group.

Notes:

  • Field Groups are optional. By default a single group holds all fields.
  • Field Groups are positioned based on their "width" property the same way than fields are positioned inside groups.

Collection

Multiple details tables can be specified with "collections".

PropertyMeaning
idUnique key for the collection.
titleCollection title.
objectModel.id for the Object to link to.
fieldsArray of fields (objects or ids). Fields in collections can be field objects or just ids of fields in the collection's object.
readOnlySpecify if the collection is readOnly.
hideIfEmptyHide Collection when it is empty in Edit view (always hidden when empty in Browse view).
helpOptional help tooltip text.
headerText to be displayed before the collection.
footerText to be displayed below the collection.

Sample model using collections:Wine Cellar.

Sample model

The following example is the model for a simple graphic novels inventory app.

{id:"comics",title:"Graphic Novels",name:"graphic novel serie",namePlural:"graphic novel series",icon:"comics.png",titleField:"title",fields:[{id:"title",type:"text",label:"Title",required:true,maxLength:255,width:100,inMany:true,},{id:"authors",type:"text",label:"Authors",inMany:true,width:62,},{id:"genre",type:"lov",label:"Genre",width:38,inMany:true,list:[{id:1,text:"Adventure"},{id:2,text:"Fairy tale"},{id:3,text:"Erotic"},{id:4,text:"Fantastic"},{id:5,text:"Heroic Fantasy"},{id:6,text:"Historic"},{id:7,text:"Humor"},{id:8,text:"One of a kind"},{id:9,text:"Youth"},{id:10,text:"Thriller"},{id:11,text:"Science-fiction"},{id:12,text:"Super Heros"},{id:13,text:"Western"}]},{id:"serie_nb",type:"integer",label:"Albums",noCharts:true,width:15,inMany:false},{id:"have_nb",type:"integer",label:"Owned",width:15,inMany:false,noCharts:true},{id:"have",type:"text",label:"Have",width:15,inMany:false},{id:"language",type:"lov",label:"Language",width:17,inMany:true,lovIcon:true,list:[{id:2,text:'French',icon:'comics/flags/fr.png'},{id:1,text:'American',icon:'comics/flags/us.png'}]},{id:"complete",type:"boolean",label:"Complete",width:19,inMany:false},{id:"finished",type:"boolean",label:"Finished",width:19,inMany:false},{id:"pix",type:"image",label:"Cover",width:30,inMany:true},{id:"notes",type:"textmultiline",label:"Notes",width:70,height:7,maxLength:5000,inMany:false}],groups:[{id:"serie",type:"panel",label:"Serie",width:70,fields:["title","authors","genre","serie_nb","have_nb","have","language","complete","finished","notes"]},{id:"pix",type:"panel",label:"Cover",width:30,fields:["pix"]}]}

More sample models:To-do list,Address book,Restaurants list,Wine cellar.

Backend

You will need to setup the GraphQL backend onHasura with the Evolutility demo database.

  1. You can signup for afree account or host it yourself (Quickstart Hasura CLI).
  2. Add a Postgres database to your Hasura setup.
  3. Add the demo tables by running the SQL scriptevol-db-schema.sql.
  4. Populate your database with sample data by runningevol-db-data.sql
  5. Add relationships in Hasura console.
    Relationships oncomics table:
    • genre (Object): comics / genre_id -> comics_genre / id
    • language (Object): comics / language_id -> comics_language / id
    Relationships oncomics_genre table:
    • comics (Array): comics_genre / id => comics / genre_id
    Relationships oncomics_language table:
    • comics (Array): comics_language / id => comics / language_id
    Relationships oncontact table:
    • category (Object): contact / category_id -> contact_category / id
    Relationships oncontact_category table:
    • contacts (Array): contact_category / id => contact / category_id
    Relationships onmusic_album table:
    • artist (Object): music_album / artist_id -> music_artist / id
    • tracks (Array): music_album / id -> music_track / album_id
    Relationships onmusic_artist table:
    • albums (Array): music_artist / id -> music_album / artist_id
    Relationships onmusic_genre table:
    • tracks (Array): music_genre / id -> music_track / genre_id
    Relationships onmusic_track table:
    • album (Object): music_track / album_id -> music_album / id
    • genre (Object): music_track / genre_id -> music_genre / id
    Relationships onrestaurant table:
    • cuisine (Object): restaurant / cuisine_id -> restaurant_cuisine / id
    • price (Object): restaurant / price_id -> restaurant_price / id
    Relationships onrestaurant_cuisine table:
    • restaurants (Array): restaurant_cuisine / id => restaurants / cuisine_id
    Relationships onrestaurant_price table:
    • restaurants (Array): restaurant_price / id => restaurants / price_id
    Relationships ontask table:
    • category (Object): task / category_id -> task_category / id
    • priority (Object): task / priority_id -> task_priority / id
    Relationships ontask_category table:
    • tasks (Array): task_category / id => task / category_id
    Relationships ontask_priority table:
    • tasks (Array): task_priority / id => task / priority_id
    Relationships onwine table:
    • wine_tastings (Array): wine / id -> wine_tasting / wine_id
    • bsize (Object): wine / bsize_id -> wine_bsize / id
    • country (Object): wine / country_id -> wine_country / id
    • grape (Object): wine / grape_id -> wine_grape / id
    • score (Object): wine / score_id -> wine_score / id
    • type (Object): wine / type_id -> wine_type / id
    Relationships onwine_bsize table:
    • wines (Array): wine_bsize / id => wine / bsize_id
    Relationships onwine_country table:
    • wines (Array): wine_country / id => wine / country_id
    Relationships onwine_grape table:
    • wines (Array): wine_grape / id => wine / grape_id
    Relationships onwine_score table:
    • wines (Array): wine_score / id => wine / score_id
    Relationships onwine_tasting table:
    • wine (Object): wine_tasting / wine_id -> wine / id
    Relationships onwine_type table:
    • wines (Array): wine_type / id => wine / type_id
  6. In Evolutility, change the "apiPath" and "adminSecret" in the ./src/config.js file.

License

Copyright (c) 2023Olivier Giulieri.

Evolutility-UI-React is released under theAGPL-3.0 license.

To suggest a feature or report a bug:https://github.com/evoluteur/evolutility-ui-react/issues

Sponsor this project

 

Packages

No packages published

Contributors3

  •  
  •  
  •  

[8]ページ先頭

©2009-2025 Movatter.jp