This project rocks and uses MIT-LICENSE.

Ui Bibz

Ui Bibz est un framework d’interface permettant de construire une interface très rapidement et simplement à l'aide de Ruby on Rails 4 et de Boostrap 3.

Ui Bibz charge la librairie boostrap et awesomefont.

Tous les composants du framework Ui Bibz comportent l'agument options et l'argument html_options. Ces éléments sont basés sur l'élément Component. Un component accepte un contenu par variable ou par block.

Component

L'élément component accepte dans content et block :

L'élément component à pour options un Hash acceptant les clefs :

L'élément component à pour html_options un Hash acceptant les clefs :

Exemple :

Component.new 'Exemple', { state: :success, glyph: { name: 'pencil', size: 3} }, { class: 'exemple' }

Component.new { state: :success, glyph: 'eye' }, { class: 'exemple' } do
  'Exemple'
end

Signature :

Component.new content = nil, options = nil, html_options = nil, &block

NB : Pour des raisons de simplicité d'écriture, l'argument class est présent dans options et html_options.

Installation

Ajouter la gem dans Rails :

gem "ui_bibz", '~> 1.2.5'

Lancer la command suivante :

bundle install

Placer la ligne suivante dans /app/views/layouts/application.rb

= ui_bibz_meta_links

Exemple (haml): !!! %html %head ... = ui_bibz_meta_links ... %body

Ui Bibz chargera les librairies en CDN directement dans votre application. Si vous préférez charger les librairies en locales, utilisez plutôt la méthode ui_bibz_local_meta_links et insérez dans le fichier /config/initializers/assets.rb de votre application cette ligne:

# For Ui bibz js
Rails.application.config.assets.precompile += %w(jquery-2.1.4.min.js)

Placer la ligne suivante dans /app/assets/stylesheets/applications.css

...
*= require ui_bibz
...

Placer la ligne suivante dans /app/assets/javascripts/applications.js

...
//= require ui_bibz
...

Ps: Vous pouvez utiliser les variables sass présentes dans boostrap.

Utilisation

Alert

L'élément notify à pour options un Hash acceptant les clefs :

notify 'Alert', state: :info, glyph: 'eye'

Voir la doc

