[PATCH] BZ 784479 add range validation to priority
by Tzu-Mainn Chen
---
src/app/models/provider_account.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/app/models/provider_account.rb b/src/app/models/provider_account.rb
index eff59f9..49f8e67 100644
--- a/src/app/models/provider_account.rb
+++ b/src/app/models/provider_account.rb
@@ -66,7 +66,7 @@ class ProviderAccount < ActiveRecord::Base
validate :validate_presence_of_credentials
validate :validate_credentials
validate :validate_unique_username
- validates :priority, :numericality => { :only_integer => true}, :allow_blank => true
+ validates :priority, :numericality => { :only_integer => true, :greater_than_or_equal_to => -100000, :less_than_or_equal_to => 100000}, :allow_blank => true
before_create :populate_profiles_and_validate
after_create :populate_realms_and_validate
--
1.7.6.5
12 years, 1 month
[PATCH] BZ#773768 validating the X-Deltacloud-Provider value
by Tomas Sedovic
https://bugzilla.redhat.com/show_bug.cgi?id=773768
Unfortunately, we cannot validate the X-Deltacloud-Provider value when we're
adding a new provider. This is because the actual validation requires a working
provider account -- which we don't have at the time.
Fixing this the correct way would require a significant changes around the
Provider and Provider Account creation UI workflow. I.e. ain't gonna happen
now.
So what the fix actually does:
1) Checks that the X-Deltacloud-Provider value is correct on Provider Account
creation.
2) Displays a (hopefully) helpful error message when the user tries to push an
image or launch a deployment whilst having X-Deltacloud-Provider set incorrectly.
Notes to the reviewers
----------------------
This code depends on a Deltacloud Core patch that's been ACKed but not pushed
at the time of writing:
http://mail-archives.apache.org/mod_mbox/deltacloud-dev/201202.mbox/%3C13...
Note that 2 cucumber tests are failing:
cucumber features/provider.feature:61 # Scenario: Create a new Provider failure when using wrong url
cucumber features/provider_account.feature:17 # Scenario: List providers in XML format
I didn't have the time to fix them. If the patch is otherwise correct and
there's a pressure for getting this in, would you be so kind and fix them?
Hopefully, it's not that difficult.
Otherwise, I'll fix it on 12th March when I'm back.
Thanks,
Thomas
12 years, 1 month
[PATCH aeolus-cli] BZ#797157 Validate aeolus config
by Martyn Taylor
From: Martyn Taylor <mtaylor(a)redhat.com>
---
lib/aeolus_cli.rb | 2 ++
lib/aeolus_cli/command/base_command.rb | 28 ++++++++++++++++++++--------
lib/aeolus_cli/exceptions.rb | 28 ++++++++++++++++++++++++++++
spec/command/base_command_spec.rb | 5 +++++
spec/spec_helper.rb | 1 +
5 files changed, 56 insertions(+), 8 deletions(-)
create mode 100644 lib/aeolus_cli/exceptions.rb
diff --git a/lib/aeolus_cli.rb b/lib/aeolus_cli.rb
index 8070845..2e6e88c 100644
--- a/lib/aeolus_cli.rb
+++ b/lib/aeolus_cli.rb
@@ -33,3 +33,5 @@ require File.join(File.dirname(__FILE__), 'aeolus_cli/model', 'provider')
require File.join(File.dirname(__FILE__), 'aeolus_cli/model', 'provider_account')
require File.join(File.dirname(__FILE__), 'aeolus_cli/model', 'provider_type')
require File.join(File.dirname(__FILE__), 'aeolus_cli/model', 'environment')
+
+require File.join(File.dirname(__FILE__), 'aeolus_cli/', 'exceptions')
diff --git a/lib/aeolus_cli/command/base_command.rb b/lib/aeolus_cli/command/base_command.rb
index 422e5f4..b9584d6 100644
--- a/lib/aeolus_cli/command/base_command.rb
+++ b/lib/aeolus_cli/command/base_command.rb
@@ -24,11 +24,15 @@ module Aeolus
attr_accessor :options
def initialize(opts={}, logger=nil)
- logger(logger)
- @options = opts
- @config_location = "~/.aeolus-cli"
- @config = load_config
- configure_active_resource
+ begin
+ logger(logger)
+ @options = opts
+ @config_location = "~/.aeolus-cli"
+ @config = load_config
+ configure_active_resource
+ rescue => e
+ handle_exception(e)
+ end
end
protected
@@ -115,6 +119,10 @@ module Aeolus
code = "Argument Error"
message = e.message
+ elsif e.is_a?(Aeolus::CLI::ConfigError)
+ code = "Config Error"
+ message = e.message + "; please check ~/.aeolus-cli"
+
elsif e.respond_to?(:response)
doc = Nokogiri::XML e.response.body
code = doc.xpath("/error/code").text
@@ -167,9 +175,13 @@ module Aeolus
end
def configure_active_resource
- Aeolus::CLI::Base.site = @config[:conductor][:url]
- Aeolus::CLI::Base.user = @config[:conductor][:username]
- Aeolus::CLI::Base.password = @config[:conductor][:password]
+ if @config.has_key?(:conductor) && @config[:conductor].keys.to_set.subset?([:url, :password, :username].to_set)
+ Aeolus::CLI::Base.site = @config[:conductor][:url]
+ Aeolus::CLI::Base.user = @config[:conductor][:username]
+ Aeolus::CLI::Base.password = @config[:conductor][:password]
+ else
+ raise Aeolus::CLI::ConfigError.new("Error in configuration file")
+ end
end
# Print Collection to STDOUT in a column layout
diff --git a/lib/aeolus_cli/exceptions.rb b/lib/aeolus_cli/exceptions.rb
new file mode 100644
index 0000000..a523266
--- /dev/null
+++ b/lib/aeolus_cli/exceptions.rb
@@ -0,0 +1,28 @@
+#
+# Copyright 2011 Red Hat, Inc.
+#
+# 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.
+#
+module Aeolus
+ module CLI
+ class Error < StandardError
+ attr_reader :message
+
+ def initialize(message)
+ @message = message
+ end
+ end
+
+ class ConfigError < Error; end
+ end
+end
\ No newline at end of file
diff --git a/spec/command/base_command_spec.rb b/spec/command/base_command_spec.rb
index 8c1ef5f..f71f91a 100644
--- a/spec/command/base_command_spec.rb
+++ b/spec/command/base_command_spec.rb
@@ -26,6 +26,11 @@ module Aeolus
Aeolus::CLI::Base.user.to_s.should == "admin"
Aeolus::CLI::Base.password.to_s.should == "password"
end
+
+ it "should raise error on invalid config" do
+ base_command.instance_eval { @config = {} }
+ lambda { base_command.send(:configure_active_resource) }.should raise_error(Aeolus::CLI::ConfigError, "Error in configuration file")
+ end
end
describe "#read_file" do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index d198732..368c18f 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -14,6 +14,7 @@
$: << File.expand_path(File.join(File.dirname(__FILE__), "../lib/aeolus_cli/command/"))
$: << File.expand_path(File.join(File.dirname(__FILE__), "../lib/aeolus_cli/model/"))
+$: << File.expand_path(File.join(File.dirname(__FILE__), "../lib/aeolus_cli/"))
require 'aeolus_cli'
require 'stringio'
--
1.7.6.4
12 years, 1 month
[PATCH conductor 0/1] #798259 - require_user handles XHR requests
by Matt Wagner
Hi,
If you become logged-out while using Conductor and your next request is done over AJAX, the require_user method fails to find a template it can render and will display an error.
This adds a handler for the :js format, which will emit a 401 Unauthorized header. That, as I learned, will automatically (through Warden?) get you UserSessionsController#unauthenticated, which will display a warning message.
I started to try to customize this because I didn't love the wording that was shown, "Login failed: The Username and Password you entered do not match", which is a fairly odd thing to see if you're browsing along. However, the code is generic enough that we don't know that you *became* logged out, just that you are unauthenticated. We might want to make the message more generic, but I'm not keen on doing that as we have strings already translated.
-- Matt
12 years, 1 month
[PATCH conductor] BZ790861, BZ788103 Remove only catalog entry when removing deployable from catalog detail page
by Jirka Tomasek
From: Jiri Tomasek <jtomasek(a)redhat.com>
When removing deployables from catalog show page, only catalog entry is removed. If there are no more catalog references to this deployable, deployable gets deleted in catalog_entry after destroy hook.
Catalog_entry removal is done in deployables multi destroy. If necessary deployable is removed in catalog_entry after_destroy hook.
When we have separate deployables list done (an we support deployables without assigned catalogs), the table in catalog show page should list catalog entries and the form should submit to catalog_entries multi_destroy.
Deployables removal should be done separatelly from deployables list or deployable show/edit pages.
BZ788103 is also fixed with this patch
---
src/app/controllers/deployables_controller.rb | 6 +++-
src/app/models/catalog_entry.rb | 6 ++--
src/app/models/deployable.rb | 2 +-
src/app/views/catalogs/show.html.haml | 2 +-
src/config/locales/en.yml | 14 ++++++------
.../controllers/deployables_controller_spec.rb | 23 +++++++++++++------
6 files changed, 32 insertions(+), 21 deletions(-)
diff --git a/src/app/controllers/deployables_controller.rb b/src/app/controllers/deployables_controller.rb
index e37bc4a..1e1477f 100644
--- a/src/app/controllers/deployables_controller.rb
+++ b/src/app/controllers/deployables_controller.rb
@@ -188,10 +188,13 @@ class DeployablesController < ApplicationController
deleted = []
not_deleted = []
not_deleted_perms = []
+
+ @catalog = Catalog.find(params[:catalog_id])
+
if params[:deployables_selected]
Deployable.find(params[:deployables_selected]).to_a.each do |d|
if check_privilege(Privilege::MODIFY, d)
- if d.destroy
+ if d.catalog_entries.where(:catalog_id => @catalog.id).first.destroy
deleted << d.name
else
not_deleted << d.name
@@ -211,7 +214,6 @@ class DeployablesController < ApplicationController
flash[:error] = t("deployables.flash.error.not_selected")
end
- @catalog = Catalog.find(params[:catalog_id]) if params[:catalog_id].present?
if @catalog.present?
redirect_to catalog_path(@catalog)
else
diff --git a/src/app/models/catalog_entry.rb b/src/app/models/catalog_entry.rb
index 8f6b15c..857d013 100644
--- a/src/app/models/catalog_entry.rb
+++ b/src/app/models/catalog_entry.rb
@@ -35,10 +35,10 @@ class CatalogEntry < ActiveRecord::Base
validates_uniqueness_of :catalog_id, :scope => [:deployable_id]
- before_destroy :check_deployable_references
+ after_destroy :destroy_deployable_if_last
- def check_deployable_references
- return deployable.catalogs.count > 1
+ def destroy_deployable_if_last
+ deployable.destroy if deployable.catalog_entries.blank?
end
# This probably goes away once we separate catalog entry creation from deployables
diff --git a/src/app/models/deployable.rb b/src/app/models/deployable.rb
index c77f094..d7ce439 100644
--- a/src/app/models/deployable.rb
+++ b/src/app/models/deployable.rb
@@ -32,7 +32,7 @@ class Deployable < ActiveRecord::Base
has_many :permissions, :as => :permission_object, :dependent => :destroy,
:include => [:role],
:order => "permissions.id ASC"
- has_many :catalog_entries, :dependent => :delete_all
+ has_many :catalog_entries, :dependent => :destroy
has_many :catalogs, :through => :catalog_entries
belongs_to :owner, :class_name => "User", :foreign_key => "owner_id"
diff --git a/src/app/views/catalogs/show.html.haml b/src/app/views/catalogs/show.html.haml
index 0ee2fe7..f925907 100644
--- a/src/app/views/catalogs/show.html.haml
+++ b/src/app/views/catalogs/show.html.haml
@@ -22,7 +22,7 @@
.content
- content_for :form_header do
- %li= restful_submit_tag t("delete"), "destroy", multi_destroy_catalog_deployables_path(@catalog), 'DELETE', :id => 'delete_button', :class => 'button danger'
+ %li= restful_submit_tag t("remove"), "destroy", multi_destroy_catalog_deployables_path(@catalog), 'DELETE', :id => 'delete_button', :class => 'button danger'
- if check_privilege(Privilege::CREATE, Deployable)
%li= link_to t("catalog_entries.new_catalog_entry"), new_catalog_deployable_path(@catalog), :class => 'button', :id => 'new_deployable_button'
diff --git a/src/config/locales/en.yml b/src/config/locales/en.yml
index 126130c..e0e4e79 100644
--- a/src/config/locales/en.yml
+++ b/src/config/locales/en.yml
@@ -913,12 +913,12 @@ en:
attribute_not_exist: "Some attribute(s) is missing in XML, please check the file!"
no_catalog: "No catalogs selected"
not_deleted:
- one: "Deployable %{not_deleted} delete failed!"
- other: "%{count} deployables %{not_deleted} were not deleted!"
+ one: "Deployable %{not_deleted} removal failed!"
+ other: "%{count} deployables %{not_deleted} were not removed!"
not_deleted_perms:
- one: "Insufficient permissions to delete deployable %{not_deleted}!"
- other: "Insufficient permissions to delete %{count} deployables %{not_deleted}!"
- not_selected: "No deployable was not selected!"
+ one: "Insufficient permissions to remove deployable %{not_deleted}!"
+ other: "Insufficient permissions to remove %{count} deployables %{not_deleted}!"
+ not_selected: "No deployable was selected!"
no_catalog_exists: "No catalog exists! Please create one."
no_hwp_exists: "No hardware profile exists! Please create one."
missing_image: "%{assembly}: Image (UUID: %{uuid}) doesn't exist"
@@ -927,8 +927,8 @@ en:
failed: "Deployable was not created: %{message}"
notice:
deleted:
- one: "Deployable %{deleted} delete successfully!"
- other: "%{count} deployables %{deleted} were deleted!"
+ one: "Deployable %{deleted} removed successfully!"
+ other: "%{count} deployables %{deleted} were removed!"
error:
attribute_not_exists: invalid
hwp_not_exists: "Hardware profile %{name} specified in XML doesn't exist."
diff --git a/src/spec/controllers/deployables_controller_spec.rb b/src/spec/controllers/deployables_controller_spec.rb
index 72d89f4..9598b3d 100644
--- a/src/spec/controllers/deployables_controller_spec.rb
+++ b/src/spec/controllers/deployables_controller_spec.rb
@@ -123,6 +123,8 @@ describe DeployablesController do
before do
@deployable1 = Factory :deployable, :name => "test_delete"
@deployable2 = Factory :deployable, :name => "test_delete2"
+ @catalog.deployables << @deployable1
+ @catalog.deployables << @deployable2
end
it "deletes both deployables and shows flash notice" do
@@ -131,16 +133,23 @@ describe DeployablesController do
end
it "not delete deployable1 but not deployable2 and shows flash notice and error" do
- Deployable.any_instance.stub(:destroy).and_return(false)
- delete :multi_destroy, :deployables_selected => [@deployable1.id, @deployable2.id]
+ CatalogEntry.any_instance.stub(:destroy).and_return(false)
+ delete :multi_destroy, :deployables_selected => [@deployable1.id, @deployable2.id], :catalog_id => @catalog.id
flash[:error].should_not be_empty
end
- end
- context "without params[:deployables_selected]" do
- it "not delete a deployable and shows flash error" do
- delete :multi_destroy
- flash[:error].should_not be_empty
+ it "not delete deployable with multiple catalogs" do
+ @catalog2 = FactoryGirl.create(:catalog)
+ @catalog2.deployables << @deployable1
+ delete :multi_destroy, :deployables_selected => [@deployable1.id], :catalog_id => @catalog.id
+ @deployable1.should_not be_nil
+ end
+
+ context "without params[:deployables_selected]" do
+ it "not delete a deployable and shows flash error" do
+ delete :multi_destroy, :catalog_id => @catalog.id
+ flash[:error].should_not be_empty
+ end
end
end
end
--
1.7.7.6
12 years, 1 month
[PATCH conductor] BZ796862 Launch Time Params, if parameter has new lines in its value, its put into textarea instead of text input
by Jirka Tomasek
From: Jiri Tomasek <jtomasek(a)redhat.com>
---
src/app/stylesheets/layout.scss | 15 ++++++++-------
.../views/deployments/launch_time_params.html.haml | 2 ++
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/src/app/stylesheets/layout.scss b/src/app/stylesheets/layout.scss
index cdf3e66..03e5f42 100644
--- a/src/app/stylesheets/layout.scss
+++ b/src/app/stylesheets/layout.scss
@@ -3389,13 +3389,6 @@ body.monitor form.generic{
font-size: 13px;
}
- body.administer input[type="text"],input[type="password"]{
- border: 1px solid #C4C4C4;
- box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.50);
- -moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.50);
- -webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.50);
- }
-
input.em{
font-size: 16px;
padding: 6px 4px;
@@ -3408,6 +3401,14 @@ body.monitor form.generic{
input.short{
width: 100px;
}
+
+ textarea{
+ padding: 5px 4px;
+ margin: 2px 0px;
+ height: 100px;
+
+ &.long{ width: 400px }
+ }
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/src/app/views/deployments/launch_time_params.html.haml b/src/app/views/deployments/launch_time_params.html.haml
index 7b98ca3..7fcbe58 100644
--- a/src/app/views/deployments/launch_time_params.html.haml
+++ b/src/app/views/deployments/launch_time_params.html.haml
@@ -33,6 +33,8 @@
- value = get_hash_multi(params, [:deployment, :launch_parameters, assembly_name, service.name, parameter.name])
- if parameter.type == "password"
= password_field_tag id, (parameter.value or value)
+ - elsif (parameter.value or value).to_s.include?("\n")
+ = text_area_tag id, (parameter.value or value), :class => 'long'
- else
= text_field_tag id, (parameter.value or value)
- else
--
1.7.7.6
12 years, 1 month
[PATCH conductor] BZ 795655 "Return to User" is not required to show for non-admin's
by jzigmund@redhat.com
From: Jozef Zigmund <jzigmund(a)redhat.com>
https://bugzilla.redhat.com/show_bug.cgi?id=795655
---
src/app/views/users/show.html.haml | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/app/views/users/show.html.haml b/src/app/views/users/show.html.haml
index 67fa197..a823832 100644
--- a/src/app/views/users/show.html.haml
+++ b/src/app/views/users/show.html.haml
@@ -1,9 +1,10 @@
= render :partial => 'layouts/admin_nav'
%header.admin-page-header
- #obj_actions
- .return_to
- =t'return_to'
- = link_to t('users.users'), users_path
+ - if check_privilege(Privilege::VIEW, User)
+ #obj_actions
+ .return_to
+ =t'return_to'
+ = link_to t('users.users'), users_path
%section.admin-content-section.user
.content
--
1.7.7.6
12 years, 1 month
[PATCH conductor] BZ784474 added word-wrap: break-word to all headers, so long words dont get off the ui
by Jirka Tomasek
From: Jiri Tomasek <jtomasek(a)redhat.com>
---
src/app/stylesheets/custom.scss | 4 +++-
src/app/stylesheets/layout.scss | 2 ++
2 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/src/app/stylesheets/custom.scss b/src/app/stylesheets/custom.scss
index be3e1ec..484d3c3 100644
--- a/src/app/stylesheets/custom.scss
+++ b/src/app/stylesheets/custom.scss
@@ -8,7 +8,7 @@
.deployable_details {
color: #606060;
position: relative;
- max-width: 500px;
+ width: 500px;
margin: auto;
background: url(../../images/launch-deployment-icon.png) no-repeat right 75%;
@@ -17,6 +17,7 @@
margin-bottom: 3em;
h2 {
+ width: 400px;
font-size: 28px;
font-weight: normal;
text-align: center;
@@ -28,6 +29,7 @@
font-size: 13px;
margin-left: 50px;
margin-right: 50px;
+ word-wrap: break-word;
}
}
diff --git a/src/app/stylesheets/layout.scss b/src/app/stylesheets/layout.scss
index cdf3e66..a80c07e 100644
--- a/src/app/stylesheets/layout.scss
+++ b/src/app/stylesheets/layout.scss
@@ -115,6 +115,8 @@ xmp {
outline: none;
}
+h1,h2,h3,h4,h5,h6{ word-wrap: break-word; }
+
html,
body {
height: 100%;
--
1.7.7.6
12 years, 1 month
Conductor UI - some ideas for a better conductor
by Andrew Fitzsimon
Hi all,
I've spent quite some time thinking about global UI improvements we can make to conductor for a future release.
Now it's time for me to share a small summary of those ideas and hopefully get some feedback.
I'll be updating http://ndftz.com/playground/ with much the stuff mentioned below but as of right now it is not a representation of the functionality described; so if you have seen it before, please disregard everything aside from the responsiveness and the vector icons aspects. I'll now switch gears to get the mock interface up to speed with all the client side features described.
(attached is a formatted copy in-case you don't like reading markdown)
.. so here we go..
======================
#Goals for a better UI
> This is a plan to evolve the conductor UI into a lean, adaptive, beautiful and considered experience.
### Specifically, we hope to address:
* Navigating and issuing tasks quickly
* Without unnecessary http-roundtrips just to check on a view.
* Without having to learn new components in every view
* Without having to refer to documentation to be assisted in core tasks.
* Keeping the ‘big 6’ consistent:
* Consistent aesthetic
* Consistent behaviour
* Consistent notification
* Consistent messaging
* Consistent help
* Consistent referencing
* Address as many media types as we can get *for free*
* __Mobile__ - 480px and up via minor accommodations in our UI
* __Workstation__ 640px-1280px - our default view
* __Section 508__ compliance including screen readers
* __Printable__ - As a read-only inventory manifest of a users entire access.
* Feel like a 2012 client app
* Cutting edge UI conventions
* Swiss style visual metaphors & elements of typographic style
* Baseline grid aligned typography consisting of 2 weights with single leading.
* Use only vector graphics
* Blazingly fast client side render times
# Glossary of terms / explanation of features.
## Views
One distinct category of content.
### explained
“the users view” or “the providers view”.
A views name can even be as specific as “userXX-provider-permissions view” or “admin-provider-permissions-userXX view”
For more information on how we implement views, see 'View anchors' below
******
## Classes
Think HTML/CSS/JS classes
Classes track status or content type but not display.
<a href="#provider23" class="provider23 enabling ec2" >online</a>`
<div id="provider23" class="provider23 enabling ec2">Ec2…</div>
### Classing convention
#### Reserved classes
.active
is reserved for navigating views
.enabling .disabling .verifying .deleting .requesting
are action classes reserved for client side action confirmation
.enabled .disabled .verified .complete .building
are action classes reserved for server events
.warning .note .info .tip .caution
are reserved for assistive content
.static-reference .assist-reference
reserved for anchored clones of content via static and assistive referencing (see section)
.progress .loading .building .compiling .altering
are progress classed to be used in conjunction with a numerical class
.50 .10 .20 .25 .75 .100 .30 etc…
are percentage classes to be used in conjunction with a value
e.g.: `<span class="75 usage">75% of 300gb </...`
or better: `<span class="75 usage">225gb of 300gb </...`
.usage .progress .load .capacity
are **status** classes reserved for identifying the **type** of measurement
.instance .provider .user .pool .group
are object classes to be used on any object
### Lack of classes for layout
We will __NOT__ use classes for defining grid layout e.g. `.span-12` or `.left-120/`
All layouts will be defined in CSS via a combination of their parent view and the relevant media query.
for example we will use the CSS
#admin #providers .account .summary{width:33.333%}
rather than relying on injecting style logic into the html like this `<class="summary span-4">`
******
## Graceful degradation
Support for all core functionality in as many scenarios as possible
* New browser features (subtle animation, gradients etc)
* Older browsers lacking features
* Browsers with javascript turned off
* Screen readers (section 508, we’re going there)
******
## Responsive design
Support for viewing from various media eg cellphones, touchscreen devices, kiosks, tv’s, even print.
### Explained
1. We collapse tables into record views for narrow screens.
2. We Grow fonts and icons for tremendously high resolutions or touchable large screens.
3. We use only vector graphics (css /webfonts) for adaptive scaling and themeing.
Anchor referencing with js inlining means repeated content is printed only once. a print version would read like an infrastructure status report from the users perspective.
******
## Visual Metaphors & Vector Graphics
Visual metaphors are graphics symbolic of the function they perform.
Vector graphics are a resolution independent implementation.
### Explained
All icons, visual indicators and ornamental graphics are implemented like this:
* Vector glyphs are encoded into a woff webfont
* The woff font is base64 encoded in the stylesheet to minimise http requests (the current set of 30 icons is ~5k) so this is very acceptable.
* We fallback to url linked images supplies for legacy browsers (no .WOFF support) by using [modernizr](http://www.modernizr.com/) classes `.no-webfonts` and `.webfonts` to discriminate our implementation through css
******
## View anchors - or 'single page app'
View anchors are portions of our design implemented within the one DOM using basic anchoring functionality.
### Explained
In the proposed change, the entire conductor is one page for all default views,
1. Link anchors will activate the specific view or sub-view.
2. Anchors that do not resolve will initiate a "cannot find" message which will most commonly occur when a user does not have access to an object and has manually entered a custom # URL. the two exceptions to this will be ~/# and ~/#top which will initiate the default app view.
### In action
For example:
> The URL below should open the admin > providers > ec2eastcoast > connectivity view.
https://conductor/#ec2eastcoast-connectivity
^ ^ ^
Server ObjectID ChildView
#### What the html does
e.g. the `<div>` representing admin > providers > ec2eastcoast would look like
<div id="ec2eastcoast">.. ec2 east coast information goes here
and the connectivity tab which exists inside the ec2eastcoast provider would look like
<div id="ec2eastcoast-connectivity">
^ ^
objectID ChildViewname
Why?
Because the provider _ec2eastcoast_ lives natively within the _admin > provider_ section, it does not need to be referenced in the ID.. it simply has to be unique. But because the connectivity tab is only unique because of the provider it is associated with, it needs to be prefixed with the objectID
All direct links to the provider view would look like `<a href=#ec2eastcoast>EC2 East Coast</a> which would activate the provider tab.
#### what JS does
1. JS hides all non active views except for the default view (classed as active by the js)
2.
3. when an ID is requested the object and all parent views get classed `.active`
4. [hashchange for old browsers](http://benalman.com/projects/jquery-hashchange-plugin/) to preserve browsing history
#### what the CSS does
The body class `.nojs` is removed once Javascript is loaded so the CSS specifies that only views be visible when they are classed as `.active`
.js div{display:none} // Hiding all views
.js div.active{display:block} // Showing active views
.nojs div{display:block} // All views are shown when tabs don't work.
******
## Referenced content
> Referenced content is a live-copy of any existing part of the application. It can be implemented with static references or assistive references
> See [this JS Fiddle demo](http://jsfiddle.net/andyfitz/hRqGa/191/)
#### example
1. Global help content can be referenced from many places at once so as to avoid redundancy and annoying ajax requests.. if the section the help comes from is loaded, so is the help.
2. Inspecting an object via a link can call the objects entire content into view.
******
### Static-references
Where an anchor link to another section has been replaced with a live copy of the section it links to.
.static-reference
> An example would be any monitoring view that requires various metrics already rendered elsewhere be included.
******
### Assist-references
like a static reference but with the link-text preserved and the section only visible when the link-text has focus (has been clicked).
.assist-reference
> An example would be a permissions editor referencing the objects that a user has permissions to by name and allowing the user to inspect that object in-place with a single click, without having to visit the object in questions default view.
******
## Help & content
Written content to help describe a feature or scenario.
Combined with admonition classes
.warning .note .info .tip .caution
Often implemented via one of the following methods
* Included in the view relevant to its description
* As static-references where the help content can be dismissed (via an X in the top right corner)
* As assist-references where the help content can be revealed upon clicking a referring link
Practically speaking this is text that can be placed inline with a view that it represents or hidden in a non displayed useful content area to be static or assist-referenced by many places.
### Explained
For example: _“don’t be silly“_ is a generic tip that may apply to an enormous variety of contexts. This is useful to be placed in the "generic tips" area and linked to via `<a href=”#dont be-silly” class=”assist-reference”>now please remember..</a>` which means it wil be rendered inline of where it is referenced.
******
##Client-side status polling
All objects relevant to a view are classed with the viewname
On any action inside the view, a status classname is added to the view as well as any objects that reference it regardless of where they are displayed
<a href=#user class=”userXX enabling”>link</a>
<div id=#”userXX” class=”userXX enabling” >UserXX View</div>.
We watch the referenced views classes and mimic them on all referencing links always as they can contain or be updated with new event styles (for example: failed, warning, upgraded, admin-only etc)
******
## Server status events *investigating*
Right now we can use ajax calls to update each view but in future it would make sense to use eventSource for more advanced monitoring: [eventSource: server sent events](http://html5doctor.com/server-sent-events/)
******
## Client verification / fast feedback
Interactive assurance that an action has been requested without the verification that the server has performed the action.
For example a user clicks the enable button.. we immediately apply “enabling” status to the button but wait for the server to return with the “enabled” confirmation...
### How it works
> **Assumption** intermittent states like verifying, enabling and disabling states are safe for client side validation.
> They confirm an action has been requested but not applied.
As a rule, all elements are given the status of the objects they represent as well as classed with the object ID.. e.g.: all buttons with `class="providerid12451-*"` get the additional class of their intermittent state ``"enabling/disabling/verifying/whatever"`` When a functional object related to them has been actioned.
1. On the client javascript side, we set the actioning classname to all elements with the same object objectid class.
2. Once the action has been done an ajax call confirm the change and refreshes the class to "enabled/disabled/done/whatever" and removes the intermediary state
******
## Important action certification
[JS Fiddle demo](http://jsfiddle.net/andyfitz/mvdST/)
Requiring the user to certify that they understand the action before allowing it to take place.
for example:
> “Do you understand what you are doing?[yes] okay, here’s the button [click]”
###explained
> Enabling and disabling providers, deleting users etc
We will use three methods to verify that a user has accepted the severity of the task they are about to perform:
1. CSS physical obfuscation.
Where the confirmation toggle sits physically on top of the action toggle so that an action can not be clicked without clicking the confirmation toggle first. this helps simplify the component to one physical space part of the same consideration set.
2. javascript validation.
The action button beneath is disabled until the confirmation toggle has been clicked
3. final server verification.
the submitted action is not accepted by the system unless the post contains both the verification enabled and the action. the server then pushes the update
******
##Global status and system notification stack.
Important information about the entire system or a current process, displayed prominently.
###explained
Using the referenced content heavily, we throw system, warning and notification content to the top of the page in a collapsing, growl-style notification system”
<div id="notifications">
<h1>System Messages</h1>
<p class=”system”>you should to install aeolus-all to properly use conductor</p>
<p class=”status provider123 build”>
<a
href=”provider123-build-status”
class=”reflink 50”>
building provider123 <span>50% Complete</span>
</a>
</p>
</div>
******
## Printable manifest
Because our content is not replicated, and all enabled views are included in the DOM;
our app can actually print as if it were a manifest for the authenticated user.
We get this feature for free by proxy of our method for referencing views and content.
Having the ability to produce a hard copy infrastructure report may be a gimmick, but it's an easy way to show how conductor can help respond an IT audit situation.
### example print stylesheet changes
@media print {
a:after {
content: " ("attr(href)") ";}
div:before{
content: " ("attr(id)") ";}}
}
This will preserve all references and links throughout the UI.
Also, we can manually define sections to be printed.
@media print {
div{display:none}
#providers, #instances, #users, #global-tips {display:block !important}
}
Which means only sections we desire to be included in the manifest get printed
also
@media print {
.tabs:before{
page-break-before: always;
content:"This section contains the following:";
.tabs li a:after{content:""}
.tabs { font-size: 2em;page-break-after: always;}
.tabs li{display:list}
}
Which will convert our tabs into whole page section summaries.
> remember, this feature is free because we are designing conductor to gracefully degrade. Very little effort goes into preserving this feature so long as our standards are maintained.
# Existing conductor paradigms
These changes don't create any changes to terminology, or have much impact for pre-existing views for components already built into conductor. It is likely that the majority of what has already been done will be preserved and only undergo minor changes to the HAML/SASS so that features may be integrated into the global view.
This has been written purely to start discussion on how we evolve Conductor going forward and I'd love to hear your thoughts: [andy.fitzsimon(a)redhat.com ](mailto:andy.fitzsimon@redhat.com)
12 years, 1 month