Compare commits
44 Commits
v1.16.0
...
developmen
Author | SHA1 | Date |
---|---|---|
Paul van Tilburg | 8af4d4d148 | |
Paul van Tilburg | 39949606e5 | |
Paul van Tilburg | 0e74472983 | |
Paul van Tilburg | 9ba33c9b71 | |
Paul van Tilburg | 975ab31440 | |
Paul van Tilburg | 8e6fcddd49 | |
Paul van Tilburg | 6b7d96ecb9 | |
Paul van Tilburg | 819fb5f530 | |
Paul van Tilburg | f4c34d8e4e | |
Paul van Tilburg | 825387cc6f | |
Paul van Tilburg | 9d48c1ac6b | |
Paul van Tilburg | c5f6808e6b | |
Paul van Tilburg | f6a412f9be | |
Paul van Tilburg | d89f9ac65b | |
Paul van Tilburg | 157af0c2c3 | |
Paul van Tilburg | fa6aa24e0d | |
Paul van Tilburg | 548dfe22cc | |
Paul van Tilburg | 1f955f55a6 | |
Paul van Tilburg | f04956cdcb | |
Paul van Tilburg | 9585515565 | |
Paul van Tilburg | cb215e54eb | |
Paul van Tilburg | 7184248ccd | |
Paul van Tilburg | bbf2566352 | |
Paul van Tilburg | 7c41c32dfd | |
Paul van Tilburg | 49bfdff822 | |
Paul van Tilburg | 81e6db24ef | |
Paul van Tilburg | faf95f842e | |
Paul van Tilburg | a2e021a6c6 | |
Paul van Tilburg | ce2ebc76d4 | |
Paul van Tilburg | 8c15c2f318 | |
Paul van Tilburg | 1376ac3828 | |
Paul van Tilburg | f5d2c5af08 | |
Paul van Tilburg | 1e33df19d6 | |
Paul van Tilburg | ebd220aac6 | |
Paul van Tilburg | 5160e79953 | |
Paul van Tilburg | 23af29b800 | |
Paul van Tilburg | 58ec60ab60 | |
Paul van Tilburg | 16b13de52c | |
Paul van Tilburg | 1cf130c1dd | |
Paul van Tilburg | 7ecece3950 | |
Paul van Tilburg | 4eef4669a5 | |
Paul van Tilburg | 43b9c1336f | |
Paul van Tilburg | ad4362f471 | |
Paul van Tilburg | c15f6c4e2e |
|
@ -1,11 +1,32 @@
|
|||
# Ignore bundler config
|
||||
/.bundle
|
||||
|
||||
# Ignore bundler installation
|
||||
/vendor/bundle
|
||||
|
||||
# Ignore SASS and YARD cache
|
||||
.sass-cache
|
||||
.yardoc
|
||||
|
||||
# Ignore the local configuration
|
||||
config.yaml
|
||||
htpasswd
|
||||
|
||||
# Ignore the SQLite databases
|
||||
db/*
|
||||
|
||||
# Ignore generated documentation
|
||||
doc/*
|
||||
|
||||
# Ignore generated invoice assets
|
||||
public/invoices/*
|
||||
|
||||
# Ignore compiled asssets
|
||||
public/stylesheets/style.css
|
||||
public/stylesheets/style.css.map
|
||||
|
||||
# Ignore custom invoice templates
|
||||
templates/*_invoice.tex.erb
|
||||
|
||||
# Ignore temporary files
|
||||
tmp/*
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
2.5.1
|
|
@ -1,5 +1,33 @@
|
|||
= Stop… Camping Time! release news
|
||||
|
||||
== 1.17.1
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* Fix the number/currency input to allow for all values ≥ 0.00
|
||||
|
||||
== 1.17.0
|
||||
|
||||
Features:
|
||||
|
||||
* Add support for choosing what date/time is used for new entries
|
||||
* Some textual and style tweaks
|
||||
|
||||
Bugfixes:
|
||||
* Fix crash when showing all entries in the timeline [#89c2a1]
|
||||
|
||||
Other bugfixes:
|
||||
* Fix check that determines if last company info is used
|
||||
|
||||
== 1.16.1
|
||||
|
||||
Features:
|
||||
|
||||
* Allow back/forth navigation through company info version
|
||||
* Only show unbilled time in the customer from (load time improvement!)
|
||||
* Tweaked some form input sizes
|
||||
* Add missing view subtitles
|
||||
|
||||
== 1.16.0
|
||||
|
||||
Features:
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
source "http://rubygems.org"
|
||||
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||
|
||||
|
||||
# This application is build on Camping, use it from our own Git master
|
||||
gem "camping", github: "paulvt/camping", branch: "master"
|
||||
|
||||
# Use ActionView for the templates.
|
||||
gem "actionview", "~> 4.2.10"
|
||||
|
||||
# Use ActiveRecord as the ORM.
|
||||
gem "activerecord", "~> 4.2.10"
|
||||
|
||||
# Use SASS for handling CSS assets/Bootstrap.
|
||||
gem "sass", "~> 3.4.6"
|
||||
|
||||
# Use SQLite as the database.
|
||||
gem "sqlite3", "~> 1.3.9"
|
|
@ -0,0 +1,74 @@
|
|||
GIT
|
||||
remote: https://github.com/paulvt/camping.git
|
||||
revision: e6834563b244e0f24af2034d679cd6e8e9d932c0
|
||||
branch: master
|
||||
specs:
|
||||
camping (2.1.602)
|
||||
mab (>= 0.0.3)
|
||||
rack (>= 1.0)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
actionview (4.2.11.3)
|
||||
activesupport (= 4.2.11.3)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
activemodel (4.2.11.3)
|
||||
activesupport (= 4.2.11.3)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.11.3)
|
||||
activemodel (= 4.2.11.3)
|
||||
activesupport (= 4.2.11.3)
|
||||
arel (~> 6.0)
|
||||
activesupport (4.2.11.3)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
arel (6.0.4)
|
||||
builder (3.2.4)
|
||||
concurrent-ruby (1.1.9)
|
||||
crass (1.0.6)
|
||||
erubis (2.7.0)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
loofah (2.12.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mab (0.0.3)
|
||||
mini_portile2 (2.6.1)
|
||||
minitest (5.14.4)
|
||||
nokogiri (1.12.5)
|
||||
mini_portile2 (~> 2.6.1)
|
||||
racc (~> 1.4)
|
||||
racc (1.5.2)
|
||||
rack (2.2.3)
|
||||
rails-deprecated_sanitizer (1.0.4)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
rails-dom-testing (1.0.9)
|
||||
activesupport (>= 4.2.0, < 5.0)
|
||||
nokogiri (~> 1.6)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.4.2)
|
||||
loofah (~> 2.3)
|
||||
sass (3.4.25)
|
||||
sqlite3 (1.3.13)
|
||||
thread_safe (0.3.6)
|
||||
tzinfo (1.2.9)
|
||||
thread_safe (~> 0.1)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
actionview (~> 4.2.10)
|
||||
activerecord (~> 4.2.10)
|
||||
camping!
|
||||
sass (~> 3.4.6)
|
||||
sqlite3 (~> 1.3.9)
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.3
|
|
@ -39,6 +39,9 @@ and the following LaTeX programs:
|
|||
* isodoc package (>= 1.00)
|
||||
* rubber
|
||||
|
||||
It is also possible to use Bundler (which is the default when using
|
||||
@config.ru@), in this you only need Ruby and Bundler installed.
|
||||
|
||||
== Installation
|
||||
|
||||
For now, Stop… Camping Time! is in a developing state and not ready for
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#!/usr/bin/env rackup
|
||||
|
||||
require "bundler/setup"
|
||||
require "./stoptime"
|
||||
|
||||
StopTime::Models::Base.establish_connection( :adapter => 'sqlite3',
|
||||
:database => 'db/stoptime.db',
|
||||
:timeout => 10000 )
|
||||
StopTime::Models::Base.establish_connection(adapter: "sqlite3",
|
||||
database: "db/stoptime.db",
|
||||
timeout: 10000)
|
||||
StopTime.create
|
||||
run StopTime
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
# Time resolution in minutes
|
||||
#time_resolution: 1
|
||||
|
||||
# Which date to use for new entries
|
||||
# Supported values are: previous, today, none
|
||||
#date_new_entry: today
|
||||
|
||||
# The default hourly rate
|
||||
#hourly_rate: 20.0
|
||||
|
||||
|
|
252
stoptime.rb
252
stoptime.rb
|
@ -55,7 +55,7 @@ end
|
|||
module StopTime
|
||||
|
||||
# The version of the application
|
||||
VERSION = '1.16.0'
|
||||
VERSION = '1.17.1'
|
||||
puts "Starting Stop… Camping Time! version #{VERSION}"
|
||||
|
||||
# @return [Hash{String=>Object}] The parsed configuration.
|
||||
|
@ -166,6 +166,7 @@ module StopTime::Models
|
|||
"invoice_template" => "invoice",
|
||||
"hourly_rate" => 20.0,
|
||||
"time_resolution" => 1,
|
||||
"date_new_entry" => "today",
|
||||
"vat_rate" => 21.0 }
|
||||
|
||||
# Creates a new configuration object and loads the configuation.
|
||||
|
@ -888,6 +889,30 @@ module StopTime::Models
|
|||
|
||||
end # StopTime::Models
|
||||
|
||||
# = The Stop… Camping Time! helpers
|
||||
module StopTime::Helpers
|
||||
|
||||
# Returns the date/time to use for new time entry defaults, or +nil+ if
|
||||
# none is to be used. This method can use the last time entry (if any
|
||||
# and if so configured). The result is based on the +date_new_entry+
|
||||
# configuration option.
|
||||
#
|
||||
# @param last_entry [DateTime] the last time entry to use if configured
|
||||
# for "previous"
|
||||
# @return [DateTime, nil] the date/time to be used for new entry defaults
|
||||
def date_time_new_entry(last_entry = nil)
|
||||
case @config["date_new_entry"]
|
||||
when "previous"
|
||||
TimeEntry.last.end
|
||||
when "today"
|
||||
DateTime.now
|
||||
when "none"
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# = The Stop… Camping Time! controllers
|
||||
module StopTime::Controllers
|
||||
|
||||
|
@ -905,6 +930,7 @@ module StopTime::Controllers
|
|||
@tasks = {}
|
||||
@task_count = 0
|
||||
@active_tasks = {}
|
||||
@active_task_count = 0
|
||||
@active_tasks_summary = {}
|
||||
@totals = [0.0, 0,0]
|
||||
Customer.all.each do |customer|
|
||||
|
@ -913,6 +939,7 @@ module StopTime::Controllers
|
|||
@task_count += tasks.count
|
||||
active_tasks = customer.active_tasks
|
||||
@active_tasks[customer] = active_tasks
|
||||
@active_task_count += active_tasks.count
|
||||
@active_tasks_summary[customer] =
|
||||
active_tasks.inject([0.0, 0.0]) do |summ, task|
|
||||
task_summ = task.summary
|
||||
|
@ -1025,7 +1052,8 @@ module StopTime::Controllers
|
|||
end
|
||||
end
|
||||
|
||||
@time_entries = @customer.time_entries.order("start DESC")
|
||||
@time_entries = @customer.time_entries.order("start DESC")\
|
||||
.reject { |te| te.task.billed? }
|
||||
@invoices = @customer.invoices
|
||||
@invoices.each do |i|
|
||||
@input["paid_#{i.number}"] = true if i.paid?
|
||||
|
@ -1069,7 +1097,7 @@ module StopTime::Controllers
|
|||
return render :customer_form
|
||||
end
|
||||
end
|
||||
redirect R(Customers)
|
||||
redirect R(CustomersN, customer_id)
|
||||
end
|
||||
end # class StopTime::Controllers::CustomersN
|
||||
|
||||
|
@ -1278,7 +1306,7 @@ module StopTime::Controllers
|
|||
tasks.each_key do |task|
|
||||
# Create a new (billed) task clone that contains the selected time
|
||||
# entries, leave the rest unbilled and associated with their task.
|
||||
bill_task = task.dup # FIXME: depends on rails version!
|
||||
bill_task = task.dup
|
||||
task.time_entries = task.time_entries - tasks[task]
|
||||
task.save
|
||||
bill_task.time_entries = tasks[task]
|
||||
|
@ -1485,13 +1513,14 @@ module StopTime::Controllers
|
|||
# Retrieves all registered time in descending order to present
|
||||
# the timeline using {Views#timeline}.
|
||||
def get
|
||||
if @input["show"] == "all"
|
||||
if @input["time_entries"] == "all"
|
||||
@time_entries = TimeEntry.order("start DESC")
|
||||
else
|
||||
@time_entries = TimeEntry.joins(:task)\
|
||||
.where("stoptime_tasks.invoice_id" => nil)\
|
||||
.order("start DESC")
|
||||
end
|
||||
@time_entries = @time_entries.where.not(task_id: nil)
|
||||
@time_entries.each do |te|
|
||||
@input["bill_#{te.id}"] = true if te.bill?
|
||||
end
|
||||
|
@ -1547,9 +1576,11 @@ module StopTime::Controllers
|
|||
@task_list[t.customer.shortest_name] << [t.id, t.name]
|
||||
end
|
||||
@input["bill"] = true
|
||||
@input["date"] = DateTime.now.to_date
|
||||
@input["start"] = Time.now.to_formatted_s(:time_only)
|
||||
|
||||
date_time_new = date_time_new_entry(TimeEntry.last)
|
||||
if date_time_new
|
||||
@input["date"] = date_time_new.to_date.to_formatted_s
|
||||
@input["start"] = date_time_new.to_formatted_s(:time_only)
|
||||
end
|
||||
@target = [Timeline]
|
||||
@button = "enter"
|
||||
render :time_entry_form
|
||||
|
@ -1679,6 +1710,7 @@ module StopTime::Controllers
|
|||
else
|
||||
CompanyInfo.last
|
||||
end
|
||||
@company_last = @company == CompanyInfo.last
|
||||
@input = @company.attributes
|
||||
@history_warn = true if @company != CompanyInfo.last
|
||||
render :company_form
|
||||
|
@ -1696,9 +1728,9 @@ module StopTime::Controllers
|
|||
# If we are editing the current info and it is already associated
|
||||
# with some invoices, create a new revision.
|
||||
@history_warn = true if @company != CompanyInfo.last
|
||||
if @company == CompanyInfo.last and @company.invoices.length > 0
|
||||
if @company.id == CompanyInfo.last.id and @company.invoices.length > 0
|
||||
old_company = @company
|
||||
@company = old_company.clone # FIXME: depends on rails version!
|
||||
@company = old_company.dup
|
||||
@company.original = old_company
|
||||
end
|
||||
|
||||
|
@ -1798,7 +1830,8 @@ module StopTime::Views
|
|||
header.page_header do
|
||||
h1 do
|
||||
text! "Overview"
|
||||
small "#{@tasks.count} customers, #{@task_count} active projects/tasks"
|
||||
small "#{@tasks.count} customers, " +
|
||||
"#{@active_task_count} active projects/tasks"
|
||||
end
|
||||
end
|
||||
if @tasks.empty?
|
||||
|
@ -1829,7 +1862,7 @@ module StopTime::Views
|
|||
elsif @active_tasks[customer].empty?
|
||||
p do
|
||||
em "No active projects/tasks found! " +
|
||||
"Register time on one of these tasks: "
|
||||
"Register time on one of these projects/tasks: "
|
||||
br
|
||||
@tasks[customer].each do |task|
|
||||
a task.name, href: R(CustomersNTasksN, customer.id, task.id)
|
||||
|
@ -1900,12 +1933,12 @@ module StopTime::Views
|
|||
a.btn.btn_default.btn_sm.dropdown_toggle role: "button", href: "#",
|
||||
data_toggle: "dropdown" do
|
||||
_icon("filter")
|
||||
text! @input["show"] == "all" ? "All" : "Unbilled"
|
||||
text! @input["time_entries"] == "all" ? "All" : "Unbilled"
|
||||
span.caret
|
||||
end
|
||||
ul.dropdown_menu role: "menu", aria_labelledby: "dLabel" do
|
||||
li { a "All", href: R(Timeline, show: "all") }
|
||||
li { a "Unbilled", href: R(Timeline, show: "unbilled") }
|
||||
li { a "All", href: R(Timeline, time_entries: "all") }
|
||||
li { a "Unbilled", href: R(Timeline, time_entries: "unbilled") }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2014,10 +2047,11 @@ module StopTime::Views
|
|||
header.page_header do
|
||||
h1 do
|
||||
text! "Customers"
|
||||
small "#{@customers.count} customers"
|
||||
div.btn_group.navbar_right do
|
||||
a.btn.btn_default.btn_sm role: "button", href: R(CustomersNew) do
|
||||
_icon("plus")
|
||||
span "Add new customer"
|
||||
span "Add customer"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2028,59 +2062,63 @@ module StopTime::Views
|
|||
"#{a "here", href: R(CustomersNew)}."
|
||||
end
|
||||
else
|
||||
table.table.table_striped.table_condensed do
|
||||
thead do
|
||||
tr do
|
||||
th.col_md_2.col_xs_5 "Name"
|
||||
th.col_md_1.hidden_xs "Short name"
|
||||
th.col_md_4.col_xs_5 "Address"
|
||||
th.col_md_2.hidden_xs "Email"
|
||||
th.col_md_2.hidden_xs "Phone"
|
||||
th.col_md_1.col_xs_2 {}
|
||||
end
|
||||
end
|
||||
tbody do
|
||||
@customers.each do |customer|
|
||||
tr do
|
||||
td { a customer.name, href: R(CustomersN, customer.id) }
|
||||
td.hidden_xs { customer.short_name || "–"}
|
||||
td do
|
||||
if customer.address_street.present?
|
||||
text! customer.address_street
|
||||
br
|
||||
text! customer.address_postal_code + " " +
|
||||
customer.address_city
|
||||
if customer.email.present?
|
||||
a.visible_xs customer.email,
|
||||
href: "mailto:#{customer.email}"
|
||||
div.row do
|
||||
div.col_md_9.col_xs_12 do
|
||||
table.table.table_striped.table_condensed do
|
||||
thead do
|
||||
tr do
|
||||
th.col_md_2.col_xs_5 "Name"
|
||||
th.col_md_2.hidden_xs "Short name"
|
||||
th.col_md_3.col_xs_5 "Address"
|
||||
th.col_md_2.hidden_xs "Email"
|
||||
th.col_md_2.hidden_xs "Phone"
|
||||
th.col_md_1.col_xs_2 {}
|
||||
end
|
||||
end
|
||||
tbody do
|
||||
@customers.each do |customer|
|
||||
tr do
|
||||
td { a customer.name, href: R(CustomersN, customer.id) }
|
||||
td.hidden_xs { customer.short_name || "–"}
|
||||
td do
|
||||
if customer.address_street.present?
|
||||
text! customer.address_street
|
||||
br
|
||||
text! customer.address_postal_code + " " +
|
||||
customer.address_city
|
||||
if customer.email.present?
|
||||
a.visible_xs customer.email,
|
||||
href: "mailto:#{customer.email}"
|
||||
end
|
||||
if customer.phone.present?
|
||||
# FIXME: hardcoded prefix!
|
||||
span.visible_xs "0#{customer.phone}"
|
||||
end
|
||||
else
|
||||
"–"
|
||||
end
|
||||
end
|
||||
if customer.phone.present?
|
||||
# FIXME: hardcoded prefix!
|
||||
span.visible_xs "0#{customer.phone}"
|
||||
td.hidden_xs do
|
||||
if customer.email.present?
|
||||
a customer.email, href: "mailto:#{customer.email}"
|
||||
else
|
||||
"–"
|
||||
end
|
||||
end
|
||||
td.hidden_xs do
|
||||
if customer.phone.present?
|
||||
# FIXME: hardcoded prefix!
|
||||
"0#{customer.phone}"
|
||||
else
|
||||
"–"
|
||||
end
|
||||
end
|
||||
td do
|
||||
form action: R(CustomersN, customer.id), method: :post do
|
||||
button.btn.btn_xs.btn_danger "Delete", type: :submit,
|
||||
name: "delete", value: "Delete"
|
||||
end
|
||||
end
|
||||
else
|
||||
"–"
|
||||
end
|
||||
end
|
||||
td.hidden_xs do
|
||||
if customer.email.present?
|
||||
a customer.email, href: "mailto:#{customer.email}"
|
||||
else
|
||||
"–"
|
||||
end
|
||||
end
|
||||
td.hidden_xs do
|
||||
if customer.phone.present?
|
||||
# FIXME: hardcoded prefix!
|
||||
"0#{customer.phone}"
|
||||
else
|
||||
"–"
|
||||
end
|
||||
end
|
||||
td do
|
||||
form action: R(CustomersN, customer.id), method: :post do
|
||||
button.btn.btn_xs.btn_danger "Delete", type: :submit,
|
||||
name: "delete", value: "Delete"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2123,11 +2161,13 @@ module StopTime::Views
|
|||
control_class: "col-sm-3 col-xs-4")
|
||||
_form_input_with_label("Financial contact", "financial_contact", :text,
|
||||
control_class: "col-sm-6 col-xs-8")
|
||||
_form_input_with_label("Default hourly rate", "hourly_rate", :text,
|
||||
control_class: "col-sm-3 col-xs-4",
|
||||
input_addon: "€ / h")
|
||||
_form_input_with_label("Default hourly rate", "hourly_rate", :number,
|
||||
control_class: "col-sm-4 col-xs-5",
|
||||
input_addon: "€ / h",
|
||||
min: "0.00",
|
||||
step: "0.01")
|
||||
div.form_group do
|
||||
label.control_label.col_sm_4.col_xs_4 "Time specifications?"
|
||||
label.control_label.col_sm_3.col_xs_4 "Time specifications?"
|
||||
div.col_sm_6.col_xs_8 do
|
||||
div.checkbox do
|
||||
_form_input_checkbox("time_specification")
|
||||
|
@ -2135,7 +2175,7 @@ module StopTime::Views
|
|||
end
|
||||
end
|
||||
div.form_group do
|
||||
div.col_sm_offset_4.col_sm_6.col_xs_offset_4.col_xs_8 do
|
||||
div.col_sm_offset_3.col_sm_6.col_xs_offset_4.col_xs_8 do
|
||||
button.btn.btn_primary @button.capitalize, type: "submit",
|
||||
name: @button, value: @button.capitalize
|
||||
button.btn.btn_default "Cancel", type: "submit",
|
||||
|
@ -2153,7 +2193,7 @@ module StopTime::Views
|
|||
a.btn.btn_default.btn_sm role: "button",
|
||||
href: R(CustomersNTasksNew, @customer.id) do
|
||||
_icon("plus")
|
||||
span "Add new project/task"
|
||||
span "Add project/task"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2243,7 +2283,7 @@ module StopTime::Views
|
|||
a.btn.btn_default.btn_sm role: "button",
|
||||
href: R(CustomersNInvoicesNew, @customer.id) do
|
||||
_icon("plus")
|
||||
span "Create new invoice"
|
||||
span "Create invoice"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2254,8 +2294,8 @@ module StopTime::Views
|
|||
|
||||
# Show registered time using the time_entries view as partial view.
|
||||
div.row do
|
||||
div.col_md_10.col_xs_12 do
|
||||
h2 "Registered time"
|
||||
div.col_xs_12 do
|
||||
h2.timeline! "Registered unbilled time"
|
||||
_time_entries(@customer)
|
||||
end
|
||||
end unless @button == "create"
|
||||
|
@ -2279,14 +2319,16 @@ module StopTime::Views
|
|||
end if @task.billed?
|
||||
div.row do
|
||||
div.col_md_6.col_xs_12 do
|
||||
form.form_horizontal.form_condensed action: R(*@target), method: :post do
|
||||
form.form_horizontal.form_condensed action: R(*@target),
|
||||
method: :post do
|
||||
div.form_group do
|
||||
label.control_label.col_sm_3.col_xs_4 "Customer", for: "customer"
|
||||
div.col_sm_4.col_xs_8 do
|
||||
_form_select("customer", @customer_list)
|
||||
end
|
||||
div.col_sm_offset_2.col_sm_3.hidden_xs do
|
||||
a.btn.btn_default role: "button", href: R(CustomersN, @customer.id) do
|
||||
a.btn.btn_default role: "button",
|
||||
href: R(CustomersN, @customer.id) do
|
||||
_icon("user")
|
||||
span "Show customer"
|
||||
end
|
||||
|
@ -2295,13 +2337,14 @@ module StopTime::Views
|
|||
_form_input_with_label("Name", "name", :text)
|
||||
div.form_group do
|
||||
label.control_label.col_sm_3.col_xs_4 "Project/Task type"
|
||||
div.col_sm_4.col_xs_8 do
|
||||
div.col_sm_5.col_xs_8 do
|
||||
div.radio do
|
||||
label do
|
||||
_form_input_radio("type", "hourly_rate", true)
|
||||
text!("Hourly rate: ")
|
||||
div.input_group do
|
||||
_form_input("hourly_rate", :number, "Hourly rate")
|
||||
_form_input("hourly_rate", :number, "Hourly rate",
|
||||
min: "0.00", step: "0.01")
|
||||
span.input_group_addon "€ / h"
|
||||
end
|
||||
end
|
||||
|
@ -2311,7 +2354,8 @@ module StopTime::Views
|
|||
_form_input_radio("type", "fixed_cost")
|
||||
text!("Fixed cost: ")
|
||||
div.input_group do
|
||||
_form_input("fixed_cost", :number, "Fixed cost")
|
||||
_form_input("fixed_cost", :number, "Fixed cost",
|
||||
min: "0.00", step: "0.01")
|
||||
span.input_group_addon "€"
|
||||
end
|
||||
end
|
||||
|
@ -2319,7 +2363,7 @@ module StopTime::Views
|
|||
end
|
||||
end
|
||||
_form_input_with_label("VAT rate", "vat_rate", :number,
|
||||
control_class: "col-sm-3 col-xs-6",
|
||||
control_class: "col-lg-3 col-sm-4 col-xs-6",
|
||||
input_addon: "%")
|
||||
if @task.billed?
|
||||
div.form_group do
|
||||
|
@ -2350,7 +2394,7 @@ module StopTime::Views
|
|||
# Show registered time (ab)using the time_entries view as partial view.
|
||||
div.row do
|
||||
div.col_md_8.col_xs_12 do
|
||||
h2 "Registered #{@task.billed? ? "billed" : "unbilled"} time"
|
||||
h2.timeline! "Registered #{@task.billed? ? "billed" : "unbilled"} time"
|
||||
_time_entries(@customer, @task)
|
||||
end
|
||||
end unless @method == "create"
|
||||
|
@ -2382,7 +2426,7 @@ module StopTime::Views
|
|||
a.btn.btn_default.btn_sm role: "button",
|
||||
href: R(CustomersNInvoicesNew, customer.id) do
|
||||
_icon("plus")
|
||||
span "Create new invoice"
|
||||
span "Create invoice"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2403,6 +2447,7 @@ module StopTime::Views
|
|||
h1 do
|
||||
text! "Invoice for "
|
||||
a @customer.name, href: R(CustomersN, @customer.id)
|
||||
small @invoice.number
|
||||
end
|
||||
end
|
||||
div.row do
|
||||
|
@ -2444,7 +2489,7 @@ module StopTime::Views
|
|||
end
|
||||
end
|
||||
div.form_group do
|
||||
div.col_sm_offset_3.col_sm_4.col_xs_offset_4.col_xs_8 do
|
||||
div.col_sm_offset_3.col_sm_6.col_xs_offset_4.col_xs_8 do
|
||||
button.btn.btn_primary "Update", type: :submit,
|
||||
name: "update", value: "Update"
|
||||
button.btn.btn_default "Reset", type: :reset,
|
||||
|
@ -2545,7 +2590,7 @@ module StopTime::Views
|
|||
href: R(CustomersNInvoicesX,
|
||||
@customer.id, "#{@invoice.number}.tex") do
|
||||
_icon("download")
|
||||
span "Download LaTeX source"
|
||||
span "Download LaTeX"
|
||||
end
|
||||
a.btn.btn_default role: "button",
|
||||
href: R(Company, revision: @company.revision) do
|
||||
|
@ -2714,7 +2759,7 @@ module StopTime::Views
|
|||
button.btn.btn_primary "Create invoice", type: :submit,
|
||||
name: "create", value: "Create invoice",
|
||||
disabled: @none_found
|
||||
button.btn.btn_default "Cancel", type: :submit, name: "cancel",
|
||||
button.btn.btn_default "Cancel", type: :submit, name: "cancel",
|
||||
value: "Cancel"
|
||||
end
|
||||
end
|
||||
|
@ -2745,11 +2790,25 @@ module StopTime::Views
|
|||
div.alert.alert_info do
|
||||
text! " Viewing revision #{@company.revision}, " +
|
||||
" last update at #{@company.updated_at}."
|
||||
if @company.original.present?
|
||||
a.btn.btn_default role: "button",
|
||||
href: R(Company, revision: @company.original.revision) do
|
||||
_icon("backward")
|
||||
span "View previous revision"
|
||||
div.btn_group do
|
||||
if @company.original.present?
|
||||
a.btn.btn_default role: "button",
|
||||
href: R(Company, revision: @company.original.revision) do
|
||||
_icon("backward")
|
||||
span "View previous revision"
|
||||
end
|
||||
end
|
||||
unless @company_last
|
||||
a.btn.btn_default role: "button",
|
||||
href: R(Company, revision: @company.revision.succ) do
|
||||
_icon("forward")
|
||||
span "View next revision"
|
||||
end
|
||||
a.btn.btn_default role: "button",
|
||||
href: R(Company) do
|
||||
_icon("fast-forward")
|
||||
span "Most recent revision"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2761,7 +2820,7 @@ module StopTime::Views
|
|||
text! "Only make changes if you know what you are doing!"
|
||||
end if @history_warn
|
||||
div.row do
|
||||
div.col_md_6.col_xs_12 do
|
||||
div.col_md_8.col_xs_12 do
|
||||
form.form_horizontal.form_condensed \
|
||||
action: R(Company, revision: @company.revision),
|
||||
method: :post do
|
||||
|
@ -2894,7 +2953,7 @@ module StopTime::Views
|
|||
tbody do
|
||||
invoices.each do |invoice|
|
||||
due_class = invoice.past_due? ? "warning" : ""
|
||||
due_class = "error" if invoice.way_past_due?
|
||||
due_class = "danger" if invoice.way_past_due?
|
||||
tr(class: due_class) do
|
||||
td do
|
||||
a invoice.number,
|
||||
|
@ -3098,6 +3157,7 @@ module StopTime::Views
|
|||
# @param [Customer, nil] task a task to show time entries for
|
||||
# @return [Mab::Mixin::Tag] the main menu
|
||||
def _time_entries(customer=nil, task=nil)
|
||||
date_time_new = date_time_new_entry(@time_entries.first)
|
||||
form.form_inline action: R(Timeline), method: :post do
|
||||
table.table.table_condensed.table_striped.table_hover do
|
||||
thead do
|
||||
|
@ -3131,11 +3191,11 @@ module StopTime::Views
|
|||
end
|
||||
td.col_md_1 do
|
||||
input.form_control type: :text, name: "date",
|
||||
value: DateTime.now.to_date.to_formatted_s
|
||||
value: date_time_new && date_time_new.to_date.to_formatted_s
|
||||
end
|
||||
td.col_md_1 do
|
||||
input.form_control type: :text, name: "start",
|
||||
value: DateTime.now.to_time.to_formatted_s(:time_only)
|
||||
value: date_time_new && date_time_new.to_formatted_s(:time_only)
|
||||
end
|
||||
td.col_md_1 do
|
||||
input.form_control type: :text, name: "end"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* CSS file for Stop… Camping Time! */
|
||||
/* CSS file for Stop... Camping Time! */
|
||||
|
||||
/* Main elements */
|
||||
html
|
||||
|
@ -52,7 +52,6 @@ table
|
|||
th
|
||||
overflow: hidden
|
||||
|
||||
|
||||
table.table-condensed
|
||||
td.indent
|
||||
padding-left: 20px
|
||||
|
@ -78,6 +77,9 @@ table.grand-total
|
|||
.form-group
|
||||
margin-bottom: 8px
|
||||
|
||||
.form-control
|
||||
padding: 4px 6px
|
||||
|
||||
.form-inline
|
||||
label
|
||||
padding-top: 6px
|
||||
|
|
Loading…
Reference in New Issue