Breadcrumb (fil d'ariane)

L'élément breadcrumb à pour enfant l'élément link qui accepte pour option un Hash avec les clefs :

breadcrumb do |b|
  b.link 'Exemple 1', url: '#exemple-1', glyph: 'home'
  b.link({ url: '#exemple-2' }, { class:'link' }) do
    'Exemple 2'
  end
  b.link 'Exemple 3', status: :active
end

Voir la doc

Buttons (Boutons)

Button

L'élément button à pour options un Hash acceptant les clefs :

button 'Button', { state: :danger, size: :xs, glyph: 'star' } , { class: 'my-button' }

Voir la doc

Button Dropdown

L'élément button_dropdown accepte pour options les mêmes clefs que l'élément dropdown.

button_dropdown 'Button Dropdown' do |bd|
  bd.link Link 1', '#'
  bd.header 'Header 1'
  bd.link 'Link 2'
  bd.divider
  bd.link 'Link 3', '#'
  bd.html link_to('Link 4', '#')
end

Voir la doc

Button group

L'élément button_group à pour options un Hash acceptant les clefs :

L'élément list à pour options un Hash acceptant les clefs :

button_group({ position: :vertical, size: :xs }) do
  button 'Button 1', status: :active
  button 'Button 2'
  button 'Button 3'
end

button_group do
  button 'Button 1', status: :active
  button 'Button 2'
  button 'Button 3'
  button_dropdown 'Button Dropdown' do |bd|
    bd.header 'header'
    bd.link 'Link 1', '#'
    bd.divider
    bd.link 'Link 2', '#'
  end
end

Voir la doc

Button Link (Lien Bouton)

L'élément button_link à pour options un Hash acceptant les clefs :

button_link 'Button', { url: '#button', state: :primary, glyph: 'star' }, { class: 'my-button' }

Voir la doc

Button Split Dropdown

L'élément button_split_dropdownaccepte pour options les mêmes clefs que l'élément dropdown.

button_split_dropdown 'Dropdown', state: :primary do |d|
  d.link url: "#" do
    'Link 1'
  end
  d.header 'Header 1'
  d.link 'Link 2', '#'
  d.divider
  d.link 'Link 3', '#'
end

Voir la doc

Dropdown

L'élément dropdown à pour options un Hash acceptant les clefs :

L'élément list est un component qui accepte pour options les clefs :

dropdown 'Dropdown', state: :success do |d|
  d.list do
    link_to 'Link 1', "#"
  end
  d.list 'Header 1', type: :header
  d.list link_to 'Link 2', '#'
  d.list '---'
  d.list link_to 'Link 3', '#'
end

Pour ajouter une ligne séparatrice, il suffit d'insérer 3 “-” à la suite

Exemple :

...
d.list '--'
...

Voir la doc

Progress Bar

L'élément progress_bar à pour options un Hash acceptant les clefs :

progress_bar 30

progress_bar state: :info, sr_only: true, type: :animated do
  70
end

progress_bar(tap: true) do |pb|
  pb.bar 10, { state: :success, label: 'Loading...' },{ class: 'test' }
  pb.bar 30, state: :warning
  pb.bar(type: :striped) do
    10
  end
end

Voir la doc

Glyph

Les glyphs utilisés proviennent de Font Awesome. L'élément glyph peut contenir un hash pour content L'élément glyph à pour options un Hash acceptant les clefs :

glyph 'star', { size: 3, type: 'fw' }, class: 'star-exemple'

glyph { name: 'star', size: 3, type: 'fw' }

Voir la doc

Stars

L'élément stars à pour options un Hash acceptant les clefs :

stars 3.2

stars 7, { num: 10, state: :danger }

stars num: 3 do
  1
end

Voir la doc

Modal

Les éléments header, body, footer sont des éléments component.

Exemple :


modal do |m|
  m.header 'Header', glyph: 'eye'
  m.body(class: 'my-body') do
   'Content body'
  end
  m.footer 'Footer'
end

Voir la doc

Panel

L'élément panel à pour options un Hash acceptant les clefs :

Les éléments header, body,footer sont des éléments component.

Exemple :

panel 'danger'

panel(state: :danger) do
  'Content'
end

panel({ tap: true, state: :danger, table_options: { actionable: true } }, { class: 'exemple' }) |p|
  p.header 'Header', glyph: 'eye'
  p.body(class: 'my-body') do
   'Content body'
  end
  p.footer 'Footer'
end

Voir la doc

Table

L'élément table est un tableau composé d'une recherche, une pagination et un trie de colonnes intégrées. Le tableau est compatible I18n. Le tableau contient pour chaque ligne un bouton dropdown 'action' avec par défaut ces 3 actions : voir, éditer, supprimer. Toutes les colonnes sont présentes et affichées par défaut.

La table doit contenir un store. Ce store doit-être créé dans le controlleur avec la méthode table_search_pagination.

La méthode table_search_pagination contient 3 arguments :

Exemple :

# app/controllers/document_controller.rb
@documents = Document.table_search_pagination(params, session)

Dans le model, insérer la méthode searchable_attributes afin de pouvoir faire une recherche sur les attributs souhaités.

Exemple :

# app/models/document.rb
searchable_attributes :name_fr, :name_en

Un champ recherche est disponible dans la vue :

table_search_field store: @documents

Une pagination est disponible dans la vue :

table_pagination store: @documents

Un champs select par page est disponible dans la vue :

table_pagination_per_page store: @documents

Simple Example table

Dans le controlleur, insérer la méthode table_search_pagination. La méthode table_search_pagination contient 3 arguments :

Exemple :

# app/controllers/document_controller.rb
@documents = Document.table_search_pagination(params, session)

Dans le model, insérer la méthode searchable_attributes afin de pouvoir faire une recherche sur les attributs souhaités. Vous pouvez même faire une recherche sur une table différente en insérant un hash avec pour clef le nom du model et en valeur le nom de l'attribut recherché.

Exemple :

# app/models/document.rb
searchable_attributes :name_fr, :name_en, { user: :name }

Dans la vue, insérer la méthode table qui peut contenir plusieurs arguments :

Une table comporte des colonnes et des actions.

Exemple :

# app/views/documents/index.html.haml
table store: @documents

Les actions par défauts peuvent être modifiées (voir exemple complexe) :

Elles sont intégrées à l'intérieur d'un bouton dropdown.

Exemple :

# app/views/documents/index.html.haml
table store: @documents do |g|
  g.actions do |acs|
    acs.headr 'Main Actions'
    acs.link 'Show', documents_path(:id), glyph: 'eye'
    acs.link 'Edit', edit_document_path(:id), glyph: 'pencil'
    acs.link 'Delete', documents_path(:id), method: :delete, glyph: 'trash', data: { confirm: 'Are you sure?' }
    acs.divider
    acs.link 'Duplicate', duplicate_document_path(:id), glyph: 'files-o'
    acs.link 'Alert', alert_document_path(:id), glyph: 'bell'
  end
end

L'ajout de colonnes à travers la méthode column contient plusieurs arguments et cette méthode est basée sur le component :

# app/views/documents/index.html.haml
table store: @documents do |g|
  g.columns do |c|
    c.column :id, { name: '#' }
    c.column :name_fr, { name: 'Name fr', link: edit_document_path(:id) }
    c.column :name_en
    c.column :hotline_access, { name: 'Hotline', format: lambda{ |records, record| glyph(record.icon) } }
    c.column :update_at, { date_format: '%Y' }
  end
end

Complex Example table

Si on souhaite voir apparaître certaines liasions avec d'autres tables il faut pour cela :

Dans le controlleur, insérer la méthode table_search_pagination en ajoutant un includes juste avant.

Exemple : ruby # app/controllers/document_controller.rb @documents = Document.includes(:users).table_search_pagination(params, session)

Dans la vue, insérer la méthod table. NB: On peut créer ses propres méthodes comme user_name dans notre model “Document” et l'appeler comme valeur pour la clef data_index.

# app/views/documents/index.html.haml
table store: @documents do |g|
  g.columns do |c|
    c.column :user_name, { name: 'User', sort: "user.name" }
  end
end

Ultra Complex Example table

Si l'on souhaite, par exemple, dénombrer des utilisateurs qui ont un lien non direct avec les documents. Imaginons par exemple, un utilisateur à des produits et que ces produits contiennent plusieurs documents. On souhaite compter le nombre d'utilisateurs par documents.

On peut ajouter des arguments dans la méthode table_search_pagination qui vont permettre de faire des jointures.

Exemple : “`

app/controllers/document_controller.rb

arguments = { sortable: { column: 'users', count: true, joins: “LEFT OUTER JOIN documents_products ON documents_products.document_id = documents.id LEFT OUTER JOIN products ON products.id = documents_products.product_id LEFT OUTER JOIN products_users ON products_users.product_id = products.id LEFT OUTER JOIN users ON users.id = products_users.user_id” } }

@documents = Document.includes(:users).table_search_pagination(params, session, arguments) “`

Ici l'argument sortable signifie que l'on souhaite s'interresser à la fonctionnalité de trie.

Pour celà il faut :

Dans la vue :

# app/views/documents/index.html.haml
table store: @documents do |g|
  g.columns do |c|
    c.column :users, { name: 'Users count', count: true, custom_sort: true }
  end
end

table actions

Les actions d'une table peuvent être formatées avec le 'record' passé en paramètre.

# app/views/documents/index.html.haml
table store: @documents do |t|
  t.columns do |cls|
    cls.column :id, { name: '#' }
    cls.column :name_en
  end
  t.actions do |acs|
    acs.format do |record|
      if record.active?
        acs.link 'Active', { url: active_document_path(record.id) }
      else
        acs.link 'Disabled', { url: disabled_document_path(record.id) }
      end
      acs.link 'Show', { url: document_path(record.id) }
    end
  end
end

Les actions ainsi que la colonne action peuvent être désactivées en passant l'agument actionable: false.

# app/views/documents/index.html.haml
table store: @documents, actionable: false

Plus d'une table sur une page html

Si vous avez plus d'une table sur votre page html et que vous souhaitez faire des recherches, paginer… Vous devez identifier chaque store pour que l'action effectuée (recherche, pagination,…) ne soit affectée que sur la table désirée.

Pour cela il faut que vous donniez un identifiant unique à vos stores.

ex:

# app/controllers/document_controller.rb
@documents = Document.includes(:users).table_search_pagination(params, session, { store_id: 'store-1'})

table I18n

La table est utilisable avec I18n. Les traductions s'executent par ordre d'importance dans cet ordre précis pour la colonne “name_fr” par exemple.

  1. ui_biz.table.headers.document.name_fr

  2. ui_biz.table.headers.defaults.name_fr

  3. activerecord.attributes.document.name_fr

  4. activerecord.attributes.defaults.name_fr

Le placeholder du champ recherche est utilisable et traduisible avec les attributs activerecord dans le fichier locale.

Exemple :

# config/locales/fr.yml
...
activerecord:
  models:
      user: 'Utilisateur'
  attributes:
    defaults:
      name_fr: 'Nom fr'
...

Voir la doc

Table Panel

Le composant table_panel est un tableau dans un panel.

table_panel store: @users

table_panel({ store: @users, tap: true, glyph: 'home', state: :danger }) do |g|
  g.columns do |cls|
    cls.column :id, { name: '#' }
    cls.column :username, { name: 'Username', link: edit_user_path(:id) }
    cls.column :name
    cls.column(:email) do
      'Email'
    end
    cls.column :role_name, { name: 'Role', sort: 'roles.name' }
  end
  g.actions do |acs|
    acs.link 'Action 1', { url: edit_user_path(:id), glyph: 'pencil' }
    acs.divider
    acs.link { url: user_path(:id), glyph: 'eye' } do
      'Action 2'
    end
  end
end

Voir la doc

List

Par défaut une liste à pour tag <li>. Mais elle peut se transformer en lien <a> à travers l'option type:. Par défaut le tag <li> est présent.

list_group type: :link do |lg|
  lg.list 'Momo', { state: :success, glyph: 'home' }, { href: '#Momo' }
  lg.list({ tap: true, status: :active }, { href: '#Toto' }) do |l|
    l.header 'My title'
    l.body 'My title'
  end
end

list_group do |lg|
  lg.list 'Momo', glyph: 'home', badge: 2
  lg.list 'Toto'
end

Voir la doc

Nav

Par défaut la navigation comporte des onglets “tab”. L'élément nav accepte en option les arguments :

L'élement link est un component.

nav(type: :pills, position: :justified) do |d|
  d.link 'Link 1', url: '#test', badge: 6
  d.link(url: '#test2', status: :active) do
    "Link 2"
  end
end

Voir la doc

Navbar

Par défaut la navigation comporte des onglets “tab”. L'élément navbar accepte en option les arguments :

L'élement nav est un component et contient les composants :

navbar(type: :inverse, position: :top) do |nb|
  nb.nav do |n|
    n.link 'Link 1', url: '#link-1'
  end
  nb.nav(position: :right) do |n|
    n.link 'Link 2', url: '#test', badge: 6
    n.link(url: '#link-2', status: :active) do
      "Link 3"
    end
  end
end

Voir la doc

Etiquette

NB : Les méthodes Tag, label sont déjà utilisées par Rails. L'élément etiquette à pour options un Hash acceptant les clefs :

Exemple :

etiquette 'label'
etiquette 'label 2', state: :success
etiquette 'label 2', state: :danger

Voir la doc

Row

Le composant row génére une div avec la class row.

row class: 'toto' do 'content' end # => <div class='row toto'>content</div>

Voir la doc

Col

L'élément col est un composant qui accèpte en arguments :

ou

Ces paramètres génèrent les classes qui seront insérées dans la div avec la classe col.

col({num: 2, size: :lg}, class: 'test') do
  'content'
end
# => <div class='col-lg-2 test'>content</div>


col([{ offset: 1, size: :xs}, { num: 3}], class: 'test') do
  'content'
end
# => <div class='col-xs-offset-1 col-md-3 test'>content</div>

Voir la doc

Grid

Une grid est un composant qui est composé de 5 vues :

La vue center est obligatoire. Une vue à pour arguments :

L'argument position détermine la position de la vue et l'argument num determine le nombre de colonnes occupées par la vue.

grid do |g|
  g.view num: 3, position: :left do
    list_group(type: :link) do |lg|
      lg.list 'Link 1', { url: '#link1' }
      lg.list 'Link 2', { url: '#link1', status: :active }
      lg.list 'Link 1', { url: '#link1' }
      lg.list 'Link 3', { url: '#link1' }
      lg.list 'Link 4', { url: '#link1' }
    end
  end
  g.view({ position: :top}) do
    button_group(type: :toolbar) do
      button 'option 1'
      button 'option 2'
      button 'option 3'
    end
  end
  g.view position: :center do
    table store: @users, type: :bordered
  end
  g.view position: :bottom do
    'bottom'
  end
end

grid do |g|
  g.view num: 5, position: :left do
    'left'
  end
  g.view position: :right do
    'right'
  end
  g.view({ position: :top}, { class: 'success'}) do
    'top'
  end
  g.view position: :center do
    'center'
  end
  g.view position: :bottom do
    'bottom'
  end
end

Voir la doc

Arguments and Values

status-values

size-values

state-values

glyph-arguments

Plus de détails

Pour plus d'informations, vous pouvez accéder à la documentation rdoc en générant cette dernière :

rake rdoc

Conflits

Certaines méthodes dans le helper peuvent être en conflit avec d'autres librairies. Le cas échéant, vous pouvez utiliser directement la librairie UiBibz comme ci-dessous.

Exemple :

UiBibz::Ui::Core::Panel.new('Exemple', { state: :success }, { class: 'exemple'}).render
# au lieu de
panel 'Exemple', { state: :success }, { class: 'exemple' }

Ui Bibz versions

Roadmap

Pour la V2.