./0000755000175000017500000000000011773315157010531 5ustar tfheentfheen./README.rdoc0000644000175000017500000001025111773315157012336 0ustar tfheentfheen= Chef = DESCRIPTION: Chef is a configuration management tool designed to bring automation to your entire infrastructure. The Chef Wiki is the definitive source of user documentation. * http://wiki.opscode.com/display/chef/Home This README focuses on developers who want to modify Chef source code. For users who just want to run the latest and greatest Chef development version in their environment, see: * http://wiki.opscode.com/display/chef/Installing+Chef+from+HEAD = DEVELOPMENT: Before working on the code, if you plan to contribute your changes, you need to read the Opscode Contributing document. * http://wiki.opscode.com/display/opscode/Contributing You will also need to set up the repository with the appropriate branches. We document the process on the Chef Wiki. * http://wiki.opscode.com/display/opscode/Working+with+Git Once your repository is set up, you can start working on the code. We do use BDD/TDD with RSpec and Cucumber, so you'll need to get a development environment running. = ENVIRONMENT: In order to have a development environment where changes to the Chef code can be tested, we'll need to install a few things after setting up the Git repository. == Requirements: Install these via your platform's preferred method; for example apt, yum, ports, emerge, etc. * Git * CouchDB Install the following RubyGems. * ohai * rake * rspec * cucumber * merb-core Ohai is also by Opscode and available on GitHub, http://github.com/opscode/ohai/tree/master. roman-merb_cucumber is available from GitHub: gem install --source http://gems.github.com/ roman-merb_cucumber == Starting the Environment: Once everything is installed, run the dev:features rake task. Since the features do integration testing, root access is required. sudo rake dev:features The dev:features task: * Installs chef, chef-server, chef-server-slice gems. It will fail if required gems above are missing. * Starts chef-server on ports 4000 and 4001. * Starts chef-indexer. * Starts CouchDB on port 5984. * Starts the stompserver on port 61613. You'll know its running when you see: ~ Activating slice 'ChefServerSlice' ... merb : worker (port 4000) ~ Starting Mongrel at port 4000 merb : worker (port 4000) ~ Successfully bound to port 4000 merb : worker (port 4001) ~ Starting Mongrel at port 4001 merb : worker (port 4001) ~ Successfully bound to port 4001 You'll want to leave this terminal running the dev environment. == Web Interface: With the dev environment running, you can now access the web interface via http://localhost:4000/. Supply an OpenID to log in. == Spec testing: We use RSpec for unit/spec tests. rake spec This doesn't actually use the development environment, because it does the testing on all the Chef internals. For integration/usage testing, we use Cucumber features. == Integration testing: We test integration with Cucumber. The available feature tests are rake tasks: rake features # Run Features with Cucumber rake features:api # Run Features with Cucumber rake features:client # Run Features with Cucumber rake features:provider:package:macports # Run Features with Cucumber rake features:provider:remote_file # Run Features with Cucumber rake features:search # Run Features with Cucumber = LINKS: Source: * http://github.com/opscode/chef/tree/master Tickets/Issues: * http://tickets.opscode.com/ Documentation: * http://wiki.opscode.com/display/chef/Home/ = LICENSE: Chef - A configuration management system Author:: Adam Jacob () Copyright:: Copyright (c) 2008, 2009 Opscode, Inc. License:: Apache License, Version 2.0 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ./app/0000755000175000017500000000000011773315157011311 5ustar tfheentfheen./app/views/0000755000175000017500000000000011773315157012446 5ustar tfheentfheen./app/views/main/0000755000175000017500000000000011773315157013372 5ustar tfheentfheen./app/views/main/index.html.erb0000644000175000017500000000010311773315157016130 0ustar tfheentfheen<%= slice.description %> (v. <%= slice.version %>)./app/views/environments/0000755000175000017500000000000011773315157015175 5ustar tfheentfheen./app/views/environments/index.html.haml0000644000175000017500000000167311773315157020121 0ustar tfheentfheen.block#block-tables .content %h2.title Environments .inner = partial('navigation', :active => 'index') .content .inner %table.table %tr %th.first{:colspan => 2} Name %th   %th.last   - even = false; - @environment_list.each do |env| %tr{ :class => even ? "even" : "odd" } %td{:colspan => 2}= link_to(env[0], url(:environment, env[0])) %td - if session[:environment] != env[0] = link_to('Select', url(:environment_select, env[0])) - else Select | = link_to('Edit', url(:edit_environment, env[0])) | = link_to('Delete', url(:environment, env[0]), :method => "delete", :confirm => "Really delete Environment #{env[0]}? there is no undo.") - even = (not even) ./app/views/environments/_version_selector.html.erb0000644000175000017500000000052711773315157022362 0ustar tfheentfheen
<%= text_field(:name => "cookbook_version[#{cookbook_version_index}]", :value => "#{cookbook_name} #{constraint}")%>
./app/views/environments/edit.html.erb0000644000175000017500000000156511773315157017566 0ustar tfheentfheen

Environment <%= params[:id] %>

<%= partial "environments/navigation", :environment => @environment, :active => 'edit'%>
<%= partial 'environments/form', :environment => @environment, :route => :environments, :method => :put, :form_url => url(:environment, @environment.name), :form_id => 'edit_environment', :form_for => 'edit', :submit_name => "Update Environment", :submit_id => "edit_environment_button", :new_object => true %>
./app/views/environments/new.html.erb0000644000175000017500000000155411773315157017430 0ustar tfheentfheen

Environment <%= params[:id] %>

<%= partial "environments/navigation", :environment => @environment, :active => 'create'%>
<%= partial 'environments/form', :environment => @environment, :route => :environments, :method => :post, :form_url => url(:environments), :form_id => 'create_environment', :form_for => 'create', :submit_name => "Create Environment", :submit_id => "create_environment_button", :new_object => true %>
./app/views/environments/_form.html.erb0000644000175000017500000001037111773315157017736 0ustar tfheentfheen
<%= form(:action => form_url, :method => (method || :post), :id => form_id, :class => 'form') do -%> <% unless form_for == 'edit' %>
<% if !@environment.invalid_fields[:name].nil? && @environment.invalid_fields[:name].size != 0 %> The environment name contains illegal characters. The following characters are allowed: a-z, A-Z, 0-9, _, and -. <% end %> <%= text_field :id => "environment_name", :name => "name", :class => "text_field", :value => params.has_key?(:name) ? h(params[:name]) : @environment.name %> The name of the Environment
<% end %>
<%= text_area(params.has_key?(:description) ? h(params[:description]) : @environment.description, :name => "description", :class => "text_area", :id => "environment_description") %> A description of this Environment
> <% if !@environment.invalid_fields[:cookbook_version].nil? && !@environment.invalid_fields[:cookbook_version].empty? %> There was a problem in one of your constraints. Please enter version constraints in acceptable formats (e.g. 0.0.0). <% end %>
Name Operator Version  
Add
<%= partial 'layout/jsonedit', :json => { :defaults => @environment.default_attributes, :overrides => @environment.override_attributes }.to_json%> A JSON hash for attributes of this environment. These attributes will be applied according to the attribute precedence rules.
<%= submit(submit_name, :id => submit_id, :class => 'button') -%>
<% end =%>
./app/views/environments/show.html.haml0000644000175000017500000000226411773315157017767 0ustar tfheentfheen.block#block-tables .content %h2.title= "Environment #{h @environment.name}" .inner = partial("navigation", :active => "show") .content .inner .left %h3 Name = @environment.name .left %h3 Description = @environment.description .left %h3 Cookbook Version Constraints %table.table %tr %th.first Name %th.last Version Constraints - if @environment.cookbook_versions.empty? %tr %td{:colspan => 2} This environment does not include any cookbook version constraints. - else - @environment.cookbook_versions.keys.sort.each do |name| - versions = @environment.cookbook_versions[name] %tr %td= name %td= versions .left %h3 Default Attributes = build_tree('defattrs', @environment.default_attributes) .left %h3 Override Attributes = build_tree('overattrs', @environment.override_attributes)./app/views/environments/_navigation.html.haml0000644000175000017500000000125411773315157021303 0ustar tfheentfheen.secondary-navigation %ul %li{ :class => "first #{active == 'index' ? "active" : ''}"}= link_to('List', url(:environments)) %li{ :class => (active == 'create' ? "active" : '')}= link_to('Create', url(:new_environment)) - if active != 'create' && active != 'index' %li{ :class => (active == 'show' ? "active" : '')}= link_to('Show', url(:environment, @environment.name)) %li{ :class => (active == 'edit' ? "active" : '')}= link_to('Edit', url(:edit_environment, @environment.name)) %li= link_to('Delete', url(:environment, @environment.name), :method => "delete", :confirm => "Really delete Environment #{@environment.name}? There is no undo.") .clear./app/views/databags/0000755000175000017500000000000011773315157014214 5ustar tfheentfheen./app/views/databags/index.html.haml0000644000175000017500000000146211773315157017134 0ustar tfheentfheen.block#block-tables .content %h2.title Databags .inner = partial('navigation', :active => 'index') .content .inner %table.table %thead %tr %th.first{:colspan => 2} Databag Name %th   %th.last   %tbody - @databags.sort.each_with_index do |databag, index| %tr{:class => "#{index % 2 == 1 ? 'odd' : 'even'}"} %td{:colspan => 2}= link_to databag[0], url(:databag, { :id => databag[0] }) %td = link_to('Edit', url(:databag, :id => databag[0])) | = link_to('Delete', url(:databag, :id => databag[0]), :method => "delete", :confirm => "Really delete Databag #{databag[0]}? There is no undo.") ./app/views/databags/_item_navigation.html.haml0000644000175000017500000000112511773315157021335 0ustar tfheentfheen.secondary-navigation %ul %li{ :class => "first #{active == 'index' ? "active" : ''}"}= link_to('List', url(:databags)) %li{ :class => (active == 'create_item' ? "active" : '')}= link_to('Create Item', url(:new_databag_databag_item, :databag_id => @databag_name)) - if active != 'create' && active != 'index' %li{ :class => (active == 'show' ? "active" : '')}= link_to('Show', url(:databag, :id => params[:id])) %li= link_to('Delete', url(:databag, :id => params[:id]), :method => "delete", :confirm => "Really delete Databag #{params[:id]}? There is no undo.") .clear ./app/views/databags/edit.html.haml0000644000175000017500000000053711773315157016754 0ustar tfheentfheen.block#block-tables .content %h2.title= "Databag: #{params[:id]}" .inner = partial('navigation', :active => 'edit') = partial('form', :header => "Edit Databag", :form_id => 'edit_databag', :submit_name => "Edit Databag", :submit_id => "edit_databag_button", :form_for => 'edit', :form_url => url(:databag, :databag_id=>params[:id])) ./app/views/databags/show.html.haml0000644000175000017500000000173311773315157017006 0ustar tfheentfheen.block#block-text .content %h2.title= "Databag: #{@databag_name}" .inner = partial('item_navigation', :active => 'show') .content .inner %table.table %tr %th.first{:colspan => 2} Databag Items %th   %th.last   - @databag.sort.each_with_index do |databag_item_uri, index| %tr{:class => "#{index % 2 == 1 ? 'odd' : 'even'}"} %td{:colspan => 2}= link_to databag_item_uri[0], url(:databag_databag_item, :id => databag_item_uri[0], :databag_id => @databag_name) %td = link_to('Edit', url(:edit_databag_databag_item, :id => databag_item_uri[0], :databag_id => @databag_name)) | = link_to('Delete', url(:databag_databag_item, :id => databag_item_uri[0], :databag_id => @databag_name), :method => "delete", :confirm => "Really delete Databag Item #{databag_item_uri[0]}? There is no undo.") ./app/views/databags/_navigation.html.haml0000644000175000017500000000120511773315157020316 0ustar tfheentfheen.secondary-navigation %ul %li{ :class => "first #{active == 'index' ? "active" : ''}"}= link_to('List', url(:databags)) %li{ :class => (active == 'create' ? "active" : '')}= link_to('Create', url(:new_databag)) - if active != 'create' && active != 'index' %li{ :class => (active == 'show' ? "active" : '')}= link_to('Show', url(:databag, @databag_name)) %li{ :class => (active == 'edit' ? "active" : '')}= link_to('Edit', url(:edit_databag, @databag_name)) %li= link_to('Delete', url(:databag, @databag_name), :method => "delete", :confirm => "Really delete Databag #{@databag_name}? There is no undo.") .clear ./app/views/databags/_form.html.haml0000644000175000017500000000071611773315157017130 0ustar tfheentfheen.content .inner %div.group.form %label.label Name = text_field :id => "databag_name", :name => "name", :class => "text_field", :value => params.has_key?(:id) ? h(params[:id]) : @databag.name %span.description The name of the Databag = form(:action => form_url, :method => :post, :id => form_id, :class => 'form') do %div.group .actions-bar .actions= submit submit_name, :id => submit_id, :class => 'button' ./app/views/databags/new.html.haml0000644000175000017500000000050611773315157016614 0ustar tfheentfheen.block#block-tables .content %h2.title= "Databag" .inner = partial('navigation', :active => 'create') = partial('form', :header => "Create new Databag", :form_id => 'create_databag', :submit_name => "Create Databag", :submit_id => "create_databag_button", :form_for => 'create', :form_url => url(:databags)) ./app/views/databag_items/0000755000175000017500000000000011773315157015232 5ustar tfheentfheen./app/views/databag_items/index.html.haml0000644000175000017500000000000011773315157020135 0ustar tfheentfheen./app/views/databag_items/edit.html.haml0000644000175000017500000000061711773315157017771 0ustar tfheentfheen.block#block-tables .content %h2.title= "Databag Item" .inner = partial('navigation', :active => 'edit') = partial('form', :header => "Edit Databag Item", :form_id => 'edit_databag_item', :submit_name => "Edit Databag Item", :submit_id => "edit_databag_item_button", :form_for => 'edit', :form_url => url(:databag_databag_item, :databag_id=>params[:databag_id], :id=>params[:id])) ./app/views/databag_items/show.html.haml0000644000175000017500000000035411773315157020022 0ustar tfheentfheen.block#block-tables .content %h2.title= "Databag Item: #{@databag_item_name}" .inner = partial('navigation', :active => 'show') .content .inner .accordion = build_tree('attrs', @databag_item) ./app/views/databag_items/_navigation.html.haml0000644000175000017500000000160211773315157021335 0ustar tfheentfheen.secondary-navigation %ul %li{ :class => "first #{active == 'index' ? "active" : ''}"}= link_to('List', url(:databag_databag_items, :databag_id=>@databag_name)) %li{ :class => (active == 'create' ? "active" : '')}= link_to('Create', url(:new_databag_databag_item, :databag_id => @databag_name)) - if active != 'create' && active != 'index' %li{ :class => (active == 'show' ? "active" : '')}= link_to('Show', url(:databag_databag_item, :id => @databag_item_name, :databag_id=>@databag_name)) %li{ :class => (active == 'edit' ? "active" : '')}= link_to('Edit', url(:edit_databag_databag_item, :id => @databag_item_name, :databag_id=>@databag_name)) %li= link_to('Delete', url(:databag_databag_item, :id => @databag_item_name, :databag_id=>@databag_name), :method => "delete", :confirm => "Really delete Databag Item #{@databag_item_name}? There is no undo.") .clear ./app/views/databag_items/_form.html.haml0000644000175000017500000000063711773315157020150 0ustar tfheentfheen.content .inner %div.group.form %label.label Data %div.group.form{:style => "position:relative;"} %label.label Attributes = partial 'layout/jsonedit', :json =>@default_data.to_json = form(:action => form_url, :method => :post, :id => form_id, :class => 'form') do %div.group .actions-bar .actions= submit submit_name, :id => submit_id, :class => 'button' ./app/views/databag_items/new.html.haml0000644000175000017500000000055411773315157017635 0ustar tfheentfheen.block#block-tables .content %h2.title= "Databag Item" .inner = partial('navigation', :active => 'create') = partial('form', :header => "Create new Databag Item", :form_id => 'create_databag_item', :submit_name => "Create Databag Item", :submit_id => "create_databag_item_button", :form_for => 'create', :form_url => url(:databag_databag_items)) ./app/views/openid_consumer/0000755000175000017500000000000011773315157015637 5ustar tfheentfheen./app/views/openid_consumer/index.html.haml0000644000175000017500000000265711773315157020566 0ustar tfheentfheen- throw_content(:sidebar_block_notice) do %h4 Where do I get a Login? %p Any existing Admin level user can create new users. %p To create the first user, please login with the default admin credential, which by default is: %p username: admin, password: p@ssw0rd1 (May be different if you've set it in Chef::Config) %b Please change the default password immediately after logging in! %p Once you have an User, you can associate an OpenID with the User and login using the OpenID as the User. %p Administrators can associate OpenID to any User. .block#block-forms .content %h2.title Login .inner %form.form{ :method => "get", "accept-charset" => "UTF-8", :action => url(:openid_consumer_login) } .group .text_field= text_field :openid_identifier .group .check_box= check_box :name => "immediate", :label => "Use immediate mode", :value => "0" .group .check_box= check_box :name => "use_sreg", :label => "Request registration data", :value => "0" .group .check_box= check_box :name => "use_pape", :label => "Request phishing-resistent auth policy", :value => "0" .group .check_box= check_box :name => "force_post", :label => "Force the transaction to POST", :value => "0" .group =link_to("Or, log in with username and password.", url(:users_login)) .group.navform .button= submit "Login →" ./app/views/openid_consumer/start.html.haml0000644000175000017500000000015411773315157020602 0ustar tfheentfheen<%= @form_text %> ./app/views/openid_register/0000755000175000017500000000000011773315157015630 5ustar tfheentfheen./app/views/openid_register/index.html.haml0000644000175000017500000000241711773315157020551 0ustar tfheentfheen.block#block-tables .content %h2.title Registrations .inner %table.table %tr %th.first Registration Name %th   %th Control %th.last   - @registered_nodes.sort{ |a,b| a.name.to_s <=> b.name.to_s }.each_with_index do |node, index| %tr{:class => "#{index % 2 == 1 ? 'odd' : 'even'}"} %td{:colspan => 2}= link_to(node.name, url(:registration, { :id => node.name })) %td = link_to( (node.validated ? "Invalidate Registration" : "Validate Registration"), url( :validate_registration, { :id => node.name} ), :method => "post", :confirm => "Are you sure you want to" + (node.validated ? " invalidate " : " validate ") + "this node's registration?") | = link_to((node.admin ? "Remove Admin Rights" : "Grant Admin Rights"), url(:admin_registration, { :id => node.name}), :method => "post", :confirm => "Are you sure you want to" + (node.admin ? " remove administrator privileges from this node?" : " grant administrator privileges to this node?")) | = link_to("Delete", url(:registration, { :id => node.name} ), :method => "delete", :confirm => "Are you sure you want to delete this registration") ./app/views/openid_register/show.html.haml0000644000175000017500000000044411773315157020420 0ustar tfheentfheen.block#block-text .content %h2.title= "Registration #{@registered_node.name}" .inner = link_to "OpenID URL", url(:openid_node, { :id => @registered_node.name.gsub(/\./, "_")}) %br= "Validated: #{@registered_node.validated}" %br= "Admin: #{@registered_node.admin}" ./app/views/openid_login/0000755000175000017500000000000011773315157015114 5ustar tfheentfheen./app/views/openid_login/index.html.haml0000644000175000017500000000027211773315157020032 0ustar tfheentfheen#login-form %form{ :method => "get", :action => url(:openid_login_submit) } %input{ :type => "text", :name => "username" }/ %input{ :type => "submit", :value => "Log In"}/ ./app/views/layout/0000755000175000017500000000000012014212446013745 5ustar tfheentfheen./app/views/layout/_jsonedit.html.haml0000644000175000017500000000617412014212446017541 0ustar tfheentfheen- throw_content :header_content do = css_include_tag "jsonedit_main.css" = js_include_tag "json.js" = js_include_tag "yetii-min.js" %script{:type=>"text/javascript", :src => "http://oss-chef-objects.s3.amazonaws.com/jsonedit_main.js"} %script= "$(document).ready(function() { $$(\"jsonstr\").value = JSON.stringify(#{json}); if (BCJTEP.build()) { $$(\"results\").innerHTML = \" \"; $$(\"editortab\").className = \"show\"; $$(\"searchtab\").className = \"show\"; }});" %div#jsoneditor %div#treecontainer %div#div1 %div#tabcontainer %div#tab-container-1.tablayout %ul#tab-container-1-nav.tablayout %li#searchtab.noshow %a{ :href => "#tab1"} search %li#editortab.noshow %a{ :href => "#tab2"} editor %li#sourcetab %a{ :href => "#tab3"} source %div#tab1.tab %table.icanhastable %tr %td %span search : %input#keyword{:type => "text"} %input#search{:type => "button", :value => "Find"} %tr %td %div#results   %div#tab2.tab %table.icanhastable %tr %td %div#add.button{:title => "Add a new attribute"} %div#delete.button{:title => "Delete current attribute"} %div#savedstatus{:style => "display:none;"} %img{ :src=> "/images/jsonedit/saved.png"} %span Saved! %div#deletedstatus{:style => "display:none;"} %img{ :src=> "/images/jsonedit/deleted.png"} %span Deleted! %td type : %select#jsontypes %option Select Type %tr %td{:colspan => "2"} %div#jsonnameinput name : %input#jsonname{:type => "text", :size=>"55", :class => ""} %tr %td{:colspan => "2"} %textarea#jsonvalue{:wrap => "virtual", :cols => "55", :rows => "5", :class => ""} %tr %td{:colspan => "2"} %div#jsonpath   %div#jsonmode   %tr %td{:style => "text-align:left !important"} %input#autodetect{:type => "checkbox", :checked=> "true"} %label{:for => "autodetect"} Autodetect type of attribute? %td %input#savebutton{:type => "button", :value => "Save Attribute"} %input#addbutton{:type => "button", :value => "Add Attribute"} %div#tab3.tab %div#tab-container-2.tablayout.nested %ul#tab-container-2-nav.tablayout %li %a{ :href => "#tab3a" } json %div#tab1a.tabn %table.icanhastable %tr %td %div#refresh.button{:title => "Reload JSON from Tree"} %div#buildbutton.button{:title => "Load JSON from Source"} %tr %td %textarea#jsonstr{:wrap => "virtual", :cols => "55", :rows => "10", :class => ""} %div#console %div#bar %a#consolebar Error Console %div#log ./app/views/layout/login.html.haml0000644000175000017500000000253111773315157016702 0ustar tfheentfheen!!! XML !!! 5 %html %head %meta{ "http-equiv" => "content-type", :content => "text/html; charset=utf-8" } %title Chef Server = css_include_tag "base", "themes/djime-cerulean/style", "chef", "/facebox/facebox.css", "jquery-ui-1.7.1.custom", "jquery.treeTable" = js_include_tag "jquery-1.5.2.min", "jquery.jeditable.mini", "jquery.localscroll", "jquery.scrollTo", "jquery.tools.min" = js_include_tag "/facebox/facebox.js" = js_include_tag "jquery-ui-1.7.1.custom.min" = js_include_tag "jquery.treeTable.min" = js_include_tag "chef" %body #container #header %h1= link_to "Chef Server", url(:top) #wrapper #main.loginPage - unless message.empty? .block#block-messages .content %h2.title Messages .inner .flash - message.each do |type, msg| %div{:class => "message #{type}"} %p= msg = catch_content :for_layout #footer .block %p= "Version #{chef_version} — Copyright © 2009-#{Time.now.year} Opscode" #sidebar .block.notice#sidebar_block_notice= catch_content :sidebar_block_notice .block#sidebar_block= catch_content :sidebar_block .clear ./app/views/layout/application.html.haml0000644000175000017500000000564311773315157020104 0ustar tfheentfheen!!! 5 %html %head %meta{ "http-equiv" => "content-type", :content => "text/html; charset=utf-8" } %title Chef Server = css_include_tag "base", "themes/djime-cerulean/style", "chef", "/facebox/facebox.css", "jquery-ui-1.7.1.custom", "jquery.treeTable", "jsonedit_main.css", "jquery.suggest.css" = js_include_tag "jquery-1.5.2.min", "jquery.jeditable.mini", "jquery.localscroll", "jquery.scrollTo", "jquery.tools.min" = js_include_tag "/facebox/facebox.js" = js_include_tag "jquery-ui-1.7.1.custom.min" = js_include_tag "jquery.treeTable.min" = js_include_tag "chef" = js_include_tag "drop_down_menu" = js_include_tag "jquery.suggest" = catch_content :header_content %body #container #header %h1 = link_to "Chef Server", url(:top) %label{:for => 'environment-select'} Environment: %select{:name => 'environment-select', :onchange => 'jump(this)', :size => 1, :class => 'title-select'} - current_env = session[:environment] %option{:value => url(:environment_select, :environment_id => '_none'), :selected => current_env == nil} None - @environments.each do |env| %option{:value => url(:environment_select, :environment_id => env), :selected => current_env == env}= env #user-navigation %ul - if session[:user] %li= link_to "Edit account", url(:users_edit, :user_id => session[:user]), :method => 'get' %li= link_to "Logout #{h session[:user]} (#{session[:level].to_s})", url(:users_logout), :method => 'get', :confirm => "Are you sure you want to logout?" - else %li= link_to "Login", url(:users_login), :rel => "facebox" .clear #main-navigation %ul = nav_link_item("Environments", :environments) = nav_link_item("Search", :searches) = nav_link_item("Status", :status) = nav_link_item("Roles", :roles) = nav_link_item("Nodes", :nodes) = nav_link_item("Cookbooks", :cookbooks) = nav_link_item("Databags", :databags) = nav_link_item("Clients", :clients) = nav_link_item("Users", :users) .clear #wrapper #main - unless message.empty? .block#block-messages .content %h2.title Messages .inner .flash - message.each do |type, msg| %div{:class => "message #{type}"} %p= msg = catch_content :for_layout #footer .block %p= "Version #{chef_version} — Copyright © 2009-#{Time.now.year} Opscode" #sidebar .block.notice#sidebar_block_notice= catch_content :sidebar_block_notice .block#sidebar_block= catch_content :sidebar_block .clear ./app/views/status/0000755000175000017500000000000011773315157013771 5ustar tfheentfheen./app/views/status/index.html.haml0000644000175000017500000001023711773315157016711 0ustar tfheentfheen.block#block-tables .content %h2.title Status .inner %table.table %thead %tr %th.first Node Name %th Platform %th FQDN %th IP Address %th Uptime %th Last Check-in %th.last Run List %tbody - if @status.empty? %tr %td{:colspan => 7}= "You appear to have no nodes #{session[:environment].nil? ? '' : "in the #{session[:environment]} environment"} - try connecting one, or creating or editing a #{link_to('client', url(:clients))}" - else - @status.sort.each_with_index do |node, index| %tr{:class => "#{index % 2 == 1 ? 'odd' : 'even'}"} %td= link_to(node[1].name, url(:node, node[1].name)) %td= "#{node[1]["platform"]} #{node[1]["platform_version"]}" %td= node[1]["fqdn"] %td= node[1]["ipaddress"] %td .accordion -unless node[1]["uptime"].nil? = link_to(node[1]["uptime"].split(" ")[0..1].join(" ") , "#", :class => 'tooltip') .tooltip %table.table.tooltip %tbody %tr %td= node[1]["uptime"] - unless node[1]["ohai_time"].nil? - current_time = Time.now.to_f - ohai_time = Time.at(node[1]["ohai_time"]) - hours, minutes, seconds = time_difference_in_hms(ohai_time) - hours_text = "#{hours} hour#{hours == 1 ? '' : 's'}" - minutes_text = "#{minutes} minute#{minutes == 1 ? '' : 's'}" %td.flash - status_class = "" - if hours > 24 - status_class = "message error" - elsif hours > 1 - status_class = "message warning" %div{ :class => status_class } .accordion - if hours > 48 - status_msg = "> #{hours/24} days ago" - elsif hours > 0 - status_msg = "> #{hours_text} ago" - elsif minutes < 1 - status_msg = "< 1 minute ago" - else - status_msg = "#{minutes_text} ago" = link_to(status_msg, "#", :class=> 'tooltip') .tooltip %table.table.tooltip %tbody %tr %td = ohai_time %br/ - if hours == 0 = "#{minutes_text} ago" - else = "#{hours_text}, #{minutes_text} ago" - else %td Not Checked In - unless node[1].run_list.nil? %td .accordion = link_to("Run List", "#", :class => 'tooltip') .tooltip %table.table.tooltip %thead %tr %th.first Position %th Name %th Version %th.last Type %tbody - if node[1].run_list.empty? %tr %td{:colspan => 2} This node has no roles or recipes applied. - else -node[1].run_list.each_with_index do |run_list_item, i| %tr %td.position= i %td= run_list_item.name %td= run_list_item.version %td= run_list_item.type ./app/views/roles/0000755000175000017500000000000011773315157013572 5ustar tfheentfheen./app/views/roles/index.html.haml0000644000175000017500000000133011773315157016504 0ustar tfheentfheen.block#block-tables .content %h2.title Roles .inner = partial('navigation', :active => 'index') .content .inner %table.table %tr %th.first{:colspan => 2} Name %th   %th.last   - even = false; - @role_list.each do |role| %tr{ :class => even ? "even" : "odd" } %td{:colspan => 2}= link_to(role[0], url(:role, role[0])) %td = link_to('Edit', url(:edit_role, role[0])) | = link_to('Delete', url(:role, role[0]), :method => "delete", :confirm => "Really delete Role #{role[0]}? there is no undo.") - even = (not even) ./app/views/roles/edit.html.haml0000644000175000017500000000054211773315157016326 0ustar tfheentfheen.block#block-tables .content %h2.title= "Role #{h @role.name}" .inner = partial('navigation', :active => 'edit') = partial('form', :header => "Edit Role #{@role.name}", :form_id => 'edit_role', :submit_name => "Save Role", :submit_id => "edit_role_button", :form_for => 'edit', :form_url => url(:role, @role.name), :method => :put) ./app/views/roles/_run_lists.html.erb0000644000175000017500000000302011773315157017403 0ustar tfheentfheen
<% run_list_class, empty_controls_class = run_list ? %w{active inactive} : %w{inactive active} -%>
    <% Array(run_list).each do |item| %>
  • <%=h display_run_list_item(item)-%>
  • <% end %>
This role has no environment specific run list for the (<%= environment -%>) environment.
Or, clone an existing run list: <%= select :environment_to_clone, :collection => @existing_run_list_environments, :id => environment, :class => 'environmentToClone' %>
<% if run_list && (environment != '_default')%> Remove environment specific run list for <%= environment %> <% end %>
./app/views/roles/_form.html.erb0000644000175000017500000001062211773315157016332 0ustar tfheentfheen
<%= form(:action => form_url, :method => method, :id => form_id, :class => 'form roleForm') do -%> <% unless form_for == 'edit' %>
<%= text_field :id => "role_name", :name => "name", :class => "text_field", :value => params.has_key?(:name) ? h(params[:name]) : @role.name %> The name of the Role
<% end %>
<%= text_area(params.has_key?(:description) ? h(params[:description]) : @role.description, :name => "description", :class => "text_area", :id => "role_description") %> A description of this Role
Available Roles
    <% @available_roles.each do |role| %>
  • <%= h(role) -%>
  • <% end %>
Available Recipes
<%= image_tag('indicator.gif') -%>
<% if @current_env == '_default' -%> Default Run List <% else -%> Run List for <%= @current_env -%> <% end -%> <%= select :environment, :collection => [['noop','Other Environments']].concat(@environments.map {|e| [e,e]}), :id => 'activeEnvironment'%>
<% @run_lists.each do |environment, run_list| %> <%= partial('run_lists', :environment => environment, :run_list => run_list)%> <% end %>
Active Run List for <%= h(@current_env) -%>
<% if @current_env != "_default" && @role.env_run_lists[@current_env].nil? %>
using <%= @role.active_run_list_for(@current_env).gsub('_default', 'default') -%> run list
<% end %>
    <% @role.run_list_for(@current_env).each do |item| %>
  • <%= h(item) -%>
  • <% end %>
<%= partial 'layout/jsonedit', :json => { :defaults => @role.default_attributes, :overrides => @role.override_attributes }.to_json%> A JSON hash for default attributes for nodes of this role. These attributes will be applied according to the attribute precedence rules.
<%= submit(submit_name, :id => submit_id, :class => 'button') -%>
<% end =%>
./app/views/roles/show.html.haml0000644000175000017500000000355711773315157016372 0ustar tfheentfheen.block#block-tables .content %h2.title= "Role #{h @role.name}" .inner = partial("navigation", :active => "show") .content .inner .left %h3 Description = @role.description .left %h3 = "Run List for Environment \"#{@current_env}\"" = @env_run_list_exists ? "" : "(_default)" %table.table %tr %th.first Position %th Name %th Version %th.last Type - if @run_list.empty? %tr %td{:colspan => 2} This role does not include any roles or recipes. - else -@run_list.each_with_index do |run_list_item, i| %tr %td.position= i %td= run_list_item.name %td= run_list_item.version %td= run_list_item.type .left.accordion %h3.head= link_to("Recipes", "#") %div %span.description.form.help This is the list of recipes, fully expanded, as they will be applied by the role in question. %table#recipes.table %tr %th.first Position %th.last Name - if @run_list.empty? %tr %td{:colspan => 2} This role applies no recipes. - else - @recipes.each_with_index do |recipe, i| %tr %td.position= i %td= recipe .left %h3 Default Attributes = build_tree('defattrs', @role.default_attributes) .left %h3 Override Attributes = build_tree('overattrs', @role.override_attributes) ./app/views/roles/_navigation.html.haml0000644000175000017500000000114711773315157017701 0ustar tfheentfheen.secondary-navigation %ul %li{ :class => "first #{active == 'index' ? "active" : ''}"}= link_to('List', url(:roles)) %li{ :class => (active == 'create' ? "active" : '')}= link_to('Create', url(:new_role)) - if active != 'create' && active != 'index' %li{ :class => (active == 'show' ? "active" : '')}= link_to('Show', url(:role, @role.name)) %li{ :class => (active == 'edit' ? "active" : '')}= link_to('Edit', url(:edit_role, @role.name)) %li= link_to('Delete', url(:role, @role.name), :method => "delete", :confirm => "Really delete Role #{@role.name}? There is no undo.") .clear ./app/views/roles/new.html.haml0000644000175000017500000000050611773315157016172 0ustar tfheentfheen.block#block-tables .content %h2.title= "Role" .inner = partial('navigation', :active => 'create') = partial('form', :header => "Create new Role", :form_id => 'create_role', :submit_name => "Create Role", :submit_id => "create_role_button", :method => :post, :form_for => 'create', :form_url => url(:roles)) ./app/views/search/0000755000175000017500000000000011773315157013713 5ustar tfheentfheen./app/views/search/index.html.haml0000644000175000017500000000064111773315157016631 0ustar tfheentfheen.block#block-forms .content %h2.title Search Indexes .inner - @search_indexes.sort{ |a,b| a.to_s <=> b.to_s}.each do |index| %form.form{ :method => "get", "accept-charset" => "UTF-8", :action => url(:search, { :id => index[0]})} .group.label= text_field :name => "q", :label => "Query (i.e. attribute:value, leave empty to search all) " .group= submit "Search #{index[0]}" ./app/views/search/_search_form.html.haml0000644000175000017500000000035111773315157020147 0ustar tfheentfheen%form{ :method => "get", :action => url(:search, { :id => index_name }) } Q: %input{ :type => "text", :name => "q" } A: %input{ :type => "text", :name => "a" } %input{ :type => "submit", :value => "Search #{index_name}" } ./app/views/search/show.html.haml0000644000175000017500000000061011773315157016476 0ustar tfheentfheen.block#block-tables .content %h2.title Search Results .inner - @results.each do |result| %table.table.search{:width => '400px'} %tr %th.first Name %th.last - @results.each do |result| - result.each do |o| %tr %td= link_to(o.name, url(@type.to_sym, determine_name(@type.to_sym, o))) ./app/views/users/0000755000175000017500000000000011773315157013607 5ustar tfheentfheen./app/views/users/index.html.haml0000644000175000017500000000134411773315157016526 0ustar tfheentfheen.block#block-tables .content %h2.title Users .inner = partial('navigation', :active => 'index') .content .inner %table.table %tr %th.first{:colspan => 2} Username %th   %th.last   - even = false - @users.sort.each do |user, user_url| %tr{:class => even ? "even": "odd" } %td{:colspan => 2}= link_to user, url(:users_show, :user_id => user) %td = link_to('Edit', url(:users_edit, :user_id => user)) | = link_to('Delete', url(:users_delete, :user_id => user), :method => "delete", :confirm => "Really delete User #{user}? There is no undo.") ./app/views/users/login.html.haml0000644000175000017500000000145011773315157016525 0ustar tfheentfheen- throw_content(:sidebar_block_notice) do %h4 Where do I get a Login? %p Any existing Admin level user can create new users. %p To create the first user, please login with the default admin credential, which by default is: %p username: admin, password: p@ssw0rd1 (May be different if you've set it in Chef::Config) %b Please change the default password immediately after logging in! %p Once you have an User, you can associate an OpenID with the User and login using the OpenID as the User. %p Administrators can associate OpenID to any User. .block#block-forms .content %h2.title Login .inner = partial('form', :header => "Login", :form_id => 'login', :submit_name => "login", :submit_id => "login_button", :form_for => 'login', :form_url => url(:users_login_exec) ) ./app/views/users/edit.html.haml0000644000175000017500000000053411773315157016344 0ustar tfheentfheen.block#block-tables .content %h2.title= "Edit user: #{h @user.name}" .inner = partial('navigation', :active => 'edit') = partial('form', :header => "Edit User #{@user.name}", :form_id => 'edit_user', :submit_name => "Save User", :submit_id => "edit_user_button", :form_for => 'edit', :form_url => url(:users_update, @user.name) ) ./app/views/users/show.html.haml0000644000175000017500000000052211773315157016374 0ustar tfheentfheen.block#block-tables .content %h2.title= "User: #{h @user.name}" .inner = partial("navigation", :active => "show") .content .inner .left %h3 Admin = @user.admin .left %h3 OpenID = @user.openid || "No OpenID associated to this user account." ./app/views/users/start.html.haml0000644000175000017500000000015311773315157016551 0ustar tfheentfheen<%= @form_text %> ./app/views/users/_navigation.html.haml0000644000175000017500000000137411773315157017720 0ustar tfheentfheen.secondary-navigation %ul - if is_admin? %li{ :class => "first #{active == 'index' ? "active" : ''}"}= link_to('List', url(:users)) - if is_admin? %li{ :class => (active == 'create' ? "active" : '')}= link_to('Create', url(:users_new)) - if active != 'create' && active != 'index' %li{ :class => (active == 'show' ? "active" : '')}= link_to('Show', url(:users_show)) - if @user.admin || @user.name == params[:user_id] %li{ :class => (active == 'edit' ? "active" : '')}= link_to('Edit', url(:users_edit, :user_id => params[:user_id])) %li= link_to('Delete', url(:users_delete, :user_id => params[:user_id]), :method => "delete", :confirm => "Really delete user #{params[:user_id]}? There is no undo.") .clear ./app/views/users/_form.html.haml0000644000175000017500000000373211773315157016524 0ustar tfheentfheen.content .inner = form(:action => form_url, :method => :post, :id => form_id, :class => 'form') do -if form_for == "login" %div.group .text_field= text_field :id => "user_name", :name => "name", :label => "Username: ", :value => params.has_key?(:name) ? h(params[:name]) : @user.name %br/ %div.group .text_field= password_field :id=> "password", :name => "password", :label=>"Password: ", :class => "password_field" %br/ =link_to("Or, log in with OpenID if you have one associated with an existing user account.", url(:openid_consumer)) %br/ - if form_for == "edit" %div.group.form %label.label New Password = password_field :id=>"user_new_password", :name => "new_password", :class =>"password_field" %span.description New password for the User. Keep blank if you do not want to change password. %div.group.form %label.label Confirm New Password = password_field :id=>"user_confirm_new_password", :name => "confirm_new_password", :class =>"password_field" %span.description Confirm new password for the User. Keep blank if you do not want to change password. - if is_admin? && !is_last_admin? %div.group.form %label.label Admin %input{ :type => "hidden", :name => "admin", :value => 0 } %input{ :type => "checkbox", :name => "admin", :value => 1, :checked => @user.admin } %span.description Whether or not the User is an admin. %div.group.form %label.label OpenID Association = text_field :id => "openid", :name => "openid", :class => "text_field", :value => @user.openid %span.description Associate an OpenID with the user account, leave blank if you do not want to associate one. %div.group .actions-bar .actions= submit submit_name, :id => submit_id, :class => 'button' ./app/views/users/new.html.haml0000644000175000017500000000144111773315157016206 0ustar tfheentfheen.block#block-forms .content %h2.title Create New User .inner = partial('navigation', :active => 'create') .content .inner %form.form{ :method => "get", "accept-charset" => "UTF-8", :action => url(:users_create) } %table.table %tr %td= "Username" %td= text_field :name %tr %td= "Password" %td= password_field :password %tr %td= "Confirm Password" %td= password_field :password2 %tr %td= "Admin" %td= check_box :name => "admin", :value => "1" %tr %td= "OpenID (optional)" %td= text_field :openid .group.navform .button= submit "Create" ./app/views/search_entries/0000755000175000017500000000000011773315157015444 5ustar tfheentfheen./app/views/search_entries/index.html.haml0000644000175000017500000000037511773315157020366 0ustar tfheentfheen- @entries.each do |result| .search_result %h3= "#{h result[:index_name]} (#{h result[:id]})" %table - result.each do |k, v| %tr.attr_group %td.attr_name= k %td.attr_value= v.kind_of?(Array) ? v.join(",") : v ./app/views/search_entries/show.html.haml0000644000175000017500000000032311773315157020230 0ustar tfheentfheen.search_result %h3= "#{h @entry[:index_name]} (#{h @entry[:id]})" %table - @entry.each do |k, v| %tr.attr_group %td.attr_name= k %td.attr_value= v.kind_of?(Array) ? v.join(",") : v ./app/views/cookbooks/0000755000175000017500000000000011773315157014437 5ustar tfheentfheen./app/views/cookbooks/_cookbook_content.html.haml0000644000175000017500000000043611773315157021747 0ustar tfheentfheen- unless @manifest[cookbook_part].empty? %h4.head= link_to(cookbook_part, "JavaScript:void(0);") .files - @manifest[cookbook_part].each do |f| .head= link_to(File.basename(f["name"]), "JavaScript:void(0);") .code %pre.ruby= highlight_content(f["url"], type) ./app/views/cookbooks/index.html.haml0000644000175000017500000000165511773315157017363 0ustar tfheentfheen.block#block-tables .content %h2.title Cookbooks .inner %table.table#cookbook_version_table %thead %tr %th Cookbook %th Latest Version %th Other Versions %tbody.cookbook_versions - @cl.keys.sort.each do |cookbook| - versions = @cl[cookbook] %tr %td= cookbook %td %ul.cookbook_versions{ :id => "#{cookbook}_versions" } - versions[0..4].each_with_index do |v, i| - klass = i > 0 ? "other_version" : "latest_version" %li{ :class => klass } = link_to(v["version"], v["url"]) - if versions.length > 5 = all_versions_link(cookbook) %td.show_more = versions.length > 1 ? more_versions_link(cookbook) : "" = js_include_tag "cookbook_versions" ./app/views/cookbooks/show.html.haml0000644000175000017500000000076011773315157017230 0ustar tfheentfheen.block#block-text .content %h2 .title = "#{@cookbook_id}" %select{:name => "choice", :onchange => "jump(this)", :size => "1"} - @versions.each do |version| - selected = @version == version %option{:value => cookbook_link(version), :selected => selected } = version .inner .accordion - cookbook_parts.each do |(part, type)| = partial('cookbook_content', :cookbook_part => part, :type => type) ./app/views/nodes/0000755000175000017500000000000011773315157013556 5ustar tfheentfheen./app/views/nodes/index.html.haml0000644000175000017500000000206611773315157016477 0ustar tfheentfheen.block#block-tables .content %h2.title Node List .inner = partial('navigation', :active => 'index') .content .inner %table.table %tr %th.first{:colspan => 2} Name %th   %th.last   - even = false - if @node_list.empty? - if session[:environment] %td{:colspan => 4}= "The environment #{session[:environment]} has no nodes" - else %td{:colspan => 4}= "You have no nodes - try connecting one, or creating or editing a #{link_to('node', url(:nodes))}" - else - @node_list.each do |node| %tr{:class => even ? "even": "odd" } %td{:colspan => 2}= link_to node, url(:node, { :id => node } ) %td = link_to('Edit', url(:edit_node, node)) | = link_to('Delete', url(:node, node), :method => "delete", :confirm => "Really delete Node #{node}? There is no undo.") - even = (not even) ./app/views/nodes/_resource.html.haml0000644000175000017500000000134511773315157017355 0ustar tfheentfheen.resource %h3= "#{h resource.to_s} (#{resource.class})" %table - resource.instance_variables.sort.each do |v| - attr_name = v.gsub(/\@/, "") - unless attr_name == "collection" %tr.attr_group %td.attr_name = "#{h attr_name}" %td.attr_value - value = resource.instance_variable_get(v) - if value.kind_of?(String) = "#{h value}" - elsif value.kind_of?(Array) = "#{h value.join(", ")}" - elsif value.kind_of?(Symbol) = "#{h value.to_s}" - elsif attr_name == "actions" = partial(:action, :actions => value) - else = "#{h value.inspect}" ./app/views/nodes/edit.html.haml0000644000175000017500000000051711773315157016314 0ustar tfheentfheen.block#block-tables .content %h2.title= "Node #{h @node.name}" .inner = partial('navigation', :active => 'edit') = partial('form', :header => "Edit Node #{@node.name}", :form_id => 'edit_node', :submit_name => "Save Node", :submit_id => "edit_node_button", :form_for => 'edit', :form_url => url(:node, @node.name) ) ./app/views/nodes/_form.html.erb0000644000175000017500000000615611773315157016325 0ustar tfheentfheen
<%= form(:action => form_url, :method => :post, :id => form_id, :class => 'form') do -%> <% unless form_for == 'edit' %>
<%= text_field :id => "node_name", :name => "name", :class => "text_field", :value => params.has_key?(:name) ? h(params[:name]) : @node.name %> The name of the Node
<% end %>
<%= select :chef_environment, :collection => @environments, :id => 'nodeEnvironment', :selected => @env %>
The node's environment
Available Roles
    <% @available_roles.each do |role| %>
  • <%= h(role) -%>
  • <% end %>
Available Recipes
    <% @available_recipes.each do |recipe| %>
  • <%= h(recipe) -%>
  • <% end %>
Run List
    <% @run_list.each do |entry| %>
  • <%=h(entry.name) -%>
  • <% end %>
<%= partial 'layout/jsonedit', :json => @node.normal_attrs.to_json %> A JSON hash for default attributes for nodes of this node. These attributes will only be applied if the node does not already have a value for the attributes.
<%= submit(submit_name, :id => submit_id, :class => 'button') -%>
<% end =%>
./app/views/nodes/show.html.haml0000644000175000017500000000421711773315157016350 0ustar tfheentfheen.block#block-tables .content %h2.title= "Node #{h @node.name}" .inner = partial('navigation', :active => 'show') .content .inner .left %h3 Environment: #{@node.chef_environment} %h3 Run List %table.table %thead %tr %th.first Position %th Name %th Version %th.last Type %tbody - if @node.run_list.empty? %tr %td{:colspan => 2} This node has no roles or recipes applied. - else -@node.run_list.each_with_index do |run_list_item, i| %tr %td.position= i %td= run_list_item.name %td= run_list_item.version %td= run_list_item.type .left.accordion %h3.head= link_to("Recipes", "#") - recipes = @node.run_list.expand(@node.chef_environment, 'server').recipes %div %span.description.form.help This is the list of recipes, fully expanded, as they will be applied to the node in question. %table#recipes.table %tr %th.first Position %th.last Name - if recipes.empty? %tr %td{:colspan => 2} This node has no recipes applied. - else - recipes.each_with_index do |recipe, i| %tr %td.position= i %td= recipe .left %h3 Tags %table#recipes.table %tr %th.first Tags %th.last   %tr - if (@node.attribute?(:tags) == false) || @node[:tags].empty? %td{:colspan => 2} This node has no tags applied. - else %td{:colspan => 2}= @node[:tags].join(", ") .left %h3 Attributes = build_tree('attrs', @node) ./app/views/nodes/_navigation.html.haml0000644000175000017500000000114711773315157017665 0ustar tfheentfheen.secondary-navigation %ul %li{ :class => "first #{active == 'index' ? "active" : ''}"}= link_to('List', url(:nodes)) %li{ :class => (active == 'create' ? "active" : '')}= link_to('Create', url(:new_node)) - if active != 'create' && active != 'index' %li{ :class => (active == 'show' ? "active" : '')}= link_to('Show', url(:node, @node.name)) %li{ :class => (active == 'edit' ? "active" : '')}= link_to('Edit', url(:edit_node, @node.name)) %li= link_to('Delete', url(:node, @node.name), :method => "delete", :confirm => "Really delete node #{@node.name}? There is no undo.") .clear ./app/views/nodes/_action.html.haml0000644000175000017500000000064511773315157017005 0ustar tfheentfheen%table - actions.each do |action, resource_hash| %tr %td.action_name= action.to_s %td.action_resources %table - resource_hash.keys.sort{ |a,b| a.to_s <=> b.to_s }.each do |rk| %tr %td.action_when= rk.to_s %td - resource_hash[rk].each do |resource| = partial(:resource, :resource => resource) ./app/views/nodes/new.html.haml0000644000175000017500000000046411773315157016161 0ustar tfheentfheen.block#block-tables .content %h2.title= "Node" .inner = partial('navigation', :active => 'create') = partial('form', :header => "Create new Node", :form_id => 'create_node', :submit_name => "Create Node", :submit_id => "create_node_button", :form_for => 'create', :form_url => url(:nodes)) ./app/views/clients/0000755000175000017500000000000011773315157014107 5ustar tfheentfheen./app/views/clients/index.html.haml0000644000175000017500000000134111773315157017023 0ustar tfheentfheen.block#block-tables .content %h2.title Clients .inner = partial('navigation', :active => 'index') .content .inner %table.table %tr %th.first{:colspan => 2} Name %th   %th.last   - even = false; - @clients_list.each do |client| %tr{ :class => even ? "even" : "odd" } %td{:colspan => 2}= link_to(client, url(:client, client)) %td = link_to('Edit', url(:edit_client, client)) | = link_to('Delete', url(:client, client), :method => "delete", :confirm => "Really delete Client #{client}? there is no undo.") - even = (not even) ./app/views/clients/edit.html.haml0000644000175000017500000000054111773315157016642 0ustar tfheentfheen.block#block-tables .content %h2.title= "Client: #{h @client.name}" .inner = partial('navigation', :active => 'edit') = partial('form', :header => "Edit Client #{@client.name}", :form_id => 'edit_client', :submit_name => "Save Client", :submit_id => "edit_client_button", :form_for => 'edit', :form_url => url(:client, @client.name) ) ./app/views/clients/show.html.haml0000644000175000017500000000114611773315157016677 0ustar tfheentfheen.block#block-tables .content %h2.title= "Client: #{h @client.name}" .inner = partial("navigation", :active => "show") .content .inner .left %h3 Admin = @client.admin .left %h3 Public Key %pre= convert_newline_to_br(@client.public_key) -unless @private_key.nil? .left %h3 Private Key (Will not show again, Please copy!) %h4.bold Please copy and save as the client's validation key (e.g. client.pem) %pre= convert_newline_to_br(@private_key) ./app/views/clients/_navigation.html.haml0000644000175000017500000000117311773315157020215 0ustar tfheentfheen.secondary-navigation %ul %li{ :class => "first #{active == 'index' ? "active" : ''}"}= link_to('List', url(:clients)) %li{ :class => (active == 'create' ? "active" : '')}= link_to('Create', url(:new_client)) - if active != 'create' && active != 'index' %li{ :class => (active == 'show' ? "active" : '')}= link_to('Show', url(:client, @client.name)) %li{ :class => (active == 'edit' ? "active" : '')}= link_to('Edit', url(:edit_client, @client.name)) %li= link_to('Delete', url(:client, @client.name), :method => "delete", :confirm => "Really delete Client #{@client.name}? There is no undo.") .clear ./app/views/clients/_form.html.haml0000644000175000017500000000165611773315157017027 0ustar tfheentfheen.content .inner - if form_for != "edit" %div.group.form %label.label Name = text_field :id => "client_name", :name => "name", :class => "text_field", :value => params.has_key?(:name) ? h(params[:name]) : @client.name %span.description The name of the Client - if form_for == "edit" %div.group.form %label.label Private Key = check_box :name => "regen_private_key", :label => "Regenerate Private Key (Existing one will no longer work!)", :value => "1" %br/ %div.group.form %label.label Admin = check_box :id => "client_admin", :name => "admin", :value => "true", :label => "Whether or not the Client is an admin", :checked => @client.admin = form(:action => form_url, :method => :post, :id => form_id, :class => 'form') do %div.group .actions-bar .actions= submit submit_name, :id => submit_id, :class => 'button' ./app/views/clients/new.html.haml0000644000175000017500000000050011773315157016501 0ustar tfheentfheen.block#block-tables .content %h2.title= "Client" .inner = partial('navigation', :active => 'create') = partial('form', :header => "Create new Client", :form_id => 'create_client', :submit_name => "Create Client", :submit_id => "create_client_button", :form_for => 'create', :form_url => url(:clients)) ./app/views/exceptions/0000755000175000017500000000000011773315157014627 5ustar tfheentfheen./app/views/exceptions/bad_request.json.erb0000644000175000017500000000007511773315157020571 0ustar tfheentfheen<%= { :error => params[:exception], :code => 400 }.to_json %>./app/views/exceptions/internal_server_error.html.erb0000644000175000017500000001674611773315157022715 0ustar tfheentfheen <%= @exception_name %>

<%= @exception_name %> <%= @exception.class::STATUS %>

<% if show_details = ::Merb::Config[:exception_details] -%>

<%= @exception.message %>

<% else -%>

Sorry about that...

<% end -%>

Parameters

    <% params[:original_params].each do |param, value| %>
  • <%= param %>: <%= value.inspect %>
  • <% end %> <%= "
  • None
  • " if params[:original_params].empty? %>

Session

    <% params[:original_session].each do |param, value| %>
  • <%= param %>: <%= value.inspect %>
  • <% end %> <%= "
  • None
  • " if params[:original_session].empty? %>

Cookies

    <% params[:original_cookies].each do |param, value| %>
  • <%= param %>: <%= value.inspect %>
  • <% end %> <%= "
  • None
  • " if params[:original_cookies].empty? %>
<% if show_details %> <% @exception.backtrace.each_with_index do |line, index| %> <% end %>
<%= (line.match(/^([^:]+)/)[1] rescue 'unknown').sub(/\/((opt|usr)\/local\/lib\/(ruby\/)?(gems\/)?(1.8\/)?(gems\/)?|.+\/app\/)/, '') %> <% unless line.match(/\.erb:/) %> in "<%= line.match(/:in `(.+)'$/)[1] rescue '?' %>" <% else %> (ERB Template) <% end %> <%=lineno%> 
<% (__caller_lines__(file, lineno, 5) rescue []).each do |llineno, lcode, lcurrent| %> <%= llineno %><%='' if llineno==lineno.to_i %><%= lcode.size > 90 ? CGI.escapeHTML(lcode[0..90])+'......' : CGI.escapeHTML(lcode) %><%='' if llineno==lineno.to_i %> <% end %>
<% end %>
./app/views/exceptions/not_acceptable.html.erb0000644000175000017500000000422211773315157021227 0ustar tfheentfheen

pocket rocket web framework


Exception:

<%= params[:exception] %>

Why am I seeing this page?

Merb couldn't find an appropriate content_type to return, based on what you said was available via provides() and what the client requested.

How to add a mime-type


      Merb.add_mime_type :pdf, :to_pdf, %w[application/pdf], "Content-Encoding" => "gzip"
    

What this means is:

  • Add a mime-type for :pdf
  • Register the method for converting objects to PDF as #to_pdf.
  • Register the incoming mime-type "Accept" header as application/pdf.
  • Specify a new header for PDF types so it will set Content-Encoding to gzip.

You can then do:


      class Foo < Application
        provides :pdf
      end
    

Where can I find help?

If you have any questions or if you can't figure something out, please take a look at our project page, feel free to come chat at irc.freenode.net, channel #merb, or post to merb mailing list on Google Groups.

What if I've found a bug?

If you want to file a bug or make your own contribution to Merb, feel free to register and create a ticket at our project development page on Lighthouse.

How do I edit this page?

You can change what people see when this happens by editing app/views/exceptions/not_acceptable.html.erb.

./app/views/exceptions/admin_access_required.html.haml0000644000175000017500000000024511773315157022747 0ustar tfheentfheen.block#block-messages .content %h2.title Messages .inner .flash %div{:class => "message error"} %p Administrative access required. ./app/views/exceptions/not_found.html.erb0000644000175000017500000000320611773315157020260 0ustar tfheentfheen

pocket rocket web framework


Exception:

<%= params[:exception] %>

Welcome to Merb!

Merb is a light-weight MVC framework written in Ruby. We hope you enjoy it.

Where can I find help?

If you have any questions or if you can't figure something out, please take a look at our project page, feel free to come chat at irc.freenode.net, channel #merb, or post to merb mailing list on Google Groups.

What if I've found a bug?

If you want to file a bug or make your own contribution to Merb, feel free to register and create a ticket at our project development page on Lighthouse.

How do I edit this page?

You're seeing this page because you need to edit the following files:

  • config/router.rb (recommended)
  • app/views/exceptions/not_found.html.erb (recommended)
  • app/views/layout/application.html.erb (change this layout)

./app/views/exceptions/standard_error.html.erb0000644000175000017500000001675011773315157021306 0ustar tfheentfheen <%= @exception_name %>

<%= @exception_name %> <%= @exception.class::STATUS %>

<% if show_details = ::Merb::Config[:exception_details] -%>

<%= @exception.message %>

<% else -%>

Sorry about that...

<% end -%>

Parameters

    <% params[:original_params].each do |param, value| %>
  • <%= param %>: <%= value.inspect %>
  • <% end %> <%= "
  • None
  • " if params[:original_params].empty? %>

Session

    <% params[:original_session].each do |param, value| %>
  • <%= param %>: <%= value.inspect %>
  • <% end %> <%= "
  • None
  • " if params[:original_session].empty? %>

Cookies

    <% params[:original_cookies].each do |param, value| %>
  • <%= param %>: <%= value.inspect %>
  • <% end %> <%= "
  • None
  • " if params[:original_cookies].empty? %>
<% if show_details %> <% @exception.backtrace.each_with_index do |line, index| %> <% end %>
<%= (line.match(/^([^:]+)/)[1] rescue 'unknown').sub(/\/((opt|usr)\/local\/lib\/(ruby\/)?(gems\/)?(1.8\/)?(gems\/)?|.+\/app\/)/, '') %> <% unless line.match(/\.erb:/) %> in "<%= line.match(/:in `(.+)'$/)[1] rescue '?' %>" <% else %> (ERB Template) <% end %> <%=lineno%> 
<% (__caller_lines__(file, lineno, 5) rescue []).each do |llineno, lcode, lcurrent| %> <%= llineno %><%='' if llineno==lineno.to_i %><%= lcode.size > 90 ? CGI.escapeHTML(lcode[0..90])+'......' : CGI.escapeHTML(lcode) %><%='' if llineno==lineno.to_i %> <% end %>
<% end %>
./app/controllers/0000755000175000017500000000000011773315157013657 5ustar tfheentfheen./app/controllers/application.rb0000644000175000017500000002030711773315157016511 0ustar tfheentfheen# # Author:: Adam Jacob () # Author:: Christopher Brown () # Author:: Nuo Yan () # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "chef" / "mixin" / "checksum" require "chef" / "cookbook_loader" class Application < Merb::Controller include Chef::Mixin::Checksum before :load_environments # Check if the user is logged in and if the user still exists def login_required if session[:user] begin load_session_user rescue logout_and_redirect_to_login else return session[:user] end else self.store_location throw(:halt, :access_denied) end end def load_session_user Chef::WebUIUser.load(session[:user]) rescue raise NotFound, "Cannot find User #{session[:user]}, maybe it got deleted by an Administrator." end def cleanup_session [:user,:level, :environment].each { |n| session.delete(n) } end def logout_and_redirect_to_login cleanup_session @user = Chef::WebUIUser.new redirect(url(:users_login), {:message => { :error => $! }, :permanent => true}) end def require_admin raise AdminAccessRequired unless is_admin? end def is_admin? user = Chef::WebUIUser.load(session[:user]) user.admin? end #return true if there is only one admin left, false otherwise def is_last_admin? count = 0 users = Chef::WebUIUser.list users.each do |u, url| user = Chef::WebUIUser.load(u) if user.admin count = count + 1 return false if count == 2 end end true end #whether or not the user should be able to edit a user's admin status def can_edit_admin? return false unless is_admin? && !is_last_admin? true end # Store the URI of the current request in the session. # # We can return to this location by calling #redirect_back_or_default. def store_location session[:return_to] = request.uri end # Redirect to the URI stored by the most recent store_location call or # to the passed default. def redirect_back_or_default(default) loc = session[:return_to] || default session[:return_to] = nil redirect loc end def access_denied case content_type when :html store_location redirect url(:users_login), :message => { :error => "You don't have access to that, please login."} else raise Unauthorized, "You must authenticate first!" end end def load_environments @environments = Chef::Environment.list.keys.sort end # Load a cookbook and return a hash with a list of all the files of a # given segment (attributes, recipes, definitions, libraries) # # === Parameters # cookbook_id:: The cookbook to load # segment:: :attributes, :recipes, :definitions, :libraries # # === Returns # :: A hash consisting of the short name of the file in :name, and the full path # to the file in :file. def load_cookbook_segment(cookbook_id, segment) r = Chef::REST.new(Chef::Config[:chef_server_url]) cookbook = r.get_rest("cookbooks/#{cookbook_id}") raise NotFound unless cookbook files_list = segment_files(segment, cookbook) files = Hash.new files_list.each do |f| files[f['name']] = { :name => f["name"], :file => f["uri"], } end files end def segment_files(segment, cookbook) files_list = nil case segment when :attributes files_list = cookbook["attributes"] when :recipes files_list = cookbook["recipes"] when :definitions files_list = cookbook["definitions"] when :libraries files_list = cookbook["libraries"] else raise ArgumentError, "segment must be one of :attributes, :recipes, :definitions or :libraries" end files_list end def build_tree(name, node) html = "" html << "" count = 0 parent = 0 append_tree(name, html, node, count, parent) html << "
AttributeValue
" html end def append_tree(name, html, node, count, parent) to_do = node #to_do = node.kind_of?(Chef::Node) ? node.attribute : node Chef::Log.debug("I have #{to_do.inspect}") to_do.sort{ |a,b| a[0] <=> b[0] }.each do |key, value| Chef::Log.debug("I am #{key.inspect} #{value.inspect}") to_send = Array.new count += 1 is_parent = false local_html = "" local_html << "" else local_html << "'>" end local_html << "#{key}" case value when Hash is_parent = true local_html << "" p = count to_send << Proc.new { append_tree(name, html, value, count, p) } when Array is_parent = true local_html << "" as_hash = {} value.each_index { |i| as_hash[i] = value[i] } p = count to_send << Proc.new { append_tree(name, html, as_hash, count, p) } else local_html << "
#{value}
" end local_html << "" local_html.sub!(/class='collapsed/, 'class=\'collapsed parent') if is_parent local_html.sub!(/ 5) return "File too large to display" else return IO.read(tempfile.path) end end end def binary?(file) s = (File.read(file, File.stat(file).blksize) || "") s.empty? || ( s.count( "^ -~", "^\r\n" ).fdiv(s.size) > 0.3 || s.index( "\x00" )) end def str_to_bool(str) str =~ /true/ ? true : false end #for showing search result def determine_name(type, object) case type when :node, :role, :client, :environment object.name else params[:id] end end def list_available_recipes_for(environment) Chef::Environment.load_filtered_recipe_list(environment).sort! end def convert_newline_to_br(string) string.to_s.gsub(/\n/, '
') unless string.nil? end def format_exception(exception) require 'pp' pretty_params = StringIO.new PP.pp({:request_params => params}, pretty_params) "#{exception.class.name}: #{exception.message}\n#{pretty_params.string}\n#{exception.backtrace.join("\n")}" end def conflict?(exception) exception.kind_of?(Net::HTTPServerException) && exception.message =~ /409/ end def forbidden?(exception) exception.kind_of?(Net::HTTPServerException) && exception.message =~ /403/ end def not_found?(exception) exception.kind_of?(Net::HTTPServerException) && exception.message =~ /404/ end def bad_request?(exception) exception.kind_of?(Net::HTTPServerException) && exception.message =~ /400/ end end ./app/controllers/openid_consumer.rb0000644000175000017500000001336211773315157017402 0ustar tfheentfheen# # Author:: Adam Jacob () # Author:: Christopher Brown () # Author:: Nuo Yan () # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'pathname' require 'openid' require (Chef::Config[:openid_cstore_couchdb] ? 'openid-store-couchdb' : 'openid/store/filesystem') class OpenidConsumer < Application provides :html def index if request.xhr? render :layout => false else render :layout => 'login' end end def start oid = params[:openid_identifier] begin oidreq = consumer.begin(oid) rescue OpenID::OpenIDError => e raise BadRequest, "Discovery failed for #{oid}: #{e}" end return_to = absolute_url(:openid_consumer_complete) realm = absolute_url(:openid_consumer) if oidreq.send_redirect?(realm, return_to, params[:immediate]) return redirect(oidreq.redirect_url(realm, return_to, params[:immediate])) else @form_text = oidreq.form_markup(realm, return_to, params[:immediate], {'id' => 'openid_form'}) render end end def login if session[:user] redirect(url(:nodes), :message => { :warning => "You've already logged in with user #{session[:user]}" }) else oid = params[:openid_identifier] raise(Unauthorized, "Sorry, #{oid} is not an authorized OpenID.") unless is_authorized_openid_identifier?(oid, Chef::Config[:authorized_openid_identifiers]) raise(Unauthorized, "Sorry, #{oid} is not an authorized OpenID Provider.") unless is_authorized_openid_provider?(oid, Chef::Config[:authorized_openid_providers]) start end end def complete # FIXME - url_for some action is not necessarily the current URL. current_url = absolute_url(:openid_consumer_complete) parameters = params.reject{|k,v| k == "controller" || k == "action"} oidresp = consumer.complete(parameters, current_url) case oidresp.status when OpenID::Consumer::FAILURE raise BadRequest, "Verification failed: #{oidresp.message}" + (oidresp.display_identifier ? " for identifier '#{oidresp.display_identifier}'" : "") when OpenID::Consumer::SUCCESS #session[:openid] = oidresp.identity_url # The "if" condition no longer seems need to/can be reached, so I took it out. [nuo] # # if oidresp.display_identifier =~ /openid\/server\/node\/(.+)$/ # reg_name = $1 # reg = Chef::OpenIDRegistration.load(reg_name) # Chef::Log.error("#{reg_name} is an admin #{reg.admin}") # session[:level] = reg.admin ? :admin : :node # session[:node_name] = $1 #else users = Chef::WebUIUser.list #TODO: This is expensive. Should think of a better way [nuo] # Go through each user object and check if the current OpenID associates with the user users.each do |u, url| user = Chef::WebUIUser.load(u) if user.openid == oidresp.identity_url session[:user] = user.name if user.admin session[:level] = :admin else session[:level] = :user end break end end if session[:user].nil? redirect(url(:openid_consumer), :message => { :error => "No user is associated with this OpenID." }) return "No user is associated with this OpenID." end #end redirect_back_or_default(absolute_url(:nodes)) return "Verification of #{oidresp.display_identifier} succeeded." when OpenID::Consumer::SETUP_NEEDED return "Immediate request failed - Setup Needed" when OpenID::Consumer::CANCEL return "OpenID transaction cancelled." else end redirect absolute_url(:openid_consumer) end def logout cleanup_session redirect url(:top) end private def is_authorized_openid_provider?(openid, authorized_providers) Chef::Log.debug("Checking for valid openid provider: openid: #{openid}, authorized providers: #{authorized_providers}") if authorized_providers and openid if authorized_providers.length > 0 authorized_providers.detect { |p| Chef::Log.debug("Openid: #{openid} (#{openid.class}), p: #{p} (#{p.class})"); openid.match(p) } else true end else true end end def is_authorized_openid_identifier?(openid, authorized_identifiers) Chef::Log.debug("Checking for valid openid identifier: openid: #{openid}, authorized openids: #{authorized_identifiers}") if authorized_identifiers and openid if authorized_identifiers.length > 0 authorized_identifiers.detect { |p| Chef::Log.debug("Openid: #{openid} (#{openid.class}), p: #{p} (#{p.class})"); openid == p } else true end else true end end def consumer @consumer ||= OpenID::Consumer.new(session, if Chef::Config[:openid_cstore_couchdb] OpenID::Store::CouchDB.new(Chef::Config[:couchdb_url]) else OpenID::Store::Filesystem.new(Chef::Config[:openid_cstore_path]) end) end end ./app/controllers/search_entries.rb0000644000175000017500000000321611773315157017204 0ustar tfheentfheen# # Author:: Adam Jacob () # Author:: Christopher Brown () # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # #require 'chef' / 'search' #require 'chef' / 'queue' class SearchEntries < Application provides :html before :login_required def index @s = Chef::Search.new @entries = @s.search(params[:search_id]) render end def show @s = Chef::Search.new @entry = @s.search(params[:search_id], "id:'#{params[:search_id]}_#{params[:id]}'").first render end def create @to_index = params @to_index.delete(:controller) @to_index["index_name"] = params[:search_id] @to_index["id"] = "#{params[:search_id]}_#{params[:id]}" @to_index.delete(:search_id) Chef::Queue.send_msg(:queue, :index, @to_index) redirect url(:search) end def update create end def destroy @s = Chef::Search.new @entries = @s.search(params[:id]) @entries.each do |entry| Chef::Queue.send_msg(:queue, :remove, entry) end @status = 202 redirect url(:search) end end ./app/controllers/search.rb0000644000175000017500000000371611773315157015460 0ustar tfheentfheen# # Author:: Nuo Yan () # Copyright:: Copyright (c) 2009 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef' / 'search' / 'query' class Search < Application provides :html before :login_required def index @s = Chef::Search::Query.new @search_indexes = begin @s.list_indexes rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = {:error => "Could not list search indexes"} {} end render end def show begin @s = Chef::Search::Query.new query = (params[:q].nil? || params[:q].empty?) ? "*:*" : URI.escape(params[:q], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")) @results = @s.search(params[:id], query) @type = if params[:id].to_s == "node" || params[:id].to_s == "role" || params[:id].to_s == "client" || params[:id].to_s == "environment" params[:id] else "databag" end @results = @results - @results.last(2) @results.each do |result| result.delete(nil) end @results render rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = { :error => "Unable to find the #{params[:id]}. (#{$!})" } @search_indexes = @s.list_indexes render :index end end end ./app/controllers/users.rb0000644000175000017500000001405511773315157015352 0ustar tfheentfheen# # Author:: Nuo Yan () # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef'/'webui_user' require 'uri' require 'merb-param-protection' class Users < Application provides :html before :login_required, :exclude => [:login, :login_exec, :complete] before :require_admin, :exclude => [:login, :login_exec, :complete, :show, :edit, :logout, :destroy] log_params_filtered :password, :password2, :new_password, :confirm_new_password # List users, only if the user is admin. def index begin @users = Chef::WebUIUser.list render rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") set_user_and_redirect end end # Edit user. Admin can edit everyone, non-admin user can only edit itself. def edit begin @user = Chef::WebUIUser.load(params[:user_id]) render rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") set_user_and_redirect end end # Show the details of a user. If the user is not admin, only able to show itself; otherwise able to show everyone def show begin @user = Chef::WebUIUser.load(params[:user_id]) render rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") set_user_and_redirect end end # PUT to /users/:user_id/update def update begin @user = Chef::WebUIUser.load(params[:user_id]) if session[:level] == :admin and !is_last_admin? @user.admin = params[:admin] =~ /1/ ? true : false end if params[:user_id] == session[:user] && params[:admin] == 'false' session[:level] = :user end if not params[:new_password].nil? and not params[:new_password].length == 0 @user.set_password(params[:new_password], params[:confirm_new_password]) end if params[:openid].length == 0 or params[:openid].nil? @user.set_openid(nil) else @user.set_openid(URI.parse(params[:openid]).normalize.to_s) end @user.save @_message = { :notice => "Updated user #{@user.name}." } render :show rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @u = Chef::WebUIUser.load(params[:user_id]) @_message = { :error => "Could not update user #{@user.name}." } render :edit end end def new begin @user = Chef::WebUIUser.new render rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") set_user_and_redirect end end def create begin @user = Chef::WebUIUser.new @user.name = params[:name] @user.set_password(params[:password], params[:password2]) @user.admin = true if params[:admin] (params[:openid].length == 0 || params[:openid].nil?) ? @user.set_openid(nil) : @user.set_openid(URI.parse(params[:openid]).normalize.to_s) @user.create redirect(url(:users), :message => { :notice => "Created User #{params[:name]}" }) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = { :error => "Could not create user" } session[:level] != :admin ? set_user_and_redirect : (render :new) end end def login @user = Chef::WebUIUser.new session[:user] ? redirect(url(:nodes), :message => { :warning => "You've already logged in with user #{session[:user]}" }) : (render :layout => 'login') end def login_exec begin @user = Chef::WebUIUser.load(params[:name]) raise(Unauthorized, "Wrong username or password.") unless @user.verify_password(params[:password]) complete rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @user = Chef::WebUIUser.new @_message = { :error => "Could not complete logging in." } render :login end end def complete session[:user] = params[:name] session[:level] = (@user.admin == true ? :admin : :user) (@user.name == Chef::Config[:web_ui_admin_user_name] && @user.verify_password(Chef::Config[:web_ui_admin_default_password])) ? redirect(url(:users_edit, :user_id => @user.name), :message => { :warning => "Please change the default password" }) : redirect_back_or_default(absolute_url(:nodes)) end def logout cleanup_session redirect url(:top) end def destroy begin raise Forbidden, "A non-admin user can only delete itself" if (params[:user_id] != session[:user] && session[:level] != :admin) raise Forbidden, "The last admin user cannot be deleted" if (is_admin? && is_last_admin? && session[:user] == params[:user_id]) @user = Chef::WebUIUser.load(params[:user_id]) @user.destroy logout if params[:user_id] == session[:user] redirect(absolute_url(:users), {:message => { :notice => "User #{params[:user_id]} deleted successfully." }, :permanent => true}) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") session[:level] != :admin ? set_user_and_redirect : redirect_to_list_users({ :error => $! }) end end private def set_user_and_redirect begin @user = Chef::WebUIUser.load(session[:user]) rescue (raise NotFound, "Cannot find User #{session[:user]}, maybe it got deleted by an Administrator.") rescue logout_and_redirect_to_login else redirect(url(:users_show, :user_id => session[:user]), {:message => { :error => $! }, :permanent => true}) end end def redirect_to_list_users(message) @_message = message @users = Chef::WebUIUser.list render :index end end ./app/controllers/exceptions.rb0000644000175000017500000000160611773315157016370 0ustar tfheentfheen# # Author:: Adam Jacob () # Author:: Christopher Brown () # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # class AdminAccessRequired < Merb::ControllerExceptions::Forbidden; end class Exceptions < Merb::Controller def admin_access_required render :layout => nil end end ./app/controllers/databags.rb0000644000175000017500000000471011773315157015754 0ustar tfheentfheen# # Author:: Nuo Yan () # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef' / 'data_bag' class Databags < Application provides :html, :json before :login_required before :require_admin def new @databag = Chef::DataBag.new render end def create begin @databag = Chef::DataBag.new @databag.name params[:name] @databag.create redirect(url(:databags), :message => { :notice => "Created Databag #{@databag.name}" }) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = { :error => "Could not create databag" } render :new end end def index @databags = begin Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("data") rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = { :error => "Could not list databags" } {} end render end def show begin @databag_name = params[:id] r = Chef::REST.new(Chef::Config[:chef_server_url]) @databag = r.get_rest("data/#{params[:id]}") raise NotFound unless @databag display @databag rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @databags = Chef::DataBag.list @_message = { :error => "Could not load databag"} render :index end end def destroy begin r = Chef::REST.new(Chef::Config[:chef_server_url]) r.delete_rest("data/#{params[:id]}") redirect(absolute_url(:databags), {:message => { :notice => "Data bag #{params[:id]} deleted successfully" }, :permanent => true}) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @databags = Chef::DataBag.list @_message = { :error => "Could not delete databag"} render :index end end end ./app/controllers/databag_items.rb0000644000175000017500000000704311773315157016774 0ustar tfheentfheen# # Author:: Nuo Yan () # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef' / 'data_bag_item' class DatabagItems < Application provides :html, :json before :login_required def edit begin @databag_item = Chef::DataBagItem.load(params[:databag_id], params[:id]) @default_data = @databag_item.raw_data rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = { :error => "Could not load the databag item" } end render end def update begin @databag_item = Chef::DataBagItem.new @databag_item.data_bag params[:databag_id] @databag_item.raw_data = Chef::JSONCompat.from_json(params[:json_data]) raise ArgumentError, "Updating id is not allowed" unless @databag_item.raw_data['id'] == params[:id] #to be consistent with other objects, changing id is not allowed. @databag_item.save redirect(url(:databag_databag_items, :databag_id => params[:databag_id], :id => @databag_item.name), :message => { :notice => "Updated Databag Item #{@databag_item.name}" }) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = { :error => "Could not update the databag item" } @databag_item = Chef::DataBagItem.load(params[:databag_id], params[:id]) @default_data = @databag_item render :edit end end def new @default_data = {'id'=>''} render end def create begin @databag_name = params[:databag_id] @databag_item = Chef::DataBagItem.new @databag_item.data_bag @databag_name @databag_item.raw_data = Chef::JSONCompat.from_json(params[:json_data]) @databag_item.create redirect(url(:databag_databag_items, :databag_id => @databag_name), :message => { :notice => "Databag item created successfully" }) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = { :error => "Could not create databag item" } render :new end end def index render end def show begin @databag_name = params[:databag_id] @databag_item_name = params[:id] r = Chef::REST.new(Chef::Config[:chef_server_url]) @databag_item = r.get_rest("data/#{params[:databag_id]}/#{params[:id]}") display @databag_item rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") redirect(url(:databag_databag_items), {:message => { :error => "Could not show the databag item" }, :permanent => true}) end end def destroy(databag_id=params[:databag_id], item_id=params[:id]) begin @databag_item = Chef::DataBagItem.new @databag_item.destroy(databag_id, item_id) redirect(url(:databag_databag_items), {:message => { :notice => "Databag item deleted successfully" }, :permanent => true}) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") redirect(url(:databag_databag_items), {:message => { :error => "Could not delete databag item" }, :permanent => true}) end end end ./app/controllers/nodes.rb0000644000175000017500000001146411773315157015322 0ustar tfheentfheen# # Author:: Adam Jacob () # Author:: Christopher Brown () # Author:: Nuo Yan () # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef/node' class Nodes < Application provides :html before :login_required before :require_admin, :only => [:destroy] def index begin if session[:environment] node_hash = Chef::Node.list_by_environment(session[:environment]) else node_hash = Chef::Node.list end @node_list = node_hash.keys.sort rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = {:error => "Could not list nodes"} @node_hash = {} end render end def show begin @node =Chef::Node.load(params[:id]) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = {:error => "Could not load node #{params[:id]}"} @node = Chef::Node.new end render end def new begin @node = Chef::Node.new @node.chef_environment(session[:environment] || "_default") @available_recipes = list_available_recipes_for(@node.chef_environment) @available_roles = Chef::Role.list.keys.sort @run_list = @node.run_list @env = session[:environment] render rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @node_list = Chef::Node.list() @_message = {:error => "Could not load available recipes, roles, or the run list"} render :index end end def edit begin @node = Chef::Node.load(params[:id]) @env = @node.chef_environment @available_recipes = list_available_recipes_for(@node.chef_environment) @available_roles = Chef::Role.list.keys.sort @run_list = @node.run_list render rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @node = Chef::Node.new @available_recipes = [] @available_roles = [] @run_list = [] @_message = {:error => "Could not load node #{params[:id]}"} render end end def create begin @node = Chef::Node.new @node.name params[:name] @node.chef_environment params[:chef_environment] @node.normal_attrs = Chef::JSONCompat.from_json(params[:attributes]) @node.run_list.reset!(params[:for_node] ? params[:for_node] : []) raise ArgumentError, "Node name cannot be blank" if (params[:name].nil? || params[:name].length==0) @node.create redirect(url(:nodes), :message => { :notice => "Created Node #{@node.name}" }) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @node.normal_attrs = Chef::JSONCompat.from_json(params[:attributes]) @available_recipes = list_available_recipes_for(@node.chef_environment) @available_roles = Chef::Role.list.keys.sort @node.run_list params[:for_node] @run_list = @node.run_list @_message = { :error => "Exception raised creating node, #{e.message.length <= 150 ? e.message : "please check logs for details"}" } render :new end end def update begin @node = Chef::Node.load(params[:id]) @node.chef_environment(params[:chef_environment]) @node.run_list.reset!(params[:for_node] ? params[:for_node] : []) @node.normal_attrs = Chef::JSONCompat.from_json(params[:attributes]) @node.save @_message = { :notice => "Updated Node" } render :show rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @available_recipes = list_available_recipes_for(@node.chef_environment) @available_roles = Chef::Role.list.keys.sort @run_list = Chef::RunList.new @run_list.reset!(params[:for_node]) @_message = { :error => "Exception raised updating node, #{e.message.length <= 150 ? e.message : "please check logs for details"}" } render :edit end end def destroy begin @node = Chef::Node.load(params[:id]) @node.destroy redirect(absolute_url(:nodes), {:message => { :notice => "Node #{params[:id]} deleted successfully" }, :permanent => true}) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @node_list = Chef::Node.list() @_message = {:error => "Could not delete the node"} render :index end end end ./app/controllers/main.rb0000644000175000017500000000010011773315157015117 0ustar tfheentfheenclass Main < Application def index render end end ./app/controllers/status.rb0000644000175000017500000000232311773315157015527 0ustar tfheentfheen# # Author:: Joe Williams (joe@joetify.com) # Author:: Nuo Yan (nuo@opscode.com) # Copyright:: Copyright (c) 2009 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef' / 'node' class Status < Application provides :html before :login_required def index begin @status = Chef::Node.list(true) if session[:environment] @status = Chef::Node.list_by_environment(session[:environment],true) else @status = Chef::Node.list(true) end render rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @status = {} @_message = {:error => "Could not list status"} render end end end ./app/controllers/environments.rb0000644000175000017500000002030711773315157016735 0ustar tfheentfheen# # Author:: Stephen Delano () # Copyright:: Copyright (c) 2010 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef/environment' class Environments < Application provides :html before :login_required before :require_admin, :only => [:create, :update, :destroy] # GET /environments def index @environment_list = begin Chef::Environment.list rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = "Could not list environments" {} end render end # GET /environments/:id def show load_environment render end # GET /environemnts/new def new @environment = Chef::Environment.new load_cookbooks render :new end # POST /environments def create @environment = Chef::Environment.new if @environment.update_from_params(processed_params=process_params) begin @environment.create redirect(url(:environments), :message => { :notice => "Created Environment #{@environment.name}" }) rescue Net::HTTPServerException => e if conflict?(e) Chef::Log.debug("Got 409 conflict creating environment #{params[:name]}\n#{format_exception(e)}") redirect(url(:new_environment), :message => { :error => "An environment with that name already exists"}) elsif forbidden?(e) # Currently it's not possible to get 403 here. I leave the code here for completeness and may be useful in the future.[nuo] Chef::Log.debug("Got 403 forbidden creating environment #{params[:name]}\n#{format_exception(e)}") redirect(url(:new_environment), :message => { :error => "Permission Denied. You do not have permission to create an environment."}) else Chef::Log.error("Error communicating with the API server\n#{format_exception(e)}") raise end end else load_cookbooks # By rendering :new, the view shows errors from @environment.invalid_fields render :new end end # GET /environments/:id/edit def edit load_environment if @environment.name == "_default" msg = { :warning => "The '_default' environment cannot be edited." } redirect(url(:environments), :message => msg) return end load_cookbooks render end # PUT /environments/:id def update load_environment if @environment.update_from_params(process_params(params[:id])) begin @environment.save redirect(url(:environment, @environment.name), :message => { :notice => "Updated Environment #{@environment.name}" }) rescue Net::HTTPServerException => e if forbidden?(e) # Currently it's not possible to get 403 here. I leave the code here for completeness and may be useful in the future.[nuo] Chef::Log.debug("Got 403 forbidden updating environment #{params[:name]}\n#{format_exception(e)}") redirect(url(:edit_environment), :message => { :error => "Permission Denied. You do not have permission to update an environment."}) else Chef::Log.error("Error communicating with the API server\n#{format_exception(e)}") raise end end else load_cookbooks # By rendering :new, the view shows errors from @environment.invalid_fields render :edit end end # DELETE /environments/:id def destroy begin @environment = Chef::Environment.load(params[:id]) @environment.destroy redirect(absolute_url(:environments), :message => { :notice => "Environment #{@environment.name} deleted successfully." }, :permanent => true) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @environment_list = Chef::Environment.list() @_message = {:error => "Could not delete environment #{params[:id]}: #{e.message}"} render :index end end # GET /environments/:environment_id/cookbooks def list_cookbooks # TODO: rescue loading the environment @environment = Chef::Environment.load(params[:environment_id]) @cookbooks = begin r = Chef::REST.new(Chef::Config[:chef_server_url]) r.get_rest("/environments/#{params[:environment_id]}/cookbooks").inject({}) do |res, (cookbook, url)| # we just want the cookbook name and the version res[cookbook] = url.split('/').last res end rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = "Could not load cookbooks for environment #{params[:environment_id]}" {} end render end # GET /environments/:environment_id/nodes def list_nodes # TODO: rescue loading the environment @environment = Chef::Environment.load(params[:environment_id]) @nodes = begin r = Chef::REST.new(Chef::Config[:chef_server_url]) r.get_rest("/environments/#{params[:environment_id]}/nodes").keys.sort rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = "Could not load nodes for environment #{params[:environment_id]}" [] end render end # GET /environments/:environment/recipes def list_recipes provides :json display(:recipes => list_available_recipes_for(params[:environment_id])) end # GET /environments/:environment_id/set def select_environment name = params[:environment_id] referer = request.referer || "/nodes" if name == '_none' session[:environment] = nil else # TODO: check if environment exists session[:environment] = name end redirect referer end private def load_environment @environment = begin Chef::Environment.load(params[:id]) rescue Net::HTTPServerException => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = "Could not load environment #{params[:id]}" @environment = Chef::Environment.new false end end def load_cookbooks begin # @cookbooks is a hash, keys are cookbook names, values are their URIs. @cookbooks = Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("cookbooks").keys.sort rescue Net::HTTPServerException => e Chef::Log.error(format_exception(e)) redirect(url(:new_environment), :message => { :error => "Could not load the list of available cookbooks."}) end end def process_params(name=params[:name]) {:name => name, :description => params[:description], :default_attributes => params[:default_attributes], :override_attributes => params[:override_attributes], :cookbook_version => search_params_for_cookbook_version_constraints} end def search_params_for_cookbook_version_constraints cookbook_version_constraints = {} index = 0 params.each do |k,v| cookbook_name_box_id = k[/cookbook_name_(\d+)/, 1] unless cookbook_name_box_id.nil? || v.nil? || v.empty? cookbook_version_constraints[index] = v + " " + params["operator_#{cookbook_name_box_id}"] + " " + params["cookbook_version_#{cookbook_name_box_id}"].strip # e.g. {"0" => "foo > 0.3.0"} index = index + 1 end end Chef::Log.debug("cookbook version constraints are: #{cookbook_version_constraints.inspect}") cookbook_version_constraints end def cookbook_version_constraints @environment.cookbook_versions.inject({}) do |ans, (cb, vc)| op, version = vc.split(" ") ans[cb] = { "version" => version, "op" => op } ans end end def constraint_operators %w(~> >= > = < <=) end end ./app/controllers/cookbooks.rb0000644000175000017500000001326611773315157016205 0ustar tfheentfheen# # Author:: Adam Jacob () # Author:: Christopher Brown () # Author:: Nuo Yan () # Author:: Seth Falcon () # Copyright:: Copyright (c) 2008-2011 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef/cookbook_loader' require 'chef/cookbook_version' class Cookbooks < Application provides :html before :login_required before :params_helper attr_reader :cookbook_id def params_helper @cookbook_id = params[:id] || params[:cookbook_id] end def index @cl = fetch_cookbook_versions(6) display @cl end def show begin all_books = fetch_cookbook_versions("all", :cookbook => cookbook_id) @versions = all_books[cookbook_id].map { |v| v["version"] } if params[:cb_version] == "_latest" redirect(url(:show_specific_version_cookbook, :cookbook_id => cookbook_id, :cb_version => @versions.first)) return end @version = params[:cb_version] if !@versions.include?(@version) msg = { :warning => ["Cookbook #{cookbook_id} (#{params[:cb_version]})", "is not available in the #{session[:environment]}", "environment." ].join(" ") } redirect(url(:cookbooks), :message => msg) return end cookbook_url = "cookbooks/#{cookbook_id}/#{@version}" rest = Chef::REST.new(Chef::Config[:chef_server_url]) @cookbook = rest.get_rest(cookbook_url) raise NotFound unless @cookbook @manifest = @cookbook.manifest display @cookbook rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = {:error => $!} @cl = {} render :index end end # GET /cookbooks/cookbook_id # provides :json, for the javascript on the environments web form. def cb_versions provides :json use_envs = session[:environment] && !params[:ignore_environments] num_versions = params[:num_versions] || "all" all_books = fetch_cookbook_versions(num_versions, :cookbook => cookbook_id, :use_envs => use_envs) display({ cookbook_id => all_books[cookbook_id] }) end ## ------ ## Helpers ## ## TODO: move these to a cookbooks helper module ## ------ def recipe_files # node = params.has_key?('node') ? params[:node] : nil # @recipe_files = load_all_files(:recipes, node) r = Chef::REST.new(Chef::Config[:chef_server_url]) @recipe_files = r.get_rest("cookbooks/#{params[:id]}/recipes") display @recipe_files end def attribute_files r = Chef::REST.new(Chef::Config[:chef_server_url]) @recipe_files = r.get_rest("cookbooks/#{params[:id]}/attributes") display @attribute_files end def definition_files r = Chef::REST.new(Chef::Config[:chef_server_url]) @recipe_files = r.get_rest("cookbooks/#{params[:id]}/definitions") display @definition_files end def library_files r = Chef::REST.new(Chef::Config[:chef_server_url]) @recipe_files = r.get_rest("cookbooks/#{params[:id]}/libraries") display @lib_files end def more_versions_link(cookbook) link_to("+", "JavaScript:void(0);", :title => "show other versions of #{cookbook}", :data => cookbook, :class => "cookbook_version_toggle") end def all_versions_link(cookbook) link_to("show all versions...", "JavaScript:void(0);", :class => "show_all", :id => "#{cookbook}_show_all", :data => cookbook, :title => "show all versions of #{cookbook}") end def cookbook_link(version) url(:show_specific_version_cookbook, :cookbook_id => @cookbook_id, :cb_version => version) end def cookbook_parts Chef::CookbookVersion::COOKBOOK_SEGMENTS.map do |p| part = p.to_s case part when "files" [part, "plain"] else [part, "ruby"] end end.sort { |a, b| a[0] <=> b[0] } end def highlight_content(url, type) case type when "plain" show_plain_file(url) else syntax_highlight(url) end end private def fetch_cookbook_versions(num_versions, options={}) opts = { :use_envs => true, :cookbook => nil }.merge(options) url = if opts[:use_envs] env = session[:environment] || "_default" "environments/#{env}/cookbooks" else "cookbooks" end # we want to display at most 5 versions, but we ask for 6. This # tells us if we should display a 'show all' button or not. url += "/#{opts[:cookbook]}" if opts[:cookbook] url += "?num_versions=#{num_versions}" begin result = Chef::REST.new(Chef::Config[:chef_server_url]).get_rest(url) result.inject({}) do |ans, (name, cb)| cb["versions"].each do |v| v["url"] = url(:show_specific_version_cookbook, :cookbook_id => name, :cb_version => v["version"]) end ans[name] = cb["versions"] ans end rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = {:error => $!} {} end end end ./app/controllers/roles.rb0000644000175000017500000001241311773315157015331 0ustar tfheentfheen# # Author:: Adam Jacob () # Author:: Nuo Yan () # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef/role' class Roles < Application provides :html before :login_required before :require_admin, :only => [:destroy] # GET /roles def index @role_list = begin Chef::Role.list() rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = {:error => "Could not list roles"} {} end render end # GET /roles/:id def show @role = begin Chef::Role.load(params[:id]) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = {:error => "Could not load role #{params[:id]}."} Chef::Role.new end @current_env = session[:environment] || "_default" @env_run_list_exists = @role.env_run_lists.has_key?(@current_env) @run_list = @role.run_list_for(@current_env) @recipes = @run_list.expand(@current_env, 'server').recipes render end # GET /roles/new def new begin @role = Chef::Role.new @available_roles = Chef::Role.list.keys.sort @environments = Chef::Environment.list.keys.sort @run_lists = @environments.inject({}) { |run_lists, env| run_lists[env] = @role.env_run_lists[env]; run_lists} @current_env = "_default" @available_recipes = list_available_recipes_for(@current_env) @existing_run_list_environments = @role.env_run_lists.keys # merb select helper has no :include_blank => true, so fix the view in the controller. @existing_run_list_environments.unshift('') render rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") redirect url(:roles), :message => {:error => "Could not load available recipes, roles, or the run list."} end end # GET /roles/:id/edit def edit begin @role = Chef::Role.load(params[:id]) @available_roles = Chef::Role.list.keys.sort @environments = Chef::Environment.list.keys.sort @current_env = session[:environment] || "_default" @run_list = @role.run_list @run_lists = @environments.inject({}) { |run_lists, env| run_lists[env] = @role.env_run_lists[env]; run_lists} @existing_run_list_environments = @role.env_run_lists.keys # merb select helper has no :include_blank => true, so fix the view in the controller. @existing_run_list_environments.unshift('') @available_recipes = list_available_recipes_for(@current_env) render rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") redirect url(:roles), :message => {:error => "Could not load role #{params[:id]}. #{e.message}"} end end # POST /roles def create begin @role = Chef::Role.new @role.name(params[:name]) @role.env_run_lists(params[:env_run_lists]) @role.description(params[:description]) if params[:description] != '' @role.default_attributes(Chef::JSONCompat.from_json(params[:default_attributes])) if params[:default_attributes] != '' @role.override_attributes(Chef::JSONCompat.from_json(params[:override_attributes])) if params[:override_attributes] != '' @role.create redirect(url(:roles), :message => { :notice => "Created Role #{@role.name}" }) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") redirect(url(:new_role), :message => { :error => "Could not create role. #{e.message}" }) end end # PUT /roles/:id def update begin @role = Chef::Role.load(params[:id]) @role.env_run_lists(params[:env_run_lists]) @role.description(params[:description]) if params[:description] != '' @role.default_attributes(Chef::JSONCompat.from_json(params[:default_attributes])) if params[:default_attributes] != '' @role.override_attributes(Chef::JSONCompat.from_json(params[:override_attributes])) if params[:override_attributes] != '' @role.save redirect(url(:role, params[:id]), :message => { :notice => "Updated Role" }) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") redirect url(:edit_role, params[:id]), :message => {:error => "Could not update role #{params[:id]}. #{e.message}"} end end # DELETE /roles/:id def destroy begin @role = Chef::Role.load(params[:id]) @role.destroy redirect(absolute_url(:roles), :message => { :notice => "Role #{@role.name} deleted successfully." }, :permanent => true) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") redirect url(:roles), :message => {:error => "Could not delete role #{params[:id]}"} end end end ./app/controllers/clients.rb0000644000175000017500000000737711773315157015663 0ustar tfheentfheen# # Author:: Nuo Yan () # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef/api_client' class Clients < Application provides :json provides :html before :login_required before :require_admin, :exclude => [:index, :show] # GET /clients def index begin @clients_list = Chef::ApiClient.list().keys.sort rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = {:error => "Could not list clients"} @clients_list = [] end render end # GET /clients/:id def show @client = begin @client = Chef::ApiClient.load(params[:id]) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = { :error => "Could not load client #{params[:id]}"} Chef::ApiClient.new end render end # GET /clients/:id/edit def edit @client = begin Chef::ApiClient.load(params[:id]) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = { :error => "Could not load client #{params[:id]}"} Chef::ApiClient.new end render end # GET /clients/new def new raise AdminAccessRequired unless params[:user_id] == session[:user] unless session[:level] == :admin @client = Chef::ApiClient.new render end # POST /clients def create begin @client = Chef::ApiClient.new @client.name(params[:name]) @client.admin(str_to_bool(params[:admin])) if params[:admin] response = @client.create @private_key = OpenSSL::PKey::RSA.new(response["private_key"]) @_message = { :notice => "Created Client #{@client.name}. Please copy the following private key as the client's validation key." } @client = Chef::ApiClient.load(params[:name]) render :show rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = { :error => "Could not create client" } render :new end end # PUT /clients/:id def update begin @client = Chef::ApiClient.load(params[:id]) if params[:regen_private_key] @client.create_keys @private_key = @client.private_key end params[:admin] ? @client.admin(true) : @client.admin(false) @client.save @_message = @private_key.nil? ? { :notice => "Updated Client" } : { :notice => "Created Client #{@client.name}. Please copy the following private key as the client's validation key." } render :show rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = { :error => "Could not update client" } render :edit end end # DELETE /clients/:id def destroy begin @client = Chef::ApiClient.load(params[:id]) @client.destroy redirect(absolute_url(:clients), {:message => { :notice => "Client #{params[:id]} deleted successfully" }, :permanent => true}) rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = {:error => "Could not delete client #{params[:id]}" } @clients_list = Chef::ApiClient.list() render :index end end end ./app/helpers/0000755000175000017500000000000011773315157012753 5ustar tfheentfheen./app/helpers/application_helper.rb0000644000175000017500000000206311773315157017143 0ustar tfheentfheenrequire 'chef/mixin/deep_merge' require 'chef-server-webui/version' module Merb module ApplicationHelper ROLE_STR = "role" RECIPE_STR = "recipe" def chef_version ::ChefServerWebui::VERSION end def class_for_run_list_item(item) case item.type.to_s when ROLE_STR 'ui-state-highlight' when RECIPE_STR 'ui-state-default' else raise ArgumentError, "Cannot generate UI class for #{item.inspect}" end end def display_run_list_item(item) case item.type.to_s when ROLE_STR item.name when RECIPE_STR # webui not sophisticated enough for versioned recipes # "#{item.name}@#{item.version}" item.name else raise ArgumentError, "can't generate display string for #{item.inspect}" end end def nav_link_item(title, dest) name = title.gsub(/ /, "").downcase klass = controller_name == name ? 'class="active"' : "" link = link_to(title, url(dest)) "
  • #{link}
  • " end end end ./app/helpers/status_helper.rb0000644000175000017500000000204111773315157016157 0ustar tfheentfheen# # Author:: Joe Williams (joe@joetify.com) # Copyright:: Copyright (c) 2009 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef' / 'node' module Merb module StatusHelper def time_difference_in_hms(unix_time) now = Time.now.to_i difference = now - unix_time.to_i hours = (difference / 3600).to_i difference = difference % 3600 minutes = (difference / 60).to_i seconds = (difference % 60) return [hours, minutes, seconds] end end end ./metadata.yml0000644000175000017500000003001311773315157013031 0ustar tfheentfheen--- !ruby/object:Gem::Specification name: chef-server-webui version: !ruby/object:Gem::Version hash: 127 prerelease: segments: - 10 - 12 - 0 version: 10.12.0 platform: ruby authors: - Opscode autorequire: bindir: bin cert_chain: [] date: 2012-06-18 00:00:00 Z dependencies: - !ruby/object:Gem::Dependency requirement: &id001 !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version hash: 19 segments: - 1 - 1 - 0 version: 1.1.0 version_requirements: *id001 name: merb-core prerelease: false type: :runtime - !ruby/object:Gem::Dependency requirement: &id002 !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version hash: 19 segments: - 1 - 1 - 0 version: 1.1.0 version_requirements: *id002 name: merb-assets prerelease: false type: :runtime - !ruby/object:Gem::Dependency requirement: &id003 !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version hash: 19 segments: - 1 - 1 - 0 version: 1.1.0 version_requirements: *id003 name: merb-helpers prerelease: false type: :runtime - !ruby/object:Gem::Dependency requirement: &id004 !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version hash: 19 segments: - 1 - 1 - 0 version: 1.1.0 version_requirements: *id004 name: merb-haml prerelease: false type: :runtime - !ruby/object:Gem::Dependency requirement: &id005 !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version hash: 19 segments: - 1 - 1 - 0 version: 1.1.0 version_requirements: *id005 name: merb-param-protection prerelease: false type: :runtime - !ruby/object:Gem::Dependency requirement: &id006 !ruby/object:Gem::Requirement none: false requirements: - - ">=" - !ruby/object:Gem::Version hash: 3 segments: - 0 version: "0" version_requirements: *id006 name: thin prerelease: false type: :runtime - !ruby/object:Gem::Dependency requirement: &id007 !ruby/object:Gem::Requirement none: false requirements: - - ">=" - !ruby/object:Gem::Version hash: 3 segments: - 0 version: "0" version_requirements: *id007 name: haml prerelease: false type: :runtime - !ruby/object:Gem::Dependency requirement: &id008 !ruby/object:Gem::Requirement none: false requirements: - - ">=" - !ruby/object:Gem::Version hash: 3 segments: - 0 version: "0" version_requirements: *id008 name: ruby-openid prerelease: false type: :runtime - !ruby/object:Gem::Dependency requirement: &id009 !ruby/object:Gem::Requirement none: false requirements: - - ">=" - !ruby/object:Gem::Version hash: 3 segments: - 0 version: "0" version_requirements: *id009 name: coderay prerelease: false type: :runtime description: A systems integration framework, built to bring the benefits of configuration management to your entire infrastructure. email: chef@opscode.com executables: - chef-server-webui extensions: [] extra_rdoc_files: - README.rdoc - LICENSE - config.ru files: - LICENSE - README.rdoc - Rakefile - config.ru - bin/chef-server-webui - config/init.rb - config/router.rb - config/rack.rb - config/environments/development.rb - config/environments/production.rb - lib/chef-server-webui/merbtasks.rb - lib/chef-server-webui/slicetasks.rb - lib/chef-server-webui/version.rb - lib/chef-server-webui/spectasks.rb - lib/chef-server-webui.rb - app/views/layout/_jsonedit.html.haml - app/views/layout/login.html.haml - app/views/layout/application.html.haml - app/views/openid_login/index.html.haml - app/views/clients/new.html.haml - app/views/clients/_navigation.html.haml - app/views/clients/show.html.haml - app/views/clients/index.html.haml - app/views/clients/_form.html.haml - app/views/clients/edit.html.haml - app/views/openid_register/show.html.haml - app/views/openid_register/index.html.haml - app/views/status/index.html.haml - app/views/users/new.html.haml - app/views/users/login.html.haml - app/views/users/_navigation.html.haml - app/views/users/start.html.haml - app/views/users/show.html.haml - app/views/users/index.html.haml - app/views/users/_form.html.haml - app/views/users/edit.html.haml - app/views/openid_consumer/start.html.haml - app/views/openid_consumer/index.html.haml - app/views/main/index.html.erb - app/views/cookbooks/show.html.haml - app/views/cookbooks/index.html.haml - app/views/cookbooks/_cookbook_content.html.haml - app/views/nodes/new.html.haml - app/views/nodes/_navigation.html.haml - app/views/nodes/show.html.haml - app/views/nodes/_form.html.erb - app/views/nodes/_resource.html.haml - app/views/nodes/index.html.haml - app/views/nodes/_action.html.haml - app/views/nodes/edit.html.haml - app/views/exceptions/not_acceptable.html.erb - app/views/exceptions/not_found.html.erb - app/views/exceptions/bad_request.json.erb - app/views/exceptions/internal_server_error.html.erb - app/views/exceptions/standard_error.html.erb - app/views/exceptions/admin_access_required.html.haml - app/views/databags/new.html.haml - app/views/databags/_navigation.html.haml - app/views/databags/show.html.haml - app/views/databags/index.html.haml - app/views/databags/_item_navigation.html.haml - app/views/databags/_form.html.haml - app/views/databags/edit.html.haml - app/views/search/show.html.haml - app/views/search/index.html.haml - app/views/search/_search_form.html.haml - app/views/search_entries/show.html.haml - app/views/search_entries/index.html.haml - app/views/databag_items/new.html.haml - app/views/databag_items/_navigation.html.haml - app/views/databag_items/show.html.haml - app/views/databag_items/index.html.haml - app/views/databag_items/_form.html.haml - app/views/databag_items/edit.html.haml - app/views/roles/new.html.haml - app/views/roles/_run_lists.html.erb - app/views/roles/_navigation.html.haml - app/views/roles/show.html.haml - app/views/roles/_form.html.erb - app/views/roles/index.html.haml - app/views/roles/edit.html.haml - app/views/environments/_navigation.html.haml - app/views/environments/new.html.erb - app/views/environments/show.html.haml - app/views/environments/_form.html.erb - app/views/environments/index.html.haml - app/views/environments/_version_selector.html.erb - app/views/environments/edit.html.erb - app/controllers/search.rb - app/controllers/exceptions.rb - app/controllers/nodes.rb - app/controllers/application.rb - app/controllers/databags.rb - app/controllers/openid_consumer.rb - app/controllers/main.rb - app/controllers/search_entries.rb - app/controllers/status.rb - app/controllers/roles.rb - app/controllers/users.rb - app/controllers/clients.rb - app/controllers/environments.rb - app/controllers/databag_items.rb - app/controllers/cookbooks.rb - app/helpers/application_helper.rb - app/helpers/status_helper.rb - public/facebox/tr.png - public/facebox/facebox.js - public/facebox/br.png - public/facebox/facebox.css - public/facebox/closelabel.gif - public/facebox/tl.png - public/facebox/README.txt - public/facebox/b.png - public/facebox/bl.png - public/facebox/loading.gif - public/javascripts/jquery.tools.min.js - public/javascripts/jquery.suggest.js - public/javascripts/json.js - public/javascripts/chef.js - public/javascripts/yetii-min.js - public/javascripts/jquery-ui-1.7.1.custom.min.js - public/javascripts/jquery.scrollTo.js - public/javascripts/drop_down_menu.js - public/javascripts/jsonedit_main.js - public/javascripts/cookbook_versions.js - public/javascripts/jquery.localscroll.js - public/javascripts/jquery.jeditable.mini.js - public/javascripts/jquery-1.5.2.min.js - public/javascripts/jquery.treeTable.min.js - public/javascripts/jquery.editinline.js - public/javascripts/cookbook_constraint_ctrl.js - public/images/treeBuilderImages/Thumbs.db - public/images/treeBuilderImages/folderNodeOpenLast.gif - public/images/treeBuilderImages/doc.gif - public/images/treeBuilderImages/folderNodeFirst.gif - public/images/treeBuilderImages/docNode.gif - public/images/treeBuilderImages/docNodeLast.gif - public/images/treeBuilderImages/folderNodeLast.gif - public/images/treeBuilderImages/docNodeLastFirst.gif - public/images/treeBuilderImages/folderNodeOpenLastFirst.gif - public/images/treeBuilderImages/vertLine.gif - public/images/treeBuilderImages/folder.gif - public/images/treeBuilderImages/folderOpen.gif - public/images/treeBuilderImages/folderNodeLastFirst.gif - public/images/treeBuilderImages/folderNodeOpen.gif - public/images/treeBuilderImages/folderNode.gif - public/images/treeBuilderImages/folderNodeOpenFirst.gif - public/images/toggle-collapse-dark.png - public/images/avatar.png - public/images/toggle-expand-dark.png - public/images/black_big.png - public/images/jsonedit/json.jpg - public/images/jsonedit/bullet_orange.png - public/images/jsonedit/plus.gif - public/images/jsonedit/label.gif - public/images/jsonedit/table_refresh.png - public/images/jsonedit/deleted.png - public/images/jsonedit/delete.png - public/images/jsonedit/minus.gif - public/images/jsonedit/value.gif - public/images/jsonedit/saved.png - public/images/jsonedit/cross.png - public/images/jsonedit/build-button.png - public/images/jsonedit/pixel.gif - public/images/jsonedit/add2.png - public/images/jsonedit/bullet.gif - public/images/indicator.gif - public/images/toggle-expand-light.png - public/images/toggle-collapse.gif - public/images/toggle-expand.gif - public/images/merb.jpg - public/images/toggle-collapse-light.png - public/stylesheets/base.css - public/stylesheets/jquery.suggest.css - public/stylesheets/chef.css - public/stylesheets/jsonedit_main.css - public/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png - public/stylesheets/images/ui-bg_highlight-soft_100_e7eef3_1x100.png - public/stylesheets/images/ui-bg_diagonals-small_0_aaaaaa_40x40.png - public/stylesheets/images/ui-icons_cd0a0a_256x240.png - public/stylesheets/images/ui-icons_2e83ff_256x240.png - public/stylesheets/images/ui-icons_2694e8_256x240.png - public/stylesheets/images/ui-icons_222222_256x240.png - public/stylesheets/images/ui-bg_glass_80_e6e6e6_1x400.png - public/stylesheets/images/ui-icons_888888_256x240.png - public/stylesheets/images/ui-bg_glass_50_99c2ff_1x400.png - public/stylesheets/images/ui-bg_highlight-hard_100_f9f9f9_1x100.png - public/stylesheets/images/ui-icons_ffffff_256x240.png - public/stylesheets/images/ui-icons_72a7cf_256x240.png - public/stylesheets/images/ui-bg_diagonals-thick_15_444444_40x40.png - public/stylesheets/images/ui-bg_glass_55_fbf5d0_1x400.png - public/stylesheets/images/ui-bg_glass_100_f0f0f0_1x400.png - public/stylesheets/themes/default/style.css - public/stylesheets/themes/kathleene/style.css - public/stylesheets/themes/djime-cerulean/style.css - public/stylesheets/themes/blue/style.css - public/stylesheets/themes/bec-green/style.css - public/stylesheets/themes/reidb-greenish/style.css - public/stylesheets/themes/orange/style.css - public/stylesheets/themes/bec/style.css - public/stylesheets/jquery.treeTable.css - public/stylesheets/jquery-ui-1.7.1.custom.css homepage: http://wiki.opscode.com/display/chef licenses: [] post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement none: false requirements: - - ">=" - !ruby/object:Gem::Version hash: 3 segments: - 0 version: "0" required_rubygems_version: !ruby/object:Gem::Requirement none: false requirements: - - ">=" - !ruby/object:Gem::Version hash: 3 segments: - 0 version: "0" requirements: [] rubyforge_project: rubygems_version: 1.8.10 signing_key: specification_version: 3 summary: A systems integration framework, built to bring the benefits of configuration management to your entire infrastructure. test_files: [] ./LICENSE0000644000175000017500000002514211773315157011542 0ustar tfheentfheen Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ./Rakefile0000644000175000017500000000252711773315157012204 0ustar tfheentfheenrequire File.dirname(__FILE__) + '/lib/chef-server-webui/version' require 'rubygems' require 'rake/gempackagetask' begin require 'merb-core' require 'merb-core/tasks/merb' rescue LoadError STDERR.puts "merb is not installed, merb rake tasks will not be available." end GEM_NAME = "chef-server-webui" AUTHOR = "Opscode" EMAIL = "chef@opscode.com" HOMEPAGE = "http://wiki.opscode.com/display/chef" SUMMARY = "A systems integration framework, built to bring the benefits of configuration management to your entire infrastructure." spec = eval(File.read("chef-server-webui.gemspec")) Rake::GemPackageTask.new(spec) do |pkg| pkg.gem_spec = spec end desc "Install the gem" task :install => :package do sh %{gem install pkg/#{GEM_NAME}-#{ChefServerWebui::VERSION} --no-rdoc --no-ri} end desc "Uninstall the gem" task :uninstall do sh %{gem uninstall #{GEM_NAME} -x -v #{ChefServerWebui::VERSION} } end desc "Create a gemspec file" task :gemspec do File.open("#{GEM_NAME}.gemspec", "w") do |file| file.puts spec.to_ruby end end desc "Create a new Balsamiq Mockups project" task :new_mockup, :name do |t, args| if args[:name].nil? puts "You must supply a name for your mockups project directory: `rake new_mockup[project-name]`" exit end src = "mockups/base-mockup/." dest = "mockups/#{args[:name]}" FileUtils.cp_r src, dest end./debian/0000755000175000017500000000000012014212320011724 5ustar tfheentfheen./debian/patches/0000755000175000017500000000000011773315157013402 5ustar tfheentfheen./debian/patches/chef_merb_root.patch0000644000175000017500000000046211773315157017402 0ustar tfheentfheen--- a/lib/chef-server-webui.rb +++ b/lib/chef-server-webui.rb @@ -1,4 +1,4 @@ require 'chef-server-webui/version' CHEF_SERVER_WEBUI_VERSION = ::ChefServerWebui::VERSION -CHEF_SERVER_WEBUI_ROOT = File.expand_path(File.dirname(__FILE__) + '/../') +CHEF_SERVER_WEBUI_ROOT = "/usr/share/chef-server-webui" ./debian/patches/disable_merb_json.patch0000644000175000017500000000055711773315157020073 0ustar tfheentfheen--- a/bin/chef-server-webui +++ b/bin/chef-server-webui @@ -26,6 +26,8 @@ require "rubygems" require "merb-core" +Merb::disable :json + # Load chef and chef-server-api from source rather than gem, if present $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../chef/lib')) $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../chef-solr/lib/')) ./debian/patches/series0000644000175000017500000000005511773315157014617 0ustar tfheentfheendisable_merb_json.patch chef_merb_root.patch ./debian/chef-server-webui.templates0000644000175000017500000000133511773315157017217 0ustar tfheentfheenTemplate: chef-server-webui/admin_password Type: password Description: New password for the 'admin' user in the Chef Server WebUI: This sets a temporary first-use password to log into the Chef Server WebUI as the 'admin' user for the first time. Once logged in, the password should be changed immediately. . Once the chef-server-webui process is running, login using the username 'admin' using the password set here. . If a password is not entered, the webui default password for 'admin' will be used, which is displayed on the webui home page. The password must be at least 6 characters or the webui will not start properly. . This will be used in /etc/chef/webui.rb as 'web_ui_admin_default_password'. . ./debian/chef-server-webui.postinst0000644000175000017500000000264611773315157017112 0ustar tfheentfheen#!/bin/bash set -e . /usr/share/debconf/confmodule . /etc/default/chef-server-webui export PATH=$PATH:/sbin:/usr/sbin:/bin:/usr/bin TEMPLATE=/usr/share/chef-server-webui/webui.rb TMPDIR=`mktemp -d` # used for holding temp files TMPFILE=`mktemp -p ${TMPDIR}` # used for holding rendered template CONFIGFILE=/etc/chef/webui.rb case "$1" in configure) db_get chef-server-webui/admin_password && chef_webui_pass="$RET" tsed=`mktemp -p ${TMPDIR}` cat << EOF > $tsed s/^web_ui_admin_default_password \".*\"/web_ui_admin_default_password \"$chef_webui_pass\"/g EOF if [ -n "$chef_webui_pass" ]; then sed -f $tsed $TEMPLATE > $TMPFILE fi ucf --debconf-ok $TMPFILE $CONFIGFILE test -f $CONFIGFILE && chmod 0640 $CONFIGFILE rm -rf $TMPDIR if ! getent passwd chef > /dev/null; then adduser --system --quiet \ --home /var/lib/chef --no-create-home \ --shell /bin/false --group --gecos "Chef Daemon" chef fi chown -R $USER:$GROUP /etc/chef chown -R $USER:$GROUP /var/lib/chef chown -R $USER:$GROUP /var/log/chef chown -R $USER:$GROUP /var/cache/chef chown -R $USER:$GROUP /var/run/chef ;; abort-upgrade|abort-remove|abort-deconfigure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac db_stop # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. #DEBHELPER# exit 0 ./debian/control0000644000175000017500000000304611773315634013361 0ustar tfheentfheenSource: chef-server-webui Section: ruby Priority: optional Maintainer: Debian Ruby Extras Maintainers Uploaders: Bryan McLellan , Tollef Fog Heen DM-Upload-Allowed: yes Build-Depends: debhelper (>= 7.0.50~), gem2deb (>= 0.2.2) Standards-Version: 3.9.2 #Vcs-Git: git://git.debian.org/pkg-ruby-extras/chef-server-webui.git #Vcs-Browser: http://git.debian.org/?p=pkg-ruby-extras/chef-server-webui.git;a=summary Homepage: http://wiki.opscode.com/display/chef XS-Ruby-Versions: all Package: chef-server-webui Architecture: all XB-Ruby-Versions: ${ruby:Versions} Depends: ${shlibs:Depends}, ${misc:Depends}, ruby | ruby-interpreter, merb-core, ruby-merb-param-protection, ruby-merb-assets, ruby-merb-haml, ruby-merb-helpers, thin, ruby-openid, ruby-json (>= 1.4.6), chef (>= ${source:Upstream-Version}), ruby-coderay, chef-server (>= ${source:Upstream-Version}), adduser, ucf Description: Chef configuration management system - Web UI Chef is a systems integration framework and configuration management system written in Ruby. Chef provides a Ruby library and API that can be used to bring the benefits of configuration management to an entire infrastructure. . The Chef Server is a Merb application that provides centralized storage and distribution for recipes stored in "cookbooks," management and authentication of client nodes and node data, and search indexes for that data. . This package provides a web UI administrators can use for interacting with the Chef server ./debian/compat0000644000175000017500000000000211773315157013151 0ustar tfheentfheen7 ./debian/chef-server-webui.default0000644000175000017500000000027711773315157016651 0ustar tfheentfheenLOGFILE=/var/log/chef/server-webui.log CONFIG=/etc/chef/webui.rb ADAPTER=thin PORT=4040 USER=chef GROUP=chef # Sleep to give daemon enough time to fully start or stop. STARTTIME=10 DIETIME=5 ./debian/chef-server-webui.logrotate0000644000175000017500000000031011773315157017211 0ustar tfheentfheen/var/log/chef/server-webui.log /var/log/chef/merb-webui*log { rotate 12 weekly compress postrotate missingok /usr/sbin/invoke-rc.d chef-server-webui force-reload > /dev/null endscript } ./debian/chef-server-webui.postrm0000644000175000017500000000133611773315157016546 0ustar tfheentfheen#!/bin/sh # postrm script for chef-server-webui # # see: dh_installdeb(1) set -e TEMPLATE=/usr/share/chef/webui.rb CONFIGFILE=/etc/chef/webui.rb case "$1" in remove) ;; purge) rm -rf /var/log/chef/server-webui* rm -rf /var/log/chef/merb-webui* test -x /usr/bin/ucf && ucf --purge $TEMPLATEFILE $CONFIGFILE rm -rf $CONFIGFILE $CONFIGFILE.ucf-old $CONFIGFILE.ucf-new $CONFIGFILE.ucf-dist ;; upgrade|failed-upgrade|abort-install|abort-upgrade|disappear|remove) ;; *) echo "postrm called with unknown argument \`$1'" >&2 exit 1 ;; esac # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. #DEBHELPER# exit 0 ./debian/chef-server-webui.init0000755000175000017500000000523711773315157016174 0ustar tfheentfheen#! /bin/sh ### BEGIN INIT INFO # Provides: chef-server-webui # Required-Start: $remote_fs $network chef-server # Required-Stop: $remote_fs $network chef-server # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start a chef-server-webui ### END INIT INFO # # Copyright (c) 2009-2010 Opscode, Inc # # chef-server-webui Startup script for chef-server-webui. # chkconfig: - 95 02 # description: starts up chef-server webui. PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/sbin/chef-server-webui PIDFILE=/var/run/chef/server-webui.%s.pid MAINPID=/var/run/chef/server-webui.main.pid NAME=chef-server-webui DESC=chef-server-webui test -x $DAEMON || exit 0 . /lib/lsb/init-functions [ -r /etc/default/$NAME ] && . /etc/default/$NAME if [ ! -d /var/run/chef ]; then mkdir /var/run/chef chown $USER:$GROUP /var/run/chef fi DAEMON_OPTS="-p $PORT -e production -d -a $ADAPTER -P $PIDFILE -L $LOGFILE -C $CONFIG -u $USER -G $GROUP" running() { [ ! -f "$MAINPID" ] && return 1 pid=`cat $MAINPID` name=$WORKER [ -z "$pid" ] && return 1 [ ! -d /proc/$pid ] && return 1 (ps -fp $pid | egrep -q "merb.*(merb : master|worker.*$PORT)") || return 1 return 0 } start_server() { $DAEMON $DAEMON_OPTS errcode=$? return $errcode } stop_server() { $DAEMON -K all -P $PIDFILE errcode=$? return $errcode } reload_server() { stop_server [ -n "$DIETIME" ] && sleep $DIETIME start_server [ -n "$STARTTIME" ] && sleep $STARTTIME } case "$1" in start) log_daemon_msg "Starting $DESC " if running ; then log_progress_msg "apparently already running" log_end_msg 0 exit 0 fi if start_server ; then [ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time if running ; then log_end_msg 0 else log_end_msg 1 fi else log_end_msg 1 fi ;; stop) log_daemon_msg "Stopping $DESC" if running ; then errcode=0 stop_server || errcode=$? log_end_msg $errcode else log_progress_msg "apparently not running" log_end_msg 0 exit 0 fi ;; restart|force-reload) log_daemon_msg "Restarting $DESC" errcode=0 reload_server running && errcode=$? log_end_msg $errcode ;; status) log_daemon_msg "Checking status of $DESC" if running ; then log_progress_msg "running" log_end_msg 0 else log_progress_msg "apparently not running" log_end_msg 1 exit 3 fi ;; *) N=/etc/init.d/$NAME echo "Usage: $N {start|stop|restart|status}" >&2 exit 1 ;; esac exit 0 ./debian/chef-server-webui.80000644000175000017500000001306111773315157015367 0ustar tfheentfheen.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "CHEF\-SERVER\-WEBUI" "8" "April 2011" "Chef 0.10.0" "Chef Manual" . .SH "NAME" \fBchef\-server\-webui\fR \- Start the Chef Server merb application slice providing Web User Interface (Management Console)\. . .SH "SYNOPSIS" \fBchef\-server\-webui\fR \fI(options)\fR . .TP \fB\-u\fR, \fB\-\-user USER\fR This flag is for having chef\-server\-webui run as a user other than the one currently logged in\. Note: if you set this you must also provide a \-\-group option for it to take effect\. . .TP \fB\-G\fR, \fB\-\-group GROUP\fR This flag is for having chef\-server\-webui run as a group other than the one currently logged in\. Note: if you set this you must also provide a \-\-user option for it to take effect\. . .TP \fB\-d\fR, \fB\-\-daemonize\fR This will run a single chef\-server\-webui in the background\. . .TP \fB\-N\fR, \fB\-\-no\-daemonize\fR This will allow you to run a cluster in console mode\. . .TP \fB\-c\fR, \fB\-\-cluster\-nodes NUM_MERBS\fR Number of merb daemons to run for chef\-server\-webui\. . .TP \fB\-I\fR, \fB\-\-init\-file FILE\fR File to use for initialization on load, defaults to config/init\.rb\. . .TP \fB\-p\fR, \fB\-\-port PORTNUM\fR Port to run chef\-server\-webui on, defaults to 4040\. Additional nodes (\-c) listen on incrementing port numbers\. . .TP \fB\-o\fR, \fB\-\-socket\-file FILE\fR Socket file to run chef\-server\-webui on, defaults to [Merb\.root]/log/merb\.sock\. This is for web servers, like thin, that use sockets\. Specify this \fIonly\fR if you \fImust\fR\. . .TP \fB\-s\fR, \fB\-\-socket SOCKNUM\fR Socket number to run chef\-server\-webui on, defaults to 0\. . .TP \fB\-n\fR, \fB\-\-name NAME\fR Set the name of the application\. This is used in the process title and log file names\. . .TP \fB\-P\fR, \fB\-\-pid PIDFILE\fR PID file, defaults to [Merb\.root]/log/merb\.main\.pid for the master process and[Merb\.root]/log/merb\.[port number]\.pid for worker processes\. For clusters, use %s to specify where in the file chef\-server\-webui should place the port number\. For instance: \-P myapp\.%s\.pid\. . .TP \fB\-h\fR, \fB\-\-host HOSTNAME\fR Host to bind to (default is 0\.0\.0\.0)\. . .TP \fB\-m\fR, \fB\-\-merb\-root PATH_TO_APP_ROOT\fR The path to the Merb\.root for the app you want to run (default is current working directory)\. . .TP \fB\-a\fR, \fB\-\-adapter ADAPTER\fR The rack adapter to use to run chef\-server\-webui (default is mongrel) [mongrel, emongrel, thin, ebb, fastcgi, webrick]\. . .TP \fB\-R\fR, \fB\-\-rackup FILE\fR Load an alternate Rack config file (default is config/rack\.rb)\. . .TP \fB\-i\fR, \fB\-\-irb\-console\fR This flag will start chef\-server\-webui in irb console mode\. All your models and other classes will be available for you in an irb session\. . .TP \fB\-S\fR, \fB\-\-sandbox\fR This flag will enable a sandboxed irb console\. If your ORM supports transactions, all edits will be rolled back on exit\. . .TP \fB\-l\fR, \fB\-\-log\-level LEVEL\fR Log levels can be set to any of these options: debug < info < warn < error < fatal (default is info)\. . .TP \fB\-L\fR, \fB\-\-log LOGFILE\fR A string representing the logfile to use\. Defaults to [Merb\.root]/log/merb\.[main]\.log for the master process and [Merb\.root]/log/merb[port number]\.logfor worker processes\. . .TP \fB\-e\fR, \fB\-\-environment STRING\fR Environment to run Merb under [development, production, testing] (default is development)\. . .TP \fB\-r\fR, \fB\-\-script\-runner [\'RUBY CODE\'| FULL_SCRIPT_PATH]\fR Command\-line option to run scripts and/or code in the chef\-server\-webui app\. . .TP \fB\-K\fR, \fB\-graceful PORT or all\fR Gracefully kill chef\-server\-webui proceses by port number\. Use chef\-server \-K all to gracefully kill all merbs\. . .TP \fB\-k\fR, \fB\-\-kill PORT\fR Force kill one merb worker by port number\. This will cause the worker to be respawned\. . .TP \fB\-\-fast\-deploy\fR Reload the code, but not yourinit\.rb or gems\. . .TP \fB\-X\fR, \fB\-\-mutex on/off\fR This flag is for turning the mutex lock on and off\. . .TP \fB\-D\fR, \fB\-\-debugger\fR Run chef\-server\-webui using rDebug\. . .TP \fB\-V\fR, \fB\-\-verbose\fR Print extra information\. . .TP \fB\-C\fR, \fB\-\-console\-trap\fR Enter an irb console on ^C\. . .TP \fB\-?\fR, \fB\-H\fR, \fB\-\-help\fR Show this help message\. . .SH "DESCRIPTION" The Chef Server WebUI (Management Console) is a Merb application slice\. The default listen port is 4040\. . .P The Management Console is Chef Server\'s web interface\. Nodes, roles, cookbooks, data bags, and API clients can be managed through the Management Console\. Search can also be done on the console\. . .P In order to start using the Management Console, you need to first create a user or change the default password on the "admin" user\. . .P The default credentials are: . .IP "\(bu" 4 \fBUsername\fR: admin . .IP "\(bu" 4 \fBPassword\fR: p@ssw0rd1 . .IP "" 0 . .SH "SEE ALSO" Full documentation for Chef and chef\-server\-webui (Management Console) is located on the Chef wiki, http://wiki\.opscode\.com/display/chef/Home\. . .SH "AUTHOR" Chef was written by Adam Jacob \fIadam@ospcode\.com\fR of Opscode (http://www\.opscode\.com), with contributions from the community\. This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR with help2man for the Debian project (but may be used by others)\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. . .P On Debian systems, the complete text of the Apache 2\.0 License can be found in /usr/share/common\-licenses/Apache\-2\.0\. ./debian/watch0000644000175000017500000000024111773315157013001 0ustar tfheentfheenversion=3 opts=dversionmangle=s/\+dfsg// \ http://pkg-ruby-extras.alioth.debian.org/cgi-bin/gemwatch/chef-server-webui .*/chef-server-webui-(.*).tar.gz debian ./debian/source/0000755000175000017500000000000011773315157013253 5ustar tfheentfheen./debian/source/format0000644000175000017500000000001411773315157014461 0ustar tfheentfheen3.0 (quilt) ./debian/chef-server-webui.dirs0000644000175000017500000000025611773315157016163 0ustar tfheentfheenetc/chef var/lib/chef/openid var/lib/chef/openid/store var/lib/chef/openid/cstore var/cache/chef var/log/chef usr/share/doc/chef-server-webui usr/share/chef-server-webui/app ./debian/chef-server-webui.links0000644000175000017500000000015311773315157016336 0ustar tfheentfheen/usr/share/javascript/jquery/jquery.js /usr/share/chef-server-webui/public/javascripts/jquery-1.3.2.min.js ./debian/copyright0000644000175000017500000001215112014212320013657 0ustar tfheentfheenFIXME. fill-in with DEP5 copyright file. http://dep.debian.net/deps/dep5/ Format: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=173 Upstream-Name: chef-server-webui Source: http://wiki.opscode.com/display/chef Files: * Copyright: Copyright 2008-2011 Opscode, Inc. License: GPL-2 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation . This program 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 this package; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA . On Debian systems, the full text of the GNU General Public License version 2 can be found in the file `/usr/share/common-licenses/GPL-2'. License: MIT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: . The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. . THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Files: public/facebox/* Copyright: Copyright 2007, 2008 Chris Wanstrath License: MIT Files: public/javascripts/jquery.localscroll.js public/javascripts/jquery.scrollTo.js Copyright: Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com License: MIT, GPL-2 Files: public/javascripts/jquery-1.5.2.*js Copyright: Copyright 2011, John Resig, Copyright 2011, The Dojo Foundation License: MIT, GPL-2 Files: public/javascripts/jquery.jeditable*js Copyright: Copyright (c) 2006-2009 Mika Tuupola, Dylan Verheul License: MIT Files: public/javascripts/jquery.suggest.js Copyright: Copyright (c) 2007 License: Feel free to do whatever you want with this file Files: public/javascripts/jquery.tools.min.js: public/javascripts/jquery.tools.js Copyright: Copyright (c) 2009 Tero Piirainen License: MIT, GPL-2 Files: public/javascripts/jquery.treeTable.min.js stylesheets/jquery.treeTable.css Copyright: Copyright (c) 2011 Ludo van den Boom, http://cubicphuse.nl License: MIT, GPL-2 Files: public/javascripts/jquery-ui-1.7.1.custom.min.js public/stylesheets/jquery-ui-1.7.1.custom.css public/javascripts/jquery-ui.js Copyright: Copyright (c) 2009 Richard D. Worth and others License: MIT, GPL-2 Files: public/javascripts/yetii-min.js Copyright: Copyright (c) kminek.pl & Grzegorz Wójcik License: All rights reserved. . Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: . * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. . * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. . * Neither the name of the kminek.pl & Grzegorz Wójcik nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. . THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Files: public/javascripts/json.js Copyright: Public Domain License: N/A public/javascripts/jsonedit_main.js /* "version": "1.1.1", "www": "http://braincast.nl", "date": "jul 2010", "description": "Braincast Json Tree object." }, */ ./debian/etc/0000755000175000017500000000000011773315157012526 5ustar tfheentfheen./debian/etc/chef/0000755000175000017500000000000011773315157013433 5ustar tfheentfheen./debian/etc/chef/webui.rb0000644000175000017500000001056711773315157015104 0ustar tfheentfheen# Configuration File For Chef (chef-server-webui) # # chef-server-webui is a Merb application slice that provides a web user # interface to the Chef Server. The WebUI is optional as of version 0.8.0+, # and is a client to the API itself, which can be running on the same server, # or optionally on a different server. # # By default, it is configured to run via Thin. It can be run manually as: # # chef-server-webui -p 4040 -e production -a thin # # This starts up the Chef Server WebUI on port 4040 in production mode using # the thin server adapter. # # This file configures the behavior of the running server-webui itself. # # It is a Ruby DSL config file, and can embed regular Ruby code in addition to # the configuration settings. Some settings use Ruby symbols, which are a value # that starts with a colon. In Ruby, anything but 'false' or 'nil' is true. To # set something to false: # # some_setting false # # log_level specifies the level of verbosity for output. # valid values are: :debug, :info, :warn, :error, :fatal log_level :info # log_location specifies where the server should log to. # valid values are: a quoted string specifying a file, or STDOUT with # no quotes. This is the application log for the Merb workers that get # spawned. The chef-server-webui daemon is configured to log to # /var/log/chef/server-webui.log in /etc/chef/default/chef-server-webui. log_location STDOUT # ssl_verify_mode specifies if the REST client should verify SSL certificates. # valid values are :verify_none, :verify_peer. The default Chef Server # installation on Debian will use a self-generated SSL certificate so this # should be :verify_none unless you replace the certificate. ssl_verify_mode :verify_none # chef_server_url specifies the URL for the server API. The process actually # listens on 0.0.0.0:PORT. # valid values are any HTTP URL. If the server API port is changed, this # value needs to be updated as well. chef_server_url "http://localhost:4000" # file_cache_path specifies where the client should cache cookbooks, server # cookie ID, and openid registration data. # valid value is any filesystem directory location. file_cache_path "/var/cache/chef" # openid_store_path specifies a location where to keep openid nonces for clients. # valid values are any filesystem directory location. # # NOTE: OpenID is optionally used in the WebUI to associate OpenIDs with webui # users. openid_store_path "/var/lib/chef/openid/store" # openid_store_path specifies a location where to keep openid nonces for clients. # valid values are any filesystem directory location. # # NOTE: OpenID is optionally used in the WebUI to associate OpenIDs with webui # users. openid_cstore_path "/var/lib/chef/openid/cstore" # Mixlib::Log::Formatter.show_time specifies whether the chef-client log should # contain timestamps. # valid values are true or false. The printed timestamp is rfc2822, for example: # Fri, 31 Jul 2009 19:19:46 -0600 Mixlib::Log::Formatter.show_time = true # The following options configure the signing CA so it can be read by # non-privileged user for the server daemon. signing_ca_cert "/etc/chef/certificates/cert.pem" signing_ca_key "/etc/chef/certificates/key.pem" signing_ca_user "chef" signing_ca_group "chef" # web_ui_client_name specifies the user to use when accessing the Chef # Server API. By default this is already set to "chef-webui". # # This user gets created by the chef-server and stored in CouchDB the # first time the server starts up if the user and key don't exist. web_ui_client_name "chef-webui" # web_ui_admin_user_name and web_ui_admin_default_password specify the # user and password that a human can use to initially log into the # chef-server-webui when it starts. The default value for the user is 'admin' # and the default password is'p@ssw0rd1' should be changed immediately on # login. The web form will display the password reset page on first login. # During package installation, debconf will prompt for a password, so this # may differ from the default. web_ui_admin_user_name "admin" web_ui_admin_default_password "p@ssw0rd1" # web_ui_key specifics the file to use for authenticating with the Chef # Server API. By default this is already set to "/etc/chef/webui.pem". # # This file gets created by the chef-server and the public key stored in # CouchDB the first time the server starts up if the user and key don't # exist. web_ui_key "/etc/chef/webui.pem" ./debian/rules0000755000175000017500000000225611773315157013040 0ustar tfheentfheen#!/usr/bin/make -f #export DH_VERBOSE=1 # # Uncomment to ignore all test failures (but the tests will run anyway) #export DH_RUBY_IGNORE_TESTS=all # # Uncomment to ignore some test failures (but the tests will run anyway). # Valid values: #export DH_RUBY_IGNORE_TESTS=ruby1.8 ruby1.9.1 require-rubygems # # If you need to specify the .gemspec (eg there is more than one) #export DH_RUBY_GEMSPEC=gem.gemspec %: dh $@ --buildsystem=ruby --with ruby override_dh_auto_install: cp -rf $(CURDIR)/debian/etc/chef/webui.rb $(CURDIR)/debian/chef-server-webui/usr/share/chef-server-webui/webui.rb cp debian/etc/chef/webui.rb debian/chef-server-webui/usr/share/chef-server-webui cp config.ru debian/chef-server-webui/usr/share/chef-server-webui cp -rf app debian/chef-server-webui/usr/share/chef-server-webui cp -rf config debian/chef-server-webui/usr/share/chef-server-webui cp -rf public debian/chef-server-webui/usr/share/chef-server-webui cp -rf lib debian/chef-server-webui/usr/share/chef-server-webui dh_ruby --install mkdir -p $(CURDIR)/debian/chef-server-webui/usr/sbin mv $(CURDIR)/debian/chef-server-webui/usr/bin/chef-server-webui $(CURDIR)/debian/chef-server-webui/usr/sbin ./debian/chef-server-webui.docs0000644000175000017500000000001411773315157016142 0ustar tfheentfheenREADME.rdoc ./debian/chef-server-webui.config0000644000175000017500000000047411773315157016471 0ustar tfheentfheen#!/bin/bash set -e . /usr/share/debconf/confmodule export PATH=$PATH:/sbin:/usr/sbin:/bin:/usr/bin case "$1" in configure|reconfigure) db_input high chef-server-webui/admin_password || true db_go ;; *) echo "config called with unknown argument \`$1'" >&2 exit 1 ;; esac db_stop exit 0 ./debian/changelog0000644000175000017500000000304711773315216013625 0ustar tfheentfheenchef-server-webui (10.12.0-1) UNRELEASED; urgency=low * New upstream release -- Tollef Fog Heen Fri, 29 Jun 2012 14:07:37 +0200 chef-server-webui (0.10.10-1) unstable; urgency=low * New upstream release -- Bryan McLellan Fri, 11 May 2012 20:46:34 +0000 chef-server-webui (0.10.8-2) unstable; urgency=low * Add 'missingok' to logrotate script (pull request #5) -- Bryan McLellan Tue, 17 Jan 2012 21:47:58 +0000 chef-server-webui (0.10.8-1) unstable; urgency=low * New upstream release -- Bryan McLellan Fri, 16 Dec 2011 03:01:54 +0000 chef-server-webui (0.10.6-1) unstable; urgency=low * New upstream release -- Bryan McLellan Wed, 14 Dec 2011 00:01:32 +0000 chef-server-webui (0.10.2-3) unstable; urgency=low * Allow upstream JS files to remain because it is simpler (Fixes CHEF-2469) * Depend on Upstream-Version of chef + chef-server rather than Version -- Bryan McLellan Fri, 29 Jul 2011 14:42:17 +0000 chef-server-webui (0.10.2-2) unstable; urgency=low * Revision bump for more flexible chef-server depends -- Bryan McLellan Wed, 13 Jul 2011 18:04:48 +0000 chef-server-webui (0.10.2-1) unstable; urgency=high * New upstream release -- Bryan McLellan Thu, 07 Jul 2011 22:01:25 +0000 chef-server-webui (0.10.0-1) UNRELEASED; urgency=low * Initial release (Closes: #nnnn) -- Bryan McLellan Fri, 06 May 2011 21:25:01 +0000 ./config/0000755000175000017500000000000011773315157011776 5ustar tfheentfheen./config/environments/0000755000175000017500000000000011773315157014525 5ustar tfheentfheen./config/environments/production.rb0000644000175000017500000000145111773315157017241 0ustar tfheentfheen# # Author:: Daniel DeLeo () # Copyright:: Copyright (c) 2010 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Merb::Config.use do |c| c[:exception_details] = false c[:reload_classes] = false c[:reload_templates] = false end ./config/environments/development.rb0000644000175000017500000000202111773315157017367 0ustar tfheentfheen# # Author:: Daniel DeLeo () # Copyright:: Copyright (c) 2010 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Chef::Log.info("") Chef::Log.info("*" * 80) Chef::Log.info("* Starting Chef Server Web UI in Development Mode.") Chef::Log.info("* Start the server with `-e production` for normal use") Chef::Log.info("*" * 80) Chef::Log.info("") Merb::Config.use do |c| c[:exception_details] = true c[:reload_classes] = true c[:reload_templates] = true end ./config/router.rb0000644000175000017500000001254411773315157013651 0ustar tfheentfheen# # Author:: Adam Jacob () # Author:: Daniel DeLeo () # Copyright:: Copyright (c) 2008-2010 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Merb::Router.prepare do resources :nodes, :id => /[^\/]+/ match("/nodes/_environments/:environment_id").to(:controller => "nodes", :action => "index").name(:nodes_by_environment) resources :clients, :id => /[^\/]+/ resources :roles resources :environments do |e| e.match("/recipes", :method => "get").to(:controller=>"environments", :action=>"list_recipes") e.match("/cookbooks").to(:contoller => "environments", :action => "list_cookbooks").name(:cookbooks) e.match("/nodes").to(:controller => "environments", :action => "list_nodes").name(:nodes) e.match("/select").to(:controller => "environments", :action => "select_environment").name(:select) end #match('/environments/create').to(:controller => "environments", :action => "create").name(:environments_create) match("/status").to(:controller => "status", :action => "index").name(:status) resources :searches, :path => "search", :controller => "search" match("/search/:search_id/entries", :method => 'get').to(:controller => "search_entries", :action => "index") match("/search/:search_id/entries", :method => 'post').to(:controller => "search_entries", :action => "create") match("/search/:search_id/entries/:id", :method => 'get').to(:controller => "search_entries", :action => "show") match("/search/:search_id/entries/:id", :method => 'put').to(:controller => "search_entries", :action => "create") match("/search/:search_id/entries/:id", :method => 'post').to(:controller => "search_entries", :action => "update") match("/search/:search_id/entries/:id", :method => 'delete').to(:controller => "search_entries", :action => "destroy") match("/cookbooks/_attribute_files").to(:controller => "cookbooks", :action => "attribute_files") match("/cookbooks/_recipe_files").to(:controller => "cookbooks", :action => "recipe_files") match("/cookbooks/_definition_files").to(:controller => "cookbooks", :action => "definition_files") match("/cookbooks/_library_files").to(:controller => "cookbooks", :action => "library_files") match("/cookbooks/_environments/:environment_id").to(:controller => "cookbooks", :action => "index").name(:cookbooks_by_environment) match("/cookbooks/:cookbook_id", :cookbook_id => /[\w\.]+/, :method => 'get').to(:controller => "cookbooks", :action => "cb_versions") match("/cookbooks/:cookbook_id/:cb_version", :cb_version => /[\w\.]+/, :method => 'get').to(:controller => "cookbooks", :action => "show").name(:show_specific_version_cookbook) resources :cookbooks resources :clients match("/databags/:databag_id/databag_items", :method => 'get').to(:controller => "databags", :action => "show", :id=>":databag_id") resources :databags do |s| s.resources :databag_items end match('/openid/consumer').to(:controller => 'openid_consumer', :action => 'index').name(:openid_consumer) match('/openid/consumer/start').to(:controller => 'openid_consumer', :action => 'start').name(:openid_consumer_start) match('/openid/consumer/login').to(:controller => 'openid_consumer', :action => 'login').name(:openid_consumer_login) match('/openid/consumer/complete').to(:controller => 'openid_consumer', :action => 'complete').name(:openid_consumer_complete) match('/openid/consumer/logout').to(:controller => 'openid_consumer', :action => 'logout').name(:openid_consumer_logout) match('/login').to(:controller=>'users', :action=>'login').name(:users_login) match('/logout').to(:controller => 'users', :action => 'logout').name(:users_logout) match('/users').to(:controller => 'users', :action => 'index').name(:users) match('/users/create').to(:controller => 'users', :action => 'create').name(:users_create) match('/users/start').to(:controller => 'users', :action => 'start').name(:users_start) match('/users/login').to(:controller => 'users', :action => 'login').name(:users_login) match('/users/login_exec').to(:controller => 'users', :action => 'login_exec').name(:users_login_exec) match('/users/complete').to(:controller => 'users', :action => 'complete').name(:users_complete) match('/users/logout').to(:controller => 'users', :action => 'logout').name(:users_logout) match('/users/new').to(:controller => 'users', :action => 'new').name(:users_new) match('/users/:user_id/edit').to(:controller => 'users', :action => 'edit').name(:users_edit) match('/users/:user_id').to(:controller => 'users', :action => 'show').name(:users_show) match('/users/:user_id/delete', :method => 'delete').to(:controller => 'users', :action => 'destroy').name(:users_delete) match('/users/:user_id/update', :method => 'put').to(:controller => 'users', :action => 'update').name(:users_update) match('/').to(:controller => 'nodes', :action =>'index').name(:top) end ./config/rack.rb0000644000175000017500000000146511773315157013251 0ustar tfheentfheen# # Author:: Daniel DeLeo () # Copyright:: Copyright (c) 2010 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # use Rack::ContentLength use Merb::Rack::Static, Merb.dir_for(:public) # this is our main merb application run Merb::Rack::Application.new ./config/init.rb0000644000175000017500000000331411773315157013267 0ustar tfheentfheen# # Author:: Adam Jacob () # Author:: Daniel DeLeo () # Copyright:: Copyright (c) 2008-2010 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "merb-core" require "merb-haml" require "merb-assets" require "merb-helpers" require 'coderay' require 'chef' require 'chef/solr' require 'chef/role' require 'chef/webui_user' use_template_engine :haml Merb::Config.use do |c| c[:name] = "chef-server-webui" c[:fork_for_class_load] = false c[:session_id_key] = '_chef_server_session_id' c[:session_secret_key] = Chef::Config.manage_secret_key c[:session_store] = 'cookie' c[:log_level] = Chef::Config[:log_level] if Chef::Config[:log_location].kind_of?(String) c[:log_file] = Chef::Config[:log_location] end end Chef::Config[:node_name] = Chef::Config[:web_ui_client_name] Chef::Config[:client_key] = Chef::Config[:web_ui_key] # Create the default admin user "admin" if no admin user exists unless Chef::WebUIUser.admin_exist user = Chef::WebUIUser.new user.name = Chef::Config[:web_ui_admin_user_name] user.set_password(Chef::Config[:web_ui_admin_default_password]) user.admin = true user.save end ./bin/0000755000175000017500000000000011773315157011301 5ustar tfheentfheen./bin/chef-server-webui0000755000175000017500000000417111773315157014554 0ustar tfheentfheen#!/usr/bin/env ruby # # ./chef-server - Serving up piping hot infrastructure! # # Author:: Adam Jacob () # Copyright:: Copyright (c) 2008 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Based on the 'merb' command, by Ezra # Add chef and chef-server-slice lib dirs to the load path # Load chef and chef-server slice from source rather than gem, if present require "rubygems" require "merb-core" # Load chef and chef-server-api from source rather than gem, if present $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../chef/lib')) $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../chef-solr/lib/')) $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib')) # Print the version if we have -v or --version if ARGV.any? { |arg| arg =~ /\-v|\-\-version/ } require 'chef-server-webui/version' puts "Chef Server (Web UI) Version: #{ChefServerWebui::VERSION}" exit 1 end require 'chef' require 'chef-server-webui' if ARGV[0] && ARGV[0] =~ /^[^-]/ ARGV.push "-H" end unless %w[-a --adapter -i --irb-console -r --script-runner].any? { |o| ARGV.index(o) } ARGV.push *%w[-a thin] end unless %w[-p --port].any? { |o| ARGV.index(o) } ARGV.push *%w[-p 4040] end # Tell merb where to root ARGV.push *[ "-m", CHEF_SERVER_WEBUI_ROOT] if index = ARGV.index("-C") config = ARGV[index+1] ARGV.delete("-C") ARGV.delete(config) Chef::Config.from_file(File.expand_path(config)) else Chef::Config.from_file( File.join("/etc", "chef", "server.rb") ) end Chef::Log.init(Chef::Config[:log_location]) Chef::Log.level = Chef::Config[:log_level] Merb.start ./public/0000755000175000017500000000000011773315157012007 5ustar tfheentfheen./public/stylesheets/0000755000175000017500000000000011773315157014363 5ustar tfheentfheen./public/stylesheets/jsonedit_main.css0000644000175000017500000001606311773315157017726 0ustar tfheentfheen/* Put this inside a @media qualifier so Netscape 4 ignores it */ @media screen, print { /* Turn off list bullets */ ul.mktree li { list-style: none; } ul.mktree {margin: 0px; margin-left: -10px !important; margin-top: 3px;} /* Control how "spaced out" the tree is */ ul.mktree, ul.mktree ul , ul.mktree li { margin-left:10px; padding:0px; white-space: nowrap} /* Provide space for our own "bullet" inside the LI */ ul.mktree li .bullet { padding-left: 15px;} /* Show "bullets" in the links, depending on the class of the LI that the link's in */ ul.mktree li.liOpen .bullet { cursor: pointer; background: url(../images/jsonedit/minus.gif) center left no-repeat; } ul.mktree li.liClosed .bullet { cursor: pointer; background: url(../images/jsonedit/plus.gif) center left no-repeat; } ul.mktree li.liBullet .bullet { cursor: default; background: url(../images/jsonedit/bullet.gif) center left no-repeat; } /* Sublists are visible or not based on class of parent LI */ ul.mktree li.liOpen ul { display: block; border-left:1px solid #f5f5f5; border-top:1px solid #f5f5f5;} ul.mktree li.liClosed ul { display: none; } ul.mktree li { line-height: 16px } /* Format menu items differently depending on what level of the tree they are in */ /* Uncomment this if you want your fonts to decrease in size the deeper they are in the tree */ /* ul.mktree li ul li { font-size: 90% } */ } #jsoneditor { height: 350px; } #treecontainer{ border:1px solid #ccc; position: absolute; width:300px; height: 350px; overflow: auto; margin-right:4px; } #treecontainer div, #treecontainer a{ color: #000000; font-size: 12px; font-family:"Helvetica Neue",Helvetica,Arial,"Bitstream Vera Sans",sans-serif; text-decoration: none; padding-left: 2px; padding-right: 2px; cursor:pointer; } #treecontainer .au{background-color: #ffffff; color: #000000} /* A tag unselected*/ #treecontainer .as{background-color: #0a246a; color: #ffffff } /* A tag selected*/ #tabcontainer{ position: absolute; left: 310px; top: 19px; overflow: hidden; } #tabcontainer #console{ margin-top:4px; border: 1px solid #ccc; width:498px; display: none; } #tabcontainer #console #log{ color:#FF0000; font-size: 12px; font-family:"Helvetica Neue",Helvetica,Arial,"Bitstream Vera Sans",sans-serif; padding:2px; } #tabcontainer #console #bar{ background-image:url(../images/jsonedit/cross.png); _background-image:url(../images/jsonedit/cross.gif); background-position: right; background-repeat:no-repeat; font-size: 12px; font-family:"Helvetica Neue",Helvetica,Arial,"Bitstream Vera Sans",sans-serif; padding:2px; background-color:#F0F0F0; } #tabcontainer #console #bar a{ display: block } #tabcontainer .noshow{display:none} #tabcontainer .show{display:block} div.tablayout { width: 500px; margin: 0 0 0px 0; } div.nested{ width: 480px; margin: 0 0 0px 0; } ul.tablayout { list-style-type: none; width: 100%; float: left; background: url(../images/jsonedit/pixel.gif) bottom left repeat-x; margin:0pt; padding:0pt; font-size: 12px; font-family:"Helvetica Neue",Helvetica,Arial,"Bitstream Vera Sans",sans-serif; } ul.tablayout li { margin: 0 2px 0 0; float: left; } ul.tablayout a { float: left; display: block; padding: 2px 8px; border: 1px solid #ccc; border-bottom: 0; color: #666; background: #eee; text-decoration: none; font-weight: bold; outline:0; } ul.tablayout a:hover {background: #fff;} ul.tablayout a.active { background: #fff; padding-bottom: 3px; cursor: default; color: red; } #tab-container-2-nav a { padding: 0px 8px; background-color:#CCCCCC; } #tab-container-2-nav a.active{ background-color:#f0f0f0; } #tab-container-2-nav li{ } .xmlchoice{ height:24px; text-align:left !important; } .xmlchoice input{ margin-top:0px; vertical-align:middle; } .tab{ clear: left; border: 1px solid #ccc; border-top: 0; padding: 8px 8px 0 8px; } .tab{ font-size: 12px; font-family:"Helvetica Neue",Helvetica,Arial,"Bitstream Vera Sans",sans-serif; } .tabn{ clear: left; border: 1px solid #ccc; border-top: 0; padding: 8px 8px 0 8px; margin-bottom:8px; background-color:#f0f0f0; } .tabn{ font-size: 12px; font-family:"Helvetica Neue",Helvetica,Arial,"Bitstream Vera Sans",sans-serif; } .tab h2{margin: 0 0 20px 0;} .tab .button{ border:1px solid white; float:left; height:20px; width:20px; background-repeat:no-repeat; background-position: center center; cursor: pointer; } .tabn .button{ border:1px solid #f0f0f0; float:left; height:20px; width:20px; background-repeat:no-repeat; background-position: center center; cursor: pointer; } .tab .button:hover{border:1px outset;} .buttondown{border:1px inset !important} .tab #addbutton { display: none; background:#EEEEEE none repeat scroll 0 0; border:1px solid #001C26; color:#001C26; cursor:pointer; padding:2px 5px; -moz-border-radius-bottomleft:4px; -moz-border-radius-bottomright:4px; -moz-border-radius-topleft:4px; -moz-border-radius-topright:4px; } .tab #savebutton { background:#EEEEEE none repeat scroll 0 0; border:1px solid #001C26; color:#001C26; cursor:pointer; padding:2px 5px; -moz-border-radius-bottomleft:4px; -moz-border-radius-bottomright:4px; -moz-border-radius-topleft:4px; -moz-border-radius-topright:4px; } .tab #search { background:#EEEEEE none repeat scroll 0 0; border:1px solid #001C26; color:#001C26; cursor:pointer; padding:2px 5px; -moz-border-radius-bottomleft:4px; -moz-border-radius-bottomright:4px; -moz-border-radius-topleft:4px; -moz-border-radius-topright:4px; } .tab #refresh{ background-image:url(../images/jsonedit/table_refresh.png); _background-image:url(../images/jsonedit/table_refresh.gif); } .tab #buildbutton{ background-image:url(../images/jsonedit/build-button.png); } .tab #add{ background-image:url(../images/jsonedit/add2.png); } .tab #delete{ background-image:url(../images/jsonedit/delete.png); _background-image:url(../images/jsonedit/delete.gif); } .tab #jsonnameinput{ display: none; } .tab textarea{ /*border: 1px solid;*/ width: 99%; font-size:13px; font-family:"Consolas","Lucida Console",Courier,monospace; } .tab select{ font-size: 12px; font-family:"Helvetica Neue",Helvetica,Arial,"Bitstream Vera Sans",sans-serif; } .tab .icanhastable td{text-align: right;} .tab .icanhastable{ border: 0px; width: 100%; padding-bottom:6px; } .tab .icanhastable td #autodetect{ vertical-align:middle; } #tab2 #jsonpath{ text-align: left; margin-left: 4px; font-size: 12px; font-family:"Helvetica Neue",Helvetica,Arial,"Bitstream Vera Sans",sans-serif; letter-spacing:1px; } #tab2 #jsonmode{ text-align: left; margin-left: 4px; font-size: 11px; font-family:"Helvetica Neue",Helvetica,Arial,"Bitstream Vera Sans",sans-serif; letter-spacing:1px; } #tab1 .icanhastable td{text-align: left;} #tab1 .icanhastable #results{ border: 1px solid #CCCCCC; max-height:283px; overflow:auto; } #tab1 .icanhastable #results table td{ background-color: #ffffcc; } #tab1 .icanhastable #results table td a{ color: #0000cc; } #tab1 .icanhastable #results table td a:hover{ text-decoration: underline; } #tab1 .icanhastable #results table .path{ font-size: 10px; } ./public/stylesheets/jquery-ui-1.7.1.custom.css0000644000175000017500000006556411773315157021022 0ustar tfheentfheen/* * jQuery UI CSS Framework * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. */ /* Layout helpers ----------------------------------*/ .ui-helper-hidden { display: none; } .ui-helper-hidden-accessible { position: absolute; left: -99999999px; } .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } .ui-helper-clearfix { display: inline-block; } /* required comment for clearfix to work in Opera \*/ * html .ui-helper-clearfix { height:1%; } .ui-helper-clearfix { display:block; } /* end clearfix */ .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } /* Interaction Cues ----------------------------------*/ .ui-state-disabled { cursor: default !important; } /* Icons ----------------------------------*/ /* states and images */ .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } /* Misc visuals ----------------------------------*/ /* Overlays */ .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } /* * jQuery UI CSS Framework * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=3px&bgColorHeader=e7eef3&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=100&borderColorHeader=b2c7d7&fcHeader=222222&iconColorHeader=72a7cf&bgColorContent=f9f9f9&bgTextureContent=04_highlight_hard.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=362b36&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=80&borderColorDefault=cccccc&fcDefault=444444&iconColorDefault=888888&bgColorHover=f0f0f0&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=b2c7d7&fcHover=0b5b98&iconColorHover=2694e8&bgColorActive=99c2ff&bgTextureActive=02_glass.png&bgImgOpacityActive=50&borderColorActive=2694e8&fcActive=000000&iconColorActive=ffffff&bgColorHighlight=fbf5d0&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=f9dd34&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=444444&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=15&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=07_diagonals_small.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=0px&offsetTopShadow=4px&offsetLeftShadow=4px&cornerRadiusShadow=4px */ /* Component containers ----------------------------------*/ .ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; } .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; } .ui-widget-content { border: 1px solid #dddddd; background: #f9f9f9 url(images/ui-bg_highlight-hard_100_f9f9f9_1x100.png) 50% top repeat-x; color: #362b36; } .ui-widget-content a { color: #362b36; } .ui-widget-header { border: 1px solid #b2c7d7; background: #e7eef3 url(images/ui-bg_highlight-soft_100_e7eef3_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } .ui-widget-header a { color: #222222; } /* Interaction states ----------------------------------*/ .ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #cccccc; background: #e6e6e6 url(images/ui-bg_glass_80_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #444444; outline: none; } .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #444444; text-decoration: none; outline: none; } .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #b2c7d7; background: #f0f0f0 url(images/ui-bg_glass_100_f0f0f0_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #0b5b98; outline: none; } .ui-state-hover a, .ui-state-hover a:hover { color: #0b5b98; text-decoration: none; outline: none; } .ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #2694e8; background: #99c2ff url(images/ui-bg_glass_50_99c2ff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #000000; outline: none; } .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #000000; outline: none; text-decoration: none; } /* Interaction Cues ----------------------------------*/ .ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #f9dd34; background: #fbf5d0 url(images/ui-bg_glass_55_fbf5d0_1x400.png) 50% 50% repeat-x; color: #363636; } .ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; } .ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } .ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; } .ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; } .ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } .ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; } .ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } /* Icons ----------------------------------*/ /* states and images */ .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } .ui-widget-header .ui-icon {background-image: url(images/ui-icons_72a7cf_256x240.png); } .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_2694e8_256x240.png); } .ui-state-active .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } /* positioning */ .ui-icon-carat-1-n { background-position: 0 0; } .ui-icon-carat-1-ne { background-position: -16px 0; } .ui-icon-carat-1-e { background-position: -32px 0; } .ui-icon-carat-1-se { background-position: -48px 0; } .ui-icon-carat-1-s { background-position: -64px 0; } .ui-icon-carat-1-sw { background-position: -80px 0; } .ui-icon-carat-1-w { background-position: -96px 0; } .ui-icon-carat-1-nw { background-position: -112px 0; } .ui-icon-carat-2-n-s { background-position: -128px 0; } .ui-icon-carat-2-e-w { background-position: -144px 0; } .ui-icon-triangle-1-n { background-position: 0 -16px; } .ui-icon-triangle-1-ne { background-position: -16px -16px; } .ui-icon-triangle-1-e { background-position: -32px -16px; } .ui-icon-triangle-1-se { background-position: -48px -16px; } .ui-icon-triangle-1-s { background-position: -64px -16px; } .ui-icon-triangle-1-sw { background-position: -80px -16px; } .ui-icon-triangle-1-w { background-position: -96px -16px; } .ui-icon-triangle-1-nw { background-position: -112px -16px; } .ui-icon-triangle-2-n-s { background-position: -128px -16px; } .ui-icon-triangle-2-e-w { background-position: -144px -16px; } .ui-icon-arrow-1-n { background-position: 0 -32px; } .ui-icon-arrow-1-ne { background-position: -16px -32px; } .ui-icon-arrow-1-e { background-position: -32px -32px; } .ui-icon-arrow-1-se { background-position: -48px -32px; } .ui-icon-arrow-1-s { background-position: -64px -32px; } .ui-icon-arrow-1-sw { background-position: -80px -32px; } .ui-icon-arrow-1-w { background-position: -96px -32px; } .ui-icon-arrow-1-nw { background-position: -112px -32px; } .ui-icon-arrow-2-n-s { background-position: -128px -32px; } .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } .ui-icon-arrow-2-e-w { background-position: -160px -32px; } .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } .ui-icon-arrowstop-1-n { background-position: -192px -32px; } .ui-icon-arrowstop-1-e { background-position: -208px -32px; } .ui-icon-arrowstop-1-s { background-position: -224px -32px; } .ui-icon-arrowstop-1-w { background-position: -240px -32px; } .ui-icon-arrowthick-1-n { background-position: 0 -48px; } .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } .ui-icon-arrowthick-1-e { background-position: -32px -48px; } .ui-icon-arrowthick-1-se { background-position: -48px -48px; } .ui-icon-arrowthick-1-s { background-position: -64px -48px; } .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } .ui-icon-arrowthick-1-w { background-position: -96px -48px; } .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } .ui-icon-arrow-4 { background-position: 0 -80px; } .ui-icon-arrow-4-diag { background-position: -16px -80px; } .ui-icon-extlink { background-position: -32px -80px; } .ui-icon-newwin { background-position: -48px -80px; } .ui-icon-refresh { background-position: -64px -80px; } .ui-icon-shuffle { background-position: -80px -80px; } .ui-icon-transfer-e-w { background-position: -96px -80px; } .ui-icon-transferthick-e-w { background-position: -112px -80px; } .ui-icon-folder-collapsed { background-position: 0 -96px; } .ui-icon-folder-open { background-position: -16px -96px; } .ui-icon-document { background-position: -32px -96px; } .ui-icon-document-b { background-position: -48px -96px; } .ui-icon-note { background-position: -64px -96px; } .ui-icon-mail-closed { background-position: -80px -96px; } .ui-icon-mail-open { background-position: -96px -96px; } .ui-icon-suitcase { background-position: -112px -96px; } .ui-icon-comment { background-position: -128px -96px; } .ui-icon-person { background-position: -144px -96px; } .ui-icon-print { background-position: -160px -96px; } .ui-icon-trash { background-position: -176px -96px; } .ui-icon-locked { background-position: -192px -96px; } .ui-icon-unlocked { background-position: -208px -96px; } .ui-icon-bookmark { background-position: -224px -96px; } .ui-icon-tag { background-position: -240px -96px; } .ui-icon-home { background-position: 0 -112px; } .ui-icon-flag { background-position: -16px -112px; } .ui-icon-calendar { background-position: -32px -112px; } .ui-icon-cart { background-position: -48px -112px; } .ui-icon-pencil { background-position: -64px -112px; } .ui-icon-clock { background-position: -80px -112px; } .ui-icon-disk { background-position: -96px -112px; } .ui-icon-calculator { background-position: -112px -112px; } .ui-icon-zoomin { background-position: -128px -112px; } .ui-icon-zoomout { background-position: -144px -112px; } .ui-icon-search { background-position: -160px -112px; } .ui-icon-wrench { background-position: -176px -112px; } .ui-icon-gear { background-position: -192px -112px; } .ui-icon-heart { background-position: -208px -112px; } .ui-icon-star { background-position: -224px -112px; } .ui-icon-link { background-position: -240px -112px; } .ui-icon-cancel { background-position: 0 -128px; } .ui-icon-plus { background-position: -16px -128px; } .ui-icon-plusthick { background-position: -32px -128px; } .ui-icon-minus { background-position: -48px -128px; } .ui-icon-minusthick { background-position: -64px -128px; } .ui-icon-close { background-position: -80px -128px; } .ui-icon-closethick { background-position: -96px -128px; } .ui-icon-key { background-position: -112px -128px; } .ui-icon-lightbulb { background-position: -128px -128px; } .ui-icon-scissors { background-position: -144px -128px; } .ui-icon-clipboard { background-position: -160px -128px; } .ui-icon-copy { background-position: -176px -128px; } .ui-icon-contact { background-position: -192px -128px; } .ui-icon-image { background-position: -208px -128px; } .ui-icon-video { background-position: -224px -128px; } .ui-icon-script { background-position: -240px -128px; } .ui-icon-alert { background-position: 0 -144px; } .ui-icon-info { background-position: -16px -144px; } .ui-icon-notice { background-position: -32px -144px; } .ui-icon-help { background-position: -48px -144px; } .ui-icon-check { background-position: -64px -144px; } .ui-icon-bullet { background-position: -80px -144px; } .ui-icon-radio-off { background-position: -96px -144px; } .ui-icon-radio-on { background-position: -112px -144px; } .ui-icon-pin-w { background-position: -128px -144px; } .ui-icon-pin-s { background-position: -144px -144px; } .ui-icon-play { background-position: 0 -160px; } .ui-icon-pause { background-position: -16px -160px; } .ui-icon-seek-next { background-position: -32px -160px; } .ui-icon-seek-prev { background-position: -48px -160px; } .ui-icon-seek-end { background-position: -64px -160px; } .ui-icon-seek-first { background-position: -80px -160px; } .ui-icon-stop { background-position: -96px -160px; } .ui-icon-eject { background-position: -112px -160px; } .ui-icon-volume-off { background-position: -128px -160px; } .ui-icon-volume-on { background-position: -144px -160px; } .ui-icon-power { background-position: 0 -176px; } .ui-icon-signal-diag { background-position: -16px -176px; } .ui-icon-signal { background-position: -32px -176px; } .ui-icon-battery-0 { background-position: -48px -176px; } .ui-icon-battery-1 { background-position: -64px -176px; } .ui-icon-battery-2 { background-position: -80px -176px; } .ui-icon-battery-3 { background-position: -96px -176px; } .ui-icon-circle-plus { background-position: 0 -192px; } .ui-icon-circle-minus { background-position: -16px -192px; } .ui-icon-circle-close { background-position: -32px -192px; } .ui-icon-circle-triangle-e { background-position: -48px -192px; } .ui-icon-circle-triangle-s { background-position: -64px -192px; } .ui-icon-circle-triangle-w { background-position: -80px -192px; } .ui-icon-circle-triangle-n { background-position: -96px -192px; } .ui-icon-circle-arrow-e { background-position: -112px -192px; } .ui-icon-circle-arrow-s { background-position: -128px -192px; } .ui-icon-circle-arrow-w { background-position: -144px -192px; } .ui-icon-circle-arrow-n { background-position: -160px -192px; } .ui-icon-circle-zoomin { background-position: -176px -192px; } .ui-icon-circle-zoomout { background-position: -192px -192px; } .ui-icon-circle-check { background-position: -208px -192px; } .ui-icon-circlesmall-plus { background-position: 0 -208px; } .ui-icon-circlesmall-minus { background-position: -16px -208px; } .ui-icon-circlesmall-close { background-position: -32px -208px; } .ui-icon-squaresmall-plus { background-position: -48px -208px; } .ui-icon-squaresmall-minus { background-position: -64px -208px; } .ui-icon-squaresmall-close { background-position: -80px -208px; } .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } .ui-icon-grip-solid-vertical { background-position: -32px -224px; } .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } .ui-icon-grip-diagonal-se { background-position: -80px -224px; } /* Misc visuals ----------------------------------*/ /* Corner radius */ .ui-corner-tl { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; } .ui-corner-tr { -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; } .ui-corner-bl { -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; } .ui-corner-br { -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; } .ui-corner-top { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; } .ui-corner-bottom { -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; } .ui-corner-right { -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; } .ui-corner-left { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; } .ui-corner-all { -moz-border-radius: 3px; -webkit-border-radius: 3px; } /* Overlays */ .ui-widget-overlay { background: #444444 url(images/ui-bg_diagonals-thick_15_444444_40x40.png) 50% 50% repeat; opacity: .30;filter:Alpha(Opacity=30); } .ui-widget-shadow { margin: 4px 0 0 4px; padding: 0px; background: #aaaaaa url(images/ui-bg_diagonals-small_0_aaaaaa_40x40.png) 50% 50% repeat; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 4px; -webkit-border-radius: 4px; }/* Accordion ----------------------------------*/ .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } .ui-accordion .ui-accordion-li-fix { display: inline; } .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; } .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; } .ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker ----------------------------------*/ .ui-datepicker { width: 17em; padding: .2em .2em 0; } .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } .ui-datepicker .ui-datepicker-prev { left:2px; } .ui-datepicker .ui-datepicker-next { right:2px; } .ui-datepicker .ui-datepicker-prev-hover { left:1px; } .ui-datepicker .ui-datepicker-next-hover { right:1px; } .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } .ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; } .ui-datepicker select.ui-datepicker-month-year {width: 100%;} .ui-datepicker select.ui-datepicker-month, .ui-datepicker select.ui-datepicker-year { width: 49%;} .ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; } .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } .ui-datepicker td { border: 0; padding: 1px; } .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } /* with multiple calendars */ .ui-datepicker.ui-datepicker-multi { width:auto; } .ui-datepicker-multi .ui-datepicker-group { float:left; } .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } .ui-datepicker-row-break { clear:both; width:100%; } /* RTL support */ .ui-datepicker-rtl { direction: rtl; } .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } .ui-datepicker-rtl .ui-datepicker-group { float:right; } .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ .ui-datepicker-cover { display: none; /*sorry for IE5*/ display/**/: block; /*sorry for IE5*/ position: absolute; /*must have*/ z-index: -1; /*must have*/ filter: mask(); /*must have*/ top: -4px; /*must have*/ left: -4px; /*must have*/ width: 200px; /*must have*/ height: 200px; /*must have*/ }/* Dialog ----------------------------------*/ .ui-dialog { position: relative; padding: .2em; width: 300px; } .ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; } .ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } .ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } .ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } .ui-draggable .ui-dialog-titlebar { cursor: move; } /* Progressbar ----------------------------------*/ .ui-progressbar { height:2em; text-align: left; } .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable ----------------------------------*/ .ui-resizable { position: relative;} .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; } .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; } .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; } .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; } .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider ----------------------------------*/ .ui-slider { position: relative; text-align: left; } .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; } .ui-slider-horizontal { height: .8em; } .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } .ui-slider-horizontal .ui-slider-range-min { left: 0; } .ui-slider-horizontal .ui-slider-range-max { right: 0; } .ui-slider-vertical { width: .8em; height: 100px; } .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } .ui-slider-vertical .ui-slider-range-min { bottom: 0; } .ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs ----------------------------------*/ .ui-tabs { padding: .2em; zoom: 1; } .ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; } .ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; } .ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; } .ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; } .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ .ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; } .ui-tabs .ui-tabs-hide { display: none !important; } ./public/stylesheets/images/0000755000175000017500000000000011773315157015630 5ustar tfheentfheen./public/stylesheets/images/ui-icons_888888_256x240.png0000644000175000017500000001043311773315157021756 0ustar tfheentfheen‰PNG  IHDRðØIJùíPLTEˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ …Ê{NtRNS2P¿ƒ™."Tp@f`Í <BHJZ&0R,…4‡ÃjÉÏÇ8D½¹|«µ¥©­³(ýŸ$ï £b•¡¯lßF>n~‘hhÒHýIDATxœí] cÛ¶ÉHªå„’-kiìZK:gó’lk×n­š-©ÓtI×õþÿÏ>p,‰’|J,wàÉJ%$$2Èö­ÂŽ‘A¸œ5ÕnnF€)Í0†­~ aÈô³G˜>¤Ü”9;`çÛ_{u î’n5‘_AA@ðl6™§ÇB诼×0PcPz@@º.ïq‡¬„ŠüK ßCb (пø$QŸÌûâØ±6ìêÿ)°wÜÿ@(!!!!!áFx>àð!â”°Ažê¡ù€ýÇA\ìóÈœeÿ¼¾§º £Å­ßo(ìQ@jœ±rV›gK"; 4çÉž{M†¤ÞKÆN`µ…ÁÝ„ES=°ô7jHöÝ´¡ù€è-Ä› WïÛ¼ÈÖ¹dë6' ÷<ıóù€Ã27!!!!!!!¡GløÇ—ªbíoœxlØ€Ð?hÐ-¥È r;€P(Òš<:C¤ÇöŪÐÓ¡«ÌßAPOi¸_ !‚D¹hLX »V…uƒRvt®Ð¿L—%aݧ{ðX?=P…Xצ>ê‹9,¡N„¢° o Oûü ùN»h¼‡@¡8?z{ö&Vh‘O)F/H¤q—ÇJ÷ýØñù·ØÑ‘ð‰`óm©†RPäâ‹C#N¸4k£Vê œÏó•CŸ¨\áÅ©¢:S¹;9¶Tç%P°ìß“ßrBmKðjeÕQ$µõlvÏ‚Dö†û: AþÄÆwÏ|‹‡"ÀÕ1EbíœyH‡=Ù8?âÓ_(à/õ4À4”ç{| ûtA€Ð@ªGËù-'À¯="*DŠEÂLEVò[ÀÛ7€Üì‰Þþ»<ë¬!îŽu<FÀAO%AY©–b38¼Ï5 ûµ@§ó{Ø«xw±‡à*Mîûþ|LBBBBBÂAc·Oq¨°ÊzÎØn`o.Ho ªÒÐÌk?a-¶òå)æ :_ æC¨|CT‘¢Ø¿î²Aûƒ–Ó¼m†*€0X‘ìS…aÕ7Hˆ‰¶(ðýžP›­W }CÉAs.¹’Î-Ф›Dž«„Ògð($4>Ïe`¥®,÷Ü™GC‘î¢[Bf÷RÍíÃ>.®xu½¶ý`pƒš™LÙý|¿§œ ¾Û5ãVùm€x¸ÌNÙ‡œ"ÙklPlþ!<tqßíKHHHH¸ßÈïøƒÌvÈå-&â·±ÿ–¼Ë,4úÊ£«³Fƒ¢ò„Û{‹´¡ýiemjî"7+¯Í*põ•pÖ‡g¹t™½ðíõÚ~’Ì{NZÅElo‡E@³zÝ©Ž1&grý®|ïJ°IŽeí-v(·À  êcÆ‚:< ®Ë¦ìòá1€ÕðÎÐäÎKøÀÇ‚Crÿá§€wÈGõs¿A|Š«Aß•¹:¢q@´<^§Á]ÿN!Ö±?!!!!áÓBaâ„bõúv§ÅP+7†j|‰Üਠ•ºL,xqæãŒÕRŸœq¬ÅcÕ!óBõ°;¡1 •å{öwBˆ ‹&<t”Lk §ÄÞVc.‹•­ãº¼Ñz0†ÁÆ¢€Éßkëª_m’V–e^2" À¸èÀõxDÐMŸh´¡44€ói’[ ¤Á NO ÀÌf³Ðꑱ¼‚—€cB ÓÑMH† ©¤„Ÿty ½™Žë1 ‘«íðHã3{ú™#àt~ü;BÀãÇ»àb³u§‹rŒýŸc¨K¶ŸúTt tzÀ‰1†'n °þß`ÚGSlUs®A} v —î~iS_6bl·9ö¤–'í¹Uhr¼²¬Ô˜>e𹦳­3vH?¶CQ8F&м]r¤Užµœ—ŠÂ7ö+Ä€>Ù€­4ÑÈflBÁ•åêz´”&˜ËÛg{n¸àkúà9³ßJsg¿‰ÍÛì—?ê×#¬P¡¯sꓵAÖ¨?©kõgœß޵0&²¢òÙà ÉFÿé´KA€:ö«ÄÆáÇie§¹ «‹6»’°tÔ‹‹—¯Î/дQ¡ýÛMøÄø üU¿FØ@]:f2N>tn<@åSª`Ì»ÅYÒß³FDãÀM5•pÔÌØuPNÖWÿoðÌ)¤íGSvqøJ}­þ.™\2¸dPÛß\ÁªAªÍoYßTÒ7­‚6™Ç¹˜1ÀÙ'àÅÅÇúå·¿ŽÔ19ØY§Fþ ¾Õ¯4²éßãV.˜ŒÊíý«Ñ Šœ€&»kÇjNş £< †j8_d´éßþvG%É_?=þçwµ|Ò4w¼š<¥WO‰[ –±øü¹“ï·ó^ƒ>`æ;ŸƒÀ&¹¿¬vO³Åˆï7h Ô¿ÿÉ 1?ïM›þñà}+üÜŒº?ïQ£~ñĘû¤Ϋ'Žùé|`3|Â<ÁŒZcb:‚™å¯¸-¼7 TãÚ,lðÅ¥£D,=ð\†™y¦£ÝÐýÆ)O*ƒŸ Îyè!ôÉùÒ9Ed㦑?>ÒÕYÑ]ŸèÀ¤ÐïIçT‡ ^SÖ~·¼hìFöû¶îNó)¶ï£þñ‘T˜í‘€²¹Þ%îœêP²[à:ÇeØ~9q»Ñ¼Mo«ŸQÀl6ë/Òu;}b-¾ZÛÉ ¸±ô;Z¨>4cmxçx‡*uñ%r‹ÇÁàNÁ½—N|‰+±“@¯¿ÚÂS@uoFØ>fÎàJƒ›F¼q•䀥Ü{MÖ1Ó²ðö—}êpH³ ;F !q×€ dèÖÑàèˆÊ%¬z&„[–ã å(7?H“27ò¤ªÔÞ–,v.E1ز¾`õÃRª²Vg{y´y¼!—Kx²¢²ûó‚:öŸ ”;ýQ+ißFXçº&`䱉÷·ù÷bèÛV" gèw àØûÐóS!{~ ö$$$$$|ÚŽì¾#ÿ¯‚_/ÐÞM¥\}Bß“k>G ¿–èó ãò­çMl¿ÿ`]ùà°„ÿiÚ¬Lì/þ^ÜN>4äp­Ô¯¥ºÆŸ¶^ÎuFK?_ë œ ô¿vû6œÑýìF*Ìkp ámQrWh<³Ûž|p`¿-;i¾_2È2s ‘OÌË}ÿž)×G²“%Àz€Æ5¾âf\Xâ ð]…ÖÅ×”#û œ¢=/:Â|ØAÀ½Ç×W×xد¦#\J ªßª¾1~¯¯Ïû;ù©ù„„„„„Á?“ù&ªuåuûÛTŽ> &ómtëÊëö·©Ã9´8_Eæ)ו×íoS9 þù€®F¾1±áM-W[imù»V.«Îò®üCgÿ ‚åfG'+§rÕ„û¼Cà:€VnQõjðÍ ^ŽÕ—墾["÷•ãÕ3ÿ;}Ôo¿ýFô3¿.V\_ƒ¦6˜Êæî½a c…D}% ×gDõQÍÿyQÙ¿=¦è;è<øÞ×1(Ú¿ÇCB`¾md°:ñ[À|ûV@¡¸Ë“cB¨=ÅêsY3°hëGÁ?àÔšAÐ b|.wªÞA’÷ÏYZÞðÓ%›{ •£èû1¶éct]9޾™M©uå8úe7 ¥×•¨‡Éö÷ãò=$ÂØ—“]öÝÈŒÅÿèáa£úJBÈŒ h~tÉìÏß:’|òcÀ§þHHHHHHHØ6²» DwAB±þF׌ý} CF¦"º®@¿ÞwÉþmx·÷NÙO=Àno·/t¬`Nû¦¾¢òýŠ®œñUÛw|`S¨ê+,ß)û7õ€;oÿ¦Oûïí³ÿîø@ÔÖ±»ùŸpàø? Ôse%©PIEND®B`‚./public/stylesheets/images/ui-bg_glass_80_e6e6e6_1x400.png0000644000175000017500000000016111773315157022753 0ustar tfheentfheen‰PNG  IHDRoX Û8IDAT8íϱ 0BQuÿUત¼#d€l|¬„í%!|KUÍ$9‘4‡Îc ù™  ôRFºÓIEND®B`‚./public/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png0000644000175000017500000000016711773315157023120 0ustar tfheentfheen‰PNG  IHDRoX Û>IDAT8íÏ1 €0CÑŸÜÿ¶‚ ã$ˆC×BÉòøÃ}1@)e_Æ…“`I8è-%cøM0ŸÒê ¥”)ˆ" ¾ ˆLIEND®B`‚./public/stylesheets/images/ui-icons_2694e8_256x240.png0000644000175000017500000001043311773315157022020 0ustar tfheentfheen‰PNG  IHDRðØIJùíPLTE&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”è&”èxë‹XNtRNS2P¿ƒ™."Tp@f`Í <BHJZ&0R,…4‡ÃjÉÏÇ8D½¹|«µ¥©­³(ýŸ$ï £b•¡¯lßF>n~‘hhÒHýIDATxœí] cÛ¶ÉHªå„’-kiìZK:gó’lk×n­š-©ÓtI×õþÿÏ>p,‰’|J,wàÉJ%$$2Èö­ÂŽ‘A¸œ5ÕnnF€)Í0†­~ aÈô³G˜>¤Ü”9;`çÛ_{u î’n5‘_AA@ðl6™§ÇB诼×0PcPz@@º.ïq‡¬„ŠüK ßCb (пø$QŸÌûâØ±6ìêÿ)°wÜÿ@(!!!!!áFx>àð!â”°Ažê¡ù€ýÇA\ìóÈœeÿ¼¾§º £Å­ßo(ìQ@jœ±rV›gK"; 4çÉž{M†¤ÞKÆN`µ…ÁÝ„ES=°ô7jHöÝ´¡ù€è-Ä› WïÛ¼ÈÖ¹dë6' ÷<ıóù€Ã27!!!!!!!¡GløÇ—ªbíoœxlØ€Ð?hÐ-¥È r;€P(Òš<:C¤ÇöŪÐÓ¡«ÌßAPOi¸_ !‚D¹hLX »V…uƒRvt®Ð¿L—%aݧ{ðX?=P…Xצ>ê‹9,¡N„¢° o Oûü ùN»h¼‡@¡8?z{ö&Vh‘O)F/H¤q—ÇJ÷ýØñù·ØÑ‘ð‰`óm©†RPäâ‹C#N¸4k£Vê œÏó•CŸ¨\áÅ©¢:S¹;9¶Tç%P°ìß“ßrBmKðjeÕQ$µõlvÏ‚Dö†û: AþÄÆwÏ|‹‡"ÀÕ1EbíœyH‡=Ù8?âÓ_(à/õ4À4”ç{| ûtA€Ð@ªGËù-'À¯="*DŠEÂLEVò[ÀÛ7€Üì‰Þþ»<ë¬!îŽu<FÀAO%AY©–b38¼Ï5 ûµ@§ó{Ø«xw±‡à*Mîûþ|LBBBBBÂAc·Oq¨°ÊzÎØn`o.Ho ªÒÐÌk?a-¶òå)æ :_ æC¨|CT‘¢Ø¿î²Aûƒ–Ó¼m†*€0X‘ìS…aÕ7Hˆ‰¶(ðýžP›­W }CÉAs.¹’Î-Ф›Dž«„Ògð($4>Ïe`¥®,÷Ü™GC‘î¢[Bf÷RÍíÃ>.®xu½¶ý`pƒš™LÙý|¿§œ ¾Û5ãVùm€x¸ÌNÙ‡œ"ÙklPlþ!<tqßíKHHHH¸ßÈïøƒÌvÈå-&â·±ÿ–¼Ë,4úÊ£«³Fƒ¢ò„Û{‹´¡ýiemjî"7+¯Í*põ•pÖ‡g¹t™½ðíõÚ~’Ì{NZÅElo‡E@³zÝ©Ž1&grý®|ïJ°IŽeí-v(·À  êcÆ‚:< ®Ë¦ìòá1€ÕðÎÐäÎKøÀÇ‚Crÿá§€wÈGõs¿A|Š«Aß•¹:¢q@´<^§Á]ÿN!Ö±?!!!!áÓBaâ„bõúv§ÅP+7†j|‰Üਠ•ºL,xqæãŒÕRŸœq¬ÅcÕ!óBõ°;¡1 •å{öwBˆ ‹&<t”Lk §ÄÞVc.‹•­ãº¼Ñz0†ÁÆ¢€Éßkëª_m’V–e^2" À¸èÀõxDÐMŸh´¡44€ói’[ ¤Á NO ÀÌf³Ðꑱ¼‚—€cB ÓÑMH† ©¤„Ÿty ½™Žë1 ‘«íðHã3{ú™#àt~ü;BÀãÇ»àb³u§‹rŒýŸc¨K¶ŸúTt tzÀ‰1†'n °þß`ÚGSlUs®A} v —î~iS_6bl·9ö¤–'í¹Uhr¼²¬Ô˜>e𹦳­3vH?¶CQ8F&м]r¤Užµœ—ŠÂ7ö+Ä€>Ù€­4ÑÈflBÁ•åêz´”&˜ËÛg{n¸àkúà9³ßJsg¿‰ÍÛì—?ê×#¬P¡¯sꓵAÖ¨?©kõgœß޵0&²¢òÙà ÉFÿé´KA€:ö«ÄÆáÇie§¹ «‹6»’°tÔ‹‹—¯Î/дQ¡ýÛMøÄø üU¿FØ@]:f2N>tn<@åSª`Ì»ÅYÒß³FDãÀM5•pÔÌØuPNÖWÿoðÌ)¤íGSvqøJ}­þ.™\2¸dPÛß\ÁªAªÍoYßTÒ7­‚6™Ç¹˜1ÀÙ'àÅÅÇúå·¿ŽÔ19ØY§Fþ ¾Õ¯4²éßãV.˜ŒÊíý«Ñ Šœ€&»kÇjNş £< †j8_d´éßþvG%É_?=þçwµ|Ò4w¼š<¥WO‰[ –±øü¹“ï·ó^ƒ>`æ;ŸƒÀ&¹¿¬vO³Åˆï7h Ô¿ÿÉ 1?ïM›þñà}+üÜŒº?ïQ£~ñĘû¤Ϋ'Žùé|`3|Â<ÁŒZcb:‚™å¯¸-¼7 TãÚ,lðÅ¥£D,=ð\†™y¦£ÝÐýÆ)O*ƒŸ Îyè!ôÉùÒ9Ed㦑?>ÒÕYÑ]ŸèÀ¤ÐïIçT‡ ^SÖ~·¼hìFöû¶îNó)¶ï£þñ‘T˜í‘€²¹Þ%îœêP²[à:ÇeØ~9q»Ñ¼Mo«ŸQÀl6ë/Òu;}b-¾ZÛÉ ¸±ô;Z¨>4cmxçx‡*uñ%r‹ÇÁàNÁ½—N|‰+±“@¯¿ÚÂS@uoFØ>fÎàJƒ›F¼q•䀥Ü{MÖ1Ó²ðö—}êpH³ ;F !q×€ dèÖÑàèˆÊ%¬z&„[–ã å(7?H“27ò¤ªÔÞ–,v.E1ز¾`õÃRª²Vg{y´y¼!—Kx²¢²ûó‚:öŸ ”;ýQ+ißFXçº&`䱉÷·ù÷bèÛV" gèw àØûÐóS!{~ ö$$$$$|ÚŽì¾#ÿ¯‚_/ÐÞM¥\}Bß“k>G ¿–èó ãò­çMl¿ÿ`]ùà°„ÿiÚ¬Lì/þ^ÜN>4äp­Ô¯¥ºÆŸ¶^ÎuFK?_ë œ ô¿vû6œÑýìF*Ìkp ámQrWh<³Ûž|p`¿-;i¾_2È2s ‘OÌË}ÿž)×G²“%Àz€Æ5¾âf\Xâ ð]…ÖÅ×”#û œ¢=/:Â|ØAÀ½Ç×W×xد¦#\J ªßª¾1~¯¯Ïû;ù©ù„„„„„Á?“ù&ªuåuûÛTŽ> &ómtëÊëö·©Ã9´8_Eæ)ו×íoS9 þù€®F¾1±áM-W[imù»V.«Îò®üCgÿ ‚åfG'+§rÕ„û¼Cà:€VnQõjðÍ ^ŽÕ—墾["÷•ãÕ3ÿ;}Ôo¿ýFô3¿.V\_ƒ¦6˜Êæî½a c…D}% ×gDõQÍÿyQÙ¿=¦è;è<øÞ×1(Ú¿ÇCB`¾md°:ñ[À|ûV@¡¸Ë“cB¨=ÅêsY3°hëGÁ?àÔšAÐ b|.wªÞA’÷ÏYZÞðÓ%›{ •£èû1¶éct]9޾™M©uå8úe7 ¥×•¨‡Éö÷ãò=$ÂØ—“]öÝÈŒÅÿèáa£úJBÈŒ h~tÉìÏß:’|òcÀ§þHHHHHHHØ6²» DwAB±þF׌ý} CF¦"º®@¿ÞwÉþmx·÷NÙO=Àno·/t¬`Nû¦¾¢òýŠ®œñUÛw|`S¨ê+,ß)û7õ€;oÿ¦Oûïí³ÿîø@ÔÖ±»ùŸpàø? Ôse%©PIEND®B`‚./public/stylesheets/images/ui-bg_diagonals-small_0_aaaaaa_40x40.png0000644000175000017500000000020011773315157025003 0ustar tfheentfheen‰PNG  IHDR((Œþ¸mGIDATX…íÎ1À 1À¿’7Y$tÈÐÙ3ó¬;_ÞTUAUPTUAUPTUAUPTUAUPTUAu0™Mš–IEND®B`‚./public/stylesheets/images/ui-icons_cd0a0a_256x240.png0000644000175000017500000001043311773315157022207 0ustar tfheentfheen‰PNG  IHDRðØIJùíPLTEÍ Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í ê7˜üNtRNS2P¿ƒ™."Tp@f`Í <BHJZ&0R,…4‡ÃjÉÏÇ8D½¹|«µ¥©­³(ýŸ$ï £b•¡¯lßF>n~‘hhÒHýIDATxœí] cÛ¶ÉHªå„’-kiìZK:gó’lk×n­š-©ÓtI×õþÿÏ>p,‰’|J,wàÉJ%$$2Èö­ÂŽ‘A¸œ5ÕnnF€)Í0†­~ aÈô³G˜>¤Ü”9;`çÛ_{u î’n5‘_AA@ðl6™§ÇB诼×0PcPz@@º.ïq‡¬„ŠüK ßCb (пø$QŸÌûâØ±6ìêÿ)°wÜÿ@(!!!!!áFx>àð!â”°Ažê¡ù€ýÇA\ìóÈœeÿ¼¾§º £Å­ßo(ìQ@jœ±rV›gK"; 4çÉž{M†¤ÞKÆN`µ…ÁÝ„ES=°ô7jHöÝ´¡ù€è-Ä› WïÛ¼ÈÖ¹dë6' ÷<ıóù€Ã27!!!!!!!¡GløÇ—ªbíoœxlØ€Ð?hÐ-¥È r;€P(Òš<:C¤ÇöŪÐÓ¡«ÌßAPOi¸_ !‚D¹hLX »V…uƒRvt®Ð¿L—%aݧ{ðX?=P…Xצ>ê‹9,¡N„¢° o Oûü ùN»h¼‡@¡8?z{ö&Vh‘O)F/H¤q—ÇJ÷ýØñù·ØÑ‘ð‰`óm©†RPäâ‹C#N¸4k£Vê œÏó•CŸ¨\áÅ©¢:S¹;9¶Tç%P°ìß“ßrBmKðjeÕQ$µõlvÏ‚Dö†û: AþÄÆwÏ|‹‡"ÀÕ1EbíœyH‡=Ù8?âÓ_(à/õ4À4”ç{| ûtA€Ð@ªGËù-'À¯="*DŠEÂLEVò[ÀÛ7€Üì‰Þþ»<ë¬!îŽu<FÀAO%AY©–b38¼Ï5 ûµ@§ó{Ø«xw±‡à*Mîûþ|LBBBBBÂAc·Oq¨°ÊzÎØn`o.Ho ªÒÐÌk?a-¶òå)æ :_ æC¨|CT‘¢Ø¿î²Aûƒ–Ó¼m†*€0X‘ìS…aÕ7Hˆ‰¶(ðýžP›­W }CÉAs.¹’Î-Ф›Dž«„Ògð($4>Ïe`¥®,÷Ü™GC‘î¢[Bf÷RÍíÃ>.®xu½¶ý`pƒš™LÙý|¿§œ ¾Û5ãVùm€x¸ÌNÙ‡œ"ÙklPlþ!<tqßíKHHHH¸ßÈïøƒÌvÈå-&â·±ÿ–¼Ë,4úÊ£«³Fƒ¢ò„Û{‹´¡ýiemjî"7+¯Í*põ•pÖ‡g¹t™½ðíõÚ~’Ì{NZÅElo‡E@³zÝ©Ž1&grý®|ïJ°IŽeí-v(·À  êcÆ‚:< ®Ë¦ìòá1€ÕðÎÐäÎKøÀÇ‚Crÿá§€wÈGõs¿A|Š«Aß•¹:¢q@´<^§Á]ÿN!Ö±?!!!!áÓBaâ„bõúv§ÅP+7†j|‰Üਠ•ºL,xqæãŒÕRŸœq¬ÅcÕ!óBõ°;¡1 •å{öwBˆ ‹&<t”Lk §ÄÞVc.‹•­ãº¼Ñz0†ÁÆ¢€Éßkëª_m’V–e^2" À¸èÀõxDÐMŸh´¡44€ói’[ ¤Á NO ÀÌf³Ðꑱ¼‚—€cB ÓÑMH† ©¤„Ÿty ½™Žë1 ‘«íðHã3{ú™#àt~ü;BÀãÇ»àb³u§‹rŒýŸc¨K¶ŸúTt tzÀ‰1†'n °þß`ÚGSlUs®A} v —î~iS_6bl·9ö¤–'í¹Uhr¼²¬Ô˜>e𹦳­3vH?¶CQ8F&м]r¤Užµœ—ŠÂ7ö+Ä€>Ù€­4ÑÈflBÁ•åêz´”&˜ËÛg{n¸àkúà9³ßJsg¿‰ÍÛì—?ê×#¬P¡¯sꓵAÖ¨?©kõgœß޵0&²¢òÙà ÉFÿé´KA€:ö«ÄÆáÇie§¹ «‹6»’°tÔ‹‹—¯Î/дQ¡ýÛMøÄø üU¿FØ@]:f2N>tn<@åSª`Ì»ÅYÒß³FDãÀM5•pÔÌØuPNÖWÿoðÌ)¤íGSvqøJ}­þ.™\2¸dPÛß\ÁªAªÍoYßTÒ7­‚6™Ç¹˜1ÀÙ'àÅÅÇúå·¿ŽÔ19ØY§Fþ ¾Õ¯4²éßãV.˜ŒÊíý«Ñ Šœ€&»kÇjNş £< †j8_d´éßþvG%É_?=þçwµ|Ò4w¼š<¥WO‰[ –±øü¹“ï·ó^ƒ>`æ;ŸƒÀ&¹¿¬vO³Åˆï7h Ô¿ÿÉ 1?ïM›þñà}+üÜŒº?ïQ£~ñĘû¤Ϋ'Žùé|`3|Â<ÁŒZcb:‚™å¯¸-¼7 TãÚ,lðÅ¥£D,=ð\†™y¦£ÝÐýÆ)O*ƒŸ Îyè!ôÉùÒ9Ed㦑?>ÒÕYÑ]ŸèÀ¤ÐïIçT‡ ^SÖ~·¼hìFöû¶îNó)¶ï£þñ‘T˜í‘€²¹Þ%îœêP²[à:ÇeØ~9q»Ñ¼Mo«ŸQÀl6ë/Òu;}b-¾ZÛÉ ¸±ô;Z¨>4cmxçx‡*uñ%r‹ÇÁàNÁ½—N|‰+±“@¯¿ÚÂS@uoFØ>fÎàJƒ›F¼q•䀥Ü{MÖ1Ó²ðö—}êpH³ ;F !q×€ dèÖÑàèˆÊ%¬z&„[–ã å(7?H“27ò¤ªÔÞ–,v.E1ز¾`õÃRª²Vg{y´y¼!—Kx²¢²ûó‚:öŸ ”;ýQ+ißFXçº&`䱉÷·ù÷bèÛV" gèw àØûÐóS!{~ ö$$$$$|ÚŽì¾#ÿ¯‚_/ÐÞM¥\}Bß“k>G ¿–èó ãò­çMl¿ÿ`]ùà°„ÿiÚ¬Lì/þ^ÜN>4äp­Ô¯¥ºÆŸ¶^ÎuFK?_ë œ ô¿vû6œÑýìF*Ìkp ámQrWh<³Ûž|p`¿-;i¾_2È2s ‘OÌË}ÿž)×G²“%Àz€Æ5¾âf\Xâ ð]…ÖÅ×”#û œ¢=/:Â|ØAÀ½Ç×W×xد¦#\J ªßª¾1~¯¯Ïû;ù©ù„„„„„Á?“ù&ªuåuûÛTŽ> &ómtëÊëö·©Ã9´8_Eæ)ו×íoS9 þù€®F¾1±áM-W[imù»V.«Îò®üCgÿ ‚åfG'+§rÕ„û¼Cà:€VnQõjðÍ ^ŽÕ—墾["÷•ãÕ3ÿ;}Ôo¿ýFô3¿.V\_ƒ¦6˜Êæî½a c…D}% ×gDõQÍÿyQÙ¿=¦è;è<øÞ×1(Ú¿ÇCB`¾md°:ñ[À|ûV@¡¸Ë“cB¨=ÅêsY3°hëGÁ?àÔšAÐ b|.wªÞA’÷ÏYZÞðÓ%›{ •£èû1¶éct]9޾™M©uå8úe7 ¥×•¨‡Éö÷ãò=$ÂØ—“]öÝÈŒÅÿèáa£úJBÈŒ h~tÉìÏß:’|òcÀ§þHHHHHHHØ6²» DwAB±þF׌ý} CF¦"º®@¿ÞwÉþmx·÷NÙO=Àno·/t¬`Nû¦¾¢òýŠ®œñUÛw|`S¨ê+,ß)û7õ€;oÿ¦Oûïí³ÿîø@ÔÖ±»ùŸpàø? Ôse%©PIEND®B`‚./public/stylesheets/images/ui-bg_highlight-hard_100_f9f9f9_1x100.png0000644000175000017500000000012611773315157024610 0ustar tfheentfheen‰PNG  IHDRdG,Z`IDAT•cøóçÏ&†áJüÿÿŸl±áIM" ±¶tg¯IEND®B`‚./public/stylesheets/images/ui-icons_2e83ff_256x240.png0000644000175000017500000001043311773315157022154 0ustar tfheentfheen‰PNG  IHDRðØIJùíPLTE.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ.ƒÿ%̘NtRNS2P¿ƒ™."Tp@f`Í <BHJZ&0R,…4‡ÃjÉÏÇ8D½¹|«µ¥©­³(ýŸ$ï £b•¡¯lßF>n~‘hhÒHýIDATxœí] cÛ¶ÉHªå„’-kiìZK:gó’lk×n­š-©ÓtI×õþÿÏ>p,‰’|J,wàÉJ%$$2Èö­ÂŽ‘A¸œ5ÕnnF€)Í0†­~ aÈô³G˜>¤Ü”9;`çÛ_{u î’n5‘_AA@ðl6™§ÇB诼×0PcPz@@º.ïq‡¬„ŠüK ßCb (пø$QŸÌûâØ±6ìêÿ)°wÜÿ@(!!!!!áFx>àð!â”°Ažê¡ù€ýÇA\ìóÈœeÿ¼¾§º £Å­ßo(ìQ@jœ±rV›gK"; 4çÉž{M†¤ÞKÆN`µ…ÁÝ„ES=°ô7jHöÝ´¡ù€è-Ä› WïÛ¼ÈÖ¹dë6' ÷<ıóù€Ã27!!!!!!!¡GløÇ—ªbíoœxlØ€Ð?hÐ-¥È r;€P(Òš<:C¤ÇöŪÐÓ¡«ÌßAPOi¸_ !‚D¹hLX »V…uƒRvt®Ð¿L—%aݧ{ðX?=P…Xצ>ê‹9,¡N„¢° o Oûü ùN»h¼‡@¡8?z{ö&Vh‘O)F/H¤q—ÇJ÷ýØñù·ØÑ‘ð‰`óm©†RPäâ‹C#N¸4k£Vê œÏó•CŸ¨\áÅ©¢:S¹;9¶Tç%P°ìß“ßrBmKðjeÕQ$µõlvÏ‚Dö†û: AþÄÆwÏ|‹‡"ÀÕ1EbíœyH‡=Ù8?âÓ_(à/õ4À4”ç{| ûtA€Ð@ªGËù-'À¯="*DŠEÂLEVò[ÀÛ7€Üì‰Þþ»<ë¬!îŽu<FÀAO%AY©–b38¼Ï5 ûµ@§ó{Ø«xw±‡à*Mîûþ|LBBBBBÂAc·Oq¨°ÊzÎØn`o.Ho ªÒÐÌk?a-¶òå)æ :_ æC¨|CT‘¢Ø¿î²Aûƒ–Ó¼m†*€0X‘ìS…aÕ7Hˆ‰¶(ðýžP›­W }CÉAs.¹’Î-Ф›Dž«„Ògð($4>Ïe`¥®,÷Ü™GC‘î¢[Bf÷RÍíÃ>.®xu½¶ý`pƒš™LÙý|¿§œ ¾Û5ãVùm€x¸ÌNÙ‡œ"ÙklPlþ!<tqßíKHHHH¸ßÈïøƒÌvÈå-&â·±ÿ–¼Ë,4úÊ£«³Fƒ¢ò„Û{‹´¡ýiemjî"7+¯Í*põ•pÖ‡g¹t™½ðíõÚ~’Ì{NZÅElo‡E@³zÝ©Ž1&grý®|ïJ°IŽeí-v(·À  êcÆ‚:< ®Ë¦ìòá1€ÕðÎÐäÎKøÀÇ‚Crÿá§€wÈGõs¿A|Š«Aß•¹:¢q@´<^§Á]ÿN!Ö±?!!!!áÓBaâ„bõúv§ÅP+7†j|‰Üਠ•ºL,xqæãŒÕRŸœq¬ÅcÕ!óBõ°;¡1 •å{öwBˆ ‹&<t”Lk §ÄÞVc.‹•­ãº¼Ñz0†ÁÆ¢€Éßkëª_m’V–e^2" À¸èÀõxDÐMŸh´¡44€ói’[ ¤Á NO ÀÌf³Ðꑱ¼‚—€cB ÓÑMH† ©¤„Ÿty ½™Žë1 ‘«íðHã3{ú™#àt~ü;BÀãÇ»àb³u§‹rŒýŸc¨K¶ŸúTt tzÀ‰1†'n °þß`ÚGSlUs®A} v —î~iS_6bl·9ö¤–'í¹Uhr¼²¬Ô˜>e𹦳­3vH?¶CQ8F&м]r¤Užµœ—ŠÂ7ö+Ä€>Ù€­4ÑÈflBÁ•åêz´”&˜ËÛg{n¸àkúà9³ßJsg¿‰ÍÛì—?ê×#¬P¡¯sꓵAÖ¨?©kõgœß޵0&²¢òÙà ÉFÿé´KA€:ö«ÄÆáÇie§¹ «‹6»’°tÔ‹‹—¯Î/дQ¡ýÛMøÄø üU¿FØ@]:f2N>tn<@åSª`Ì»ÅYÒß³FDãÀM5•pÔÌØuPNÖWÿoðÌ)¤íGSvqøJ}­þ.™\2¸dPÛß\ÁªAªÍoYßTÒ7­‚6™Ç¹˜1ÀÙ'àÅÅÇúå·¿ŽÔ19ØY§Fþ ¾Õ¯4²éßãV.˜ŒÊíý«Ñ Šœ€&»kÇjNş £< †j8_d´éßþvG%É_?=þçwµ|Ò4w¼š<¥WO‰[ –±øü¹“ï·ó^ƒ>`æ;ŸƒÀ&¹¿¬vO³Åˆï7h Ô¿ÿÉ 1?ïM›þñà}+üÜŒº?ïQ£~ñĘû¤Ϋ'Žùé|`3|Â<ÁŒZcb:‚™å¯¸-¼7 TãÚ,lðÅ¥£D,=ð\†™y¦£ÝÐýÆ)O*ƒŸ Îyè!ôÉùÒ9Ed㦑?>ÒÕYÑ]ŸèÀ¤ÐïIçT‡ ^SÖ~·¼hìFöû¶îNó)¶ï£þñ‘T˜í‘€²¹Þ%îœêP²[à:ÇeØ~9q»Ñ¼Mo«ŸQÀl6ë/Òu;}b-¾ZÛÉ ¸±ô;Z¨>4cmxçx‡*uñ%r‹ÇÁàNÁ½—N|‰+±“@¯¿ÚÂS@uoFØ>fÎàJƒ›F¼q•䀥Ü{MÖ1Ó²ðö—}êpH³ ;F !q×€ dèÖÑàèˆÊ%¬z&„[–ã å(7?H“27ò¤ªÔÞ–,v.E1ز¾`õÃRª²Vg{y´y¼!—Kx²¢²ûó‚:öŸ ”;ýQ+ißFXçº&`䱉÷·ù÷bèÛV" gèw àØûÐóS!{~ ö$$$$$|ÚŽì¾#ÿ¯‚_/ÐÞM¥\}Bß“k>G ¿–èó ãò­çMl¿ÿ`]ùà°„ÿiÚ¬Lì/þ^ÜN>4äp­Ô¯¥ºÆŸ¶^ÎuFK?_ë œ ô¿vû6œÑýìF*Ìkp ámQrWh<³Ûž|p`¿-;i¾_2È2s ‘OÌË}ÿž)×G²“%Àz€Æ5¾âf\Xâ ð]…ÖÅ×”#û œ¢=/:Â|ØAÀ½Ç×W×xد¦#\J ªßª¾1~¯¯Ïû;ù©ù„„„„„Á?“ù&ªuåuûÛTŽ> &ómtëÊëö·©Ã9´8_Eæ)ו×íoS9 þù€®F¾1±áM-W[imù»V.«Îò®üCgÿ ‚åfG'+§rÕ„û¼Cà:€VnQõjðÍ ^ŽÕ—墾["÷•ãÕ3ÿ;}Ôo¿ýFô3¿.V\_ƒ¦6˜Êæî½a c…D}% ×gDõQÍÿyQÙ¿=¦è;è<øÞ×1(Ú¿ÇCB`¾md°:ñ[À|ûV@¡¸Ë“cB¨=ÅêsY3°hëGÁ?àÔšAÐ b|.wªÞA’÷ÏYZÞðÓ%›{ •£èû1¶éct]9޾™M©uå8úe7 ¥×•¨‡Éö÷ãò=$ÂØ—“]öÝÈŒÅÿèáa£úJBÈŒ h~tÉìÏß:’|òcÀ§þHHHHHHHØ6²» DwAB±þF׌ý} CF¦"º®@¿ÞwÉþmx·÷NÙO=Àno·/t¬`Nû¦¾¢òýŠ®œñUÛw|`S¨ê+,ß)û7õ€;oÿ¦Oûïí³ÿîø@ÔÖ±»ùŸpàø? Ôse%©PIEND®B`‚./public/stylesheets/images/ui-icons_222222_256x240.png0000644000175000017500000001043311773315157021712 0ustar tfheentfheen‰PNG  IHDRðØIJùíPLTE"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""]šóNtRNS2P¿ƒ™."Tp@f`Í <BHJZ&0R,…4‡ÃjÉÏÇ8D½¹|«µ¥©­³(ýŸ$ï £b•¡¯lßF>n~‘hhÒHýIDATxœí] cÛ¶ÉHªå„’-kiìZK:gó’lk×n­š-©ÓtI×õþÿÏ>p,‰’|J,wàÉJ%$$2Èö­ÂŽ‘A¸œ5ÕnnF€)Í0†­~ aÈô³G˜>¤Ü”9;`çÛ_{u î’n5‘_AA@ðl6™§ÇB诼×0PcPz@@º.ïq‡¬„ŠüK ßCb (пø$QŸÌûâØ±6ìêÿ)°wÜÿ@(!!!!!áFx>àð!â”°Ažê¡ù€ýÇA\ìóÈœeÿ¼¾§º £Å­ßo(ìQ@jœ±rV›gK"; 4çÉž{M†¤ÞKÆN`µ…ÁÝ„ES=°ô7jHöÝ´¡ù€è-Ä› WïÛ¼ÈÖ¹dë6' ÷<ıóù€Ã27!!!!!!!¡GløÇ—ªbíoœxlØ€Ð?hÐ-¥È r;€P(Òš<:C¤ÇöŪÐÓ¡«ÌßAPOi¸_ !‚D¹hLX »V…uƒRvt®Ð¿L—%aݧ{ðX?=P…Xצ>ê‹9,¡N„¢° o Oûü ùN»h¼‡@¡8?z{ö&Vh‘O)F/H¤q—ÇJ÷ýØñù·ØÑ‘ð‰`óm©†RPäâ‹C#N¸4k£Vê œÏó•CŸ¨\áÅ©¢:S¹;9¶Tç%P°ìß“ßrBmKðjeÕQ$µõlvÏ‚Dö†û: AþÄÆwÏ|‹‡"ÀÕ1EbíœyH‡=Ù8?âÓ_(à/õ4À4”ç{| ûtA€Ð@ªGËù-'À¯="*DŠEÂLEVò[ÀÛ7€Üì‰Þþ»<ë¬!îŽu<FÀAO%AY©–b38¼Ï5 ûµ@§ó{Ø«xw±‡à*Mîûþ|LBBBBBÂAc·Oq¨°ÊzÎØn`o.Ho ªÒÐÌk?a-¶òå)æ :_ æC¨|CT‘¢Ø¿î²Aûƒ–Ó¼m†*€0X‘ìS…aÕ7Hˆ‰¶(ðýžP›­W }CÉAs.¹’Î-Ф›Dž«„Ògð($4>Ïe`¥®,÷Ü™GC‘î¢[Bf÷RÍíÃ>.®xu½¶ý`pƒš™LÙý|¿§œ ¾Û5ãVùm€x¸ÌNÙ‡œ"ÙklPlþ!<tqßíKHHHH¸ßÈïøƒÌvÈå-&â·±ÿ–¼Ë,4úÊ£«³Fƒ¢ò„Û{‹´¡ýiemjî"7+¯Í*põ•pÖ‡g¹t™½ðíõÚ~’Ì{NZÅElo‡E@³zÝ©Ž1&grý®|ïJ°IŽeí-v(·À  êcÆ‚:< ®Ë¦ìòá1€ÕðÎÐäÎKøÀÇ‚Crÿá§€wÈGõs¿A|Š«Aß•¹:¢q@´<^§Á]ÿN!Ö±?!!!!áÓBaâ„bõúv§ÅP+7†j|‰Üਠ•ºL,xqæãŒÕRŸœq¬ÅcÕ!óBõ°;¡1 •å{öwBˆ ‹&<t”Lk §ÄÞVc.‹•­ãº¼Ñz0†ÁÆ¢€Éßkëª_m’V–e^2" À¸èÀõxDÐMŸh´¡44€ói’[ ¤Á NO ÀÌf³Ðꑱ¼‚—€cB ÓÑMH† ©¤„Ÿty ½™Žë1 ‘«íðHã3{ú™#àt~ü;BÀãÇ»àb³u§‹rŒýŸc¨K¶ŸúTt tzÀ‰1†'n °þß`ÚGSlUs®A} v —î~iS_6bl·9ö¤–'í¹Uhr¼²¬Ô˜>e𹦳­3vH?¶CQ8F&м]r¤Užµœ—ŠÂ7ö+Ä€>Ù€­4ÑÈflBÁ•åêz´”&˜ËÛg{n¸àkúà9³ßJsg¿‰ÍÛì—?ê×#¬P¡¯sꓵAÖ¨?©kõgœß޵0&²¢òÙà ÉFÿé´KA€:ö«ÄÆáÇie§¹ «‹6»’°tÔ‹‹—¯Î/дQ¡ýÛMøÄø üU¿FØ@]:f2N>tn<@åSª`Ì»ÅYÒß³FDãÀM5•pÔÌØuPNÖWÿoðÌ)¤íGSvqøJ}­þ.™\2¸dPÛß\ÁªAªÍoYßTÒ7­‚6™Ç¹˜1ÀÙ'àÅÅÇúå·¿ŽÔ19ØY§Fþ ¾Õ¯4²éßãV.˜ŒÊíý«Ñ Šœ€&»kÇjNş £< †j8_d´éßþvG%É_?=þçwµ|Ò4w¼š<¥WO‰[ –±øü¹“ï·ó^ƒ>`æ;ŸƒÀ&¹¿¬vO³Åˆï7h Ô¿ÿÉ 1?ïM›þñà}+üÜŒº?ïQ£~ñĘû¤Ϋ'Žùé|`3|Â<ÁŒZcb:‚™å¯¸-¼7 TãÚ,lðÅ¥£D,=ð\†™y¦£ÝÐýÆ)O*ƒŸ Îyè!ôÉùÒ9Ed㦑?>ÒÕYÑ]ŸèÀ¤ÐïIçT‡ ^SÖ~·¼hìFöû¶îNó)¶ï£þñ‘T˜í‘€²¹Þ%îœêP²[à:ÇeØ~9q»Ñ¼Mo«ŸQÀl6ë/Òu;}b-¾ZÛÉ ¸±ô;Z¨>4cmxçx‡*uñ%r‹ÇÁàNÁ½—N|‰+±“@¯¿ÚÂS@uoFØ>fÎàJƒ›F¼q•䀥Ü{MÖ1Ó²ðö—}êpH³ ;F !q×€ dèÖÑàèˆÊ%¬z&„[–ã å(7?H“27ò¤ªÔÞ–,v.E1ز¾`õÃRª²Vg{y´y¼!—Kx²¢²ûó‚:öŸ ”;ýQ+ißFXçº&`䱉÷·ù÷bèÛV" gèw àØûÐóS!{~ ö$$$$$|ÚŽì¾#ÿ¯‚_/ÐÞM¥\}Bß“k>G ¿–èó ãò­çMl¿ÿ`]ùà°„ÿiÚ¬Lì/þ^ÜN>4äp­Ô¯¥ºÆŸ¶^ÎuFK?_ë œ ô¿vû6œÑýìF*Ìkp ámQrWh<³Ûž|p`¿-;i¾_2È2s ‘OÌË}ÿž)×G²“%Àz€Æ5¾âf\Xâ ð]…ÖÅ×”#û œ¢=/:Â|ØAÀ½Ç×W×xد¦#\J ªßª¾1~¯¯Ïû;ù©ù„„„„„Á?“ù&ªuåuûÛTŽ> &ómtëÊëö·©Ã9´8_Eæ)ו×íoS9 þù€®F¾1±áM-W[imù»V.«Îò®üCgÿ ‚åfG'+§rÕ„û¼Cà:€VnQõjðÍ ^ŽÕ—墾["÷•ãÕ3ÿ;}Ôo¿ýFô3¿.V\_ƒ¦6˜Êæî½a c…D}% ×gDõQÍÿyQÙ¿=¦è;è<øÞ×1(Ú¿ÇCB`¾md°:ñ[À|ûV@¡¸Ë“cB¨=ÅêsY3°hëGÁ?àÔšAÐ b|.wªÞA’÷ÏYZÞðÓ%›{ •£èû1¶éct]9޾™M©uå8úe7 ¥×•¨‡Éö÷ãò=$ÂØ—“]öÝÈŒÅÿèáa£úJBÈŒ h~tÉìÏß:’|òcÀ§þHHHHHHHØ6²» DwAB±þF׌ý} CF¦"º®@¿ÞwÉþmx·÷NÙO=Àno·/t¬`Nû¦¾¢òýŠ®œñUÛw|`S¨ê+,ß)û7õ€;oÿ¦Oûïí³ÿîø@ÔÖ±»ùŸpàø? Ôse%©PIEND®B`‚./public/stylesheets/images/ui-icons_72a7cf_256x240.png0000644000175000017500000001043311773315157022150 0ustar tfheentfheen‰PNG  IHDRðØIJùíPLTEr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§Ïr§ÏÂüeyNtRNS2P¿ƒ™."Tp@f`Í <BHJZ&0R,…4‡ÃjÉÏÇ8D½¹|«µ¥©­³(ýŸ$ï £b•¡¯lßF>n~‘hhÒHýIDATxœí] cÛ¶ÉHªå„’-kiìZK:gó’lk×n­š-©ÓtI×õþÿÏ>p,‰’|J,wàÉJ%$$2Èö­ÂŽ‘A¸œ5ÕnnF€)Í0†­~ aÈô³G˜>¤Ü”9;`çÛ_{u î’n5‘_AA@ðl6™§ÇB诼×0PcPz@@º.ïq‡¬„ŠüK ßCb (пø$QŸÌûâØ±6ìêÿ)°wÜÿ@(!!!!!áFx>àð!â”°Ažê¡ù€ýÇA\ìóÈœeÿ¼¾§º £Å­ßo(ìQ@jœ±rV›gK"; 4çÉž{M†¤ÞKÆN`µ…ÁÝ„ES=°ô7jHöÝ´¡ù€è-Ä› WïÛ¼ÈÖ¹dë6' ÷<ıóù€Ã27!!!!!!!¡GløÇ—ªbíoœxlØ€Ð?hÐ-¥È r;€P(Òš<:C¤ÇöŪÐÓ¡«ÌßAPOi¸_ !‚D¹hLX »V…uƒRvt®Ð¿L—%aݧ{ðX?=P…Xצ>ê‹9,¡N„¢° o Oûü ùN»h¼‡@¡8?z{ö&Vh‘O)F/H¤q—ÇJ÷ýØñù·ØÑ‘ð‰`óm©†RPäâ‹C#N¸4k£Vê œÏó•CŸ¨\áÅ©¢:S¹;9¶Tç%P°ìß“ßrBmKðjeÕQ$µõlvÏ‚Dö†û: AþÄÆwÏ|‹‡"ÀÕ1EbíœyH‡=Ù8?âÓ_(à/õ4À4”ç{| ûtA€Ð@ªGËù-'À¯="*DŠEÂLEVò[ÀÛ7€Üì‰Þþ»<ë¬!îŽu<FÀAO%AY©–b38¼Ï5 ûµ@§ó{Ø«xw±‡à*Mîûþ|LBBBBBÂAc·Oq¨°ÊzÎØn`o.Ho ªÒÐÌk?a-¶òå)æ :_ æC¨|CT‘¢Ø¿î²Aûƒ–Ó¼m†*€0X‘ìS…aÕ7Hˆ‰¶(ðýžP›­W }CÉAs.¹’Î-Ф›Dž«„Ògð($4>Ïe`¥®,÷Ü™GC‘î¢[Bf÷RÍíÃ>.®xu½¶ý`pƒš™LÙý|¿§œ ¾Û5ãVùm€x¸ÌNÙ‡œ"ÙklPlþ!<tqßíKHHHH¸ßÈïøƒÌvÈå-&â·±ÿ–¼Ë,4úÊ£«³Fƒ¢ò„Û{‹´¡ýiemjî"7+¯Í*põ•pÖ‡g¹t™½ðíõÚ~’Ì{NZÅElo‡E@³zÝ©Ž1&grý®|ïJ°IŽeí-v(·À  êcÆ‚:< ®Ë¦ìòá1€ÕðÎÐäÎKøÀÇ‚Crÿá§€wÈGõs¿A|Š«Aß•¹:¢q@´<^§Á]ÿN!Ö±?!!!!áÓBaâ„bõúv§ÅP+7†j|‰Üਠ•ºL,xqæãŒÕRŸœq¬ÅcÕ!óBõ°;¡1 •å{öwBˆ ‹&<t”Lk §ÄÞVc.‹•­ãº¼Ñz0†ÁÆ¢€Éßkëª_m’V–e^2" À¸èÀõxDÐMŸh´¡44€ói’[ ¤Á NO ÀÌf³Ðꑱ¼‚—€cB ÓÑMH† ©¤„Ÿty ½™Žë1 ‘«íðHã3{ú™#àt~ü;BÀãÇ»àb³u§‹rŒýŸc¨K¶ŸúTt tzÀ‰1†'n °þß`ÚGSlUs®A} v —î~iS_6bl·9ö¤–'í¹Uhr¼²¬Ô˜>e𹦳­3vH?¶CQ8F&м]r¤Užµœ—ŠÂ7ö+Ä€>Ù€­4ÑÈflBÁ•åêz´”&˜ËÛg{n¸àkúà9³ßJsg¿‰ÍÛì—?ê×#¬P¡¯sꓵAÖ¨?©kõgœß޵0&²¢òÙà ÉFÿé´KA€:ö«ÄÆáÇie§¹ «‹6»’°tÔ‹‹—¯Î/дQ¡ýÛMøÄø üU¿FØ@]:f2N>tn<@åSª`Ì»ÅYÒß³FDãÀM5•pÔÌØuPNÖWÿoðÌ)¤íGSvqøJ}­þ.™\2¸dPÛß\ÁªAªÍoYßTÒ7­‚6™Ç¹˜1ÀÙ'àÅÅÇúå·¿ŽÔ19ØY§Fþ ¾Õ¯4²éßãV.˜ŒÊíý«Ñ Šœ€&»kÇjNş £< †j8_d´éßþvG%É_?=þçwµ|Ò4w¼š<¥WO‰[ –±øü¹“ï·ó^ƒ>`æ;ŸƒÀ&¹¿¬vO³Åˆï7h Ô¿ÿÉ 1?ïM›þñà}+üÜŒº?ïQ£~ñĘû¤Ϋ'Žùé|`3|Â<ÁŒZcb:‚™å¯¸-¼7 TãÚ,lðÅ¥£D,=ð\†™y¦£ÝÐýÆ)O*ƒŸ Îyè!ôÉùÒ9Ed㦑?>ÒÕYÑ]ŸèÀ¤ÐïIçT‡ ^SÖ~·¼hìFöû¶îNó)¶ï£þñ‘T˜í‘€²¹Þ%îœêP²[à:ÇeØ~9q»Ñ¼Mo«ŸQÀl6ë/Òu;}b-¾ZÛÉ ¸±ô;Z¨>4cmxçx‡*uñ%r‹ÇÁàNÁ½—N|‰+±“@¯¿ÚÂS@uoFØ>fÎàJƒ›F¼q•䀥Ü{MÖ1Ó²ðö—}êpH³ ;F !q×€ dèÖÑàèˆÊ%¬z&„[–ã å(7?H“27ò¤ªÔÞ–,v.E1ز¾`õÃRª²Vg{y´y¼!—Kx²¢²ûó‚:öŸ ”;ýQ+ißFXçº&`䱉÷·ù÷bèÛV" gèw àØûÐóS!{~ ö$$$$$|ÚŽì¾#ÿ¯‚_/ÐÞM¥\}Bß“k>G ¿–èó ãò­çMl¿ÿ`]ùà°„ÿiÚ¬Lì/þ^ÜN>4äp­Ô¯¥ºÆŸ¶^ÎuFK?_ë œ ô¿vû6œÑýìF*Ìkp ámQrWh<³Ûž|p`¿-;i¾_2È2s ‘OÌË}ÿž)×G²“%Àz€Æ5¾âf\Xâ ð]…ÖÅ×”#û œ¢=/:Â|ØAÀ½Ç×W×xد¦#\J ªßª¾1~¯¯Ïû;ù©ù„„„„„Á?“ù&ªuåuûÛTŽ> &ómtëÊëö·©Ã9´8_Eæ)ו×íoS9 þù€®F¾1±áM-W[imù»V.«Îò®üCgÿ ‚åfG'+§rÕ„û¼Cà:€VnQõjðÍ ^ŽÕ—墾["÷•ãÕ3ÿ;}Ôo¿ýFô3¿.V\_ƒ¦6˜Êæî½a c…D}% ×gDõQÍÿyQÙ¿=¦è;è<øÞ×1(Ú¿ÇCB`¾md°:ñ[À|ûV@¡¸Ë“cB¨=ÅêsY3°hëGÁ?àÔšAÐ b|.wªÞA’÷ÏYZÞðÓ%›{ •£èû1¶éct]9޾™M©uå8úe7 ¥×•¨‡Éö÷ãò=$ÂØ—“]öÝÈŒÅÿèáa£úJBÈŒ h~tÉìÏß:’|òcÀ§þHHHHHHHØ6²» DwAB±þF׌ý} CF¦"º®@¿ÞwÉþmx·÷NÙO=Àno·/t¬`Nû¦¾¢òýŠ®œñUÛw|`S¨ê+,ß)û7õ€;oÿ¦Oûïí³ÿîø@ÔÖ±»ùŸpàø? Ôse%©PIEND®B`‚./public/stylesheets/images/ui-bg_highlight-soft_100_e7eef3_1x100.png0000644000175000017500000000022511773315157024707 0ustar tfheentfheen‰PNG  IHDRd0+jö\IDAT•µŽÁ €@BþÿïQ;Ú¥‚b‹öÐå¡à82ÍKpGÙhmFk+”N€^AÔÊhi…Êù~û'ÈÎ>­|X§_ÿޱçCH‚’Cù´» r@á’ûeKÏSÝ4Ú›IEND®B`‚./public/stylesheets/images/ui-bg_glass_100_f0f0f0_1x400.png0000644000175000017500000000015211773315157023005 0ustar tfheentfheen‰PNG  IHDRoX Û1IDAT8cøöíÛ&†Qb”%†-ñë×/(‹‘‘™…‹&†Æ%F‰QbpB) b77˜IEND®B`‚./public/stylesheets/images/ui-bg_glass_55_fbf5d0_1x400.png0000644000175000017500000000023111773315157023021 0ustar tfheentfheen‰PNG  IHDR_:M`IDAT8íÔ1 €0DÑ?ƒ‚÷¿œ1’µ°ñ&Bl^±Íî°0œe ô êŽÑ‚ÑÜx9“XiÅ*yWj-XÊe Ó®jÀÀ?—»^1Fư”ž³öíóó&¢s"Y]„…ÍIEND®B`‚./public/stylesheets/images/ui-icons_ffffff_256x240.png0000644000175000017500000001043311773315157022402 0ustar tfheentfheen‰PNG  IHDRðØIJùíPLTEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿí¦à—NtRNS2P¿ƒ™."Tp@f`Í <BHJZ&0R,…4‡ÃjÉÏÇ8D½¹|«µ¥©­³(ýŸ$ï £b•¡¯lßF>n~‘hhÒHýIDATxœí] cÛ¶ÉHªå„’-kiìZK:gó’lk×n­š-©ÓtI×õþÿÏ>p,‰’|J,wàÉJ%$$2Èö­ÂŽ‘A¸œ5ÕnnF€)Í0†­~ aÈô³G˜>¤Ü”9;`çÛ_{u î’n5‘_AA@ðl6™§ÇB诼×0PcPz@@º.ïq‡¬„ŠüK ßCb (пø$QŸÌûâØ±6ìêÿ)°wÜÿ@(!!!!!áFx>àð!â”°Ažê¡ù€ýÇA\ìóÈœeÿ¼¾§º £Å­ßo(ìQ@jœ±rV›gK"; 4çÉž{M†¤ÞKÆN`µ…ÁÝ„ES=°ô7jHöÝ´¡ù€è-Ä› WïÛ¼ÈÖ¹dë6' ÷<ıóù€Ã27!!!!!!!¡GløÇ—ªbíoœxlØ€Ð?hÐ-¥È r;€P(Òš<:C¤ÇöŪÐÓ¡«ÌßAPOi¸_ !‚D¹hLX »V…uƒRvt®Ð¿L—%aݧ{ðX?=P…Xצ>ê‹9,¡N„¢° o Oûü ùN»h¼‡@¡8?z{ö&Vh‘O)F/H¤q—ÇJ÷ýØñù·ØÑ‘ð‰`óm©†RPäâ‹C#N¸4k£Vê œÏó•CŸ¨\áÅ©¢:S¹;9¶Tç%P°ìß“ßrBmKðjeÕQ$µõlvÏ‚Dö†û: AþÄÆwÏ|‹‡"ÀÕ1EbíœyH‡=Ù8?âÓ_(à/õ4À4”ç{| ûtA€Ð@ªGËù-'À¯="*DŠEÂLEVò[ÀÛ7€Üì‰Þþ»<ë¬!îŽu<FÀAO%AY©–b38¼Ï5 ûµ@§ó{Ø«xw±‡à*Mîûþ|LBBBBBÂAc·Oq¨°ÊzÎØn`o.Ho ªÒÐÌk?a-¶òå)æ :_ æC¨|CT‘¢Ø¿î²Aûƒ–Ó¼m†*€0X‘ìS…aÕ7Hˆ‰¶(ðýžP›­W }CÉAs.¹’Î-Ф›Dž«„Ògð($4>Ïe`¥®,÷Ü™GC‘î¢[Bf÷RÍíÃ>.®xu½¶ý`pƒš™LÙý|¿§œ ¾Û5ãVùm€x¸ÌNÙ‡œ"ÙklPlþ!<tqßíKHHHH¸ßÈïøƒÌvÈå-&â·±ÿ–¼Ë,4úÊ£«³Fƒ¢ò„Û{‹´¡ýiemjî"7+¯Í*põ•pÖ‡g¹t™½ðíõÚ~’Ì{NZÅElo‡E@³zÝ©Ž1&grý®|ïJ°IŽeí-v(·À  êcÆ‚:< ®Ë¦ìòá1€ÕðÎÐäÎKøÀÇ‚Crÿá§€wÈGõs¿A|Š«Aß•¹:¢q@´<^§Á]ÿN!Ö±?!!!!áÓBaâ„bõúv§ÅP+7†j|‰Üਠ•ºL,xqæãŒÕRŸœq¬ÅcÕ!óBõ°;¡1 •å{öwBˆ ‹&<t”Lk §ÄÞVc.‹•­ãº¼Ñz0†ÁÆ¢€Éßkëª_m’V–e^2" À¸èÀõxDÐMŸh´¡44€ói’[ ¤Á NO ÀÌf³Ðꑱ¼‚—€cB ÓÑMH† ©¤„Ÿty ½™Žë1 ‘«íðHã3{ú™#àt~ü;BÀãÇ»àb³u§‹rŒýŸc¨K¶ŸúTt tzÀ‰1†'n °þß`ÚGSlUs®A} v —î~iS_6bl·9ö¤–'í¹Uhr¼²¬Ô˜>e𹦳­3vH?¶CQ8F&м]r¤Užµœ—ŠÂ7ö+Ä€>Ù€­4ÑÈflBÁ•åêz´”&˜ËÛg{n¸àkúà9³ßJsg¿‰ÍÛì—?ê×#¬P¡¯sꓵAÖ¨?©kõgœß޵0&²¢òÙà ÉFÿé´KA€:ö«ÄÆáÇie§¹ «‹6»’°tÔ‹‹—¯Î/дQ¡ýÛMøÄø üU¿FØ@]:f2N>tn<@åSª`Ì»ÅYÒß³FDãÀM5•pÔÌØuPNÖWÿoðÌ)¤íGSvqøJ}­þ.™\2¸dPÛß\ÁªAªÍoYßTÒ7­‚6™Ç¹˜1ÀÙ'àÅÅÇúå·¿ŽÔ19ØY§Fþ ¾Õ¯4²éßãV.˜ŒÊíý«Ñ Šœ€&»kÇjNş £< †j8_d´éßþvG%É_?=þçwµ|Ò4w¼š<¥WO‰[ –±øü¹“ï·ó^ƒ>`æ;ŸƒÀ&¹¿¬vO³Åˆï7h Ô¿ÿÉ 1?ïM›þñà}+üÜŒº?ïQ£~ñĘû¤Ϋ'Žùé|`3|Â<ÁŒZcb:‚™å¯¸-¼7 TãÚ,lðÅ¥£D,=ð\†™y¦£ÝÐýÆ)O*ƒŸ Îyè!ôÉùÒ9Ed㦑?>ÒÕYÑ]ŸèÀ¤ÐïIçT‡ ^SÖ~·¼hìFöû¶îNó)¶ï£þñ‘T˜í‘€²¹Þ%îœêP²[à:ÇeØ~9q»Ñ¼Mo«ŸQÀl6ë/Òu;}b-¾ZÛÉ ¸±ô;Z¨>4cmxçx‡*uñ%r‹ÇÁàNÁ½—N|‰+±“@¯¿ÚÂS@uoFØ>fÎàJƒ›F¼q•䀥Ü{MÖ1Ó²ðö—}êpH³ ;F !q×€ dèÖÑàèˆÊ%¬z&„[–ã å(7?H“27ò¤ªÔÞ–,v.E1ز¾`õÃRª²Vg{y´y¼!—Kx²¢²ûó‚:öŸ ”;ýQ+ißFXçº&`䱉÷·ù÷bèÛV" gèw àØûÐóS!{~ ö$$$$$|ÚŽì¾#ÿ¯‚_/ÐÞM¥\}Bß“k>G ¿–èó ãò­çMl¿ÿ`]ùà°„ÿiÚ¬Lì/þ^ÜN>4äp­Ô¯¥ºÆŸ¶^ÎuFK?_ë œ ô¿vû6œÑýìF*Ìkp ámQrWh<³Ûž|p`¿-;i¾_2È2s ‘OÌË}ÿž)×G²“%Àz€Æ5¾âf\Xâ ð]…ÖÅ×”#û œ¢=/:Â|ØAÀ½Ç×W×xد¦#\J ªßª¾1~¯¯Ïû;ù©ù„„„„„Á?“ù&ªuåuûÛTŽ> &ómtëÊëö·©Ã9´8_Eæ)ו×íoS9 þù€®F¾1±áM-W[imù»V.«Îò®üCgÿ ‚åfG'+§rÕ„û¼Cà:€VnQõjðÍ ^ŽÕ—墾["÷•ãÕ3ÿ;}Ôo¿ýFô3¿.V\_ƒ¦6˜Êæî½a c…D}% ×gDõQÍÿyQÙ¿=¦è;è<øÞ×1(Ú¿ÇCB`¾md°:ñ[À|ûV@¡¸Ë“cB¨=ÅêsY3°hëGÁ?àÔšAÐ b|.wªÞA’÷ÏYZÞðÓ%›{ •£èû1¶éct]9޾™M©uå8úe7 ¥×•¨‡Éö÷ãò=$ÂØ—“]öÝÈŒÅÿèáa£úJBÈŒ h~tÉìÏß:’|òcÀ§þHHHHHHHØ6²» DwAB±þF׌ý} CF¦"º®@¿ÞwÉþmx·÷NÙO=Àno·/t¬`Nû¦¾¢òýŠ®œñUÛw|`S¨ê+,ß)û7õ€;oÿ¦Oûïí³ÿîø@ÔÖ±»ùŸpàø? Ôse%©PIEND®B`‚./public/stylesheets/images/ui-bg_diagonals-thick_15_444444_40x40.png0000644000175000017500000000037511773315157024462 0ustar tfheentfheen‰PNG  IHDR((Œþ¸mÄIDATX…í×] ƒ0DÑÛ, ‹ËþW‘ Ô iš_£d(ß<Š GAüBo²ÄóK?ñÞwï¹£ÏÝYVÊjßP  P'Pà”qPøHVÊžxØ&p7oP   @%d@5$@Eœ@U€SÆÁÀz¦ì‰‡î<»ÀÝgu¸  *@Ø&±M2Wö‰m’«e¶IVËZ±M2RVŠm’™²4¶I®”m’µ²ÑØ&©•õò—›ä(×òEtÓôIEND®B`‚./public/stylesheets/images/ui-bg_glass_50_99c2ff_1x400.png0000644000175000017500000000017311773315157022755 0ustar tfheentfheen‰PNG  IHDRoX ÛBIDAT8íÏ1 €@ÁÍÞÿŸâW|‰¥ýYyØX ’f °MØö9(¥ü–㘀 Ž€Þ<æê\]òõRÊ+T¨÷•IEND®B`‚./public/stylesheets/jquery.suggest.css0000644000175000017500000000063411773315157020077 0ustar tfheentfheen.ac_results { width: 152px; border: 1px solid gray; background-color: white; padding: 0; margin: 0; list-style: none; position: absolute; z-index: 10000; display: none; } .ac_results li { padding: 2px 5px; white-space: nowrap; color: #101010; text-align: left; } .ac_over { cursor: pointer; background-color: #F0F0B8; } .ac_match { text-decoration: underline; color: black; }./public/stylesheets/base.css0000644000175000017500000001153111773315157016010 0ustar tfheentfheen* {margin:0;padding:0} .clear { clear: both; height: 0; } h1 { margin: 15px 0; font-size: 22px; font-weight: normal; } h2 { font-size: 22px; margin: 15px 0; font-weight: normal;} h3 { font-size: 18px; margin: 10px 0; font-weight: normal;} h4 { font-size: 16px; margin: 10px 0; font-weight: normal;} hr {height: 1px; border: 0; } p { margin: 15px 0;} a img { border: none; } body { font-size: 12px; font-family: sans-serif; } #container { min-width: 960px; } #header, #wrapper { padding: 0 20px; } #header { position: relative; padding-top: 1px; } #header h1 { margin: 0; padding: 10px 0; font-size: 30px; } #header h1 a:link, #header h1 a:active, #header h1 a:hover, #header h1 a:visited { text-decoration: none; } #main { width: 100%; float: left; } #main.loginPage { width: 80%; } .actions-bar { padding: 10px 1px; } .actions-bar .actions { float: left; } .actions-bar .pagination { float: right; padding: 1px 0; } #sidebar { width: 15%; float: right; } #sidebar h3 { padding: 10px 15px; margin: 0; font-size: 13px; } #sidebar .block { margin-bottom: 20px; padding-bottom: 10px; } #sidebar .block .content { padding: 0 15px; } #sidebar ul.navigation li a:link, #sidebar ul.navigation li a:visited { display: block; padding: 10px 15px; } #sidebar .block .sidebar-block, #sidebar .notice { padding:10px; } #wrapper { padding-top: 20px; background: #F4F4F6; } #main .block { margin-bottom: 20px; padding-top: 1px; } #main .block .content .inner { padding: 0 15px 15px; } #main .main p.first { margin-top: 0; } #user-navigation { position: absolute; top: 0px; right: 20px; } #main-navigation { width: 100%; } #user-navigation ul, #main-navigation ul, .secondary-navigation ul, #sidebar ul.navigation { margin: 0; padding: 0; list-style-type: none; } #user-navigation ul li, #main-navigation ul li, .secondary-navigation ul li { float: left; padding-top: 0; } #main-navigation ul li { margin-right: 5px; } #user-navigation ul li { padding: 60px 10px; } #main-navigation ul li a:link, #main-navigation ul li a:visited, #main-navigation ul li a:hover, #main-navigation ul li a:active, .secondary-navigation ul li a:link, .secondary-navigation ul li a:visited, .secondary-navigation ul li a:hover, .secondary-navigation ul li a:active, #user-navigation ul li a:link, #user-navigation ul li a:visited, #user-navigation ul li a:hover, #user-navigation ul li a:active { text-decoration: none; } #main-navigation ul li a { font-size: 15px; display: block; padding: 8px 15px; } .secondary-navigation { font-size: 13px; border-bottom-width: 10px; border-bottom-style: solid; } .secondary-navigation ul li a { display: block; padding: 10px 15px; } #footer { padding-bottom: 20px; } /* pagination */ .pagination a, .pagination span { padding: 2px 5px; margin-right: 5px; display: block; float: left; border-style: solid; border-width: 1px; } .pagination span.current { font-weight: bold; } .pagination a { text-decoration: none; } /* tables */ .table { width: 100%; border-collapse: collapse; margin-bottom: 15px; } .table th { padding: 10px; font-weight: bold; text-align: left; } .table th.first { width: 30px; } .table th.last { width: 200px; } .table .checkbox { margin-left: 10px; } .table td { padding: 10px; } .table td.last { text-align: right; } /* forms */ input.checkbox { margin: 0; padding: 0; } .form .group { margin-bottom: 15px; } .form div.left { width: 20%; float: left; } .form div.right { width: 75%; float: right; } .form .columns .column { width: 48%; } .form .columns .left { float: left; } .form .columns .right { float: right; } .form label.label, .form input.text_field, .form textarea.text_area { font-size: 1.2em; padding: 1px 0; margin: 0; } .form label.right { text-align: right; } .form input.checkbox, .form input.radio { margin-right: 5px; } .form label.checkbox, .form label.radio { line-height: 1.5em; } .form label.label { display: inline-block; padding-bottom: 2px; font-weight: bold; } .form div.fieldWithErrors label.label { display: inline; } .form .fieldWithErrors .error { color: red; } .form input.text_field, .form textarea.text_area { width: 100%; border-width: 1px; border-style: solid; } /* lists */ ul.list { margin: 0; padding: 0; list-style-type: none; } ul.list li { clear: left; padding-bottom: 5px; } ul.list li .left { float: left; } ul.list li .left .avatar { width: 50px; height: 50px; } ul.list li .item { margin-left: 80px; } ul.list li .item .avatar { float: left; margin: 0 5px 5px 0; width: 30px; height: 30px; } /* box */ #box { width: 500px; margin: 50px auto; } #box .block { margin-bottom: 20px; } #box .block h2 { padding: 10px 15px; margin: 0; } #box .block .content { padding: 10px 20px; } ./public/stylesheets/chef.css0000644000175000017500000001343711773315157016012 0ustar tfheentfheen.ruby .normal {} .ruby .comment { color: #005; font-style: italic; } .ruby .keyword { color: #A00; font-weight: bold; } .ruby .method { color: #077; } .ruby .class { color: #074; } .ruby .module { color: #050; } .ruby .punct { color: #447; font-weight: bold; } .ruby .symbol { color: #099; } .ruby .string { color: #944; background: #FFE; } .ruby .char { color: #F07; } .ruby .ident { color: #004; } .ruby .constant { color: #07F; } .ruby .regex { color: #B66; background: #FEF; } .ruby .number { color: #F99; } .ruby .attribute { color: #7BB; } .ruby .global { color: #7FB; } .ruby .expr { color: #227; } .ruby .escape { color: #277; } .todo{ color:red; } .files { padding-left: 20px; } .code { overflow: auto; font-size: 0.8em; } .search td { font-size: 0.8em; } dl dt { font-weight: bold; } .content td dl { margin: 0; padding: 0; } .content td dt { background: transparent url(/images/toggle-collapse.gif) 0 3px no-repeat; clear: left; color: #333; cursor: pointer; line-height: 1em; margin-left: -12px; padding-left: 14px; } .content td dd { margin: 0; padding: 0 0 0 1em; } .content td dt.collapsed { background-image: url(/images/toggle-expand.gif); } .content td dt.inline { background-image: none; cursor: default; float: left; margin-left: 0; padding-left: 2px; padding-right: .5em; padding-top: 2px; } div.roleFormContainer, div.nodeFormContainer, div.environmentFormContainer{ padding: 0 15px 15px; min-width:1050px; } div#run_list_editor_container { min-height:450px; min-width:1050px; } div.runListEditorColumn { float:left; margin-top: 20px; } div#current_run_list_display_container{ margin-left:20px; } span#cookbook_constraints_picker{ float:left; margin-left:10px; } span#cookbook_constraints_picker select{ size: 15; margin-right:50px; } span#environment_run_list_selection_control{ float:right; margin-right:10px; } div.runListEditorLabel, div#activeRunListName{ font-size: 1.2em; font-weight: bold; } div.runListEditorLabel{ padding: 3px 0 5px 0; margin: 0; color:white; background:#005573; background: -moz-linear-gradient(top, #007BA7, #005573); background:-webkit-gradient(linear, left top, left bottom, from(#007BA7), to(#005573)); text-shadow: #005573 0px -1px 0px; display: block; text-align:center; } div.activeRunListLabel{ padding-right:15px; padding-left:15px; } div#activeRunListName{ padding:2px; text-align:center; } div.runListItemListContainer{ border: 1px solid #999; margin-top:5px; margin-right: 10px; box-shadow:2px 2px 2px #dfdfdf; /* Safari 5 has a weird problem where these divs increase in width by 15px after updating contents with ajax. Problem doesn't occur in webkit nightlies. setting max-width works around.*/ max-width:360px; } div.emptyRunListControlsContainer{ padding:10px; } div.runListAvailableItemContainer, div.runListContainer { width: 360px; overflow-y: scroll; background: #eee; } div.runListAvailableItemContainer{ height: 200px; } div.runListAvailableItemContainer .spinner{ position: relative; top: 100px; left: 0; z-index: 1000; text-align: center; } div.runListContainer{ height: 407px; } div.runListContainerForNode{ height:432px; } div.inactive, ul.inactive{ display:none; } ul.runListAvailableItemList, ul.runListItemList { padding:5px 0px 0px 0px; min-height:185px; width:100%; list-style-type: none; margin: 0px; } ul.runListItemList{ min-height:405.5px; } ul#for_node.runListItemList{ min-height:420.5px; } li.runListItem{ margin: 0px 5px 5px 5px; padding: 5px; width: 93%; overflow:hidden; cursor:pointer; } li.displayRunListItem{ padding: 5px 5px 5px 5px; margin: 0px 5px 0px 5px; width: 93%; border-bottom:1px solid #eee; } div.cloneRunListOption{ padding: 5px 5px 5px 5px; margin: 0px 5px 0px 5px; width: 93%; } div.runListAdditionalControls{ min-height:15px; padding:5px; color:#fff; background:#005573; background:-webkit-gradient(linear, left top, left bottom, from(#006589), to(#005573)); } div.runListAdditionalControls a{ color:#fff; } div.clear { clear: left; } table.form th { font-weight: bold; text-align: right; padding-right: 10px; } div.help { padding: 10px; text-align: left; vertical-align: top; } table.form td { text-align: left; } table.sortable td { vertical-align: top; } table.sortable ul { background: #ff00ff; margin: 5px; padding: 5px; } td.table-key { font-weight: bold; } div.json-attr { overflow: auto; max-width: 400px; } td.position { font-weight: bold; } div#tree { float: left; } div#jform { float: left; margin-left: 50px; } div.editor { border: 1px solid black; } div.attrEditor{ clear:both; } div.attrEditor #treecontainer, div.attrEditor #tabcontainer{ float:left; } div.attrEditor #tabcontainer{ position:relative; top:0px; } #sidebar_block { display: none; } #sidebar_block_notice { display: none; } div.tooltip { background-color: #000; outline: 1px solid #669; border: 2px solid #fff; padding: 10px 15px; /* width: 200px; */ display: none; color: #fff; text-align: left; font-size: 12px; outline-radius: 4px; -moz-outline-radius: 4px; -webkit-outline-radius: 4px; } table.tooltip { width: 190px; } h1 a, h1 label, h1 .title-select { display: inline-block; vertical-align: middle; } h1 label { font-size: 12px; color: #F7F7F8; padding-left: 10px; } .cookbook_version_constraints_cb_name{ width:80%; } a.cookbook_version_toggle{ text-decoration:none; font-weight:bold; font-size: 24px; } ul.cookbook_versions{ list-style-type:none; } #cookbook_version_table{ width: auto; } tbody.cookbook_versions td { vertical-align:top; } .invalid_version_error { color: red; font-weight: bold; } #cbVerAddRow td { background: #c1c8d2; } ./public/stylesheets/jquery.treeTable.css0000644000175000017500000000242711773315157020327 0ustar tfheentfheen/* jQuery TreeTable Core 2.0 stylesheet * * This file contains styles that are used to display the tree table. Each tree * table is assigned the +treeTable+ class. * ========================================================================= */ /* jquery.treeTable.collapsible * ------------------------------------------------------------------------- */ .treeTable tr td .expander { background-position: left center; background-repeat: no-repeat; cursor: pointer; padding: 0; zoom: 1; /* IE7 Hack */ } .treeTable tr.collapsed td .expander { background-image: url(../images/toggle-expand-dark.png); } .treeTable tr.expanded td .expander { background-image: url(../images/toggle-collapse-dark.png); } /* jquery.treeTable.sortable * ------------------------------------------------------------------------- */ .treeTable tr.selected, .treeTable tr.accept { background-color: #3875d7; color: #fff; } .treeTable tr.collapsed.selected td .expander, .treeTable tr.collapsed.accept td .expander { background-image: url(../images/toggle-expand-light.png); } .treeTable tr.expanded.selected td .expander, .treeTable tr.expanded.accept td .expander { background-image: url(../images/toggle-collapse-light.png); } .treeTable .ui-draggable-dragging { color: #000; z-index: 1; }./public/stylesheets/themes/0000755000175000017500000000000011773315157015650 5ustar tfheentfheen./public/stylesheets/themes/default/0000755000175000017500000000000011773315157017274 5ustar tfheentfheen./public/stylesheets/themes/default/style.css0000644000175000017500000001160411773315157021150 0ustar tfheentfheen.small { font-size:11px; } .gray { color:#999999; } .hightlight { background-color:#FFFFCC; } a:link, a:visited, a:hover, a:active, h1, h2, h3 { color: #7A1818; } a { -moz-outline: none; } body { color: #222; background: #f0f0ee; font-family: helvetica, arial, sans-serif; } hr { background: #f0f0ee; color: #f0f0ee; } #header { background: #7A1818; } #header h1 { padding: 20px 0; } #header h1 a:link, #header h1 a:active, #header h1 a:hover, #header h1 a:visited { color: #FFF; } #user-navigation { top: auto; bottom: 5px; right: 25px; } #main .block .content { background: #FFF; padding-top: 1px; } #main .block .content h2 { margin-left: 15px; } #sidebar .block { background: #FFF; } #sidebar h3 { background: #7A1818; color: #FFF; border-bottom: 10px solid #262626; } #main-navigation ul li { padding-left: 15px; } #main-navigation ul li a { padding: 8px 0; } #main-navigation ul li.active { padding: 0; margin-left: 15px; } #main-navigation ul li.active { margin-left: 15px; } #main-navigation ul li.active a { padding: 8px 15px; } #sidebar ul li a:link, #sidebar ul li a:visited { background: #FFF; border-bottom: 1px solid #F0F0EE; text-decoration: none; } #sidebar ul li a:hover, #sidebar ul li a:active { background: #470E0E; color: #FFF; } #main-navigation { background: #262626; } #main-navigation ul li { background: #262626; margin-right: 0; } #main-navigation ul li.active { background: #f0f0ee; } #main-navigation ul li a:link, #main-navigation ul li a:visited, #main-navigation ul li a:hover, #main-navigation ul li a:active, .secondary-navigation ul li a:link, .secondary-navigation ul li a:visited, .secondary-navigation ul li a:hover, .secondary-navigation ul li a:active, #user-navigation ul li a:link, #user-navigation ul li a:visited, #user-navigation ul li a:hover, #user-navigation ul li a:active { text-decoration: none; color: #FFF; } .secondary-navigation li a:hover { background: #470E0E; } #main-navigation ul li.active a:link, #main-navigation ul li.active a:visited, #main-navigation ul li.active a:hover, #main-navigation ul li.active a:active { color: #262626; } .secondary-navigation { background: #7A1818; border-bottom-color: #262626; } .secondary-navigation ul li.active, .secondary-navigation ul li.active a:hover { background-color: #262626; } #footer .block { color: #FFF; background: #262626; } #footer .block p { margin: 0; padding: 10px; } /* pagination */ .pagination span.current { background: #262626; color: #FFF; border-color: #262626; } .pagination a { color: #262626; border-color: #262626; } .pagination a:hover { color: #FFF; background: #262626; } /* tables */ .table th { background: #262626; color: #FFF; } .table td { border-bottom:1px solid #F0F0EE; } /* forms */ .form input.text_field, .form textarea.text_area { width: 100%; border: 1px solid #262626; } .form input.button { background: #EEE; color: #262626; padding: 2px 5px; border: 1px solid #262626; cursor: pointer; } .form .description { font-style: italic; color: #8C8C8C; font-size: .9em; } /* flash-messages */ .flash .message { -moz-border-radius: 3px; -webkit-border-radius: 3px; text-align:center; margin: 0 auto 15px; } .flash .message p { margin:8px; } .flash .error { border: 1px solid #fbb; background-color: #fdd; } .flash .warning { border: 1px solid #fffaaa; background-color: #ffffcc; } .flash .notice { border: 1px solid #1FDF00; background-color: #BBFFB6; } /* lists */ ul.list li { border-bottom-color: #F0F0EE; border-bottom-width: 1px; border-bottom-style: solid; } ul.list li .item .avatar { border-color: #F0F0EE; border-width: 1px; border-style: solid; padding: 2px; } /* box */ #box .block { background: #FFF; } #box .block h2 { background: #7A1818; color: #FFF; } /* rounded borders */ #main, #main-navigation, #main-navigation li, .secondary-navigation, #main .block, #sidebar .block, #sidebar h3, ul.list li, #footer .block, .form input.button, #box .block, #box .block h2 { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation li.first a, .secondary-navigation ul li.first, .table th.first, .table th.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } .table th.last { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation ul li.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } #sidebar, #sidebar .block, #main .block, #sidebar ul.navigation, ul.list li, #footer .block, .form input.button, #box .block { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } ./public/stylesheets/themes/blue/0000755000175000017500000000000011773315157016577 5ustar tfheentfheen./public/stylesheets/themes/blue/style.css0000644000175000017500000001213411773315157020452 0ustar tfheentfheen.small { font-size:12px; } .gray { color:#999999; } .hightlight { background-color:#FFFFCC; } a:link, a:visited, a:hover, a:active, h1, h2, h3 { color: #2F427A; } a { -moz-outline: none; } body { color: #222; background: #f0f0ee; font-family: helvetica, arial, sans-serif; font-size: 14px; } hr { background: #f0f0ee; color: #f0f0ee; } #header { background: #2F427A; } #header h1 { padding: 20px 0; } #header h1 a:link, #header h1 a:active, #header h1 a:hover, #header h1 a:visited { color: #FFF; } #user-navigation { top: auto; bottom: 5px; right: 25px; } #main .block .content { background: #FFF; padding-top: 1px; } #main .block .content h2 { margin-left: 15px; } #sidebar .block { background: #FFF; } #sidebar .notice { background: #FFFFCC; } #sidebar h3 { background: #2F427A; color: #FFF; border-bottom: 10px solid #262626; font-size: 15px; } #main-navigation ul li { padding-left: 15px; } #main-navigation ul li a { padding: 8px 0; } #main-navigation ul li.active { padding: 0; margin-left: 15px; } #main-navigation ul li.active { margin-left: 15px; } #main-navigation ul li.active a { padding: 8px 15px; } #sidebar ul li a:link, #sidebar ul li a:visited { background: #FFF; border-bottom: 1px solid #F0F0EE; text-decoration: none; } #sidebar ul li a:hover, #sidebar ul li a:active { background: #316291; color: #FFF; } #main-navigation { background: #262626; } #main-navigation ul li { background: #262626; margin-right: 0; } #main-navigation ul li.active { background: #f0f0ee; } #main-navigation ul li a:link, #main-navigation ul li a:visited, #main-navigation ul li a:hover, #main-navigation ul li a:active, .secondary-navigation ul li a:link, .secondary-navigation ul li a:visited, .secondary-navigation ul li a:hover, .secondary-navigation ul li a:active, #user-navigation ul li a:link, #user-navigation ul li a:visited, #user-navigation ul li a:hover, #user-navigation ul li a:active { text-decoration: none; color: #FFF; } .secondary-navigation li a:hover { background: #5C637A; } #main-navigation ul li.active a:link, #main-navigation ul li.active a:visited, #main-navigation ul li.active a:hover, #main-navigation ul li.active a:active { color: #262626; } .secondary-navigation { background: #2F427A; border-bottom-color: #262626; font-size: 15px; } .secondary-navigation ul li.active, .secondary-navigation ul li.active a:hover { background-color: #262626; } #footer .block { color: #FFF; background: #262626; } #footer .block p { margin: 0; padding: 10px; } /* pagination */ .pagination span, .pagination a { -moz-border-radius: 3px; -webkit-border-radius: 3px; padding-top: 4px; } .pagination span.current { background: #262626; color: #FFF; border-color: #262626; } .pagination a { color: #262626; border-color: #262626; } .pagination a:hover { color: #FFF; background: #262626; } /* tables */ .table th { background: #262626; color: #FFF; } .table td { border-bottom:1px solid #F0F0EE; } /* forms */ .form input.text_field, .form textarea.text_area { width: 100%; border: 1px solid #262626; } .form input.button { background: #EEE; color: #262626; padding: 2px 5px; border: 1px solid #262626; cursor: pointer; } .form .description { font-style: italic; color: #8C8C8C; font-size: .9em; } /* flash-messages */ .flash .message { -moz-border-radius: 3px; -webkit-border-radius: 3px; text-align:center; margin: 0 auto 15px; } .flash .message p { margin:8px; } .flash .error { border: 1px solid #fbb; background-color: #fdd; } .flash .warning { border: 1px solid #fffaaa; background-color: #ffffcc; } .flash .notice { border: 1px solid #1FDF00; background-color: #BBFFB6; } /* lists */ ul.list li { border-bottom-color: #F0F0EE; border-bottom-width: 1px; border-bottom-style: solid; } ul.list li .item .avatar { border-color: #F0F0EE; border-width: 1px; border-style: solid; padding: 2px; } /* box */ #box .block { background: #FFF; } #box .block h2 { background: #2F427A; color: #FFF; } /* rounded borders */ #main, #main-navigation, #main-navigation li, .secondary-navigation, #main .block, #sidebar .block, #sidebar h3, ul.list li, #footer .block, .form input.button, #box .block, #box .block h2 { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation li.first a, .secondary-navigation ul li.first, .table th.first, .table th.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } .table th.last { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation ul li.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } #sidebar, #sidebar .block, #main .block, #sidebar ul.navigation, ul.list li, #footer .block, .form input.button, #box .block { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } ./public/stylesheets/themes/orange/0000755000175000017500000000000011773315157017123 5ustar tfheentfheen./public/stylesheets/themes/orange/style.css0000644000175000017500000001153611773315157021003 0ustar tfheentfheen.small { font-size:11px; } .gray { color:#999999; } .hightlight { background-color:#FFFFCC; } a:link, a:visited, a:hover, a:active, h1, h2, h3 { color: #ff7900; } a { -moz-outline: none; } body { color: #222; background: #f0f0ee; font-family: helvetica, arial, sans-serif; } hr { background: #f0f0ee; color: #f0f0ee; } #header { background: #ff7900; } #header h1 a:link, #header h1 a:active, #header h1 a:hover, #header h1 a:visited { color: #FFF; } #user-navigation { top: auto; bottom: 5px; right: 25px; } #main .block .content { background: #FFF; padding-top: 1px; } #main .block .content h2 { margin-left: 15px; } #sidebar .block { background: #FFF; } #sidebar h3 { background: #ff7900; color: #FFF; border-bottom: 10px solid #262626; } #main-navigation ul li { padding-left: 15px; } #main-navigation ul li a { padding: 8px 0; } #main-navigation ul li.active { padding: 0; margin-left: 15px; } #main-navigation ul li.active { margin-left: 15px; } #main-navigation ul li.active a { padding: 8px 15px; } #sidebar ul li a:link, #sidebar ul li a:visited { background: #FFF; border-bottom: 1px solid #F0F0EE; text-decoration: none; } #sidebar ul li a:hover, #sidebar ul li a:active { background: #863800; color: #FFF; } #main-navigation { background: #262626; } #main-navigation ul li { background: #262626; margin-right: 0; } #main-navigation ul li.active { background: #f0f0ee; } #main-navigation ul li a:link, #main-navigation ul li a:visited, #main-navigation ul li a:hover, #main-navigation ul li a:active, .secondary-navigation ul li a:link, .secondary-navigation ul li a:visited, .secondary-navigation ul li a:hover, .secondary-navigation ul li a:active, #user-navigation ul li a:link, #user-navigation ul li a:visited, #user-navigation ul li a:hover, #user-navigation ul li a:active { text-decoration: none; color: #FFF; } .secondary-navigation li a:hover { background: #863800; } #main-navigation ul li.active a:link, #main-navigation ul li.active a:visited, #main-navigation ul li.active a:hover, #main-navigation ul li.active a:active { color: #262626; } .secondary-navigation { background: #ff7900; border-bottom-color: #262626; } .secondary-navigation ul li.active, .secondary-navigation ul li.active a:hover { background-color: #262626; } #footer .block { color: #FFF; background: #262626; width: 70%; } #footer .block p { margin: 0; padding: 10px; } /* pagination */ .pagination span.current { background: #262626; color: #FFF; border-color: #262626; } .pagination a { color: #262626; border-color: #262626; } .pagination a:hover { color: #FFF; background: #262626; } /* tables */ .table th { background: #262626; color: #FFF; } .table td { border-bottom:1px solid #F0F0EE; } /* forms */ .form input.text, .form textarea { width: 100%; border: 1px solid #262626; } .form input.button { background: #EEE; color: #262626; padding: 2px 5px; border: 1px solid #262626; cursor: pointer; } .form .description { font-style: italic; color: #8C8C8C; font-size: .9em; } /* flash-messages */ .flash .message { -moz-border-radius: 3px; -webkit-border-radius: 3px; text-align:center; margin:0 auto 5px; } .flash .message p { margin:8px; } .flash .error { border: 1px solid #fbb; background-color: #fdd; } .flash .warning { border: 1px solid #fffaaa; background-color: #ffffcc; } .flash .notice { border: 1px solid #1FDF00; background-color: #BBFFB6; } /* lists */ ul.list li { border-bottom-color: #F0F0EE; border-bottom-width: 1px; border-bottom-style: solid; } ul.list li .item .avatar { border-color: #F0F0EE; border-width: 1px; border-style: solid; padding: 2px; } /* box */ #box .block { background: #FFF; } #box .block h2 { background: #ff7900; color: #FFF; } /* rounded borders */ #main, #main-navigation, #main-navigation li, .secondary-navigation, #main .block, #sidebar .block, #sidebar h3, ul.list li, #footer .block, .form input.button, #box .block, #box .block h2 { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation li.first a, .secondary-navigation ul li.first, .table th.first, .table th.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } .table th.last { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation ul li.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } #sidebar, #sidebar .block, #main .block, #sidebar ul.navigation, ul.list li, #footer .block, .form input.button, #box .block { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } ./public/stylesheets/themes/kathleene/0000755000175000017500000000000011773315157017610 5ustar tfheentfheen./public/stylesheets/themes/kathleene/style.css0000644000175000017500000001173611773315157021472 0ustar tfheentfheen.small { font-size:11px; } .gray { color:#999999; } .hightlight { background-color:#FFFFCC; } a:link, a:visited, a:hover, a:active, h1, h2, h3 { color: #AF0000; } a { -moz-outline: none; } body { color: #222; background: #f0f0ee; font-family: helvetica, arial, sans-serif; } hr { background: #f0f0ee; color: #f0f0ee; } #header { background: #AF0000; } #header h1 { padding: 20px 0; } #header h1 a:link, #header h1 a:active, #header h1 a:hover, #header h1 a:visited { color: #FFF; } #user-navigation { top: auto; bottom: 5px; right: 25px; } #main .block .content { background: #FFF; padding-top: 1px; } #main .block .content h2 { margin-left: 15px; } #sidebar .block { background: #FFF; } #sidebar h3 { background: #AF0000; color: #FFF; border-bottom: 5px solid #2a0000; } #main-navigation ul li { padding-left: 15px; } #main-navigation ul li a { padding: 8px 0; } #main-navigation ul li.active { padding: 0; margin-left: 15px; } #main-navigation ul li.active { margin-left: 15px; } #main-navigation ul li.active a { padding: 8px 15px; } #sidebar ul li a:link, #sidebar ul li a:visited { background: #FFF; border-bottom: 1px solid #F0F0EE; text-decoration: none; } #sidebar ul li a:hover, #sidebar ul li a:active { background: #470E0E; color: #FFF; } #main-navigation { background: #2a0000; } #main-navigation ul li { background: #2a0000; margin-right: 0; } #main-navigation ul li.active { background: #f0f0ee; } #main-navigation ul li a:link, #main-navigation ul li a:visited, #main-navigation ul li a:hover, #main-navigation ul li a:active, .secondary-navigation ul li a:link, .secondary-navigation ul li a:visited, .secondary-navigation ul li a:hover, .secondary-navigation ul li a:active, #user-navigation ul li a:link, #user-navigation ul li a:visited, #user-navigation ul li a:hover, #user-navigation ul li a:active { text-decoration: none; color: #FFF; } .secondary-navigation li a:hover { background: #470E0E; } #main-navigation ul li.active a:link, #main-navigation ul li.active a:visited, #main-navigation ul li.active a:hover, #main-navigation ul li.active a:active { color: #2a0000; } .secondary-navigation { background: #AF0000; border-bottom-color: #2a0000; } .secondary-navigation ul li.active, .secondary-navigation ul li.active a:hover { background-color: #2a0000; } #footer .block { color: #FFF; background: #2a0000; } #footer .block p { margin: 0; padding: 10px; } /* pagination */ .pagination span.current { background: #2a0000; color: #FFF; border-color: #2a0000; } .pagination a { color: #2a0000; border-color: #2a0000; } .pagination a:hover { color: #FFF; background: #2a0000; } /* tables */ .table th { background: #100000; border-bottom: 3px solid #700000; color: #FFF; } .table td { border-bottom:1px solid #F0F0EE; } /* forms */ .form input.text_field, .form textarea.text_area { width: 100%; border: 1px solid #2a0000; } .form input.button { background: #EEE; color: #2a0000; padding: 2px 5px; border: 1px solid #2a0000; cursor: pointer; } .form .description { font-style: italic; color: #8C8C8C; font-size: .9em; } /* flash-messages */ .flash .message { -moz-border-radius: 3px; -webkit-border-radius: 3px; text-align:center; margin: 0 auto 15px; } .flash .message p { margin:8px; } .flash .error { border: 1px solid #fbb; background-color: #fdd; } .flash .warning { border: 1px solid #fffaaa; background-color: #ffffcc; } .flash .notice { border: 1px solid #1FDF00; background-color: #BBFFB6; } /* lists */ ul.list li { border-bottom-color: #F0F0EE; border-bottom-width: 1px; border-bottom-style: solid; } ul.list li .item .avatar { border-color: #F0F0EE; border-width: 1px; border-style: solid; padding: 2px; } /* box */ #box .block { background: #FFF; } #box .block h2 { background: #AF0000; color: #FFF; } /* rounded borders */ #main, #main-navigation, #main-navigation li, .secondary-navigation, #main .block, #sidebar .block, #sidebar h3, ul.list li, #footer .block, .form input.button, #box .block, #box .block h2 { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation li.first a, .secondary-navigation ul li.first, .table th.first, .table th.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } .table th.last { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation ul li.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } #sidebar, #sidebar .block, #main .block, #sidebar ul.navigation, ul.list li, #footer .block, .form input.button, #box .block { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } .secondary-navigation { border-bottom-width: 5px; } ./public/stylesheets/themes/bec-green/0000755000175000017500000000000011773315157017477 5ustar tfheentfheen./public/stylesheets/themes/bec-green/style.css0000644000175000017500000001167311773315157021361 0ustar tfheentfheena:link, a:visited, a:hover, a:active { color: #33f; } h1, h2, h3 {color:#444} body { color: #222; background: #e5e5e5; font-family: "Bitstream Vera Sans", verdana, sans-serif; } hr { background: #f0f0ee; } p { font-size: 14px; line-height: 20px; } input.checkbox { vertical-align:middle; } #header h1 { font-size: 28px; padding: 5px 0; margin: 5px 0; } .hightlight { background-color: #ffc; } .small { font-size: 11px; } .gray { color: #999; } #header { background: #48625B; } #header h1 a:link, #header h1 a:active, #header h1 a:hover, #header h1 a:visited { color: #FFF; } #main { background: #e5e5e5; width: 69%; } #main .block { -moz-border-radius-topleft: 4px; -moz-border-radius-topright: 4px; padding: 0; margin-bottom:20px; padding-bottom: 20px; background: #fff; } #main .block h2.title { margin: 0 0 20px 0; background-color: #E9FAE6; padding: 5px 5px 5px 15px; font-size:18px; } .main_container { padding:10px; } /* #sidebar .block { background: #FFF; padding-bottom:0px; } */ #sidebar .notice { background-color: #ffc; padding: 0 10px; border-bottom:1px solid #ddd; border-right:1px solid #ddd; border-top:1px solid #fff; border-left:1px solid #fff; } #sidebar .notice h2 { font-size:16px; margin: 5px 0; border-bottom:1px solid #aaa; } #sidebar .notice p { font-size:12px; } #sidebar .block { padding-bottom: 0; } #sidebar .block .content { padding: 0 10px; } #sidebar h3 { background: #c7d8d8; border-bottom:1px solid #999; padding: 5px 10px; } #sidebar ul li a:link, #sidebar ul li a:visited { font-size:14px; } #sidebar ul li a:hover, #sidebar ul li a:active { background: #E9FAE6; color: #444; font-size:14px; text-decoration:underline; } #sidebar ul.navigation li.last a { border-bottom: none; } #sidebar ul.navigation li a:link,#sidebar ul.navigation li a:visited { padding: 5px 10px; color:#444; text-decoration: none; } #sidebar ul.navigation li a:hover { text-decoration:underline; } #sidebar .block .sidebar-block h4 { border-bottom: 1px solid #bbb; } #main-navigation ul li { background: #30423E; } #main-navigation ul li:hover { background: #23302D; } #main-navigation ul li.active { background: #e5e5e5; } #main-navigation ul li a:link, #main-navigation ul li a:visited, #main-navigation ul li a:hover, #main-navigation ul li a:active, .secondary-navigation ul li a:link, .secondary-navigation ul li a:visited, .secondary-navigation ul li a:hover, .secondary-navigation ul li a:active, #user-navigation ul li a:link, #user-navigation ul li a:visited, #user-navigation ul li a:hover, #user-navigation ul li a:active { text-decoration: none; color: #FFF; } #main-navigation ul li a { font-size: 14px; padding: 4px 10px; } #main-navigation ul li.active a:link, #main-navigation ul li.active a:visited, #main-navigation ul li.active a:hover, #main-navigation ul li.active a:active { color: #333; } #user-navigation ul li a:hover { text-decoration: underline; } .secondary-navigation { background: #48625B; border-bottom-color: #30423e; border-bottom: 5px solid #30423e; } .secondary-navigation ul li.active { background-color: #30423e; } .secondary-navigation ul li:hover { background-color: #23302d; } /* pagination */ .pagination span.current { background: #30423e; color: #FFF; border: 1px solid #30423e; -moz-border-radius:5px; } .pagination a { color: #364B69; border: 1px solid #ddd; -moz-border-radius:5px; } .pagination a:hover { color: #444; background: #E9FAE6; } /* tables */ .table th { background: #48625B; color: #FFF; font-weight:normal; padding:3px; } .table th a.toggle { display: block; width: 12px; height: 12px; background: transparent url('images/tick.png') center no-repeat; text-indent: -9999px; -moz-outline: none; } .table th.first { width: 30px; text-align: center; } .table td { border-bottom: 1px solid #F0F0EE; } /* forms */ .form input.text, .form textarea.textarea { border: 1px solid #ddd; padding: 5px; width: 95%; } .form .navform { padding:10px; background-color: #E9FAE6; font-size:14px; border-bottom:1px solid #ddd; border-right:1px solid #ddd; border-top:1px solid #eee; border-left:1px solid #eee; } .form .navform input { font-size:14px; } /* flash-messages */ .flash .message { -moz-border-radius: 3px; -webkit-border-radius: 3px; text-align:center; margin:0 auto 5px; width:80%; } .flash .message p { margin:8px; } .flash .error { border: 1px solid #fbb; background-color: #fdd; } .flash .warning { border: 1px solid #fffaaa; background-color: #ffffcc; } .flash .notice { border: 1px solid #ddf; background-color: #eef; } /* lists */ ul.list li { border-bottom-color: #F0F0EE; } ul.list li .item .avatar { border-color: #F0F0EE; margin: 3px 10px 0 0; } ul.list li .left { padding: 5px 5px; } /* box */ #box .block { background: #FFF; } #box .block h2 { background: #48625B; color: #FFF; } ./public/stylesheets/themes/bec/0000755000175000017500000000000011773315157016401 5ustar tfheentfheen./public/stylesheets/themes/bec/style.css0000644000175000017500000001211211773315157020250 0ustar tfheentfheena:link, a:visited, a:hover, a:active { color: #33f; } h1, h2, h3 {color:#444} body { color: #333; background: #e5e5e5; font-family: Verdana, Arial, "Bitstream Vera Sans", sans-serif; } hr { background: #f0f0ee; } p { font-size: 12px; line-height: 20px; } input.checkbox { vertical-align:middle; } #header h1 { font-size: 28px; padding: 5px 0; margin: 5px 0; } .hightlight { background-color: #ffc; } .small { font-size: 11px; } .gray { color: #999; } #header { background: #006666; } #header h1 a:link, #header h1 a:active, #header h1 a:hover, #header h1 a:visited { color: #FFF; } #main { background: #e5e5e5; width: 73%; } #main .block { -moz-border-radius-topleft: 4px; -moz-border-radius-topright: 4px; padding: 0; margin-bottom:20px; padding-bottom: 20px; background: #fff; } #main .block h2.title { margin: 0 0 20px 0; background-color: #E6FAFA; padding: 5px 5px 5px 15px; font-size:18px; } .main_container { padding:10px; } #footer .block p { color:#aaa; font-size:11px; } /* #sidebar .block { background: #FFF; padding-bottom:0px; } */ #sidebar .notice { background-color: #ffc; padding: 0 10px; border-bottom:1px solid #ddd; border-right:1px solid #ddd; border-top:1px solid #fff; border-left:1px solid #fff; } #sidebar .notice h2 { font-size:16px; margin: 5px 0; border-bottom:1px solid #aaa; } #sidebar .notice p { font-size:12px; } #sidebar .block { padding-bottom: 0; } #sidebar .block .content { padding: 0 10px; } #sidebar h3 { background: #c7d8d8; border-bottom:1px solid #999; padding: 5px 10px; } #sidebar ul li a:link, #sidebar ul li a:visited { font-size:12px; } #sidebar ul li a:hover, #sidebar ul li a:active { background: #e1efef; color: #444; font-size:12px; text-decoration:underline; } #sidebar ul.navigation li.last a { border-bottom: none; } #sidebar ul.navigation li a:link,#sidebar ul.navigation li a:visited { padding: 5px 10px; color:#444; text-decoration: none; } #sidebar ul.navigation li a:hover { text-decoration:underline; } #sidebar .block .sidebar-block h4 { border-bottom: 1px solid #bbb; } #main-navigation ul li { background: #008c8c; } #main-navigation ul li:hover { background: #00b2b2; } #main-navigation ul li.active { background: #f0f0ee; } #main-navigation ul li a:link, #main-navigation ul li a:visited, #main-navigation ul li a:hover, #main-navigation ul li a:active, .secondary-navigation ul li a:link, .secondary-navigation ul li a:visited, .secondary-navigation ul li a:hover, .secondary-navigation ul li a:active, #user-navigation ul li a:link, #user-navigation ul li a:visited, #user-navigation ul li a:hover, #user-navigation ul li a:active { text-decoration: none; color: #FFF; } #main-navigation ul li a { font-size: 12px; padding: 4px 10px; } #main-navigation ul li.active a:link, #main-navigation ul li.active a:visited, #main-navigation ul li.active a:hover, #main-navigation ul li.active a:active { color: #364b69; } #user-navigation ul li a:hover { text-decoration: underline; } .secondary-navigation { background: #006666; border-bottom-color: #008c8c; border-bottom: 5px solid #008c8c; } .secondary-navigation ul li.active { background-color: #008c8c; } .secondary-navigation ul li:hover { background-color: #00b2b2; } /* pagination */ .pagination span.current { background: #008c8c; color: #FFF; border: 1px solid #008c8c; -moz-border-radius:5px; } .pagination a { color: #364B69; border: 1px solid #ddd; -moz-border-radius:5px; font-size:11px; } .pagination a:hover { color: #444; background: #E6FAFA; } /* tables */ .table th { background: #006666; color: #FFF; font-weight:normal; padding:3px; } .table th a.toggle { display: block; width: 12px; height: 12px; background: transparent url('images/tick.png') center no-repeat; text-indent: -9999px; -moz-outline: none; } .table th.first { width: 30px; text-align: center; } .table td { border-bottom: 1px solid #F0F0EE; } /* forms */ .form input.text, .form textarea.textarea { border: 1px solid #ddd; padding: 5px; width:99%; } .form .navform { padding:10px; background-color: #f1f8f8; font-size:14px; border-bottom:1px solid #ddd; border-right:1px solid #ddd; border-top:1px solid #eee; border-left:1px solid #eee; } .form .navform input { font-size:14px; } .description { color:#aaa; font-family:Georgia, serif; } /* flash-messages */ .flash .message { -moz-border-radius: 3px; -webkit-border-radius: 3px; text-align:center; margin:0 auto 5px; width:80%; } .flash .message p { margin:8px; } .flash .error { border: 1px solid #fbb; background-color: #fdd; } .flash .warning { border: 1px solid #fffaaa; background-color: #ffffcc; } .flash .notice { border: 1px solid #ddf; background-color: #eef; } /* lists */ ul.list li { border-bottom-color: #F0F0EE; } ul.list li .item .avatar { border-color: #F0F0EE; margin: 3px 10px 0 0; } ul.list li .left { padding: 5px 5px; } /* box */ #box .block { background: #FFF; } #box .block h2 { background: #006666; color: #FFF; } ./public/stylesheets/themes/djime-cerulean/0000755000175000017500000000000011773315157020534 5ustar tfheentfheen./public/stylesheets/themes/djime-cerulean/style.css0000644000175000017500000001300711773315157022407 0ustar tfheentfheen/** * Cerulean web-app-theme made for Djime: http://github.com/mikl/djime/ * * Please note that we're using CSSEdit's @group comment syntax. * * Colour sheme: * Cerulean: #007BA7 * Bright blue: #01B8DE * Near-white: #F7F7F8 * Silver grey: #C2C8D1 * Dark blue: #001C26 * * http://www.colourlovers.com/palette/646252/Cerulean_touch */ /* @group General styles */ .small { font-size:11px; } .gray { color:#999; } .hightlight { background-color:#ffc; } a:link, a:visited, a:hover, a:active, h1, h2, h3 { color: #007BA7; } body { color: #222; background: #F4F4F6; font-family: "Helvetica Neue",Helvetica,Arial,"Bitstream Vera Sans",sans-serif; } hr { background: #EEF0F0; color: #EEF0F0; } /* @end */ /* @group Header */ #header { background: #007BA7; } #header h1 { padding: 20px 0; } #header h1 a:link, #header h1 a:active, #header h1 a:hover, #header h1 a:visited { color: #F7F7F8; } /* @end */ #main .block .content { background: #F7F7F8; padding-top: 1px; } #main .block .content h2 { margin-left: 15px; } /* @group Main navigation */ #main-navigation ul li { padding-left: 0; } #main-navigation ul li a { padding: 8px 0; } #main-navigation ul li a { padding: 8px 15px; } #main-navigation { background-color: #005573; } #main-navigation ul li a:hover { background-color: #102E41; } #main-navigation ul li.active a, #main-navigation ul li.active a:visited { background: #F4F4F6; color: #102E41; font-weight: bold; } /* @end */ /* @group Secondary navigation */ .secondary-navigation li a:hover { background: #005573; } .secondary-navigation { background: #007BA7; border-bottom-width: 7px; border-bottom-color: #005573; } .secondary-navigation ul li.active, .secondary-navigation ul li.active a:hover { background-color: #005573; } /* @end */ /* @group Sidebar */ #sidebar .block { background: #F7F7F8; } #sidebar h3 { background: #007BA7; color: #F7F7F8; border-bottom: 7px solid #005573; } #sidebar ul li a:link, #sidebar ul li a:visited { background: #F7F7F8; border-bottom: 1px solid #EEF0F0; text-decoration: none; } #sidebar ul li a:hover, #sidebar ul li a:active { background: #005573; color: #F7F7F8; } /* @end */ #main-navigation ul li a:visited, #main-navigation ul li a:hover, .secondary-navigation ul li a:link, .secondary-navigation ul li a:visited, .secondary-navigation ul li a:hover, .secondary-navigation ul li a:active, #user-navigation ul li a:link, #user-navigation ul li a:visited, #user-navigation ul li a:hover, #user-navigation ul li a:active { text-decoration: none; color: #F7F7F8; } #footer .block { color: #F7F7F8; background: #005573; } #footer .block p { margin: 0; padding: 10px; } /* pagination */ .pagination span.current { background: #005573; color: #F7F7F8; border-color: #005573; } .pagination a, .pagination span { color: #001C26; border-color: #005573; } .pagination a:hover { color: #F7F7F8; background: #005573; } /* tables */ .table th { background: #C2C8D1; color: #001C26; } .table td { border-bottom:1px solid #EEF0F0; } /* forms */ .form input.text_field, .form textarea.text_area { width: 100%; border: 1px solid #001C26; } .form input.button { background: #EEE; color: #001C26; padding: 2px 5px; border: 1px solid #001C26; cursor: pointer; } .form .description { color: #8C8C8C; font-size: .9em; } .form .inline_error_message { color: #FF0000; font-weight: bold; padding-left:5px; } /* @group Flash messages */ .flash .message { -moz-border-radius: 3px; -webkit-border-radius: 3px; text-align:center; margin: 0 auto 15px; } .flash .message p { margin:8px; } .flash .error { border: 1px solid #fbb; background-color: #fdd; } .flash .warning { border: 1px solid #e0d300; background-color: #ffffcc; } .flash .notice { border: 1px solid #8ec4df; background-color: #dffaff; } /* @end */ /* lists */ ul.list li { border-bottom-color: #EEF0F0; border-bottom-width: 1px; border-bottom-style: solid; } ul.list li .item .avatar { border-color: #EEF0F0; border-width: 1px; border-style: solid; padding: 2px; } /* box */ #box .block { background: #F7F7F8; } #box .block h2 { background: #005573; color: #F7F7F8; } /* rounded borders */ #main, #main-navigation, #main-navigation li, #main-navigation li a, .secondary-navigation, #main .block, #sidebar .block, #sidebar h3, ul.list li, #footer .block, .form input.button, #box .block, #box .block h2 { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation li.first a, .secondary-navigation ul li.first, .table th.first, .table th.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } .table th.first#CookbookVersionConstraints{ width:30%; } .table th.operator#CookbookVersionConstraints{ width:15%; } .table th.version#CookbookVersionConstraints{ width:20%; } .table th.last#CookbookVersionConstraints{ width:40%; } .table th.last { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation ul li.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } #sidebar, #sidebar .block, #main .block, #sidebar ul.navigation, ul.list li, #footer .block, .form input.button, #box .block { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } ./public/stylesheets/themes/reidb-greenish/0000755000175000017500000000000011773315157020537 5ustar tfheentfheen./public/stylesheets/themes/reidb-greenish/style.css0000644000175000017500000001252311773315157022414 0ustar tfheentfheen.small { font-size:11px; } .gray { color:#a2b0b6; } .hightlight { background-color:#d6e7c7; } a:link, a:visited, a:hover, a:active { color: #81B953; } h1, h2, h3 { color: #3B5526; } a { -moz-outline: none; } body { color: #222; background: #e4ebe4; font-family: helvetica, arial, sans-serif; } hr { background: #f0f0ee; color: #f0f0ee; } #header { background: #c9deb7; } #header h1{ padding: 20px 0; font-weight: bold; } #header h1 a:link, #header h1 a:active, #header h1 a:hover, #header h1 a:visited { color: #3B5526; } #main .block .content { background: #FFF; padding-top: 1px; } #main .block .content h2 { margin-left: 15px; } #main .content { border: 1px solid #81B953;} #sidebar .block { background: #FFF; border: none; } #sidebar h3 { padding: 8px 12px; background: #3B5526; color: #FFF; font-weight: bold; border-bottom: 5px solid #81B953; } #sidebar ul li a:link, #sidebar ul li a:visited { background: #FFF; border-bottom: 1px solid #F0F0EE; text-decoration: none; } #sidebar ul li a:hover, #sidebar ul li a:active { background: #D3E8C1; color: #FFF; } #main-navigation { background: #44721e; margin-right: 20px; padding: 7px 7px 0 7px; } #main-navigation ul li { background: #91B96F; margin-right: 7px; } #main-navigation ul li a { padding: 10px 10px 5px 10px; } #main-navigation ul li.active { background: #e4ebe4; border: 1px solid #91B96F; border-bottom: none; font-weight: bold; } #main-navigation ul li a:hover, #main-navigation ul li a:link, #main-navigation ul li a:visited, #main-navigation ul li a:active, .secondary-navigation ul li a:link, .secondary-navigation ul li a:visited, .secondary-navigation ul li a:hover, .secondary-navigation ul li a:active { text-decoration: none; color: #FFF; } #user-navigation ul li a:link, #user-navigation ul li a:visited, #user-navigation ul li a:active { color: #3B5526; } #user-navigation ul li a:hover { color: #fff; } #main-navigation ul li.active a:link, #main-navigation ul li.active a:visited, #main-navigation ul li.active a:hover, #main-navigation ul li.active a:active { color: #262626; } .secondary-navigation { background: #3B5526; border-bottom: 5px solid #81b953; } .secondary-navigation ul li a { display:block; padding: 8px 12px; } .secondary-navigation ul li.active {background: #81b953; font-weight: bold;} .secondary-navigation ul li.active a:hover { background-color: #81B953; } .secondary-navigation li a:hover { background: #81B953; } #footer .block { color: #FFF; background: #3B5526; } #footer .block p { margin: 0; padding: 5px; } /* pagination */ .pagination span.current { background: #262626; color: #FFF; border-color: #262626; } .pagination a { color: #262626; border-color: #262626; } .pagination a:hover { color: #FFF; background: #262626; } /* tables */ .table th { background: #253618; color: #FFF; } .table tr th { padding: 5px; } .table td { border-bottom:1px solid #F0F0EE; } .table tr.odd {background: #ebfadf;} .table tr.even {background: #d3e8c1;} /* forms */ .form input.text_field, .form textarea.text_area { width: 100%; border: 1px solid #262626; } .form input.button { background: #EEE; color: #262626; padding: 2px 5px; border: 1px solid #262626; cursor: pointer; } .form .description { font-style: italic; color: #8C8C8C; font-size: .9em; } /* flash-messages */ .flash .message { -moz-border-radius: 3px; -webkit-border-radius: 3px; text-align:center; margin: 0 auto 15px; } .flash .message p { margin:8px; } .flash .error { border: 1px solid #fbb; background-color: #fdd; } .flash .warning { border: 1px solid #fffaaa; background-color: #ffffcc; } .flash .notice { border: 1px solid #1FDF00; background-color: #BBFFB6; } /* lists */ ul.list li { border-bottom-color: #F0F0EE; border-bottom-width: 1px; border-bottom-style: solid; } ul.list li .item .avatar { border-color: #F0F0EE; border-width: 1px; border-style: solid; padding: 2px; } /* box */ #box .block { background: #FFF; } #box .block h2 { color: #fff; background: #3B5526; border-bottom: 5px solid #81b953; } #box .block .content { border: 1px solid #81b953; border} /* login */ #block-login { } #block-login h2 { background: #3B5526;border-bottom: 5px solid #81b953;} /* rounded borders */ #main, #main-navigation, #main-navigation li, .secondary-navigation, #main .block, #sidebar .block, #sidebar h3, ul.list li, #footer .block, .form input.button, #box .block, #box .block h2 { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation li.first a, .secondary-navigation ul li.first, .table th.first, .table th.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } .table th.last { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } .secondary-navigation ul li.first { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } #sidebar, #sidebar .block, #main .block, #sidebar ul.navigation, ul.list li, #footer .block, .form input.button, #box .block { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }./public/images/0000755000175000017500000000000011773315157013254 5ustar tfheentfheen./public/images/toggle-collapse-dark.png0000644000175000017500000000550611773315157017770 0ustar tfheentfheen‰PNG  IHDRóÿa pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFqIDATxÚbüÿÿ?%€‰BÀ8à. ¾ÚÛÛ÷3008àÑs ²²Òo´··ã ˜ÊÊJFb¼0‹Xqœ±ÐÞÞþŒAIèyee¥)E€O8 (JÀ¡€ÿÿÿãÅmmmÿñÉSœÞŠ“2`kÁ_GC›KIEND®B`‚./public/images/jsonedit/0000755000175000017500000000000011773315157015073 5ustar tfheentfheen./public/images/jsonedit/json.jpg0000644000175000017500000000271511773315157016553 0ustar tfheentfheenÿØÿàJFIFHHÿÛC    !'"#%%%),($+!$%$ÿÛC   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ÿÀ<<"ÿÄ ÿÄ4!1Aa"Qq2B‘¡#3C±ÁÑrÿÄÿÄÿÚ ?ªi]œÿ‡2¡£ `Üï«NÓvöU¦À<â¾AÓy>ë¼þÍäeN †[rûpÚj jÞ§Äꇂu¹’BŸ›y¸?p¸HvT¹+.:óª*RÔw’M{DfF5}ͻ㶨Š=ضÂXJGP;jõUûÅÂs½¬©²¤8N¥nº¥|ɬ֋ Û›Á˜Pß”ç†[+?ADgÞ­èí%Zf²€5*[*§MÔ,˜˜¿ <Ú­÷™…„‘¬w]R›#ÃBwziT¦ÏD^"!w&¶€Ñ.”Ìhõ:*c‡oẉ,¥ºB]oPÙPñœ)±®1[•ä<ÃT­PEf©Ë/³-Ì'wCÝ*µIX$ŸÒ'÷—?éTb—•¡AIPÔuPAžÐx¡ìiš×w …q-Ëü>2y%-’GšöϨ­ Á²1Må›{=Äžó®é¨m‰þ‡R+ì¹6å*S —yn(žd¨“N<Ÿ¶7n³Kž@íd;Ùƒà”ôŸ¥ÎÃpl‘ãÙìÑRÞÚ‚ùœQù”yšsÙ0ô;,.Á ¥Ç?5Å K‡Ÿ§J[åñD¼XÎÖþɵ¸<ôÓû¦åýœ¹]Å!û3 f‡6$0¢ZpðRG$û¹=Àíü7U?˜0Ûƒn­85‚àóI qHX8n ^Þ^÷YN²N› "¨ÜÇQîØ3w IKðT=Vw©)§è•éRþ5œ”â èI܇6=@ÿ¥·ã;…¥Çˆò…,¬ã Р&ĘmVLUv·->ï-Ô§Ë´t?M áÄl<††í—¯óF™ñTÝÙ¼O­Y’Ô­Âà%G¡1Ö—‘¨Q”ƒ¹$ê<è p†'jÇŠà˰˜ûe·TNä¥CMOA¨>•D‚Px&Î㾎0_´¬-oËÄEÜc2–Jôq±É'_ˆ}ÇZVc\‘9(vÓm#žÈ:¨ùi»Ö“7Ûœl1e‘r’S£iÑ´ú‹<<ÏÛZÕâ,ö´Ï}sŸnl—ÈÑ %)@ä5'púÒ_cÙø¶XrI Go^Æ:u¾½OZ =Òèä—yÕ•8âŠÔO2N¦›/“ ÌL(ýåÄ„¤M[*Ý´”¡QêHô¤­²ß?Þ"YíŒ.DÙŽ¥–[O(Ÿã™<…}˼`»VŒBýÍp~ã§¼µz¨“A¼5ÎÐå²—£¼’…¡\¤~3ÊùRï`õ½{Ûx TÑäþð4÷®”´”¨$< ?~nMªRãJABÓ¼x(xB³§ñßV®3ÊÌ-‰`¹ï° Ô¤²­‚“ÓÃÒ£¬ÌÃ10µñpa=!mi«Êý€ ›;]w׎Ýmºb[›6Ë<)¦¾­–ÙaJWø:ÂY3’˜o0ž ¼É¹„§¼[aÔ!*è{„ý U87.°®_Ä1°åš4¡£Ž¤m:çý,ê£äMçÙÿÙýŒ²Œ/—ÀÔœK!$§¼ˆHw_3:*ÞWìrÙí×lNC/ -Î좕ÎB‹'{ u_€×a46¶ðëåÊçêâÒ½€¿bäß¡E¥%D47·;ٻƩ;šÑ8Ë£}>6[ãåÓ•S@*ÍZ Qkí¾>~‚–͵hB\öø9u‡²è½ìàxþ¹Zæ®vYÐb ¦¾Ž©š˜Þ€šJ£ ƒºCيٽ?çŠÉBâYvnˆÍÈ&k„ÖÕft‡ì¼öò$Ì™,d•9³Zžžaý§p“\^ Y²ãö7 ¦Q™×JFý¿ 9=íQ4 ØœÀŠØI’o SüB€äpsÉåŽI‘„) Fv(@yÕŽ²Þˆïcãü\@Íîâ’Ó %´Ð%‡ –Zœ2h'‹Ë@dµË(<|ŒÃ¡aÞ ÍâÔJðuM@¢O§°Ô⤞L°£ñGjÕd‚!œX¬8ÅÁ­AÞÐf 5›J iÕ K->Ówû62ƾßWHÖü}€ý:¡Ëm–P]XBÉ0­QX=iÞb_ï¨gÅ=!–ôF¡ðt’õû™t·Ùþõ›Â…c¼lýr»¤ÇÛí¾IEND®B`‚./public/images/jsonedit/build-button.png0000644000175000017500000000135511773315157020215 0ustar tfheentfheen‰PNG  IHDRóÿa´IDATxÚ}“mHSQÆŸ{w·Ô妢ø²Ò†™Û‡¤Œˆ2óe¡m–øš*ˆ$!S$#è“øB%Af‚9+ ‡Ihšs¦¦QZ!Ì—ÈÀ´™nè¶»{×Ý qN}àÏ{ÎÿwŸsÎs»ÝŽZ3[)n8@D®qÕœ´°´¬&¢U&•,c Í@À2¶h–eÓ¸o ®ø6†Å¯l6fV$7µ¨ËJ®Ï¹2³óŽYo¦( |ŠÄoà ®\¾ä'TGx‹Jõ+‹ÈÜ@”ø8îLäÃÆÒìAùþfç_|׸Ì4«ÕºÇõu 3S“½NÀÕÏñþ^<ê6f•‹o´O¾­ŒÂ¬!#¸Šà<˜V-èÖö~­©¬xøñÃh×÷Çå >ÅùrÙ-ØsÚ*”yÅ(qL”Ž·ýƒúÚ»5 ïûÛ†ùáö˜6‹Û§÷Óš¾ À šêʺ>í›V.`ß·}[I$Ë©4›×ôöòý‰²9sßéHêIEND®B`‚./public/images/jsonedit/bullet.gif0000644000175000017500000000007611773315157017054 0ustar tfheentfheenGIF89a€îîî!ù,Œ©Ëí£œ´.€):Û†âHB;./public/images/jsonedit/label.gif0000644000175000017500000000026511773315157016644 0ustar tfheentfheenGIF89aÄT™L¤Ô¢…ʃ–¸‘éïè^½X™Ì™µÜ´›Ö—™Ì™V¡O»ßºÂŒëöêŸÜœ_ÃZ‹ÌŠÂâÁìøëžÖš—º’_ÀYX¦Pÿÿÿ!ù,2à%Ždižhª®ì)9O55ªƒD‹a¨O„@‹ªp€ ÕÄ00(ª0 ´®Ø¬V;./public/images/jsonedit/value.gif0000644000175000017500000000026611773315157016702 0ustar tfheentfheenGIF89aÄÓ*-ø¬©ò€Í…ôlgûååò,*î||óˆ…äxyõtnõ”‘û¼¸ÿ‚Ç*/ü-*úµ±ÿæåÍ*.ø†~÷-*ë€ý€æ€õwpÿÿÿ!ù,3`&Ždižhª®ì5%jÓ0ÐQ©3) €ÊÀ•à°@$ªÂEâÐZجv› ;./public/images/jsonedit/saved.png0000644000175000017500000000064511773315157016710 0ustar tfheentfheen‰PNG  IHDRóÿalIDATxÚcd€6áèÃ?Ho—ÚŠ©_Œ Póÿî{öÜvÊ|-e¾_5 #ITµâû£©¤ªõ¯–$Çaš:[»gz¤- ‹b}ORbQJÛ7N£1ˆ»O’ž-Šôå34Í~|y¼ 5✥füu7>Ê­JÄ‘_ 6Oß7–äºn€1voÿ‘.ñ<ˆù4B³á;`l;ÏÁ6âLje=xÔ°íf楎Ȼ- ºÐ´Ù¬^?ϲ¼§¼•·Š®;«ÏYµ³NE¿­ÉF¨LàJEIEND®B`‚./public/images/jsonedit/deleted.png0000644000175000017500000000146411773315157017214 0ustar tfheentfheen‰PNG  IHDRóÿaûIDATxÚ]“ýKSaÇϳ{ÝœÛÚæÞŒiQ&F1Ñ|)DôCAý”"2#%1Cú5ÈÐ0É~èÇt­)jJhà 1|!¬ŒH´|‰Ým¹Í»Û^Üîíy7S8÷<çûá<çžÁoi®SkuízKž=+[a!¹D<Î…8Î#ì„÷èÛƒõ(¼ºéв,ë²UVÕ›ssAây¢‰Ê€4ðmo×…ùiQۚܣá}À˜£Q+gOUuuƒÀH08/ÃN©Œ#H¯‡ùÙÙ¥¤(Úc“á=@ãõ©r›­ * †B`Ñé|8§Ã9K*5|X^ž¾ñúMr^»R[”—çÑg±ˆˆ·år(lë€õÁ°ˆ) àd œìè„5× è î&¥ŸgGÃW/OëuM .æŠzûÁR|xŽƒ¯ºé|ÎõôÆbnå¬ôtF­‚†®C“hôR­×ЧÍâBâ;¸½Ò'OAc¶ïã( /Ý¿j§$±ÿŽÅ9ä*=/רŠÇbQøk0A¹sÔf3D|>X¸Ý Ê€ [ ’BI

    ~¬Ñt’$­vºH#¥SÚ€¿>^MÒIv:–Ò«%þ6aLÓ-‹(Àm¯Ö²^¯Ç–m5RlÅPd/¥Œ&{ëÌ\xÿ1#D\Ö€¯>K·q.–>#ÝäÒ$Ø2˜§¥œœ¶–wïÿ?¦ƒö¢æB2k×D£v†ß¡Ï9¥9ÆE”JOT®p¶ÍÌzÎÿne6›«ëðIEND®B`‚./public/images/jsonedit/plus.gif0000644000175000017500000000013111773315157016540 0ustar tfheentfheenGIF89a‘ÿÿÿ€€€îîî!ù,*œ©Ëíc ´V€Þ à-lÞŠŸ€¢Ý§…ÚÈd­Ir/fYÒÎ÷þ?(;./public/images/jsonedit/delete.png0000644000175000017500000000127011773315157017043 0ustar tfheentfheen‰PNG  IHDRa~esBITÛáOàPLTEÁM3õæµð‘Ön_ò­ªÿÿÿæVLïɣ갓ö„lÇkMÿÿÌùÓÌ볕Þymܦ|éc[êƒ}ÄdDúš‡øÃ¾×]Qèzuô žãkaø¶¨í“Žîj^ÄP4çÄ—óycæVPð…pÖ`TÐO>ñŽz¾\;ûë¿Þkhú«ÎbRöÏ­ñœ–îfRõ¦¡ýÜØø†pÔq_ùËÄ᫆¿S7æZRÛVKú£‘úº®ø¯¤ùé¼íÉ ôŽòwcÞ{sós]ÌR<àe\æXL÷“~éxðƒ{ÍhSç]YïʤÛicðµœú‹ô´ªîŠuõ£ŸºR2ÉkOüÔÍÅkBüǺîŒÿ­œøŒvâpf˜Þ1VVtRNSÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØc) pHYs ð ðB¬4˜!tEXtSoftwareMacromedia Fireworks 4.0ê&'u¾IDATxœ}ÐgÁ`†áÖµgQ#FuТF5^U{„ðÿÿ NÛ4"ܯOç9Xø+ì5·:ÃÄ¢ªK¼Ne"½ýûvˆg|¢<Ú±W’Ó,j’‚˜ö4ºò+h›¼ìÐxUQê®°šŒ—g FFU?´(¶ú@¶CØ”°)vCÓ…•¡§€‚C¥ÝKq µ›WLóMÇ[§¸¹`$L#—=•AÚjFR‰Ñew¶*…è~*ŽÿÎGO! #ÒUm—³IEND®B`‚./public/images/avatar.png0000644000175000017500000000621611773315157015245 0ustar tfheentfheen‰PNG  IHDR22‘]æ CiCCPICC profilexÚSwX“÷>ß÷eVBØð±—l"#¬ÈY¢’a„@Å…ˆ VœHUÄ‚Õ Hˆâ (¸gAŠˆZ‹U\8îܧµ}zïííû×û¼çœçüÎyÏ€&‘æ¢j9R…<:ØOHÄɽ€Hà æËÂgÅðyx~t°?ü¯opÕ.$ÇáÿƒºP&W ‘à"ç RÈ.TÈȰS³d ”ly|B"ª ìôI>Ø©“ÜØ¢©™(G$@»`UR,À ¬@".À®€Y¶2G€½vŽX@`€™B,Ì 8CÍ L 0Ò¿à©_p…¸HÀ˕͗KÒ3¸•Ðwòðàâ!âÂl±Ba)f ä"œ—›#HçLÎ ùÑÁþ8?çæäáæfçlïôÅ¢þkðo">!ñßþ¼ŒNÏïÚ_ååÖpǰu¿k©[ÚVhßù]3Û  Z Ðzù‹y8ü@ž¡PÈ< í%b¡½0ã‹>ÿ3áoà‹~öü@þÛzðqš@™­À£ƒýqanv®RŽçËB1n÷ç#þÇ…ýŽ)Ñâ4±\,ŠñX‰¸P"MÇy¹R‘D!É•âé2ñ–ý “w ¬†OÀN¶µËlÀ~î‹XÒv@~ó-Œ ‘g42y÷“¿ù@+Í—¤ã¼è\¨”LÆD *°A Á¬ÀœÁ¼ÀaD@ $À<Bä€ ¡–ATÀ:ص° šá´Á18 çà\ëp`žÂ¼† AÈa!:ˆbŽØ"ΙŽ"aH4’€¤ éˆQ"ÅÈr¤©Bj‘]H#ò-r9\@úÛÈ 2ŠüмG1”²QÔu@¹¨ŠÆ sÑt4]€–¢kÑ´=€¶¢§ÑKèut}ŠŽc€Ñ1fŒÙa\Œ‡E`‰X&ÇcåX5V5cX7vÀžaï$‹€ì^„Âl‚GXLXC¨%ì#´ºW ƒ„1Â'"“¨O´%zùÄxb:±XF¬&î!!ž%^'_“H$É’äN !%2I IkHÛH-¤S¤>ÒiœL&ëmÉÞä²€¬ —‘·O’ûÉÃä·:ňâL ¢$R¤”J5e?奟2B™ ªQÍ©žÔªˆ:ŸZIm vP/S‡©4uš%Í›Cˤ-£ÕКigi÷h/étº ݃E—ЗÒkèéçéƒôw † ƒÇHb(k{§·/™L¦Ó—™ÈT0×2™g˜˜oUX*ö*|‘Ê•:•V•~•çªTUsU?Õyª T«U«^V}¦FU³Pã© Ô«Õ©U»©6®ÎRwRPÏQ_£¾_ý‚úc ²†…F †H£Tc·Æ!Æ2eñXBÖrVë,k˜Mb[²ùìLvûv/{LSCsªf¬f‘fæqÍƱàð9ÙœJÎ!Î Î{--?-±Öj­f­~­7ÚzÚ¾ÚbírííëÚïup@,õ:m:÷u º6ºQº…ºÛuÏê>Ócëyé õÊõéÝÑGõmô£õêïÖïÑ7046l18cðÌcèk˜i¸Ñð„á¨Ëhº‘Äh£ÑI£'¸&î‡gã5x>f¬ob¬4ÞeÜkVyVõV׬IÖ\ë,ëmÖWlPW› ›:›Ë¶¨­›­Äv›mßâ)Ò)õSnÚ1ìüì ìšìí9öaö%ömöÏÌÖ;t;|rtuÌvlp¼ë¤á4éĩÃéWgg¡só5¦KË—v—Sm§Š§nŸzË•åîºÒµÓõ£›»›Ü­ÙmÔÝÌ=Å}«ûM.›É]Ã=ïAôð÷XâqÌã§›§Âóç/^v^Y^û½O³œ&žÖ0mÈÛÄ[à½Ë{`:>=eúÎé>Æ>ŸzŸ‡¾¦¾"ß=¾#~Ö~™~üžû;úËýø¿áyòñN`Áå½³k™¥5»/ >B Yr“oÀòùc3Üg,šÑÊZú0Ì&LÖކÏß~o¦ùLé̶ˆàGlˆ¸i™ù})*2ª.êQ´Stqt÷,Ö¬äYûg½Žñ©Œ¹;Ûj¶rvg¬jlRlc웸€¸ª¸x‡øEñ—t$ í‰äÄØÄ=‰ãsçlš3œäšT–tc®åÜ¢¹æéÎËžwç|þü/÷„óû€9%bKGDÿÿÿ ½§“ pHYs  šœtIMEÙmLróÌIDATXÃíYMoƒ0 µcCT*QmR¥õÿÿ:.¸T MðýŠP ¬SÚ05§"Lýxy~6€MÓ@~‹€˜I©L¹¾wÖ2RÌœ QÖ:Y®La ÷ν˲œ™ ë:‰†i­§`í¿÷ñ[!Þn·3aµmk†í¾v ØÄ7¬¿HÞ_ŸŸ%>°ÆThŒ™Ðñ{ÿ¹¶R8ÁS›ÍFy¾ïû¶mƒ‘UUÍë\XÖÙ£9OÕRû‡"2YêRƒ~k+µ¶ÖÕúö›ˆÒ%&"?WV]×Oâƒy"×[[¿Õ–ˆD'5d »Éàr‹DÀh¢s6MS1e“³ît:]ØÉeûÎl±™¶r‚%Ù»üŒJ|¦¸2×– æX‰peËŸõ´Ö麵s΂¯ª*ÄÖuù3«d/˜œs~®Õjå³µÀž("}ß'Õÿ°” Â=Q ¡Ÿ RÞ!  Š7‚¤]fÒåGíôi6{K„€€“./)›ÒàŸï°#•Øu“¹ÿ,AD ðâxÉÜ!ZÙL§ tù²(_C–§­À¼¥^ôñgPœÚÍÓ~ÆÓ©BÅE._Ȫ ,"" ¬ØúÖ ×–—ü½IEND®B`‚./public/images/toggle-collapse.gif0000644000175000017500000000026011773315157017022 0ustar tfheentfheenGIF89a Äÿÿÿ÷÷öïðíêêéææãããàâàÝàÞÛÜÛרÖÑÓÑÌÌÉÃÉžºÄ˸ÁÉ¿»´ºµ­‰™¦‡˜¦!ùÿ, -`däD@ª’´¦A̳`´Â¤ë>„"Ñ:$È£µx@žO‰£Em9B;./public/images/black_big.png0000644000175000017500000000525611773315157015667 0ustar tfheentfheen‰PNG  IHDRrÂT™IÈtEXtSoftwareAdobe ImageReadyqÉe< PIDATxÚìÝO‹[×Çá{¯4×cS]ÜwY²é¾²YŒÁ oº0”¾šn ÞÍlì]¡!ôµ¸ËRB¡8N3I·£±4œ9ú{u¥qIÏeþ>óõ‘FSWë««Ílúqû¢ý˜WßáÛkñçv@´Û¡¡î{}]x¿ZÔÖŠw[xŸ¶'Üí:Á®{žGºôº!Ÿ`_Ã…:{éu}Ÿ«sQw*¬ôháì{Èó­ïüš_:K¿µÀ«ÂÏxï£äåô6ÿ˜h•;^åX%]àéÚždñ¾ÌB> >&ZæÅG¦äOC½¼Ž’˜ƒ¨7Á:¯Ä8ˆWÁ Ÿe‘ž$×eóIö>yÌo­òèÑ)ù%á%Ÿ_÷’˜eA–yo1ö!âUµúH•è<÷òö}ó(èÑ*Ÿ•B>*,ñ£ âé•=y~ݯaÏϳóˆçO¯Ë èù2ŸF!îÜW·Ï£x1–y´ÊöUiçÇ(iÀ/ QŸT«çç·ŽW¢;8GAÈÓ~œ\÷ç·/_¾üÃW_}uúèÑ£ßúþô{ûöí¿^¿~}þüùó,"þãâö"‰zºÌ§…c–vTu?Z%?ZI×÷uÄÏÎξ|öìÙŸúÖ¬gÞÌÏ>ûì÷Ÿ~úé^½zõ¦ZýýÒcÇWKž«¤k|\­ž‡ßO–ø¯æ·ïÞ½ûëƒ>9??ÿï·ß~ûƒo@¿/¾øâÁéé鯯úÝÇÿ¸XäÿK–ùÕê¹y~ççuðÓóêÒ3æ¿ìsópÃ'Ož<šGüââ¢q€õÍ›9oçÉÉÉoæ-­VÊ=`$ü-ùqðù£§§m‚˜]™¯óªmÛë €õ-»¹héÑbu—^|Ô_ӱƣçLIÏÎÇWÿ#ß €­ƒ>ÊÖxÔÞâ6Á¯ªÕßøŒž(ktõÅǾ[‡¼tœ2êèòqÕýœäÑO…› Ïf³qþO†Y´´ëI£c•›vG¿œÕ¿ô$ZŽV¶—¯ð®ç¨*ž‘G!ÏßgåÑ,W+ÜoiliÑÒèÑ)Q§WB^:ã.ýå[“? ¹£€­B¾ÒØjÍ?ÌÓž—¿îˆ;Û)E»ë>ÌÁ‹¼+ê9Àö!ÔÜ®E>ô‹YäwòAm½³Ç[ä?:Øq9À-òâÒØÚFoð,r€Ÿ.êw¾Èø…qF°ã,r‹Ü"°Èøy¹¿Ù °Y;-rœ‘ì:‹À"·È„€9Z°È-r!`cŽV,r‹À"À"r!ØIŽV,r‹@Èؘ£‹Ü"r6æhÀ"·È,r,r!r€ähÀ"·È„!r!ØIîì°È?¬q‹`x;-rœ‘¹9Bp°ÜÙ `‘[ä99€ 9€ ä äÎN‹Ü"r„àP9#°È-r!@È„\Èv’;;,r‹@Èؘ£‹ü÷Ȇ·óò»ü@ÈŠ3r‹Ü"r„@È…`'¹³À"·È„!8TÎÈ,r‹@Èr!r€äÎN‹Ü"°È°È„\È„!` wvXä9€EÀÏ»ÈçkÜ"ÞÎ_LÈïò!r!Øîì°È-r!`cŽV,r‹À"À"r!ØIŽV,r‹@Èؘ£‹Ü"r6æhÀ"·È,r,r!r€ähÀ"·È„€9Z°È-r‹‹À"àpù|[äÃÛi‘àŒ`×Yä´È[‹à'³vT› ?±j|¼xj¬3r€çŒ`ÇYä¶ÈÛà`Ë-¼M[Çk~Ò*»]ùb9À…¼·¹]‹<Ƕã§ÅÌ"¸³Ï:–yÛÑéµù,¹]^m]×3‹`;‹–®4¶÷ÞE^ï­òù'Ÿ¦!`«Oƒpw5y­çá^^Óävê[°µiÖÖ|™w…ýúh¥ë ¦t¬rýE›¦™Ü|€£€,Z:-D<Šù­Ñݬ±ÆÛÅ'o“/t}]ýs`â[°EK§Ù•¶·s•7=O*¤³þE'W_ÜÑ Àö!¿éjÖÚ¼ÃaÐÇk|–ýwú“bþÅ.¯\,þYàh` y;«1·ô2 yzÌ5ùÖ*o²çµŸsù…&oÞ¼yûîÝ»ïNNNê/^<ðmXϼ™óvÎ:oiÚÖ »³ŽNWurÍ£>J®ùZ?Jnï]]ÇW×ýäöþÙÙÙ—§§§òmîüüü/OŸ>ýûÕþ¸¸.’Û÷ÉR/.öQó<ìËÕÞ”ÞïÕ«WÿüüóÏxüøñïîÝ»wâÛÐïûï¿ÿ÷7ß|söõ×_ÿmìe¸ßÑžT·Írë˜%wºÌÇ‹Û|•§×ñ⺷xûQòþãdÝ/?gú`_EIïмL®eÄÓ¿Öxzìr롉ˈWIÈӸ޳c–ôÊ£~”ÇŒ²ÏUgË`E¿ƒ³ò`‘ä6ŠwzM²Už>ãaô ˆkýš~qä!¯³˜G+=ºJOw¬ÚñJéiÁ£•ž†>ÿ!PU«­òèÑ,ÑB¯ ÏTBhÈ«Bˆ£_ð)-ðèWôWBÞó舤é¹Í×}t”°¯1Oc; ¢Þuýmäâs’w-ä(æ¥_å¯{Þ_ÈCyôô³Q°»þørô7;ÛR¼«Bx랣—!ñràPŽWÖ‰ú¬'øUÕñ·;£ v½.ŠtéuC>?À¾Æ<ŠzWØû¾òºRTû^_¯±àE ¼ÎÛo/þè í·;:¶ÖÛž_­óö!ÁÝ4΢ˆ÷Gü¸»Š¬Xü´‘¿ñ̉·‘óâIEND®B`‚./public/images/toggle-expand.gif0000644000175000017500000000026511773315157016504 0ustar tfheentfheenGIF89a Äÿÿÿ÷÷öïðíêêéææãâàÝàÞÛÜÛרÖÑÓÑÌÒÏÉÌÉÃÉžºÄ˸ÁÉ·ÁÈ¿»´»µ®·²ª‰™¦‡˜¦!ùÿ, 2`3ääL@ª£Zð– £PY¼…ä‚¥pøM ˆ„E±`P( HDBPNÏ,å;./public/images/merb.jpg0000644000175000017500000001326711773315157014714 0ustar tfheentfheenÿØÿàJFIFddÿìDuckyPÿî&AdobedÀ § ÐçµÿÛ„      ÿÂWÈÿÄî !23@4 P1#5 1!Q±"4Aaq2Rs‘B’# @¡Á¢Cc“PðÑbr‚â!2 q01"@PAQa‘ÁÑpð!1AQaq ð¡±@‘ÁÑPáñ0ÿÚ ßÀ^¹\¿_¬‡~Ÿ [üÖ Õ,³o¨â•Ù¦âoÖˆñvÄÙyÐqÛõ~̘ù°é?^7ä zqE«]ùû‘&:Kß‘ò³ùæ6jô¬o¥º’®Œ¿Zë亾ätèzÓËvÎ~ìû¯ùòKF󕇙}k‡§’?ÏÇ6³d¯©øÞúÞµhøŸUêGž»†§©5Ó›\íËÖË~´2×Ëù½}hï¢ti*V”kC¯fÛU›ÚR¡¥óÈ ÁäÓ«›@_÷òOÉù\¼ñ>7²Ñ±íÃ9XcÚ8®ûží³mÛÇß!äz›Zý_ª¿?¸óç|Užû±þ™ÜÍtnUYÆÓÓw·¿}ÈT>(ÖYÊvs}1«†ÂèlìO¦vòÿÏù4ÏGX]ûµ—s üš¼Ël›ïr[Öˇ¨µÏXÛ¿èölsCàSœ½ p°«—¸š›]’Ë4z8e9ö­ÚÃò*ç“«|;w£½³/ö ›EâQžf’°u®ûKüþ®áîOÐO£Ú<ÇÏÍú=Âý"úUÃÑë´§?›·í6Ur–ªV.-ÞÅÕèe*÷ ‰o’²2nÕxônmîŽ×½Xò%+Ÿyœ«wc¡[`Ñåï»Ë`ºl=Q5hãûéç#^œ8ãñ~ÔÁ¬:ä“®ä‘àŒoCƒw/YúƒV²IÓrMº±O†+ö¦Í©Ë4ܶäÿÚû\™æÃß*à‰'rߦ¸&æŸoô‘î ÝÄ RRGs‚A™ ¾Awm›s¢^t±j \%ÝR”…Ynçj¸E»Û¦·&ñlˆ›íÖ-ÓŽjªÞÇ=V[† à·Féu¸5l‚·Ík„Ó“eGe1Ø•íž[ËrÝŸ~9æoš£ƒ„˜ÿŽ›ç¹/+‰Ê:ÉjHm™rv«í¾ÏGÍóƒþƒ_£‚?“&Ë.\÷•$¹Žq~3ñ)D¢ØCx93ªØC 4Û)q¦ÝNÂD8ͨ:Ëo'à­ÙŽËãMº„0ˆ‘šPr,wa 6Ól¦MªÝ0Ø‹1z¿ÿÚû\»GWÍ$E‘®MxòÐZ¼?Nº²Ìh6êW‚¥4‰-¯¾„ ë! J‚”Ièê 8ò%“‹ µøW)¤„ÊiX»Ù@_™ñÐ6£AÉš§E¾I¨¥Î5Œµ €âI 4Ò‰èõ! Ä¡Ç_ÕUHT‚%+Ml©‚ ÃI‡{((´–‰P@Ž• ì$“Д„#"wpÐRzŒ£(E­ÅñÍ¥e–H<Ñ:š¢3š»ÙAL&ùj-Çúî^,£(ÊѬön›¡QÖ‘”EE]ýÙE³Æ]r‹q~§{( ð˜_¶‚ÝÙpñÐLεjD¦Ô-¤‰/­PD/Ü'y¨ 9•RÓA$e #"^ì¨V¼¢ßÙ?Æ#ydCê(:mDB7”Mò‚dÔ’ë„X¹qÛ66Íà¶P¡¶l!€´’†Ù°–Pœ‚XزÒP’PÛ6Ê‚ÙB†Ù°„Bã6³m”7ë?ÿÚûg_P_Ÿ®¢¸f¢¸ÔfÆ¢¢¢½jTW¢¢ ÌW˜5aÔTféQQ˜TTf¡'ŠŠŒ¡]¡B£8Ì}s¨¨¨¨&Ì+ ¨h ŒÁ'R1PGƒ§×8gµÞÚŠŠ‚ê4Ô4Ô !P×Uÿ5 v…Z†»LTº‰Õû_í¨AfÁ·2™,ŒÒAÅ’‘Q¸JüÔFXZ²•Bz™0a=ÂWpÙ#°EîyŒÀÒ¢3”ˆ½Â_ä5J” Dfg&9He,(2–9HS 4Ša”…0 ÊXÁ¬ÿÚ?î½°V­ÝœeÀ¸+ƒ\ºKN¥"ýE\¤¦® Euó*U9Éý4¨ ÛW‚ÛG&ŒA^­»5ÿΕÔe\˜äð‚ 6â· 4˜•Ãß y(5£IqR9`-ª×µZ¦–ÓíŽl\倱ÍjÐ * š»åKÍ©mËmóÀ)Ue€±ÍjÔþø-Ô{}`Ý 5- ùmÜßu\ÞÕkD…j’šµDšµt…5jˆ 0­RQ!tŽÙÿÚ?ü‡<¸[‚Ÿ{ÿÚ?þÁqî±W/ô>¥Ê·æÊspÁ„°Òµù¹yA´¬“Í}òjú—3¾Ë™‹ßeˆŸ 5îë˜gì«ì_ Q’—ÒÊ`jÚ´ìXcœ\¼7?Óm$œü5Óê\ÃzV)FÖ/UŠC`dô\Ì^û,!8xX™Óq¤`­ËGˆxc§ÒVšûPç.–¿b f½ ú6Û?–[,eˆÞ÷qô5ƒ$e„ÆçB ð£¦øøŸ¦Ó‚R«ÄØ„ßÃÖŠ<¹`…½¦¼“µH®eÅ(÷[I3=]–0“†mí'7vâE ´¬ÛWy ¦[±“û¨¦·‹ù¢½w“dá*c7rq½ëЛDÏuZ–ZbÅ茟ÙédþYl°GÅ¡4|:6ñUÝIzŒBݶjai7°Æ%v…ú˜£ˆ˜©¡wÑðë¾8K±Ö„%˜”@#&ÅFj®nÌ0ÔɆšªŒ÷dïzê{¦9d1{¥4“»bJõ6xڮς.­jL¼—H×ê~‡F¡Ñ×}eç­HÁ±öô©ü²ØCþccâzn ÝÞBˆK0ÿÜ;~G(I«N¥Ê}¦\§Údóærø"Ê­f\OKGY=Ö³/äývWñ‹ê³9K¸Å¶Ì¾/kOЧòËb.Õ–Þw”vÙÛÙþ!¬×hí°òѽ%áÇÖ㦉ÀÛ ‚ej˜Á·e§M,¸Ü_¡É™ýKù؇«_èY¬ÆPª# ÖûÊ=–e|Ÿ®Éÿn¨nüH+Ó­”ù™Køm¬º›ÞoWPå¢lE)³( ¢ô,Ç–[âÄúVN¢ôãÛ45~®ã¨|ÃY¿õÚ»Ž£ÄÔøG±s!HóyÌiãÌåŽ"ml´="†I‰õ3ºÎœñ´Iðcˆûõ®Š2î: MO„{,ÉáÓð_jî:‡÷oÛœß5¿GH¦첑Œ2WB²Ð¤wadù¬Ý=#]Ð c³Ü÷®X.«1É™xrÀ°Æ ©–ˆu:åcŽk‰¬Ã(1ާ\_ÐÇÄñ骤1 }‹ €Æ:rÀ±Ç7´Öb’!2º®¹`XcÔËg*>·X`‰£n¯žÿÚ?!þ-°X×Å%hK¦”îŽR5«_ "@®'›2æ†]íˆÇ” ë§®÷ < y;›èóŽ…«ß(AfÙØ£¯X&Æ`øûƒòJœ‚ŸiÂãTêÏ6þam”c Ãœ¯`¶5;os{Îésç1æ±Ü´$ËÝY톾kÏPÎì"ú1šEÂàü½gth °øí-®OsË‘¡¼Í{5Â'”@ϧ¯À‰½ÔyUŽðÊ9¡øx`}y”Y\[t:1å¾Ì©†ä°u€Ð­ô´ó‰ä *¥q¶Àk1ówl×23’+¥ŠZ›ñ{iä¼ÑÍÌQ\ z³jt[f.KפîŠÎ±(+OxF¡Äæ›À^™øœð͵î{Þ9äW„£-s‹°áÙK+! ©”i¬ífK\ q¸ÕQeé‚_H梚â´3]è¶}à-蘵lÓÌj8"Ç<ËË%ºCå<—šqþ,©Þÿ6”ç¤ÙŠûñ*ñž“ ‘wÎùßYPû:ï'YÔù:ÆÀº¥ÛfwÀm;Z'¾ì>S¾ޝÛFeà~éß8Úì‰ä¼Ñh¯y¨˜Û#Ž˜H{çP¿±ò“¾%±zžáÊ”á0 nâjº¢˜è@]zZ?ê¾ Žõ;åw–ƒ¾ÔwÊ¡`CŠâ¡@;Çï'º·m2r\³ãs¥EKÉýñ « o¡ÉQ šX/¥´_ þ -›sԗÖèGø,"Äá±"ÊîW/ðf÷¼²½¢Ù_E!­¥Ì^–YÈgø,"çoeh¼‚‹€¸ÿ‡¤W#”ñé1rÚÀº‚>ðÝPÁ•p:¼t2ìsþl“#¡ [‰þlË6½²Øí1dÿ6»),­,×pîzôí+{å)ÀèüÌË Þ,ŸæÂ7J‚’ñ¥W£ Úå?Í™æ×´[2·nž>ŒV­¿ÝúÏÿÚ?!þ, µ—:Ÿ¼ %}8Ð>w [?Ô'û„kÒ ÷fŽP_ßâ%FºìIà‚Û³¤Õgú„fõ†XúÙZO½ˆÑÜfŠõ÷/&ƒ/ËÐi ”Ã=_Ö»ȱéýE”®n/õèÞ]q3]‰¿YÖ—³°½£+iu õo„߃¾ kg—õ§¹CLVm¡ûÒrwš!ð·H¢%ù±éš ßË¿ZªqÔ¼+¡Þqw¾4ZN??‰Ä+ÍËGzoYï=Êê§Øø‰—?.û^P-O·îu~߸]°i3<ïì_Ηz:8ù»Z_(æÏr†ƒK½?'ï~ ñ´ˆ ÿþ ÉÀÜâBì§G¼ÞÛ/i~à%:jõ> ­$Yöwåöø—Oެ ©gîðLàT÷ˆX-”­+öþ%œçèM®Ég9O]ùF·©ù~‘¡§' £0—:±|±¾%œå~÷Ã¥/œãS…Òq6ÉÏæS+¿y‹£~\c*ú_߯ˆ%3¦‡%¢´tÐ*5¡d飔A¨Üà|ŸÜ>€ƒÐ²tÑÊ¢6Lé t(› }¾!´GÖÿÚ?!þ.Û¢vAúu”¸qñWœ¯=)í¥`]PJA¢Ô¯8 Þ4qÄÀë±Ð±¶ú–è¹Ã–ö—èoͯÉ.´S6:€ ¶ÐIl ²WPÜçR4|."ó,+Z©›4ªÆ÷ƒ•Ñ:s§ ´Ó‰£¡¥hÈÓµ61ƒ¦ŽµÝ¨‹S!±›ë&‡zU ˜$XÝ ”61+/Nú|33bnLèï·Fi4\ÞÓ3áÓbf1îÄK´|ï¯Jt4K:Ph—:P&ˆw™®  ¢ó¥h‡yÒ€Mì€mõŸÿÚ hÀ XD#1ÚÿØþñà /Õò5! 6‡ÀkW|À7$†Ñ7ä4ºMW {T§ †Âv@äs±ÚÍ&hšÿÚ?þ/€É—*šH*y•ŸêE¿LêŒåæ@v8‚ ÿ ! D8¤¾ÈÐ.±{tÒ~kû)¾á[ÒP¯-‹­MÝiY…ÝÂÃNÄ•#ÅH›.UÿR <Ó i6Ÿ%y/géþ‚™Ý2–ôCÓ¦ >Òø5|(…½à=~ó‰IòE½5éå¦A6úÏØŠîbZ .þÐJž=ÛEèXv>|žž Ü;¤ò­Þÿ|ã¬qÆñAþ7ŠE‡¶Ãˆvõ©þÞ 8mñçØS`jà Ksï.²‰sVõ§ÀT6Vºµ'¿Û\µ§ñ­»G@ƒwí]z’1Ô¥ÿoÆ–Œçî4ú$š[=ô:ø†Í?‘â¡§C ?ÎT+ÛF¼°ò ÝŽe”¯ö–øð<ƒO×"…îm ðý±£ùŽ*>åKÕ‰Õw±úÏÿÚ?þ-aó‰äÿ©ÅÉ__m`ó·çL±äha¡ÒgÏÙ½ÏÔ¡ù(º;~eáÝâP‹à/üèW©ÕæÚ¯Æî•O×Ä>ü4¢Ýº•[^úâÙ #ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF[IDATxÚbüÿÿ?%€‰BÀ8à. ‰ ÿñàbÂ_À0ãG¢Åÿÿÿ ïÿ öcS‡Ï4°©Ã  MrBúp¤¦Æ¡—I€šº!èÝ‚xIEND®B`‚./public/images/toggle-expand-dark.png0000644000175000017500000000551611773315157017446 0ustar tfheentfheen‰PNG  IHDRóÿa pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFyIDATxÚÜS[ €0ë&p60€†X5€™ÍÍd¿ËXø¡IîÑôšœ33´ C#¾ZŒ’LÒZp¹%‹ ÀL2¾Í`îΪ q<9«ˆ$Ý`"9åš}ay#¹IEND®B`‚./public/images/treeBuilderImages/0000755000175000017500000000000011773315157016650 5ustar tfheentfheen./public/images/treeBuilderImages/folderNodeOpenLastFirst.gif0000644000175000017500000000153711773315157024104 0ustar tfheentfheenGIF89a÷ €€€ÿÿÿÿÿÿ!ù ,<H° Áƒ*\Ȱ €‡!0±¢AŠ-:\ð¯cÇCĸ1£É’( F\Ù°¥Ë—0cÊœ;./public/images/treeBuilderImages/folder.gif0000644000175000017500000000171611773315157020617 0ustar tfheentfheenGIF89a÷ÿÿ™ÿ÷‘ÿôŽÿë…ÿæ€ÿàzÿÔn™fšgœižk m£p ¥r ¨u«x®{°}³€´µ‚·„¸…º‡!¼‰#½Š$¿Œ&À'Â)Å’,Ç”.É–0˘2Ì™3Ó :Ü©Cæ³Mï¼VøÅ_ÿÌfÿÿÿfff,@³SH° Á ðÀ°!‡ (L˜p Š‹3b¬8PD8rä€ÂC(S¢,@ ‘0cÊ)"E€›RhÀ`¡Â 0=³èͼ<ˆÅ…¢J:"‚¥3³jݺµæÀ[C@–lÁX~0àc Òì€"Dxóâ5`ÜPl` °áÂ$$ø;Ч„8hÀ`‚WsÝÌYk@;./public/images/treeBuilderImages/folderNodeLastFirst.gif0000644000175000017500000000155011773315157023255 0ustar tfheentfheenGIF89a÷ €€€ÿÿÿÿÿÿ!ù ,EH° Áƒ*\Ȱ €‡!0±¢À)Ô¸£@Ž)þ9rÅ“z4i±cÊ-CFŒØ°¦Í›8sêÜ;./public/images/treeBuilderImages/folderNodeOpenFirst.gif0000644000175000017500000000154411773315157023256 0ustar tfheentfheenGIF89a÷ €€€ÿÿÿÿÿÿ!ù ,AH° Áƒ*\Ȱ €‡!0±¢AŠ-:\ð¯cÇCĸ1£É’( F\Ù°%É–.aÊ|)s!Í;./public/images/treeBuilderImages/folderNode.gif0000644000175000017500000000020511773315157021415 0ustar tfheentfheenGIF89a³€€€ÿÿÿÀÀÀÿÿÿ!ù ,2pÉI«•àê}3ÿ ŽcgZÞ"L)•®˜)Ìó’ÝìÛ§š£=‰*ÆŒH^ÒØZrš“;./public/images/treeBuilderImages/folderNodeOpenLast.gif0000644000175000017500000000017511773315157023071 0ustar tfheentfheenGIF89a³€€€ÿÿÿÿÿÿ!ù,*0ÈI«•àê}3ÿ ŽcgZ^xªh ¼oÍSJÙõzë5I‚À pH,5;./public/images/treeBuilderImages/Thumbs.db0000644000175000017500000005000011773315157020414 0ustar tfheentfheenÐÏࡱá>þÿ þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿ   þÿÿÿ! "þÿÿÿ#$%&þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot EntryÿÿÿÿÿÿÿÿðÀ:…ýJÇ€=1ÿÿÿÿÿÿÿÿÿÿÿÿÁ2ÿÿÿÿ3ÿÿÿÿÿÿÿÿÿÿÿÿã þÿÿÿþÿÿÿ !"#$%&'(þÿÿÿ*+,-./01234567þÿÿÿ9:;<=>?@ABCDEþÿÿÿGHIJKLMNOPQRþÿÿÿTUVWXYZ[\]^_`þÿÿÿbcdefghijklmþÿÿÿopqrstuvwxyz{|þÿÿÿ~€ µÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?û¿â?Çð‰n´éå‰c¹¸†$Óüçò-¡´’yÚæ!o#T=Á«ÑüSÖü?ãÈô¯éñIáÛÙ!´²×, 1s#*¢É‘Ø«¼Š€Œm+’ ±hü7ö¯³“Xñ3GÚ›Zê‚é¤}¸ÇºÏO$gûRÙ£þxçòÓ'7ð«BÔlŠëz•¥¼ëÞ%Ñ.^àÛÃÕÌ«©.÷JÓäÜYØæU¶âFÐI±y})eËdŸ+õo£_%ùü¼ëTŒùÜôoEø[õùv¹÷eQ_z'‘üJý™|+ñCÅvÞ!Ô®o­µiâ-eÎ/ž7+ ”*?t‡É-´ý›tè5=2îãÆ)ÔÂò 䶺ž×Êy!‘d@ÁmÔ‘¹F@#ëEÐñœyݶµÝ‰q‹whõê(¢¹Ê?ÿÙ üÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý>ñdßgð®³/›äì²™¼Ï3ËÙ„';¼Èöã×ÌL}zZÊñdßgð®³/›äì²™¼Ï3ËÙ„';¼Èöã×ÌL}z‚o ZOæî›PfüìÔ®¼Üã ®|cÄxÇ—Ð|o~šW‚õûÙHã¶Óî&g‡võ Wk£gŽ0è}zº( ÿÙ ×ÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý>ñdßgð®³/›äì²™¼Ï3ËÙ„';¼Èöã×ÌL}zZ†îÙ/mf·È±ÌdhÜ0vºÊ} Ž Õ ¼5i?›ºm@y›ó³R¸\nósŒH1þ¹ñŒcã\{@5h¢ŠÿÙ ŒÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵ4ÿÿÿÿ)˜5ÿÿÿÿÿÿÿÿÿÿÿÿ8Z6ÿÿÿÿF:7ÿÿÿÿÿÿÿÿÿÿÿÿSTw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý&‡Æ×7IülW$ª$Ib¸f»xˆâE·à‚>m¡÷íþÿ»«t-C[µÒ<û«=Jí${k}FÂâÌܸŒÍ‡*J®H8À&¼'Àþ)ð…†‹%¿Šÿ±Sµ’;_'Y™ T¶€ñ'Ì 9ã ¾k”øíã/5I|-7‡luØaI­.tƒoÔr­Ý¶ o0_0ü§8 Øüà Å5¥(¢¼¤Ö–µ®ößô>Ž®[Ý“Iuè}EWéçÎƳð¿Á¾"Ô¦Ô5_ hZüØón¯4Øf•ðÎÊIÀ ž€ †ËátÛÛ{Ë?øzÖîÞE–àÒ I#u9VV A‚:bŠ(­¢Š(ÿÙ NÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ýø…ãè´]~ÄØÞì´“yª-޽µŒ.&Y$’æP¾LŒJ²í ËÔmø{Å­®j·úmƨh×¶pÃpÑ_4 ¾9ZUR¦da|‚Aéë^KûI|/‰:Žt‹ÛmrßIÖ<8–i¬hÚ¢Ú%œª—ÊÏpŸk·óáUºVhd&'Æp1ÕxÀ¦ËPÔb“Mñ&“¤¦ŸmilÚο-åì®$½iK\ ©¥pÐÛæIò»qå®;_ߦ•à½~öG’8í´û‰™áݽBÆÄ•ÚèÙãŒ:F^£nŠ(ÿÙ .ÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ýø…ãè´]~ÄØÞì´“yª-޽µŒ.&Y$’æP¾LŒJ²í ËÔmø{Å­®j·úmƨh×¶pÃpÑ_4 ¾9ZUR¦da|‚Aéë^UûCü$ºø³¥xÏÃÒXx€ÙkÞO·Ô´H[}žà-òsº·ÃŸ ëÚ„·ÚŸ†4mFö\y—7z|RÈø ³)'ô­è>м+çÿbèºvçíó¾ÁifÜíݰ ãqÆzdúÑEb¨ÓRçQWïmKç“V¾†½Q[ÿÙ ÞÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ‚ƒ„…†‡ˆþÿÿÿŠ‹ŒŽŸ’“”•–—˜™š›œžþÿÿÿ®¡¢£¤¥¦§¨©ª«¬­þÿÿÿ¼°±²³´µ¶·¸¹º»þÿÿÿʾ¿ÀÁÂÃÄÅÆÇÈÉþÿÿÿØÌÍÎÏÐÑÒÓÔÕÖ×þÿÿÿÙçÛÜÝÞßàáâãäåæþÿÿÿþÿÿÿéêëìíîïðñòóôõþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý>ñdßgð®³/›äì²™¼Ï3ËÙ„';¼Èöã×ÌL}zZÊñdßgð®³/›äì²™¼Ï3ËÙ„';¼Èöã×ÌL}zZÄñ½úi^ ×ïdy#ŽÛO¸™žÛÔ,lI]®ž8áôeê6袀?ÿÙ``"5Á)€Ãdoc.gif*8eŽÒ½docNode.gif2e–Ò½docNodeLast.gif(m]Ö(€Ãfolder.gif0Lš>o ½folderNode.gif8ÄTvn ½folderNodeLast.gif8ŒåŠo ½folderNodeOpen.gif@ W8n ½folderNodeOpenLast.gif0 ¦~†(€ÃfolderOpen.gif, e–Ò½vertLine.gif8 ]¥úJ MÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵ11ÿÿÿÿÿÿÿÿÿÿÿÿ‘Y21 ÿÿÿÿ P31ÿÿÿÿÿÿÿÿÿÿÿÿ¯/41ÿÿÿÿ½8w!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý#ñgÄ«oÝjQϦ^\Ûišzêw÷ë=¤Ö–äËóÉ$óÆŒO@I¡áï¶¹ªßé·6¡£^Ùà ÃE|Ð6øåiUJ˜eu…ò §­y/í%ð½þ$è9Ò/mµË}'XðâY¦±£j‹h–rª_+=Â}®ßÏ…VéY¡˜ŸaÀÇUà›-CQŠM7ÄšN’š}µ¥³k:ü·—²¸’õ¥-p.¦•ÀCo™'ÊvíÇ–¸í|o~šW‚õûÙHã¶Óî&g‡võ Wk£gŽ0è}zº( ÿÙÇfoderNodeFirst.gifB ÇùÁúJÇfol DÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý.Õ¼i-†¿6‘gáýSZ¹†Ö+¹^É­•#IU@LÓFI&èoZ—ÃÞ-msU¿Ón4mCF½³††Šù mñÊÒª•0Ë ë äOZá~(xY5=S»ÕtÏO¡>ÎC}á¿6Šð¼x_Íš;Ëi6¸S‚JdŒ¨"×€< lµ F)4ßi:Jiö֖ͬëòÞ^ÊâKÖ”µÀºšW] ¾dŸ)Û·Zàµñ½úi^ ×ïdy#ŽÛO¸™žÛÔ,lI]®ž8áôeê6袀?ÿÙderNodeOpenFirst.gifJ ¶ÏúJÇfo #ÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý.Õ¼i-†¿6‘gáýSZ¹†Ö+¹^É­•#IU@LÓFI&èoZ—ÃÞ-msU¿Ón4mCF½³††Šù mñÊÒª•0Ë ë äOZâ¾"ø.Oø¦ôÞhÞ(¿Òç²±Üx[ĤL³B÷›•äŠîÞF]· vä¡8$eF%ðM–¡¨Å&›âM'IM>ÚÒÙµ~[ËÙ\IzÒ–¸SJà ¡·Ì“å;vãË\z…Q@ÿÙlderNodeOpenFirstLast.gifBY ,ÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý#ñgÄ«oÝjQϦ^\Ûišzêw÷ë=¤Ö–äËóÉ$óÆŒO@I¡áï¶¹ªßé·6¡£^Ùà ÃE|Ð6øåiUJ˜eu…ò §­yWíð’ëâΕã?Iaâe¯x~=>ßRÐu!mö{€·ÈLñ‹»sqHÆ-˜Ã:_xÙjŒRi¾$Òt”Óí­-›Y×å¼½•Ä—­)ku4®º|É>S·n<µÀ¨QEÿÙøàúJÇfolderNodeFirstLast.gifJ #ÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdef51ÿÿÿÿÿÿÿÿÿÿÿÿË/61ÿÿÿÿÚ871ÿÿÿÿ ÿÿÿÿèYÿÿÿÿÿÿÿÿÿÿÿÿghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý.Õ¼i-†¿6‘gáýSZ¹†Ö+¹^É­•#IU@LÓFI&èoZ—ÃÞ-msU¿Ón4mCF½³††Šù mñÊÒª•0Ë ë äOZâ¾"ø.Oø¦ôÞhÞ(¿Òç²±Üx[ĤL³B÷›•äŠîÞF]· vä¡8$eF%ðM–¡¨Å&›âM'IM>ÚÒÙµ~[ËÙ\IzÒ–¸SJà ¡·Ì“å;vãË\z…Q@ÿÙ¶ÏúJÇfolderNodeOpenLastFirst.gifBYøàúJÇfolderNodeLastFirst.gif ,ÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý#ñgÄ«oÝjQϦ^\Ûišzêw÷ë=¤Ö–äËóÉ$óÆŒO@I¡áï¶¹ªßé·6¡£^Ùà ÃE|Ð6øåiUJ˜eu…ò §­yWíð’ëâΕã?Iaâe¯x~=>ßRÐu!mö{€·ÈLñ‹»sqHÆ-˜Ã:_xÙjŒRi¾$Òt”Óí­-›Y×å¼½•Ä—­)ku4®º|É>S·n<µÀ¨QEÿÙ:]¥úJÇfolderNodeFirst.gif MÿØÿàJFIF``ÿÛC     ÿÛC   ÿÀ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ý#ñgÄ«oÝjQϦ^\Ûišzêw÷ë=¤Ö–äËóÉ$óÆŒO@I¡áï¶¹ªßé·6¡£^Ùà ÃE|Ð6øåiUJ˜eu…ò §­y/í%ð½þ$è9Ò/mµË}'XðâY¦±£j‹h–rª_+=Â}®ßÏ…VéY¡˜ŸaÀÇUà›-CQŠM7ÄšN’š}µ¥³k:ü·—²¸’õ¥-p.¦•ÀCo™'ÊvíÇ–¸í|o~šW‚õûÙHã¶Óî&g‡võ Wk£gŽ0è}zº( ÿÙ./public/images/treeBuilderImages/folderOpen.gif0000644000175000017500000000037611773315157021442 0ustar tfheentfheenGIF89aÄÿÿÿüþüüúôüþœüú”üö”üòŒôòŒüê„üæ„ôæ|üÞ|üÖ„üÖlÌÊÌüÆ\äÂLä¾TܾlìºD̾\Ôº<ä²DÌ¢$ĞĚ¼š,Ä–œz¤r þ!ù,{ Ždižhª®l{^ðå–rÙ,æC?à™`p•16› ÃQe¡TÚIeIrHª¨Lãé+ð)c¹ 8¼PˆPԦ̥2@øÿ~xy  ˆŠ ƒ% “””Žš›M, ¡¢:¤¥¦§¨¨!;./public/images/treeBuilderImages/docNodeLast.gif0000644000175000017500000000021611773315157021535 0ustar tfheentfheenGIF89a³€€€ÿÿÿÿÿÿ!ù!þUlead GIF SmartSaver Ver 2.0,@ðÉI«½8ëÍ»ÿ`(rÀWzg—’Oé¶c,Ï^;./public/images/treeBuilderImages/doc.gif0000644000175000017500000000174111773315157020107 0ustar tfheentfheenGIF89a÷ýýþ÷ÿÿç÷ÿçï÷çïïçççÞïÿÖïÿÖç÷ÌìÿÎçÿÆçÿÞçïÆÞÿÎÖÿ½ÞÿµÖÿ­Öÿ¥Öÿ½Îÿ­Î÷µÆç­µ÷µ½ç¥µÞ¥­Öœ¥Ö„¥Þ„œÎŒ”½fÿÿfÌÿk­çB¥÷{”Æ{„ÎBŒÖ3™ÿs„½33Ìks¥ff™3™cccÿÿÿ,@Æÿ H° Á‚¨8Áð€Š‡ *¬8HЂ‡*(PˆÀQÂ…‰& @I@€ )CŒ03NXɲ¦Í›,ªð ÅX°@óà†11>˜Ysƒ¤(L PôàŠ«X³^ÅÉÕà†¯`ÁV¥˜°„Ù„Ab,B…>¤( À€k0àçŸ HÔKÀ.‚ / 0˜¥‡,H !*Õš&(P0™Be ÝD!ƒ†Ó¨Owݵ5×€;./public/images/treeBuilderImages/folderNodeLast.gif0000644000175000017500000000020211773315157022236 0ustar tfheentfheenGIF89a³€€€ÿÿÿÿÿÿ!ù,/0ÈI«•àê}3ÿ ŽcgZ^ L)•®˜)ÌsÝìÛ§š£=‰*Ȥr©‰;./public/images/treeBuilderImages/docNode.gif0000644000175000017500000000022311773315157020707 0ustar tfheentfheenGIF89a³€€€ÿÿÿÿÿÿ!ù!þUlead GIF SmartSaver Ver 2.0,@ ðÉI«½8ëÍ»ÿ`(rÀWzg—’Oé¶×ºÉÙc;./public/images/treeBuilderImages/folderNodeOpen.gif0000644000175000017500000000020111773315157022233 0ustar tfheentfheenGIF89a³€€€ÿÿÿÀÀÀÿÿÿ!ù ,.pÉI«•àê}3ÿ ŽcgZ^xªè"¼ï’ÍSJÙõzë5I‚@Lp($qÆ R;./public/images/treeBuilderImages/docNodeLastFirst.gif0000644000175000017500000000015311773315157022545 0ustar tfheentfheenGIF89a³€€€ÿÿÿÿÿÿ!ù,@ðÉI«½8ëÍ»ÿ`(Žd ª¦fë¾R;./public/images/treeBuilderImages/vertLine.gif0000644000175000017500000000021411773315157021124 0ustar tfheentfheenGIF89a³€€€ÿÿÿÿÿÿ!ù!þUlead GIF SmartSaver Ver 2.0,@ðÉI«½8ëÍ»ÿ`(rÀWzg—’f‹º*\E;./public/images/treeBuilderImages/folderNodeFirst.gif0000644000175000017500000000155611773315157022437 0ustar tfheentfheenGIF89a÷ €€€ÿÿÿÿÿÿ!ù ,KH° Áƒ*\Ȱ €‡!0±¢À)Ô¸£@Ž)þ9rÅ“z4i±cÊ-CFŒØ°&Èš oâ\¨sgž ;./public/images/indicator.gif0000644000175000017500000000302111773315157015713 0ustar tfheentfheenGIF89aÄÿÿÿîîîÝÝÝ»»»ªªª™™™ˆˆˆwwwfffUUUDDD333"""ÿÿÿ!ÿ NETSCAPE2.0!ù,w $B‰$å¨B#Ï#«( R!!ù,c $ŽP¨xB‚ +*œ-[Ädà¶á¢+“i@ )`L¢ ?'I`¨JG‚ƒ¶øb P¾©âñhŽ ƒÊñX¸B)0¢Â׸X›Q# } No "tI+ZI!!ù,\ $ŽP`©Š¦8¬êù®©*ÔÅ „1¶•‚h0‚r°x8°BÁ‡µQaùˆÅVÄ  ¥!ÑMD„l!¡4%ØB‡öBe PDY00!!ù,] $Ž$”è¥À¢ÂI>QÊÁðôóŽ]éð ´d"†28 G£qH9 ¯A2–¢ŸÈ€ðBª"á, D‡‚H('4³Á½C \0`UL"r(!!ù ,d $ŽdI`®Ãìkò°øBÂó˜B ·mè• ŽAÉ72, ƒ©(PX鲪‚ø “’8@R%‚a K‡*¡€þD¨ÁŒè2E {$ƒ„ft5†C%!;./public/images/toggle-expand-light.png0000644000175000017500000000545711773315157017640 0ustar tfheentfheen‰PNG  IHDRóÿa pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFZIDATxÚbüÿÿ?%€qÀ `øÿÿ?6Ü€Cã’€J øÿÿÿÿýø "Ædƒ0Ô2‘\ ÿ‰ Dªºàƒ#3ê²cètÀ8ôóÅ`{#ÉqíIEND®B`‚./public/facebox/0000755000175000017500000000000011773315157013416 5ustar tfheentfheen./public/facebox/tl.png0000644000175000017500000000020411773315157014537 0ustar tfheentfheen‰PNG  IHDR 2ϽKIDATxÚΡ DQ–"ìÑ%ºà µtÃr '¾¹u¬/y³N´IEND®B`‚./public/facebox/README.txt0000644000175000017500000000026211773315157015114 0ustar tfheentfheenPlease visit http://famspam.com/facebox/ or open index.html in your favorite browser. Need help? Join our Google Groups mailing list: http://groups.google.com/group/facebox/ ./public/facebox/loading.gif0000644000175000017500000000531711773315157015530 0ustar tfheentfheenGIF89a ÷ÿÿÿ³³³ûûûÖÖÖáááòòòººº444ÄÄÄ———ýýýTTT!ÿ NETSCAPE2.0!ù , úHà‚ *\Èpà‡ h¨p€‚À‘"ÁÌ8°ÇG>D)¤À“R4ðCˆœ”IÁË\Âä9pÀŸ:ȹs Î1_2`p`€Ÿ u–< uà‚©SY­ÚkÇž`§FõhvíÆ´6S>u»ð+–ryJ´/Q³M.0@¸p_À +æ+óä˜/öKY&]Š—Îõ¸9¥Ù‰ Mrå ¸`iÌxŸr\«ºëË˪ vfêúåjMO‚&*ZìÙØ‡oã>;¼¶Ü¦Å"÷,,¨@C§PؼràS‚E.¸Ù´jT¨WYR Y´+Ñ«¶¶¬Š­K¥»b ê•íÚŒ!ù ,€Hð€ƒ*Terms * Loads the #terms div in the box * * Terms * Loads the terms.html page in the box * * Terms * Loads the terms.png image in the box * * * You can also use it programmatically: * * jQuery.facebox('some html') * * The above will open a facebox with "some html" as the content. * * jQuery.facebox(function($) { * $.get('blah.html', function(data) { $.facebox(data) }) * }) * * The above will show a loading screen before the passed function is called, * allowing for a better ajaxy experience. * * The facebox function can also display an ajax page or image: * * jQuery.facebox({ ajax: 'remote.html' }) * jQuery.facebox({ image: 'dude.jpg' }) * * Want to close the facebox? Trigger the 'close.facebox' document event: * * jQuery(document).trigger('close.facebox') * * Facebox also has a bunch of other hooks: * * loading.facebox * beforeReveal.facebox * reveal.facebox (aliased as 'afterReveal.facebox') * init.facebox * * Simply bind a function to any of these hooks: * * $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... }) * */ (function($) { $.facebox = function(data, klass) { $.facebox.loading() if (data.ajax) fillFaceboxFromAjax(data.ajax) else if (data.image) fillFaceboxFromImage(data.image) else if (data.div) fillFaceboxFromHref(data.div) else if ($.isFunction(data)) data.call($) else $.facebox.reveal(data, klass) } /* * Public, $.facebox methods */ $.extend($.facebox, { settings: { opacity : 0, overlay : true, loadingImage : '/facebox/loading.gif', closeImage : '/facebox/closelabel.gif', imageTypes : [ 'png', 'jpg', 'jpeg', 'gif' ], faceboxHtml : '\

    ' }, loading: function() { init() if ($('#facebox .loading').length == 1) return true showOverlay() $('#facebox .content').empty() $('#facebox .body').children().hide().end(). append('
    ') $('#facebox').css({ top: getPageScroll()[1] + (getPageHeight() / 10), left: 385.5 }).show() $(document).bind('keydown.facebox', function(e) { if (e.keyCode == 27) $.facebox.close() return true }) $(document).trigger('loading.facebox') }, reveal: function(data, klass) { $(document).trigger('beforeReveal.facebox') if (klass) $('#facebox .content').addClass(klass) $('#facebox .content').append(data) $('#facebox .loading').remove() $('#facebox .body').children().fadeIn('normal') $('#facebox').css('left', $(window).width() / 2 - ($('#facebox table').width() / 2)) $(document).trigger('reveal.facebox').trigger('afterReveal.facebox') }, close: function() { $(document).trigger('close.facebox') return false } }) /* * Public, $.fn methods */ $.fn.facebox = function(settings) { init(settings) function clickHandler() { $.facebox.loading(true) // support for rel="facebox.inline_popup" syntax, to add a class // also supports deprecated "facebox[.inline_popup]" syntax var klass = this.rel.match(/facebox\[?\.(\w+)\]?/) if (klass) klass = klass[1] fillFaceboxFromHref(this.href, klass) return false } return this.click(clickHandler) } /* * Private methods */ // called one time to setup facebox on this page function init(settings) { if ($.facebox.settings.inited) return true else $.facebox.settings.inited = true $(document).trigger('init.facebox') makeCompatible() var imageTypes = $.facebox.settings.imageTypes.join('|') $.facebox.settings.imageTypesRegexp = new RegExp('\.' + imageTypes + '$', 'i') if (settings) $.extend($.facebox.settings, settings) $('body').append($.facebox.settings.faceboxHtml) var preload = [ new Image(), new Image() ] preload[0].src = $.facebox.settings.closeImage preload[1].src = $.facebox.settings.loadingImage $('#facebox').find('.b:first, .bl, .br, .tl, .tr').each(function() { preload.push(new Image()) preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1') }) $('#facebox .close').click($.facebox.close) $('#facebox .close_image').attr('src', $.facebox.settings.closeImage) } // getPageScroll() by quirksmode.com function getPageScroll() { var xScroll, yScroll; if (self.pageYOffset) { yScroll = self.pageYOffset; xScroll = self.pageXOffset; } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict yScroll = document.documentElement.scrollTop; xScroll = document.documentElement.scrollLeft; } else if (document.body) {// all other Explorers yScroll = document.body.scrollTop; xScroll = document.body.scrollLeft; } return new Array(xScroll,yScroll) } // Adapted from getPageSize() by quirksmode.com function getPageHeight() { var windowHeight if (self.innerHeight) { // all except Explorer windowHeight = self.innerHeight; } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode windowHeight = document.documentElement.clientHeight; } else if (document.body) { // other Explorers windowHeight = document.body.clientHeight; } return windowHeight } // Backwards compatibility function makeCompatible() { var $s = $.facebox.settings $s.loadingImage = $s.loading_image || $s.loadingImage $s.closeImage = $s.close_image || $s.closeImage $s.imageTypes = $s.image_types || $s.imageTypes $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml } // Figures out what you want to display and displays it // formats are: // div: #id // image: blah.extension // ajax: anything else function fillFaceboxFromHref(href, klass) { // div if (href.match(/#/)) { var url = window.location.href.split('#')[0] var target = href.replace(url,'') $.facebox.reveal($(target).clone().show(), klass) // image } else if (href.match($.facebox.settings.imageTypesRegexp)) { fillFaceboxFromImage(href, klass) // ajax } else { fillFaceboxFromAjax(href, klass) } } function fillFaceboxFromImage(href, klass) { var image = new Image() image.onload = function() { $.facebox.reveal('
    ', klass) } image.src = href } function fillFaceboxFromAjax(href, klass) { $.get(href, function(data) { $.facebox.reveal(data, klass) }) } function skipOverlay() { return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null } function showOverlay() { if (skipOverlay()) return if ($('facebox_overlay').length == 0) $("body").append('
    ') $('#facebox_overlay').hide().addClass("facebox_overlayBG") .css('opacity', $.facebox.settings.opacity) .click(function() { $(document).trigger('close.facebox') }) .fadeIn(200) return false } function hideOverlay() { if (skipOverlay()) return $('#facebox_overlay').fadeOut(200, function(){ $("#facebox_overlay").removeClass("facebox_overlayBG") $("#facebox_overlay").addClass("facebox_hide") $("#facebox_overlay").remove() }) return false } /* * Bindings */ $(document).bind('close.facebox', function() { $(document).unbind('keydown.facebox') $('#facebox').fadeOut(function() { $('#facebox .content').removeClass().addClass('content') hideOverlay() $('#facebox .loading').remove() }) }) })(jQuery); ./public/facebox/b.png0000644000175000017500000000012411773315157014342 0ustar tfheentfheen‰PNG  IHDRð1”_IDAT8c Ú@)f5dÔQCF ÚvÀpÂåi\IEND®B`‚./public/facebox/tr.png0000644000175000017500000000017511773315157014554 0ustar tfheentfheen‰PNG  IHDR 2ϽDIDATxÚÊ¡ 0–âØ£Kt<¦3Ô– Ë£Àp¼ˆK‘ƒ -3ËmÇù0 þãQÙ8ظ56*;ÎÆXEþ¬/¦öQIEND®B`‚./public/facebox/closelabel.gif0000644000175000017500000000172311773315157016215 0ustar tfheentfheenGIF89aBæÀÀÀÁÁÁYYYÒÒÒƒƒƒ¯¯¯õõõäääPPP¸¸¸ŒŒŒ”””TTTVVVÜÜÜRRRÉÉÉQQQXXXUUUìììSSSöööýýýêêêúúú¦¦¦WWW¢¢¢LLLOOOfff÷÷÷ÝÝÝÌÌÌ```{{{¡¡¡üüüðððÞÞÞlllµµµûûû•••ÍÍÍÊÊÊxxxëëëKKKààà___¹¹¹ßßß´´´†††pppcccååå’’’ˆˆˆ©©©nnn———oooÕÕÕŽŽŽíííeeevvv˜˜˜mmm|||ïïïççç±±±³³³ñññyyyZZZdddMMMsssggg–––‡‡‡ãããNNNiiiÛÛÛzzzÿÿÿþþþ!ù,Bÿ€\‚ƒ„…†‡ˆ‰Š‹ŒŽŒ]’“”•–——\'˜žŸ˜‘’\,GB\–\#¨ ¯ ¢]!@Q"®]‚.4U”Z°]×ZZº‹£M2EZ®ª$ >’ [à ][Ì•à[” ë/\ë냣[ T6‚Fа0 ]"lYAK„È™«d` Z0ØQ¢Œ.Ðã d|ùJ$Ð@Å ØH±U&å”xN‚-* ˜8”’ z­P‚$Ø&$è!²‹–-î,•ëɳÒU]**ØytKRC•¸ÄHa€ÿ ©)ië%»“ŠZÚ¥‚º-”m! °”FQ¡0`Bƒ­&áE71ï–K|»ðÍìH†Oâ¢$c– tM"€õneIðÆQbU2Ç‘g ¥1%qM`puàæNc9'[Íl™˜æI@q+B…iY@8˜¡ÃpI :,°`3Gè™U¼˜q#ذì7l9YÏ€ÉDQq=Œ+/8°¹âM<ã”cOV鬳@m ‚sØHöxf @E%d H N A'PrŒs¯œxÉ29EÂÅ:¬ä_ ¨²‚p à Åô˜Š3\8Álá¡Q+X@0"øèä(ÎèÂOT ”Lü°Ã•OÂ" Tu KpÙå+²4ã‰~gú˜f;./public/facebox/facebox.css0000644000175000017500000000250511773315157015541 0ustar tfheentfheen#facebox .b { background:url(/facebox/b.png); } #facebox .tl { background:url(/facebox/tl.png); } #facebox .tr { background:url(/facebox/tr.png); } #facebox .bl { background:url(/facebox/bl.png); } #facebox .br { background:url(/facebox/br.png); } #facebox { position: absolute; top: 0; left: 0; z-index: 100; text-align: left; } #facebox .popup { position: relative; } #facebox table { border-collapse: collapse; } #facebox td { border-bottom: 0; padding: 0; } #facebox .body { padding: 10px; background: #fff; width: 370px; } #facebox .loading { text-align: center; } #facebox .image { text-align: center; } #facebox img { border: 0; margin: 0; } #facebox .footer { border-top: 1px solid #DDDDDD; padding-top: 5px; margin-top: 10px; text-align: right; } #facebox .tl, #facebox .tr, #facebox .bl, #facebox .br { height: 10px; width: 10px; overflow: hidden; padding: 0; } #facebox_overlay { position: fixed; top: 0px; left: 0px; height:100%; width:100%; } .facebox_hide { z-index:-100; } .facebox_overlayBG { background-color: #000; z-index: 99; } * html #facebox_overlay { /* ie6 hack */ position: absolute; height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'); } ./public/facebox/br.png0000644000175000017500000000017411773315157014531 0ustar tfheentfheen‰PNG  IHDR 2ϽCIDAT•Ê¡ EQ–ò¸Ç[‚Eèf°ê†˜ÈþpÛ5à Ž‰q«1Õjt5N%®ª2%Ž_\:` àÀìÐS>¬/×çzÍIEND®B`‚./public/javascripts/0000755000175000017500000000000012014212503014314 5ustar tfheentfheen./public/javascripts/jquery.treeTable.min.js0000644000175000017500000001137111773315157020710 0ustar tfheentfheen/* jQuery treeTable Plugin 2.2.1 - http://ludo.cubicphuse.nl/jquery-plugins/treeTable/ */ (function($) { // Helps to make options available to all functions // TODO: This gives problems when there are both expandable and non-expandable // trees on a page. The options shouldn't be global to all these instances! var options; $.fn.treeTable = function(opts) { options = $.extend({}, $.fn.treeTable.defaults, opts); return this.each(function() { $(this).addClass("treeTable").find("tbody tr").each(function() { // Initialize root nodes only whenever possible if(!options.expandable || $(this)[0].className.search("child-of-") == -1) { initialize($(this)); } }); }); }; $.fn.treeTable.defaults = { childPrefix: "child-of-", expandable: true, indent: 19, initialState: "collapsed", treeColumn: 0 }; // Recursively hide all node's children in a tree $.fn.collapse = function() { $(this).addClass("collapsed"); childrenOf($(this)).each(function() { initialize($(this)); if(!$(this).hasClass("collapsed")) { $(this).collapse(); } $(this).hide(); }); return this; }; // Recursively show all node's children in a tree $.fn.expand = function() { $(this).removeClass("collapsed").addClass("expanded"); childrenOf($(this)).each(function() { initialize($(this)); if($(this).is(".expanded.parent")) { $(this).expand(); } $(this).show(); }); return this; }; // Add an entire branch to +destination+ $.fn.appendBranchTo = function(destination) { var node = $(this); var parent = parentOf(node); var ancestorNames = $.map(ancestorsOf($(destination)), function(a) { return a.id; }); // Conditions: // 1: +node+ should not be inserted in a location in a branch if this would // result in +node+ being an ancestor of itself. // 2: +node+ should not have a parent OR the destination should not be the // same as +node+'s current parent (this last condition prevents +node+ // from being moved to the same location where it already is). // 3: +node+ should not be inserted as a child of +node+ itself. if($.inArray(node[0].id, ancestorNames) == -1 && (!parent || (destination.id != parent[0].id)) && destination.id != node[0].id) { indent(node, ancestorsOf(node).length * options.indent * -1); // Remove indentation if(parent) { node.removeClass(options.childPrefix + parent[0].id); } node.addClass(options.childPrefix + destination.id); move(node, destination); // Recursively move nodes to new location indent(node, ancestorsOf(node).length * options.indent); } return this; }; // Add reverse() function from JS Arrays $.fn.reverse = function() { return this.pushStack(this.get().reverse(), arguments); }; // Toggle an entire branch $.fn.toggleBranch = function() { if($(this).hasClass("collapsed")) { $(this).expand(); } else { $(this).removeClass("expanded").collapse(); } return this; }; // === Private functions function ancestorsOf(node) { var ancestors = []; while(node = parentOf(node)) { ancestors[ancestors.length] = node[0]; } return ancestors; }; function childrenOf(node) { return $("table.treeTable tbody tr." + options.childPrefix + node[0].id); }; function indent(node, value) { var cell = $(node.children("td")[options.treeColumn]); var padding = parseInt(cell.css("padding-left"), 10) + value; cell.css("padding-left", + padding + "px"); childrenOf(node).each(function() { indent($(this), value); }); }; function initialize(node) { if(!node.hasClass("initialized")) { node.addClass("initialized"); var childNodes = childrenOf(node); if(node.hasClass("parent")) { var cell = $(node.children("td")[options.treeColumn]); var padding = parseInt(cell.css("padding-left"), 10) + options.indent; childNodes.each(function() { $($(this).children("td")[options.treeColumn]).css("padding-left", padding + "px"); }); $(cell[0].firstChild).css({ "margin-left": '-' + options.indent + 'px', "padding-left": options.indent + 'px' }); } } }; function move(node, destination) { node.insertAfter(destination); childrenOf(node).reverse().each(function() { move($(this), node[0]); }); }; function parentOf(node) { var classNames = node[0].className.split(' '); for(key in classNames) { if(classNames[key].match("child-of-")) { return $("#" + classNames[key].substring(9)); } } }; })(jQuery); ./public/javascripts/jquery.editinline.js0000644000175000017500000000660511773315157020347 0ustar tfheentfheen// Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. (function($) { function startEditing(elem, options) { var editable = $(elem); var origHtml = editable.html(); var origText = options.populate($.trim(editable.text())); if (!options.begin.apply(elem, [origText])) { return; } var input = options.createInput.apply(elem, [origText]) .addClass("editinline").val(origText) .dblclick(function() { return false; }) .keydown(function(evt) { switch (evt.keyCode) { case 13: { // return if (!input.is("textarea")) applyChange(evt.keyCode); break; } case 27: { // escape cancelChange(evt.keyCode); break; } case 9: { // tab if (!input.is("textarea")) { applyChange(evt.keyCode); return false; } } } }); function applyChange(keyCode) { var newText = input.val(); if (newText == origText) { cancelChange(keyCode); return true; } if ((!options.allowEmpty && !newText.length) || !options.validate.apply(elem, [newText])) { input.addClass("invalid"); return false; } input.remove(); tools.remove(); options.accept.apply(elem, [newText, origText]); editable.removeClass("editinline-container"); options.end.apply(elem, [keyCode]); return true; } function cancelChange(keyCode) { options.cancel.apply(elem, [origText]); editable.html(origHtml).removeClass("editinline-container"); options.end.apply(elem, [keyCode]); } var tools = $(""); $("") .text(options.acceptLabel).click(applyChange).appendTo(tools); $("") .text(options.cancelLabel).click(cancelChange).appendTo(tools) editable.html("").append(tools).append(input) .addClass("editinline-container"); options.prepareInput.apply(elem, [input[0]]); input.each(function() { this.focus(); this.select(); }); } $.fn.makeEditable = function(options) { options = $.extend({ allowEmpty: true, acceptLabel: "", cancelLabel: "", toolTip: "Double click to edit", // callbacks begin: function() { return true }, accept: function(newValue, oldValue) {}, cancel: function(oldValue) {}, createInput: function(value) { return $("") }, prepareInput: function(input) {}, end: function(keyCode) {}, populate: function(value) { return value }, validate: function() { return true } }, options || {}); return this.each(function() { $(this).attr("title", options.toolTip).dblclick(function() { startEditing(this, options); }); }); } })(jQuery); ./public/javascripts/jquery.tools.js~0000644000175000017500000002731312005570266017551 0ustar tfheentfheen/* * jquery.tools 1.0.0 - The missing UI library * * [tools.tooltip-1.0.0, tools.expose-1.0.2] * * Copyright (c) 2009 Tero Piirainen * http://flowplayer.org/tools/ * * Dual licensed under MIT and GPL 2+ licenses * http://www.opensource.org/licenses * * ----- * * Build: Wed Jun 03 19:51:51 GMT+00:00 2009 */ (function ($) { $.tools = $.tools || { version: {} }; $.tools.version.tooltip = "1.0.0"; var effects = { toggle: [function () { this.getTip().show() }, function () { this.getTip().hide() }] }; $.tools.addTipEffect = function (name, loadFn, hideFn) { effects[name] = [loadFn, hideFn] }; /* this is how you add custom effects */ /* default effect: "slideup", custom configuration variables: - slideOffset - slideInSpeed - slideOutSpeed */ $.tools.addTipEffect("slideup", function () { var conf = this.getConf(); var o = conf.slideOffset || 10; this.getTip().css({ opacity: 0 }).animate({ top: "-=" + o, opacity: conf.opacity }, conf.slideInSpeed || 200).show() }, function () { var conf = this.getConf(); var o = conf.slideOffset || 10; this.getTip().animate({ top: "-=" + o, opacity: 0 }, conf.slideOutSpeed || 200, function () { c(this).hide().animate({ top: "+=" + (e * 2) }, 0) }) }); function a(g, e) { var d = this; function i(j, k) { c(d).bind(j, function (m, l) { if (k && k.call(this) === false && l) { l.proceed = false } }); return d } $.each(e, function (j, k) { if ($.isFunction(k)) { i(j, k) } }); var f = e.triggers ? c(e.triggers) : g.prev(e.trigger); if (!f.length) { throw "cannot find trigges for tip: " + g.selector } f.bind(f.is("input") ? "focus" : "mouseover", function (j) { d.show(j); g.hover(function () { d.show() }, function () { d.hide() }) }); f.bind(f.is("input") ? "blur" : "mouseout", function () { d.hide() }); g.css("opacity", e.opacity); var h = 0; $.extend(d, { show: function (o) { if (o) { f = c(o.target) } clearTimeout(h); if (g.is(":animated") || g.is(":visible")) { return d } var n = { proceed: true }; c(d).trigger("onBeforeShow", n); if (!n.proceed) { return d } var m = f.position().top - g.outerHeight(); var j = g.outerHeight() + f.outerHeight(); var q = e.position[0]; if (q == "center") { m += j / 2 } if (q == "bottom") { m += j } var k = f.outerWidth() + g.outerWidth(); var l = f.position().left + f.outerWidth(); q = e.position[1]; if (q == "center") { l -= k / 2 } if (q == "left") { l -= k } m += e.offset[0]; l += e.offset[1]; g.css({ position: "absolute", top: m, left: l }); effects[e.effect][0].call(d); c(d).trigger("onShow"); return d }, hide: function () { clearTimeout(h); h = setTimeout(function () { if (g.is(":animated") || !g.is(":visible")) { return d } var j = { proceed: true }; c(d).trigger("onBeforeHide", j); if (!j.proceed) { return d } effects[e.effect][1].call(d); c(d).trigger("onHide") }, e.delay || 1); return d }, isShown: function () { return g.is(":visible, :animated") }, getConf: function () { return e }, getTip: function () { return g }, getTrigger: function () { return f }, onBeforeShow: function (j) { return i("onBeforeShow", j) }, onShow: function (j) { return i("onShow", j) }, onBeforeHide: function (j) { return i("onBeforeHide", j) }, onHide: function (j) { return i("onHide", j) } }) } $.prototype.tooltip = function (d) { var e = this.eq(typeof d == "number" ? d : 0).data("tooltip"); if (e) { return e } var f = { trigger: null, triggers: null, effect: "slideup", delay: 30, opacity: 1, position: ["top", "center"], offset: [0, 0], api: false }; if ($.isFunction(d)) { d = { onBeforeShow: d } } $.extend(f, d); this.each(function () { e = new a(c(this), f); c(this).data("tooltip", e) }); return f.api ? e : this } })(jQuery); (function (b) { b.tools = b.tools || { version: {} }; b.tools.version.expose = "1.0.2"; function a() { var e = b(window).width(); if (b.browser.mozilla) { return e } var d; if (window.innerHeight && window.scrollMaxY) { d = window.innerWidth + window.scrollMaxX } else { if (document.body.scrollHeight > document.body.offsetHeight) { d = document.body.scrollWidth } else { d = document.body.offsetWidth } } return d < e ? d + 20 : e } function c(g, h) { var e = this, d = null, f = false, i = 0; function j(k, l) { b(e).bind(k, function (n, m) { if (l && l.call(this) === false && m) { m.proceed = false } }); return e } b.each(h, function (k, l) { if (b.isFunction(l)) { j(k, l) } }); b(window).bind("resize.expose", function () { if (d) { d.css({ width: a(), height: b(document).height() }) } }); b.extend(this, { getMask: function () { return d }, getExposed: function () { return g }, getConf: function () { return h }, isLoaded: function () { return f }, load: function () { if (f) { return e } i = g.eq(0).css("zIndex"); if (h.maskId) { d = b("#" + h.maskId) } if (!d || !d.length) { d = b("
    ").css({ position: "absolute", top: 0, left: 0, width: a(), height: b(document).height(), display: "none", opacity: 0, zIndex: h.zIndex }); if (h.maskId) { d.attr("id", h.maskId) } b("body").append(d); var k = d.css("backgroundColor"); if (!k || k == "transparent" || k == "rgba(0, 0, 0, 0)") { d.css("backgroundColor", h.color) } if (h.closeOnEsc) { b(document).bind("keydown.unexpose", function (n) { if (n.keyCode == 27) { e.close() } }) } if (h.closeOnClick) { d.bind("click.unexpose", function () { e.close() }) } } var m = { proceed: true }; b(e).trigger("onBeforeLoad", m); if (!m.proceed) { return e } b.each(g, function () { var n = b(this); if (!/relative|absolute/i.test(n.css("position"))) { n.css("position", "relative") } }); g.css({ zIndex: h.zIndex + 1 }); var l = d.height(); if (!this.isLoaded()) { d.css({ opacity: 0, display: "block" }).fadeTo(h.loadSpeed, h.opacity, function () { if (d.height() != l) { d.css("height", l) } b(e).trigger("onLoad") }) } f = true; return e }, close: function () { if (!f) { return e } var k = { proceed: true }; b(e).trigger("onBeforeClose", k); if (k.proceed === false) { return e } d.fadeOut(h.closeSpeed, function () { b(e).trigger("onClose"); g.css({ zIndex: b.browser.msie ? i : null }) }); f = false; return e }, onBeforeLoad: function (k) { return j("onBeforeLoad", k) }, onLoad: function (k) { return j("onLoad", k) }, onBeforeClose: function (k) { return j("onBeforeClose", k) }, onClose: function (k) { return j("onClose", k) } }) } b.fn.expose = function (d) { var e = this.eq(typeof d == "number" ? d : 0).data("expose"); if (e) { return e } var f = { maskId: null, loadSpeed: "slow", closeSpeed: "fast", closeOnClick: true, closeOnEsc: true, zIndex: 9998, opacity: 0.8, color: "#456", api: false }; if (typeof d == "string") { d = { color: d } } b.extend(f, d); this.each(function () { e = new c(b(this), f); b(this).data("expose", e) }); return f.api ? e : this } })(jQuery);./public/javascripts/cookbook_constraint_ctrl.js0000644000175000017500000001416011773315157021776 0ustar tfheentfheen$(document).ready(function() { // add version constraints, sorted by cookbook name var cookbook, versions, constraints = [], i = 0, max, row; if (document.getElementById('edit') != null) { versions = cookbook_versions(); for (cookbook in versions) { constraints.push([cookbook, versions[cookbook]["op"], versions[cookbook]["version"]]); } constraints.sort(); for (i = constraints.length - 1; i >= 0; i--) { row = constraints[i]; addTableRow(row[0], row[1], row[2]); } } }) function jQuerySuggest(timestamp){ $(".ac_results").remove(); // FIXME issue w/ jquery suggest var cb_name = retrieveCbName(timestamp); populateVersionBoxContent(timestamp, cb_name); $("#cookbook_version_" + timestamp)[0].value = "0.0.0"; } function populateVersionBoxContent(timestamp, cb_name){ // Ignore environments when editing the environments constraints $.getJSON('/cookbooks/'+cb_name+'?num_versions=all&ignore_environments=true', function(result){ var versions = $.map(result[cb_name], function(item, i) { return item["version"]; }); jQuery('#cookbook_version_' + timestamp).suggest(versions); }); } function clearVersionBox(box, timestamp){ populateVersionBoxContent(timestamp, retrieveCbName(timestamp)); $('#invalid_version_error_' + timestamp).remove(); } function validVersion(version) { var xyz_match = version.match(/^\d+\.\d+\.\d+$/); var xy_match = version.match(/^\d+\.\d+$/); return (xyz_match || xy_match); } function do_validateVersionBoxValue(box, timestamp) { var msg_class = 'invalid_version_error'; var msg_id = 'invalid_version_error_' + timestamp; if (!validVersion(box.value)) { if (box.value.length != 0 && $('.' + msg_class).length == 0) { var error_msg = $('
    ') .addClass(msg_class) .attr('id', msg_id).text("Version must be x.y.z or x.y"); $(box).parent().append(error_msg); } if (box.value.length == 0) { box.value = "0.0.0"; } return false; } return true; } function validateVersionBoxValue(box, timestamp) { // a short delay prevents validation from firing // when user clicks on one of the suggestions. setTimeout(function() { return do_validateVersionBoxValue(box, timestamp); }, 100); } function appendOperatorsOptions(default_operator, obj) { var ops = ["~>", ">=", ">", "=", "<", "<="]; for (i in ops) { var op = ops[i] var option = $('