refactor and fixes for mobile

This commit is contained in:
2012-08-26 20:50:43 +02:00
parent e56badcbf8
commit c087aa0267
16 changed files with 214 additions and 166 deletions
+1 -86
View File
@@ -19,36 +19,10 @@ root.Qrammer =
wrapper.modal() wrapper.modal()
currency: (num) -> currency: (num) ->
num = 0.0 if isNaN(num) || num == '' || num == null num = 0.0 if isNaN(num) || num == '' || num == null
'€ ' + parseFloat(num).toFixed(2) '€ ' + parseFloat(num).toFixed(2)
add_product: (product) ->
window.active_products_list = {} unless window.active_products_list
window.active_products_list[product._id] = {product: product, number: 0} unless window.active_products_list[product._id]
window.active_products_list[product._id].number += 1
Qrammer.build_product_list()
build_product_list: ->
table = $('#active-order-table')
tbody = table.find('tbody')
tbody = $('<tbody></tbody>').appendTo(table) unless tbody.length
tbody.find('tr').remove()
total = 0.0
for product_id, info of window.active_products_list
total += info.product.price * info.number
row = $('<tr></tr>').attr('id', 'active-order-row-'+product_id).appendTo(tbody)
row.append('<td>'+info.product.name+'</td>')
row.append('<td>'+info.number+'</td>')
row.append('<td class="currency">'+Qrammer.currency(info.product.price * info.number)+'</td>')
x_btn = $('<button class="btn btn-warning btn-mini">x</button>').click(-> delete(window.active_products_list[product_id]) && Qrammer.build_product_list() )
row.append($('<td></td>').append(x_btn))
$('#active-order-total').html(Qrammer.currency(total))
table.show()
clear_active_list: -> clear_active_list: ->
window.active_products_list = {} window.active_products_list = {}
$('#active-order-table').hide() $('#active-order-table').hide()
order_active_products_list: (post_uri)->
h = {list_id: active_list_id}
for product_id, info of window.active_products_list
h['products['+product_id+']'] = info.number
$.post(post_uri, h, ((res) -> Qrammer.handle_response(res)), 'json')
handle_response: (res) -> handle_response: (res) ->
if(typeof(res) == 'string') if(typeof(res) == 'string')
return unless res.length return unless res.length
@@ -97,38 +71,6 @@ root.Qrammer =
#foot.append('<tr><td></td><td class="currency"><strong>'+Qrammer.currency(res.total_amount)+'</strong></td></tr>'); #foot.append('<tr><td></td><td class="currency"><strong>'+Qrammer.currency(res.total_amount)+'</strong></td></tr>');
) )
handle_active_user_list: (callback) ->
$.get('/user/list_info.json', (res) ->
if !res.list_active
window.location = '/phone_home?list_closed=true'
return
window.active_list = res
callback.call() if callback
Qrammer.handle_active_user_list_default_actions()
)
handle_active_user_list_default_actions: ->
Qrammer.list_needs_payment_default_action()
Qrammer.list_needs_help_default_action()
list_needs_help_default_action: ->
needs_help_container = $('#list-needs-help-button')
if needs_help_container.length
if window.active_list.needs_help
needs_help_container.html('<i class="icon-hand-up"></i>')
else
needs_help_container.html($('<button class="btn btn-info">I have a question</button>').click(Qrammer.list_needs_help)) #TODO TEXT
list_needs_help: ->
return unless window.active_list && !window.active_list.needs_help
$.post('/user/needs_help.json', (res) -> window.active_list = res; Qrammer.list_needs_help_default_action())
list_needs_payment_default_action: ->
needs_payment_container = $('#list-needs-payment-button')
if needs_payment_container.length
if window.active_list.needs_payment
needs_payment_container.html('<i class="icon-check"></i>')
else
needs_payment_container.html($('<button class="btn btn-warning">Check please</button>').click(Qrammer.list_needs_payment)) #TODO TEXT
list_needs_payment: ->
return unless window.active_list && !window.active_list.needs_payment
$.post('/user/list_needs_payment.json', (res) -> window.active_list = res; Qrammer.list_needs_payment_default_action())
load_active_lists: () -> load_active_lists: () ->
$.get('/supplier/active_lists.json', (res) -> $.get('/supplier/active_lists.json', (res) ->
@@ -167,33 +109,6 @@ root.Qrammer =
row.append(td_buttons) row.append(td_buttons)
#foot.append('<tr><td></td><td class="currency"><strong>'+Qrammer.currency(res.total_amount)+'</strong></td></tr>'); #foot.append('<tr><td></td><td class="currency"><strong>'+Qrammer.currency(res.total_amount)+'</strong></td></tr>');
) )
active_user_list: (list_id) ->
$.get('/user/active_list.json', (res) ->
window.active_list = res
unless res.list_active
window.location = '/user/list_history/'+res._id + '?list_closed=true'
return
Qrammer.handle_active_user_list_default_actions()
body = $('#active-list-table tbody')
foot = $('#active-list-table tfoot')
body.find('tr').remove()
foot.find('tr').remove()
if !res.orders && !res.orders.length
alert('No orders in list')
return
for order in res.orders
order_txts = []
row = $('<tr></tr>').appendTo(body)
row.addClass(order.state)
#if(order.state == 'placed') row.addClass('info');
#if(order.state == 'delivered') row.addClass('success');
row.addClass('error') if order.state == 'cancelled'
for product in order.products
order_txts.push(product.name + ' (' + product['number'] + ')')
row.append($('<td></td>').text(order_txts.join(', ')))
row.append($('<td class="currency"></td>').html(Qrammer.currency(order.total_amount)))
foot.append('<tr><td></td><td class="currency"><strong>'+Qrammer.currency(res.total_amount)+'</strong></td></tr>')
)
build_product_list_as_modal: -> build_product_list_as_modal: ->
wrapper = $('<div class="modal"></div>') wrapper = $('<div class="modal"></div>')
+126
View File
@@ -0,0 +1,126 @@
root = exports ? this
root.Quser=
handle_active_list: (callback) ->
$.get('/user/list_info.json', (res) ->
if !res.list_active
window.location = '/phone_home?list_closed=true'
return
window.active_list = res
callback.call() if callback
Quser.handle_active_list_default_actions()
)
handle_active_list_default_actions: ->
Quser.list_needs_payment_default_action()
Quser.list_needs_help_default_action()
list_needs_help_default_action: ->
needs_help_container = $('#list-needs-help-button')
if needs_help_container.length
if window.active_list.needs_help
needs_help_container.html('<i class="icon-hand-up"></i>')
else
needs_help_container.html($('<button class="btn btn-info">I have a question</button>').click(Quser.list_needs_help)) #TODO TEXT
list_needs_help: ->
return unless window.active_list && !window.active_list.needs_help
$.post('/user/needs_help.json', (res) -> window.active_list = res; Quser.list_needs_help_default_action())
list_needs_payment_default_action: ->
needs_payment_container = $('#list-needs-payment-button')
if needs_payment_container.length
if window.active_list.needs_payment
needs_payment_container.html('<i class="icon-check"></i>')
else
needs_payment_container.html($('<button class="btn btn-warning">Check please</button>').click(Quser.list_needs_payment)) #TODO TEXT
list_needs_payment: ->
return unless window.active_list && !window.active_list.needs_payment
$.post('/user/list_needs_payment.json', (res) -> window.active_list = res; Quser.list_needs_payment_default_action())
load_active_list: () ->
$.get('/user/active_list.json', (res) ->
window.active_list = res
unless res.list_active
window.location = '/user/list_history/'+res._id + '?list_closed=true'
return
Quser.handle_active_list_default_actions()
body = $('#active-list-table tbody')
foot = $('#active-list-table tfoot')
body.find('tr').remove()
foot.find('tr').remove()
if !res.orders && !res.orders.length
alert('No orders in list')
return
for order in res.orders
order_txts = []
row = $('<tr></tr>').appendTo(body)
row.addClass(order.state)
#if(order.state == 'placed') row.addClass('info');
#if(order.state == 'delivered') row.addClass('success');
row.addClass('error') if order.state == 'cancelled'
for product in order.products
order_txts.push(product.name + ' (' + product['number'] + ')')
row.append($('<td></td>').text(order_txts.join(', ')))
row.append($('<td class="currency"></td>').html(Qrammer.currency(order.total_amount)))
foot.append('<tr><td></td><td class="currency"><strong>'+Qrammer.currency(res.total_amount)+'</strong></td></tr>')
)
order_selected_products: ()->
h = {list_id: active_list_id}
for product_id, info of window.active_products_list
h['products['+product_id+']'] = info.number
$.post('/user/order_selected_products', h, ((res) -> Qrammer.handle_response(res)), 'json')
build_product_list: ->
table = $('#active-order-table')
tbody = table.find('tbody')
tbody = $('<tbody></tbody>').appendTo(table) unless tbody.length
tbody.find('tr').remove()
total = 0.0
for product_id, info of window.active_products_list
total += info.product.price * info.number
row = $('<tr></tr>').attr('id', 'active-order-row-'+product_id).appendTo(tbody)
row.append('<td>'+info.product.name+'</td>')
row.append('<td>'+info.number+'</td>')
row.append('<td class="currency">'+Qrammer.currency(info.product.price * info.number)+'</td>')
x_btn = $('<button class="btn btn-warning btn-mini">x</button>').click(-> delete(window.active_products_list[product_id]) && Quser.build_product_list() )
row.append($('<td></td>').append(x_btn))
$('#active-order-total').html(Qrammer.currency(total))
table.show()
load_active_list_products: ->
$.get('/user/list_products.json', (res) ->
window.products = res
body = $('#products-table tbody')
for category, products of window.products
body.append('<tr><td colspan="4"><h4>'+category+'<h4></td></tr>')
for product in products
row = $('<tr></tr>')
button = $('<button class="btn btn-mini btn-primary">Add</button>')
callback = ((prod) ->
->
product_count_holder = $('#order-product-count-'+prod._id)
count = parseInt(product_count_holder.text())
product_count_holder.text(1)
Quser.add_product(prod, count)
)(product)
button.click(callback)
row.append('<td>'+product.name+'</td>')
order_product_count = $('<span id="order-product-count-'+product._id+'" class="order-product-count">1</span>')
order_count_minus = $('<span class="btn btn-info btn-mini">-</span>')
order_count_minus.click(->
val_holder = $(this).siblings('.order-product-count')
val = parseInt(val_holder.text())
val_holder.text(val - 1) if val > 1
)
order_count_plus = $('<span class="btn btn-info btn-mini">+</span>')
order_count_plus.click(->
val_holder = $(this).siblings('.order-product-count')
val = parseInt(val_holder.text())
val_holder.text(val + 1)
)
row.append($('<td class="order-count-cell"></td>').append(order_count_minus).append('&nbsp;').append(order_product_count).append('&nbsp;').append(order_count_plus))
row.append('<td>'+Qrammer.currency(product.price)+'</td>')
row.append($('<td></td>').append(button))
body.append(row)
)
add_product: (product, count) ->
count ||= 1
window.active_products_list = {} unless window.active_products_list
window.active_products_list[product._id] = {product: product, number: 0} unless window.active_products_list[product._id]
window.active_products_list[product._id].number += count
Quser.build_product_list()
@@ -11,3 +11,9 @@ body
margin-top: 4px margin-top: 4px
margin-bottom: 6px margin-bottom: 6px
padding-bottom: 0 padding-bottom: 0
.order-product-count
width: 30px
text-align: right
margin-bottom: 0
.order-count-cell
white-space: nowrap
@@ -73,3 +73,7 @@ table
margin-left: 5px margin-left: 5px
i i
padding-left: 5px padding-left: 5px
#qr-list
list-style: none
margin: 0
padding: 0
+12 -4
View File
@@ -1,14 +1,23 @@
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
layout :layout_by_resource
protect_from_forgery protect_from_forgery
private private
def layout_by_resource
if devise_controller?
"phone"
else
"application"
end
end
def check_active_list_state def check_active_list_state
if session[:active_list_id] if session[:active_list_id]
unless active_list.active? unless active_list.active?
session[:active_list_id] = nil session[:active_list_id] = nil
redirect_to phone_root_path, alert: t('messages.the_list_has_been_closed', list: List.model_name.human) redirect_to user_root_path, alert: t('messages.the_list_has_been_closed', list: List.model_name.human)
end end
end end
@@ -18,6 +27,8 @@ class ApplicationController < ActionController::Base
return nil unless session[:active_list_id].present? return nil unless session[:active_list_id].present?
@active_list ||= List.find(session[:active_list_id]) @active_list ||= List.find(session[:active_list_id])
end end
alias :active_list_object :active_list
helper_method :active_list_object
def js_alert(message) def js_alert(message)
{ok: false, message: message}.to_json {ok: false, message: message}.to_json
@@ -25,7 +36,4 @@ class ApplicationController < ActionController::Base
def js_notice(message) def js_notice(message)
{ok: true, message: message}.to_json {ok: true, message: message}.to_json
end end
helper_method :active_list
end end
-39
View File
@@ -4,10 +4,6 @@ class DashboardController < ApplicationController
def home def home
end end
def phone_home
flash.now[:notice] = t('messages.the_list_has_been_closed', list: List.model_name.human) if params[:list_closed].present?
render layout: 'phone'
end
# Testing action # Testing action
def select_qrcode def select_qrcode
@@ -15,41 +11,6 @@ class DashboardController < ApplicationController
render layout: 'phone' render layout: 'phone'
end end
def order_active_products_list
respond_to do |format|
format.html do
redirect_to(root_path, alert: t('messages.cannot_order_without_list_id')) and return if params[:list_id].blank?
@list = List.find(params[:list_id])
redirect_to(root_path, alert: t('messages.cannot_order_on_non_active_list')) and return unless @list.active?
@list.place_order current_user, params[:products]
redirect_to root_path, notice: t('messages.order_is_placed')
end
format.js do
render js: js_alert(t('messages.cannot_order_without_list_id')) and return if params[:list_id].blank?
@list = List.find(params[:list_id])
render js: js_alert(t('messages.cannot_order_on_non_active_list')) and return unless @list.active?
@list.place_order current_user, params[:products]
render js: js_notice( t('messages.order_is_placed') )
end
end
end
# GET /suppliers/1/product_list
# GET /suppliers/1/product_list.json
def product_list
@supplier = active_list.supplier
respond_to do |format|
format.html # show.html.erb
format.json do
products = active_list.supplier.products
products.include_relation(:product_categories)
products.sort_by!{|p| p.product_category.try(:position) || 90000}
h = products.inject({}){|h, p| n = p.product_category.try(:name) || 'other'; h[n] ||= []; h[n] << p; h}
render json: h
end
end
end
def supplier_home def supplier_home
redirect_to active_orders_supplier_path(Supplier.first) redirect_to active_orders_supplier_path(Supplier.first)
+45 -2
View File
@@ -3,6 +3,11 @@ class UserController < ApplicationController
alias :list :active_list alias :list :active_list
def home
flash.now[:notice] = t('messages.the_list_has_been_closed', list: List.model_name.human) if params[:list_closed].present?
render layout: 'phone'
end
# POST /user/create_list {table_id: 1234} # POST /user/create_list {table_id: 1234}
def create_list def create_list
@table = Table.find(params[:table_id]) @table = Table.find(params[:table_id])
@@ -18,9 +23,22 @@ class UserController < ApplicationController
end end
end end
# GET /suppliers/1/product_list
# GET /suppliers/1/product_list.json
def list_products def list_products
@supplier = Supplier.first @supplier = list.supplier
render layout: 'phone' respond_to do |format|
format.html do
render layout: 'phone'
end
format.json do
products = list.supplier.products
products.include_relation(:product_categories)
products.sort_by!{|p| p.product_category.try(:position) || 90000}
h = products.inject({}){|h, p| n = p.product_category.try(:name) || 'other'; h[n] ||= []; h[n] << p; h}
render json: h
end
end
end end
# GET /user/current_list.json # GET /user/current_list.json
@@ -95,7 +113,9 @@ class UserController < ApplicationController
## ##
# Displays the closed lists of the user # Displays the closed lists of the user
# GET /user/list_history
def list_history def list_history
@lists = current_user.lists
render layout: 'phone' render layout: 'phone'
end end
@@ -104,8 +124,31 @@ class UserController < ApplicationController
# GET /user/list_history/:list_id # GET /user/list_history/:list_id
def history_list def history_list
@list = List.find(params[:list_id]) @list = List.find(params[:list_id])
if params[:list_closed].present? && session[:active_list_id] == @list.id
session[:active_list_id] = nil
flash.now[:notice] = t('messages.the_list_has_been_closed', list: List.model_name.human)
end
redirect_to user_root_path, alert: t('messages.illegal_history_list_attempt') and return unless @list.user_ids.include?(current_user.id) redirect_to user_root_path, alert: t('messages.illegal_history_list_attempt') and return unless @list.user_ids.include?(current_user.id)
render layout: 'phone' render layout: 'phone'
end end
def order_selected_products
respond_to do |format|
format.html do
redirect_to(root_path, alert: t('messages.cannot_order_without_list_id')) and return if params[:list_id].blank?
@list = List.find(params[:list_id])
redirect_to(root_path, alert: t('messages.cannot_order_on_non_active_list')) and return unless @list.active?
@list.place_order current_user, params[:products]
redirect_to root_path, notice: t('messages.order_is_placed')
end
format.js do
render js: js_alert(t('messages.cannot_order_without_list_id')) and return if params[:list_id].blank?
@list = List.find(params[:list_id])
render js: js_alert(t('messages.cannot_order_on_non_active_list')) and return unless @list.active?
@list.place_order current_user, params[:products]
render js: js_notice( t('messages.order_is_placed') )
end
end
end
end end
+4
View File
@@ -18,6 +18,10 @@ module ApplicationHelper
t('helpers.links.are_you_sure') t('helpers.links.are_you_sure')
end end
def active_list
active_list_object
end
def list_open? def list_open?
session[:active_list_id].present? session[:active_list_id].present?
end end
+1 -1
View File
@@ -1,5 +1,5 @@
.phone-wrapper .phone-wrapper
iframe.phone-content-frame src=phone_root_path iframe.phone-content-frame src=user_root_path
.tablet-wrapper .tablet-wrapper
iframe.tablet-content-frame src=supplier_root_path iframe.tablet-content-frame src=supplier_root_path
+1 -1
View File
@@ -1,4 +1,4 @@
.page-header= title 'Select Qr code' .page-header= title 'Select Qr code'
ul ul#qr-list
- for table in @tables - for table in @tables
li= link_to image_tag(url_for(qrcode_table_path(table, format: :png))), user_create_list_path(table_id: table.id) li= link_to image_tag(url_for(qrcode_table_path(table, format: :png))), user_create_list_path(table_id: table.id)
+3 -1
View File
@@ -28,9 +28,11 @@ html lang="en"
span.icon-bar span.icon-bar
span.icon-bar span.icon-bar
span.icon-bar span.icon-bar
a.brand href=phone_root_path Qrammer a.brand href=user_root_path Qrammer
.container.nav-collapse .container.nav-collapse
ul.nav#top-navigation-list ul.nav#top-navigation-list
- if list_open?
li= link_to 'Move table', '#'
li= link_to 'View history', user_history_path li= link_to 'View history', user_history_path
.container .container
+2 -2
View File
@@ -13,6 +13,6 @@ table#active-list-table.table.table-striped
- content_for :footer do - content_for :footer do
javascript: javascript:
jQuery(function(){ jQuery(function(){
Qrammer.active_user_list('#{session[:active_list_id]}') Quser.load_active_list();
setInterval( "Qrammer.active_user_list('#{session[:active_list_id]}')", 7500); setInterval( "Quser.load_active_list()", 7500);
}) })
@@ -2,9 +2,6 @@ ul.nav.nav-tabs.nav-stacked
- if list_open? - if list_open?
li= link_to 'Place order', user_list_products_path(supplier_id: active_list.supplier.id) li= link_to 'Place order', user_list_products_path(supplier_id: active_list.supplier.id)
li= link_to 'Active list', user_active_list_path li= link_to 'Active list', user_active_list_path
li= link_to 'Request bill', '#'
li= link_to 'Move table', '#'
li= link_to 'I have a question', '#'
- else - else
li= link_to 'Join table with Qr scan', '/select_qrcode' li= link_to 'Join table with Qr scan', '/select_qrcode'
li= link_to 'Subscribe to list', '#' li= link_to 'Subscribe to list', '#'
+4 -24
View File
@@ -16,7 +16,7 @@ table#active-order-table.table.table-striped.hide
tfoot tfoot
tr tr
td colspan=2 td colspan=2
button class="btn btn-primary" onClick="Qrammer.handle_active_user_list(function(){Qrammer.order_active_products_list('/order_active_products_list')})" Bestellen button class="btn btn-primary" onClick="Quser.handle_active_list(function(){Quser.order_selected_products()})" Bestellen
|&nbsp; |&nbsp;
button class="btn btn btn-warning" onClick="Qrammer.clear_active_list()" Clear button class="btn btn btn-warning" onClick="Qrammer.clear_active_list()" Clear
td.currency td.currency
@@ -25,29 +25,9 @@ table#active-order-table.table.table-striped.hide
- content_for :footer do - content_for :footer do
javascript: javascript:
jQuery(function(){ jQuery(function(){
Qrammer.handle_active_user_list(function(){ Quser.handle_active_list(function(){
$.get('/user/product_list.json', function(res){ Quser.load_active_list_products();
window.products = res setInterval('Quser.handle_active_list()', 7500);
body = $('#products-table tbody')
for(var category in window.products){
body.append('<tr><td colspan="3"><h4>'+category+'<h4></td></tr>');
var category_ref = window.products[category];
for(var iproduct = 0; iproduct < window.products[category].length; iproduct++){
var product = window.products[category][iproduct];
row = $('<tr></tr>');
button = $('<button class="btn btn-mini btn-primary">Add</button>');
var callback = (function(prod){
return function(){ Qrammer.add_product(prod) }
})(product)
button.click(callback);
row.append('<td>'+product.name+'</td>');
row.append('<td>'+Qrammer.currency(product.price)+'</td>');
row.append($('<td></td>').append(button));
body.append(row);
}
}
})
setInterval('Qrammer.handle_active_user_list()', 7500);
}) })
}) })
+2
View File
@@ -40,6 +40,7 @@ en:
table: Table table: Table
list: List list: List
product: Product product: Product
order: Order
product_category: Product category product_category: Product category
plural: plural:
user: Users user: Users
@@ -47,6 +48,7 @@ en:
table: Tables table: Tables
list: Lists list: Lists
product: Products product: Products
order: Orders
product_category: Product categories product_category: Product categories
attributes: attributes:
product: product:
+3 -3
View File
@@ -28,19 +28,19 @@ Qrammer::Application.routes.draw do
post '/supplier/mark_order_in_process' => 'supplier#mark_order_in_process', as: :supplier_mark_order_in_process post '/supplier/mark_order_in_process' => 'supplier#mark_order_in_process', as: :supplier_mark_order_in_process
post '/supplier/order_is_delivered' => 'supplier#order_is_delivered', as: :supplier_order_is_delivered post '/supplier/order_is_delivered' => 'supplier#order_is_delivered', as: :supplier_order_is_delivered
match '/user' => 'user#home', as: :user_root
get '/user/active_list(.:format)' => 'user#active_list', as: :user_active_list get '/user/active_list(.:format)' => 'user#active_list', as: :user_active_list
get '/user/list_info' => 'user#list_info', as: :user_list_info get '/user/list_info' => 'user#list_info', as: :user_list_info
post '/user/needs_help' => 'user#needs_help', as: :user_needs_help post '/user/needs_help' => 'user#needs_help', as: :user_needs_help
post '/user/list_needs_payment' => 'user#list_needs_payment', as: :user_list_needs_payment post '/user/list_needs_payment' => 'user#list_needs_payment', as: :user_list_needs_payment
match '/user/create_list' => 'user#create_list', as: :user_create_list match '/user/create_list' => 'user#create_list', as: :user_create_list
get '/user/list_products' => 'user#list_products', as: :user_list_products get '/user/list_products' => 'user#list_products', as: :user_list_products
match '/phone_home' => 'dashboard#phone_home', as: :phone_root
match '/user/list_history' => 'user#list_history', as: :user_list_history match '/user/list_history' => 'user#list_history', as: :user_list_history
match '/user/list_history/:list_id' => 'user#history_list', as: :user_history_list match '/user/list_history/:list_id' => 'user#history_list', as: :user_history_list
post '/user/order_selected_products' => 'user#order_selected_products', as: :user_order_selected_products
match '/show_products' => 'dashboard#show_products', as: :user_products match '/show_products' => 'dashboard#show_products', as: :user_products
match '/user/product_list(.:format)' => 'dashboard#product_list'
match "/:action", controller: 'dashboard' match "/:action", controller: 'dashboard'
# The priority is based upon order of creation: # The priority is based upon order of creation: