Add some style to the application, use SASS for this.
This commit is contained in:
parent
c792cb70a8
commit
347691c4b1
159
stoptime.rb
159
stoptime.rb
|
@ -16,6 +16,7 @@ require "camping"
|
||||||
require "markaby"
|
require "markaby"
|
||||||
require "mime/types"
|
require "mime/types"
|
||||||
require "pathname"
|
require "pathname"
|
||||||
|
require "sass/plugin/rack"
|
||||||
|
|
||||||
Markaby::Builder.set(:indent, 2)
|
Markaby::Builder.set(:indent, 2)
|
||||||
Camping.goes :StopTime
|
Camping.goes :StopTime
|
||||||
|
@ -27,6 +28,9 @@ unless defined? PUBLIC_DIR
|
||||||
# Set up the locales.
|
# Set up the locales.
|
||||||
I18n.load_path += Dir[ File.join('locale', '*.yml') ]
|
I18n.load_path += Dir[ File.join('locale', '*.yml') ]
|
||||||
|
|
||||||
|
# Set up SASS.
|
||||||
|
Sass::Plugin.options[:template_location] = "templates/sass"
|
||||||
|
|
||||||
# Set the default date(/time) format.
|
# Set the default date(/time) format.
|
||||||
ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.merge!(
|
ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.merge!(
|
||||||
:default => "%Y-%m-%d %H:%M",
|
:default => "%Y-%m-%d %H:%M",
|
||||||
|
@ -522,11 +526,11 @@ module StopTime::Controllers
|
||||||
elsif @format == "tex"
|
elsif @format == "tex"
|
||||||
tex_file = PUBLIC_DIR + "#{@number}.tex"
|
tex_file = PUBLIC_DIR + "#{@number}.tex"
|
||||||
_generate_invoice_tex(@number) unless tex_file.exist?
|
_generate_invoice_tex(@number) unless tex_file.exist?
|
||||||
redirect(StaticX, tex_file.basename)
|
redirect(Static, tex_file.basename)
|
||||||
elsif @format == "pdf"
|
elsif @format == "pdf"
|
||||||
pdf_file = PUBLIC_DIR + "#{@number}.pdf"
|
pdf_file = PUBLIC_DIR + "#{@number}.pdf"
|
||||||
_generate_invoice_pdf(@number) unless pdf_file.exist?
|
_generate_invoice_pdf(@number) unless pdf_file.exist?
|
||||||
redirect(StaticX, pdf_file.basename)
|
redirect(Static, pdf_file.basename)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -705,7 +709,7 @@ module StopTime::Controllers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class StaticX
|
class Static < R '/static/(.+)'
|
||||||
def get(path)
|
def get(path)
|
||||||
mime_type = MIME::Types.type_for(path).first
|
mime_type = MIME::Types.type_for(path).first
|
||||||
@headers['Content-Type'] = mime_type.nil? ? "text/plain" : mime_type.to_s
|
@headers['Content-Type'] = mime_type.nil? ? "text/plain" : mime_type.to_s
|
||||||
|
@ -726,6 +730,8 @@ module StopTime::Views
|
||||||
xhtml_strict do
|
xhtml_strict do
|
||||||
head do
|
head do
|
||||||
title "Stop… Camping Time!"
|
title "Stop… Camping Time!"
|
||||||
|
link :rel => "stylesheet", :type => "text/css",
|
||||||
|
:media => "screen", :href => R(Static, "stylesheets/style.css")
|
||||||
end
|
end
|
||||||
body do
|
body do
|
||||||
div.wrapper! do
|
div.wrapper! do
|
||||||
|
@ -766,8 +772,11 @@ module StopTime::Views
|
||||||
a "here", :href => R(CustomersNTasksNew, customer.id)
|
a "here", :href => R(CustomersNTasksNew, customer.id)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
table do
|
table.overview do
|
||||||
@tasks[customer].each do |task|
|
@tasks[customer].each do |task|
|
||||||
|
col.task {}
|
||||||
|
col.hours {}
|
||||||
|
col.amount {}
|
||||||
tr do
|
tr do
|
||||||
td do
|
td do
|
||||||
a task.name,
|
a task.name,
|
||||||
|
@ -777,10 +786,10 @@ module StopTime::Views
|
||||||
case task.type
|
case task.type
|
||||||
when "fixed_rate"
|
when "fixed_rate"
|
||||||
td ""
|
td ""
|
||||||
td { "€ %.2f" % summary[2] }
|
td.right { "€ %.2f" % summary[2] }
|
||||||
when "hourly_rate"
|
when "hourly_rate"
|
||||||
td { "%.2fh" % summary[0] }
|
td.right { "%.2fh" % summary[0] }
|
||||||
td { "€ %.2f" % summary[2] }
|
td.right { "€ %.2f" % summary[2] }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -792,10 +801,15 @@ module StopTime::Views
|
||||||
|
|
||||||
def time_entries
|
def time_entries
|
||||||
h2 "Timeline"
|
h2 "Timeline"
|
||||||
table do
|
table.timeline do
|
||||||
|
col.task {}
|
||||||
|
col.start_time {}
|
||||||
|
col.end_time {}
|
||||||
|
col.comment {}
|
||||||
|
col.hours {}
|
||||||
|
col.flag {}
|
||||||
tr do
|
tr do
|
||||||
th "Customer"
|
th "Project/Task"
|
||||||
th "Project/task"
|
|
||||||
th "Start time"
|
th "Start time"
|
||||||
th "End time"
|
th "End time"
|
||||||
th "Comment"
|
th "Comment"
|
||||||
|
@ -875,8 +889,13 @@ module StopTime::Views
|
||||||
end
|
end
|
||||||
|
|
||||||
def customers
|
def customers
|
||||||
h2 "List of customers"
|
h2 "Customers"
|
||||||
table do
|
table.customers do
|
||||||
|
col.name {}
|
||||||
|
col.short_name {}
|
||||||
|
col.address {}
|
||||||
|
col.email {}
|
||||||
|
col.phone {}
|
||||||
tr do
|
tr do
|
||||||
th "Name"
|
th "Name"
|
||||||
th "Short name"
|
th "Short name"
|
||||||
|
@ -901,13 +920,13 @@ module StopTime::Views
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
p do
|
|
||||||
a "Add a new customer", :href=> R(CustomersNew)
|
a "Add a new customer", :href=> R(CustomersNew)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def customer_form
|
def customer_form
|
||||||
form :action => R(*@target), :method => :post do
|
form.float_left :action => R(*@target), :method => :post do
|
||||||
|
h2 "Customer information"
|
||||||
ol do
|
ol do
|
||||||
li { _form_input_with_label("Name", "name", :text) }
|
li { _form_input_with_label("Name", "name", :text) }
|
||||||
li { _form_input_with_label("Short name", "short_name", :text) }
|
li { _form_input_with_label("Short name", "short_name", :text) }
|
||||||
|
@ -935,15 +954,18 @@ module StopTime::Views
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
input :type => :submit, :name => "edit", :value => "Edit"
|
div do
|
||||||
input :type => :submit, :name => "delete", :value => "Delete"
|
input :type => :submit, :name => "edit", :value => "Edit"
|
||||||
|
input :type => :submit, :name => "delete", :value => "Delete"
|
||||||
|
a "Add a new project/task", :href => R(CustomersNTasksNew, @customer.id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
a "Add a new project/task", :href => R(CustomersNTasksNew, @customer.id)
|
|
||||||
|
|
||||||
|
div.clear do
|
||||||
h2 "Invoices"
|
h2 "Invoices"
|
||||||
_invoice_list(@invoices)
|
_invoice_list(@invoices)
|
||||||
a "Create a new invoice", :href => R(CustomersNInvoicesNew, @customer.id)
|
a "Create a new invoice", :href => R(CustomersNInvoicesNew, @customer.id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -951,7 +973,11 @@ module StopTime::Views
|
||||||
if invoices.empty?
|
if invoices.empty?
|
||||||
p "None!"
|
p "None!"
|
||||||
else
|
else
|
||||||
table do
|
table.invoices do
|
||||||
|
col.number {}
|
||||||
|
col.date {}
|
||||||
|
col.period {}
|
||||||
|
col.flag {}
|
||||||
tr do
|
tr do
|
||||||
th "Number"
|
th "Number"
|
||||||
th "Date"
|
th "Date"
|
||||||
|
@ -964,7 +990,7 @@ module StopTime::Views
|
||||||
a invoice.number,
|
a invoice.number,
|
||||||
:href => R(CustomersNInvoicesX, @customer.id, invoice.number)
|
:href => R(CustomersNInvoicesX, @customer.id, invoice.number)
|
||||||
end
|
end
|
||||||
td { invoice.created_at }
|
td { invoice.created_at.to_formatted_s(:date_only) }
|
||||||
td { _format_period(invoice.period) }
|
td { _format_period(invoice.period) }
|
||||||
# FIXME: really retrieve the payed flag.
|
# FIXME: really retrieve the payed flag.
|
||||||
td { _form_input_checkbox("payed_#{invoice.number}") }
|
td { _form_input_checkbox("payed_#{invoice.number}") }
|
||||||
|
@ -984,9 +1010,10 @@ module StopTime::Views
|
||||||
|
|
||||||
def task_form
|
def task_form
|
||||||
form :action => R(*@target), :method => :post do
|
form :action => R(*@target), :method => :post do
|
||||||
ul do
|
ol do
|
||||||
li { _form_input_with_label("Name", "name", :text) }
|
li { _form_input_with_label("Name", "name", :text) }
|
||||||
li do
|
li do
|
||||||
|
label "Project/Task type"
|
||||||
ol.radio do
|
ol.radio do
|
||||||
li do
|
li do
|
||||||
_form_input_radio("type", "hourly_rate", default=true)
|
_form_input_radio("type", "hourly_rate", default=true)
|
||||||
|
@ -1025,20 +1052,20 @@ module StopTime::Views
|
||||||
:method => :post do
|
:method => :post do
|
||||||
table do
|
table do
|
||||||
tr do
|
tr do
|
||||||
td { b "Number" }
|
td.key { b "Number" }
|
||||||
td { @invoice.number }
|
td.val { @invoice.number }
|
||||||
end
|
end
|
||||||
tr do
|
tr do
|
||||||
td { b "Date" }
|
td.key { b "Date" }
|
||||||
td { @invoice.created_at.to_formatted_s(:date_only) }
|
td.val { @invoice.created_at.to_formatted_s(:date_only) }
|
||||||
end
|
end
|
||||||
tr do
|
tr do
|
||||||
td { b "Period" }
|
td.key { b "Period" }
|
||||||
td { _format_period(@invoice.period) }
|
td.val { _format_period(@invoice.period) }
|
||||||
end
|
end
|
||||||
tr do
|
tr do
|
||||||
td { b "Payed" }
|
td.key { b "Payed" }
|
||||||
td do
|
td.val do
|
||||||
_form_input_checkbox("payed")
|
_form_input_checkbox("payed")
|
||||||
input :type => :submit, :name => "update", :value => "Update"
|
input :type => :submit, :name => "update", :value => "Update"
|
||||||
end
|
end
|
||||||
|
@ -1046,25 +1073,29 @@ module StopTime::Views
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
table do
|
table.tasks do
|
||||||
|
col.task {}
|
||||||
|
col.hours {}
|
||||||
|
col.hourly_rate {}
|
||||||
|
col.amount {}
|
||||||
tr do
|
tr do
|
||||||
th { "Description" }
|
th { "Project/Task" }
|
||||||
th { "Number of hours" }
|
th.right { "Registered time" }
|
||||||
th { "Hourly rate" }
|
th.right { "Hourly rate" }
|
||||||
th { "Amount" }
|
th.right { "Amount" }
|
||||||
end
|
end
|
||||||
subtotal = 0.0
|
subtotal = 0.0
|
||||||
@tasks.each do |task, line|
|
@tasks.each do |task, line|
|
||||||
tr do
|
tr do
|
||||||
td { task }
|
td { task }
|
||||||
if line[0].nil? and line[1].nil?
|
if line[0].nil? and line[1].nil?
|
||||||
td "–"
|
td.right "–"
|
||||||
td "–"
|
td.right "–"
|
||||||
else
|
else
|
||||||
td { "%.2fh" % line[0] }
|
td.right { "%.2fh" % line[0] }
|
||||||
td { "€ %.2f" % line[1] }
|
td.right { "€ %.2f" % line[1] }
|
||||||
end
|
end
|
||||||
td { "€ %.2f" % line[2] }
|
td.right { "€ %.2f" % line[2] }
|
||||||
end
|
end
|
||||||
subtotal += line[2]
|
subtotal += line[2]
|
||||||
end
|
end
|
||||||
|
@ -1075,21 +1106,21 @@ module StopTime::Views
|
||||||
td { i "Sub-total" }
|
td { i "Sub-total" }
|
||||||
td ""
|
td ""
|
||||||
td ""
|
td ""
|
||||||
td { "€ %.2f" % subtotal }
|
td.right { "€ %.2f" % subtotal }
|
||||||
end
|
end
|
||||||
vat = subtotal * VATRate/100
|
vat = subtotal * VATRate/100
|
||||||
tr do
|
tr do
|
||||||
td { i "VAT #{VATRate}%" }
|
td { i "VAT #{VATRate}%" }
|
||||||
td ""
|
td ""
|
||||||
td ""
|
td ""
|
||||||
td { "€ %.2f" % vat }
|
td.right { "€ %.2f" % vat }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
tr do
|
tr.total do
|
||||||
td { b "Total amount" }
|
td { b "Total amount" }
|
||||||
td ""
|
td ""
|
||||||
td ""
|
td ""
|
||||||
td { "€ %.2f" % (subtotal + vat) }
|
td.right { "€ %.2f" % (subtotal + vat) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1103,14 +1134,20 @@ module StopTime::Views
|
||||||
form :action => R(CustomersNInvoices, @customer.id), :method => :post do
|
form :action => R(CustomersNInvoices, @customer.id), :method => :post do
|
||||||
unless @hourly_rate_tasks.empty?
|
unless @hourly_rate_tasks.empty?
|
||||||
h2 "Registered time"
|
h2 "Registered time"
|
||||||
table do
|
table.time_entries do
|
||||||
|
col.flag {}
|
||||||
|
col.start_time {}
|
||||||
|
col.end_time {}
|
||||||
|
col.comment {}
|
||||||
|
col.hours {}
|
||||||
|
col.amount {}
|
||||||
tr do
|
tr do
|
||||||
th ""
|
th ""
|
||||||
th "Start"
|
th "Start time"
|
||||||
th "End"
|
th "End time"
|
||||||
th "Comment"
|
th "Comment"
|
||||||
th "Total"
|
th.right "Total time"
|
||||||
th "Amount"
|
th.right "Amount"
|
||||||
end
|
end
|
||||||
@hourly_rate_tasks.keys.each do |task|
|
@hourly_rate_tasks.keys.each do |task|
|
||||||
tr.task do
|
tr.task do
|
||||||
|
@ -1123,8 +1160,8 @@ module StopTime::Views
|
||||||
td { label entry.start, :for => "time_entries[]_#{entry.id}" }
|
td { label entry.start, :for => "time_entries[]_#{entry.id}" }
|
||||||
td { entry.end }
|
td { entry.end }
|
||||||
td { entry.comment }
|
td { entry.comment }
|
||||||
td { "%.2fh" % entry.hours_total }
|
td.right { "%.2fh" % entry.hours_total }
|
||||||
td { "€ %.2f" % (entry.hours_total * entry.task.hourly_rate) }
|
td.right { "€ %.2f" % (entry.hours_total * entry.task.hourly_rate) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1133,10 +1170,14 @@ module StopTime::Views
|
||||||
|
|
||||||
unless @fixed_cost_tasks.empty?
|
unless @fixed_cost_tasks.empty?
|
||||||
h2 "Fixed cost tasks"
|
h2 "Fixed cost tasks"
|
||||||
table do
|
table.tasks do
|
||||||
|
col.flag {}
|
||||||
|
col.task {}
|
||||||
|
col.hours {}
|
||||||
|
col.amount {}
|
||||||
tr do
|
tr do
|
||||||
th ""
|
th ""
|
||||||
th "Task"
|
th "Project/Task"
|
||||||
th "Registered time"
|
th "Registered time"
|
||||||
th "Amount"
|
th "Amount"
|
||||||
end
|
end
|
||||||
|
@ -1144,8 +1185,8 @@ module StopTime::Views
|
||||||
tr do
|
tr do
|
||||||
td { _form_input_checkbox("tasks[]", task.id) }
|
td { _form_input_checkbox("tasks[]", task.id) }
|
||||||
td { label task.name, :for => "tasks[]_#{task.id}" }
|
td { label task.name, :for => "tasks[]_#{task.id}" }
|
||||||
td { "%.2fh" % @fixed_cost_tasks[task] }
|
td.right { "%.2fh" % @fixed_cost_tasks[task] }
|
||||||
td { task.fixed_cost }
|
td.right { task.fixed_cost }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
/* CSS file for Stop… Camping Time! */
|
||||||
|
|
||||||
|
// Colours
|
||||||
|
$light-grey: #efefef
|
||||||
|
$dark-grey: #9f9f9f
|
||||||
|
$dark-red: #990000
|
||||||
|
|
||||||
|
/* General classes */
|
||||||
|
.right
|
||||||
|
text-align: right
|
||||||
|
|
||||||
|
.float_left
|
||||||
|
float: left
|
||||||
|
margin-right: 50px
|
||||||
|
|
||||||
|
.clear
|
||||||
|
clear: both
|
||||||
|
padding-top: 10px
|
||||||
|
|
||||||
|
/* Basic elements */
|
||||||
|
a
|
||||||
|
text-decoration: none
|
||||||
|
color: $dark-red
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
text-decoration: underline
|
||||||
|
|
||||||
|
body
|
||||||
|
font-family: sans-serif
|
||||||
|
font-size: 13px
|
||||||
|
margin: 0px
|
||||||
|
|
||||||
|
/* Main layout */
|
||||||
|
#wrapper
|
||||||
|
width: auto
|
||||||
|
height: auto
|
||||||
|
margin: 10px 10px
|
||||||
|
|
||||||
|
#content
|
||||||
|
padding: 10px
|
||||||
|
border: 1px solid
|
||||||
|
background: $light-grey
|
||||||
|
|
||||||
|
ol#menu
|
||||||
|
list-style: none
|
||||||
|
padding: 0px
|
||||||
|
margin: 5px
|
||||||
|
|
||||||
|
li
|
||||||
|
display: inline
|
||||||
|
border: solid black
|
||||||
|
border-width: 1px 1px 0 1px
|
||||||
|
padding: 5px 10px
|
||||||
|
margin: 0px 0.5em 0px 0px
|
||||||
|
|
||||||
|
&.selected
|
||||||
|
padding-bottom: 6px
|
||||||
|
background: $light-grey
|
||||||
|
|
||||||
|
/* Table layout */
|
||||||
|
table
|
||||||
|
padding: 3px 0px
|
||||||
|
border-spacing: 0px 4px
|
||||||
|
|
||||||
|
col.amount, col.hours, col.hourly_rate
|
||||||
|
width: 15%
|
||||||
|
col.flag
|
||||||
|
width: 3%
|
||||||
|
col.start_time, col.end_time
|
||||||
|
width: 15%
|
||||||
|
col.comment
|
||||||
|
width: 30%
|
||||||
|
col.task
|
||||||
|
width: 25%
|
||||||
|
col.name, col.period
|
||||||
|
width: 25%
|
||||||
|
col.short_name
|
||||||
|
width: 20%
|
||||||
|
col.address
|
||||||
|
width: 20%
|
||||||
|
col.email, col.phone, col.date
|
||||||
|
width: 15%
|
||||||
|
col.number
|
||||||
|
width: 7%
|
||||||
|
|
||||||
|
&.overview
|
||||||
|
width: 50%
|
||||||
|
|
||||||
|
&.timeline
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
&.tasks
|
||||||
|
width: 60%
|
||||||
|
|
||||||
|
&.customers
|
||||||
|
width: 75%
|
||||||
|
|
||||||
|
&.invoices
|
||||||
|
width: 50%
|
||||||
|
|
||||||
|
td
|
||||||
|
vertical-align: top
|
||||||
|
|
||||||
|
th
|
||||||
|
text-align: left
|
||||||
|
background: $dark-grey
|
||||||
|
|
||||||
|
tr.total
|
||||||
|
border-top: solid black
|
||||||
|
|
||||||
|
td.key
|
||||||
|
font-weight: bold
|
||||||
|
width: 80px
|
||||||
|
padding-bottom: 5px
|
||||||
|
|
||||||
|
/* Form layout */
|
||||||
|
form
|
||||||
|
ol
|
||||||
|
list-style: none
|
||||||
|
padding: 10px
|
||||||
|
|
||||||
|
label
|
||||||
|
width: 180px
|
||||||
|
margin: 5px
|
||||||
|
margin-right: 10px
|
||||||
|
float: left
|
||||||
|
|
||||||
|
input, select
|
||||||
|
width: 250px
|
||||||
|
|
||||||
|
ol.radio
|
||||||
|
margin-left: 195px
|
||||||
|
padding: 0px
|
||||||
|
|
||||||
|
label
|
||||||
|
float: none
|
||||||
|
|
||||||
|
input
|
||||||
|
width: auto
|
||||||
|
|
||||||
|
select
|
||||||
|
width: 300px
|
||||||
|
|
||||||
|
input[type="submit"], input[type="reset"]
|
||||||
|
width: auto
|
Loading…
Reference in New Issue