# This file is part of Taskr.
#
# Taskr is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Taskr is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Taskr. If not, see .
# need auto_validation off to render non-XHTML XML
Markaby::Builder.set(:auto_validation, false)
Markaby::Builder.set(:indent, 2)
module Taskr::Views
module XML
include Taskr::Models
CONTENT_TYPE = 'text/xml'
def tasks_list
@tasks.to_xml(:root => 'tasks', :include => [:task_actions])
end
def view_task
@task.to_xml(:root => 'task', :include => [:task_actions])
end
end
module HTML
include Taskr::Controllers
CONTENT_TYPE = 'text/html'
def tasks_list
html_scaffold do
h1 {"Tasks"}
p{a(:href => R(Taskr::Controllers::Tasks, 'new')) {"Schedule New Task"}}
table do
thead do
tr do
th "Name"
th "Schedule"
th "Last Triggered"
th "Job ID"
th "Created On"
th "Created By"
th ""
end
end
tbody do
@tasks.each do |t|
tr_css = []
tr_css << "error" if t.last_triggered_error
tr_css << "expired" if t.next_trigger_time != :unknown && t.next_trigger_time < Time.now
tr(:class => tr_css.join(" ")) do
td {a(:href => R(t)) {strong{t.name}}}
td "#{t.schedule_method} #{t.schedule_when}"
td do
if t.last_triggered
"#{distance_of_time_in_words(t.last_triggered, Time.now, true)} ago"
else
em "Not yet triggered"
end
end
td(:class => "job-id") {t.scheduler_job_id}
td t.created_on
td t.created_by
td {a(:href => R(t, 'edit')) {"Edit"}}
end
end
end
end
br
div {scheduler_status}
end
end
def edit_task
html_scaffold do
script(:type => 'text/javascript') do
%{
function show_action_parameters(num) {
new Ajax.Updater('parameters_'+num, '#{R(Actions)}', {
method: 'get',
parameters: {
id: $F('action_class_name_'+num),
action: 'parameters_form',
num: num
}
});
}
}
end
a(:href => R(Tasks, :list)) {"Back to Task List"}
form :method => 'put', :action => R(@task, 'update') do
h1 "Edit Task \"#{@task.name}\""
p do
label 'name'
br
input :type => 'text', :name => 'name', :value => @task.name, :size => 40
end
p do
label 'schedule'
br
select(:name => 'schedule_method') do
['every','at','in','cron'].each do |method|
if @task.schedule_method == method
option(:value => method, :selected => 'selected') {method}
else
option(:value => method) {method}
end
end
end
input :type => 'text', :name => 'schedule_when', :value => @task.schedule_when, :size => 30
end
p do
label 'description/memo'
br
textarea(:name => 'memo', :cols => '60', :rows => '4'){@task.memo}
end
p do
label "Actions:"
@task.task_actions.each do |action|
div {action_parameters_form(action)}
end
# div do
# if @task.task_actions.length > 1
# ol(:style => 'padding-left: 20px') do
# @task.task_actions.each do |ta|
# html_task_action_li(ta)
# end
# end
# else
# html_task_action_li(@task.task_actions.first)
# end
# end
end
p do
a(:id => 'add_action', :href => '#'){'Add another action'}
end
script(:type => 'text/javascript') do
%{
Event.observe('add_action', 'click', function() {
new Ajax.Updater('add_action', '#{R(Actions, :new)}', {
method: 'get',
parameters: { num: $$('select.action_class_name').size() },
insertion: Insertion.Before
});
return false;
})
}
end
button(:type => 'submit') {"Save"}
end
end
end
def new_task
html_scaffold do
script(:type => 'text/javascript') do
%{
function show_action_parameters(num) {
new Ajax.Updater('parameters_'+num, '#{R(Actions)}', {
method: 'get',
parameters: {
id: $F('action_class_name_'+num),
action: 'parameters_form',
num: num
}
});
}
}
end
form :method => 'post', :action => self/"/tasks?format=#{@format}" do
h1 "New Task"
input :type => 'hidden', :name => '_method', :value => 'post'
p do
label 'name'
br
input :type => 'text', :name => 'name', :size => 40
end
p do
label 'schedule'
br
select(:name => 'schedule_method') do
['every','at','in','cron'].each do |method|
option(:value => method) {method}
end
end
input :type => 'text', :name => 'schedule_when', :size => 30
end
p do
label 'description/memo'
br
textarea(:name => 'memo', :cols => '60', :rows => '4'){""}
end
action_form
p do
a(:id => 'add_action', :href => '#'){'Add another action'}
end
script(:type => 'text/javascript') do
%{
Event.observe('add_action', 'click', function() {
new Ajax.Updater('add_action', '#{R(Actions, :new)}', {
method: 'get',
parameters: { num: $$('select.action_class_name').size() },
insertion: Insertion.Before
});
return false;
})
}
end
button(:type => 'submit') {"submit"}
end
end
end
def view_task
html_scaffold do
form(:method => 'delete', :style => 'display: inline', :action => R(@task)) do
button(:type => 'submit', :value => 'delete', :onclick => 'return confirm("Are you sure you want to unschedule and delete this task?")') {"Delete"}
end
form(:method => 'put', :style => 'display: inline', :action => R(@task, 'run')) do
button(:type => 'submit', :value => 'run') {"Run Now!"}
end
form(:method => 'put', :style => 'display: inline', :action => R(@task, 'reload')) do
button(:type => 'submit', :value => 'reload') {"Reload!"}
end
br
a(:href => R(Tasks, :list)) {"Back to Task List"}
h1 "Task #{@task.id}"
table do
tr do
th "Name:"
td @task.name
end
tr do
th "Schedule:"
td "#{@task.schedule_method} #{@task.schedule_when}"
end
tr do
th "Description/Memo:"
td "#{@task.memo}"
end
tr do
th "Job ID:"
td @task.scheduler_job_id
end
tr do
th "Triggered:"
td do
if @task.last_triggered
span "#{distance_of_time_in_words(@task.last_triggered, Time.now, true)} ago"
span(:style => 'font-size: 8pt; color: #bbb'){"(#{@task.last_triggered})"}
else
em "Not yet triggered"
end
end
end
if @task.last_triggered_error
th "Error:"
td(:style => 'color: #e00;') do
strong "#{@task.last_triggered_error[:type]}"
br
pre @task.last_triggered_error[:message]
end
end
tr do
th "Actions:"
td do
if @task.task_actions.length > 1
ol(:style => 'padding-left: 20px') do
@task.task_actions.each do |ta|
html_task_action_li(ta)
end
end
else
html_task_action_li(@task.task_actions.first)
end
end
end
tr do
th "Created By:"
td @task.created_by
end
tr do
th "Created On:"
td @task.created_on
end
end
script %{
function clickbold(el) {
$$('#logfilter a').each(function(a){a.style.fontWeight = 'normal'})
el.style.fontWeight = 'bold'
}
}
p(:style => "margin-top: 20px; border-top: 1px dotted black; padding-top: 10px", :id => 'logfilter') do
strong "Show: "
a(:href => R(LogEntries, :list, :task_id => @task.id, :since => (Time.now - 1.day).to_formatted_s(:db)),
:target => 'log', :onclick => "clickbold(this)", :style => 'font-weight: bold') {"Last 24 Hours"}
text "|"
a(:href => R(LogEntries, :list, :task_id => @task.id, :since => (Time.now - 2.days).to_formatted_s(:db)),
:target => 'log', :onclick => "clickbold(this)") {"48 Hours"}
text "|"
a(:href => R(LogEntries, :list, :task_id => @task.id),
:target => 'log', :onclick => "clickbold(this)") {"All"}
br
strong "Level: "
a(:href => R(LogEntries, :list, :task_id => @task.id, :level => 'DEBUG'),
:target => 'log', :onclick => "clickbold(this)") {"DEBUG"}
text "|"
a(:href => R(LogEntries, :list, :task_id => @task.id, :level => 'INFO'),
:target => 'log', :onclick => "clickbold(this)") {"INFO"}
text "|"
a(:href => R(LogEntries, :list, :task_id => @task.id, :level => 'WARN'),
:target => 'log', :onclick => "clickbold(this)") {"WARN"}
text "|"
a(:href => R(LogEntries, :list, :task_id => @task.id, :level => 'ERROR'),
:target => 'log', :onclick => "clickbold(this)") {"ERROR"}
end
iframe(:src => R(LogEntries, :list, :task_id => @task.id, :since => (Time.now - 1.day).to_formatted_s(:db)),
:style => 'width: 100%; height: 300px', :name => 'log')
end
end
def scheduler_status
s = Taskr.scheduler
h3(:style => "margin-bottom: 8px;") {"Scheduler Status"}
strong "Running?"
span(:style => 'margin-right: 10px') {s.instance_variable_get(:@stopped) ? "NO" : "Yes"}
strong "Precision:"
span(:style => 'margin-right: 10px') {"#{s.instance_variable_get(:@precision)}s"}
strong "Pending Jobs:"
span(:style => 'margin-right: 10px') {s.instance_variable_get(:@pending_jobs).size}
strong "Thread Status:"
span(:style => 'margin-right: 10px') {s.instance_variable_get(:@scheduler_thread).status}
end
def action_list
h1 "Actions"
ul do
@actions.each do |a|
li a
end
end
end
def action_parameters_form(action = @action)
@num ||= 0
p {em action.description}
action.parameters.each do |param|
p do
label param
br
unless action.is_a?(Taskr::Models::TaskAction) # Setting up a new task
input :type => 'text', :name => "action[#{@num}][#{param}]", :size => 50
else # Editing an existing task
input :type => 'text', :name => "action[action_id_#{action.id}][#{param.name}]", :size => 50, :value => param.value
end
end
end
end
def action_form
@num ||= 0
p do
label 'action_class_name'
br
select(:name => "action[#{@num}][action_class_name]",
:id => "action_class_name_#{@num}",
:class => "action_class_name",
:onchange => "show_action_parameters(#{@num})") do
option(:value => "")
@actions.each do |a|
a.to_s =~ /Taskr::Actions::([^:]*?)$/
option(:value => $~[1]) {$~[1]}
end
end
end
div(:id => "parameters_#{@num}")
end
def log_entries_list
h2 "Log"
p(:style => 'margin: 0px') do
em(:style => "font-weight: normal; font-size: 9pt"){"Entries since #{@since}
"} unless @since.blank?
em(:style => "font-weight: normal; font-size: 9pt"){"With levels #{@level.join(", ")}
"} unless @level.blank?
end
table do
@log_entries.each do |entry|
case entry.level.downcase.intern
when :error
bg_color = '#faa'
when :warn
bg_color = '#ffa'
when :info
bg_color = '#aaf'
when :debug
bg_color = '#eee'
else
bg_color = '#fff; '+entry.level.inspect
end
tr do
td(:style => "vertical-align: top; font-size: 9pt; white-space: nowrap; background: #{bg_color}") do
entry.timestamp
end
td(:style => "vertical-align: top; font-size: 9pt; background-color: #{bg_color}; font-size: 9pt; font-family: monospace") do
entry.data.gsub(/<\/?(html|body)>/, '').gsub(/\n/, "
")
end
end
end
end
end
end
default_format :HTML
end