doc: cleanup formatting

* Clean up unnecessary vertical quotes at the left side
  caused by extra spaces at the beginning of lines.
* Do not use backquotes in the title lines
  (ref/run_tests.rst, ref/horizon.rst)
  When backquotes are used in the first-level title,
  it will be included in the navigation at the top-right corner
  https://docs.openstack.org/developer/horizon/contributor/ref/index.html
* Remove duplicated contents:: directive in ref/run_tests.sh.
  openstackdocstheme generates the toc by default, so having contents::
  directive leads to duplicated toc in a page.

Change-Id: Icc641927ad7cd7a8d79632c64a3ce212f0dc0b64
This commit is contained in:
Akihiro Motoki 2017-06-29 14:40:30 +09:00
parent 614bc7600a
commit 563908e2c0
17 changed files with 198 additions and 185 deletions

View File

@ -198,7 +198,8 @@ Required
* Use ``===`` as opposed to ``==`` for equality checks. The ``==`` will do a
type cast before comparing, which can lead to unwanted results.
.. Note ::
.. note::
If typecasting is desired, explicit casting is preferred to keep the
meaning of your code clear.
@ -282,16 +283,18 @@ Required
3. Avoid using classes for detection purposes only, instead, defer to
attributes. For example to find a div:
::
<div class="something"></div>
$(".something").html("Don't find me this way!");
.. code-block:: html
Is better found like:
::
<div class="something"></div>
$(".something").html("Don't find me this way!");
<div data-something></div>
$("div[data-something]").html("You found me correctly!");
is better found like:
.. code-block:: html
<div data-something></div>
$("div[data-something]").html("You found me correctly!");
* Avoid commented-out code.
* Avoid dead code.
@ -563,13 +566,13 @@ Conventions
Simply by convention, we have a few rules about naming:
* The term "project" is used in place of Keystone's "tenant" terminology
in all user-facing text. The term "tenant" is still used in API code to
make things more obvious for developers.
* The term "project" is used in place of Keystone's "tenant" terminology
in all user-facing text. The term "tenant" is still used in API code to
make things more obvious for developers.
* The term "dashboard" refers to a top-level dashboard class, and "panel" to
the sub-items within a dashboard. Referring to a panel as a dashboard is
both confusing and incorrect.
* The term "dashboard" refers to a top-level dashboard class, and "panel" to
the sub-items within a dashboard. Referring to a panel as a dashboard is
both confusing and incorrect.
Release Notes
=============

View File

@ -15,12 +15,12 @@ Values
Horizon holds several key values at the core of its design and architecture:
* Core Support: Out-of-the-box support for all core OpenStack projects.
* Extensible: Anyone can add a new component as a "first-class citizen".
* Manageable: The core codebase should be simple and easy-to-navigate.
* Consistent: Visual and interaction paradigms are maintained throughout.
* Stable: A reliable API with an emphasis on backwards-compatibility.
* Usable: Providing an *awesome* interface that people *want* to use.
* Core Support: Out-of-the-box support for all core OpenStack projects.
* Extensible: Anyone can add a new component as a "first-class citizen".
* Manageable: The core codebase should be simple and easy-to-navigate.
* Consistent: Visual and interaction paradigms are maintained throughout.
* Stable: A reliable API with an emphasis on backwards-compatibility.
* Usable: Providing an *awesome* interface that people *want* to use.
The only way to attain and uphold those ideals is to make it *easy* for
developers to implement those values.
@ -113,11 +113,6 @@ on the best possible experience.
.. seealso::
:ref:`quickstart`
A short guide to getting started with using Horizon.
:ref:`faq`
Common questions and answers.
:ref:`glossary`
Common terms and their definitions.
* :ref:`quickstart` A short guide to getting started with using Horizon.
* :ref:`faq` Common questions and answers.
* :ref:`glossary` Common terms and their definitions.

View File

@ -88,11 +88,12 @@ That code would create the ``"switchable"`` control field ``source``, and the
two ``"switched"`` fields ``cidr`` and ``security group`` which are hidden or
shown depending on the value of ``source``.
.. note::
NOTE: A field can only safely define one slug in its ``"switch-on"`` attribute.
While switching on multiple fields is possible, the behavior is very hard to
predict due to the events being fired from the various switchable fields in
order. You generally end up just having it hidden most of the time by accident,
so it's not recommended. Instead just add a second field to the form and control
the two independently, then merge their results in the form's clean or handle
methods at the end.
A field can only safely define one slug in its ``"switch-on"`` attribute.
While switching on multiple fields is possible, the behavior is very hard to
predict due to the events being fired from the various switchable fields in
order. You generally end up just having it hidden most of the time by
accident, so it's not recommended. Instead just add a second field to the
form and control the two independently, then merge their results in the
form's clean or handle methods at the end.

View File

@ -41,5 +41,8 @@ Panel
.. autoclass:: Panel
:members:
Panel Group
===========
.. autoclass:: PanelGroup
:members:

View File

@ -8,9 +8,6 @@ The run_tests.sh Script
Queens (13.0), in favor of tox. The tox docs can be found at
https://tox.readthedocs.io/en/latest/
.. contents:: Contents:
:local:
Horizon ships with a script called ``run_tests.sh`` at the root of the
repository. This script provides many crucial functions for the project,
and also makes several otherwise complex tasks trivial for you as a
@ -23,10 +20,10 @@ If you start with a clean copy of the Horizon repository, the first thing
you should do is to run ``./run_tests.sh`` from the root of the repository.
This will do two things for you:
#. Set up a virtual environment for both the ``horizon`` module and
the ``openstack_dashboard`` project using ``./tools/install_venv.py``.
#. Run the tests for both ``horizon`` and ``openstack_dashboard`` using
their respective environments and verify that everything is working.
#. Set up a virtual environment for both the ``horizon`` module and
the ``openstack_dashboard`` project using ``./tools/install_venv.py``.
#. Run the tests for both ``horizon`` and ``openstack_dashboard`` using
their respective environments and verify that everything is working.
Setting up the environment the first time can take several minutes, but only
needs to be done once. If dependencies are added in the future, updating the
@ -48,14 +45,13 @@ Selenium tests by using the ``--with-selenium`` flag::
If you run horizon in a minimal installation VM, you will probably need
the following (steps for Fedora 18 minimal installation):
#. Install these packages in the VM:
``yum install xorg-x11-xauth xorg-x11-fonts-Type1.noarch``.
#. Install firefox in the VM:
``yum install firefox``.
#. Connect to the VM by ``ssh -X``
(if you run ``set|grep DISP``, you should see that the DISPLAY is set).
#. Run
``./run_tests.sh --with-selenium``.
#. Install these packages in the VM:
``yum install xorg-x11-xauth xorg-x11-fonts-Type1.noarch``.
#. Install firefox in the VM:
``yum install firefox``.
#. Connect to the VM by ``ssh -X``
(if you run ``set|grep DISP``, you should see that the DISPLAY is set).
#. Run ``./run_tests.sh --with-selenium``.
Running a subset of tests
-------------------------

View File

@ -12,10 +12,10 @@ correctly and consistently, table-level and row-level actions all have a consist
API and appearance, and generally you don't have to reinvent the wheel or
copy-and-paste every time you need a new table!
.. seealso::
.. seealso::
For usage information, tips & tricks and more examples check out
the :ref:`topics-datatables`.
For usage information, tips & tricks and more examples check out
the :ref:`topics-datatables`.
DataTable
=========

View File

@ -10,10 +10,10 @@ One of the most challenging aspects of building a compelling user experience
is crafting complex multi-part workflows. Horizon's ``workflows`` module
aims to bring that capability within everyday reach.
.. seealso::
.. seealso::
For usage information, tips & tricks and more examples check out the
:ref:`topics-workflows`.
For usage information, tips & tricks and more examples check out the
:ref:`topics-workflows`.
Workflows
=========

View File

@ -266,11 +266,11 @@ To use the automatic functionality, add::
to your enabled file (``enabled/<plugin_name>.py``). To make this possible,
you need to follow some structural conventions:
- Static files should be put in a ``static/`` folder, which should be found directly under
the folder for the dashboard/panel/panel groups Python package.
- JS code that defines an Angular module should be in a file with extension of ``.module.js``.
- JS code for testing should be named with extension of ``.mock.js`` and of ``.spec.js``.
- Angular templates should have extension of ``.html``.
- Static files should be put in a ``static/`` folder, which should be found directly under
the folder for the dashboard/panel/panel groups Python package.
- JS code that defines an Angular module should be in a file with extension of ``.module.js``.
- JS code for testing should be named with extension of ``.mock.js`` and of ``.spec.js``.
- Angular templates should have extension of ``.html``.
You can read more about the functionality in the
:ref:`auto_discover_static_files` section of the settings documentation.

View File

@ -5,18 +5,19 @@ JavaScript Testing
==================
There are multiple components in our JavaScript testing framework:
* `Jasmine`_ is our testing framework, so this defines the syntax and file
structure we use to test our JavaScript.
* `Karma`_ is our test runner. Amongst other things, this lets us run the
tests against multiple browsers and generate test coverage reports.
Alternatively, tests can be run inside the browser with the Jasmine spec
runner.
* `PhantomJS`_ provides a headless WebKit (the browser engine). This gives us
native support for many web features without relying on specific browsers
being installed.
* `ESLint`_ is a pluggable code linting utility. This will catch small errors
and inconsistencies in your JS, which may lead to bigger issues later on.
See :ref:`js_code_style` for more detail.
* `Jasmine`_ is our testing framework, so this defines the syntax and file
structure we use to test our JavaScript.
* `Karma`_ is our test runner. Amongst other things, this lets us run the
tests against multiple browsers and generate test coverage reports.
Alternatively, tests can be run inside the browser with the Jasmine spec
runner.
* `PhantomJS`_ provides a headless WebKit (the browser engine). This gives us
native support for many web features without relying on specific browsers
being installed.
* `ESLint`_ is a pluggable code linting utility. This will catch small errors
and inconsistencies in your JS, which may lead to bigger issues later on.
See :ref:`js_code_style` for more detail.
Jasmine uses specs (``.spec.js``) which are kept with the JavaScript files
that they are testing. See the :ref:`js_file_structure` section or the `Examples`_
@ -32,11 +33,11 @@ Running Tests
Tests can be run in two ways:
1. Open <dev_server_ip:port>/jasmine in a browser. The development server can be
run with ``tox -e runserver`` from the horizon root directory.
2. ``tox -e npm`` from the horizon root directory. This runs Karma,
so it will run all the tests against PhantomJS and generate coverage
reports.
1. Open <dev_server_ip:port>/jasmine in a browser. The development server can be
run with ``tox -e runserver`` from the horizon root directory.
2. ``tox -e npm`` from the horizon root directory. This runs Karma,
so it will run all the tests against PhantomJS and generate coverage
reports.
The code linting job can be run with ``tox -e npm -- lint``, or
``tox -e npm -- lintq`` to show errors, but not warnings.
@ -66,14 +67,15 @@ Writing Tests
=============
Jasmine uses suites and specs:
* Suites begin with a call to ``describe``, which takes two parameters; a
string and a function. The string is a name or title for the spec suite,
whilst the function is a block that implements the suite.
* Specs begin with a call to ``it``, which also takes a string and a function
as parameters. The string is a name or title, whilst the function is a
block with one or more expectations (``expect``) that test the state of
the code. An expectation in Jasmine is an assertion that is either true or
false; every expectation in a spec must be true for the spec to pass.
* Suites begin with a call to ``describe``, which takes two parameters; a
string and a function. The string is a name or title for the spec suite,
whilst the function is a block that implements the suite.
* Specs begin with a call to ``it``, which also takes a string and a function
as parameters. The string is a name or title, whilst the function is a
block with one or more expectations (``expect``) that test the state of
the code. An expectation in Jasmine is an assertion that is either true or
false; every expectation in a spec must be true for the spec to pass.
``.spec.js`` files can be handled manually or automatically. To use the
automatic file discovery add::
@ -88,7 +90,8 @@ You can read more about the functionality in the
To manually add specs, add the following array and relevant file paths to your
enabled file:
::
.. code-block:: python
ADD_JS_SPEC_FILES = [
...
@ -100,15 +103,17 @@ Examples
========
.. Note::
The code below is just for example purposes, and may not be current in
horizon. Ellipses (...) are used to represent code that has been
removed for the sake of brevity.
The code below is just for example purposes, and may not be current in
horizon. Ellipses (...) are used to represent code that has been
removed for the sake of brevity.
Example 1 - A reusable component in the **horizon** directory
-------------------------------------------------------------
File tree:
::
.. code-block:: none
horizon/static/framework/widgets/modal
├── modal.controller.js
@ -117,7 +122,8 @@ File tree:
└── modal.spec.js
Lines added to ``horizon/test/jasmine/jasmine_tests.py``:
::
.. code-block:: python
class ServicesTests(test.JasmineTests):
sources = [
@ -135,7 +141,8 @@ Lines added to ``horizon/test/jasmine/jasmine_tests.py``:
]
``modal.spec.js``:
::
.. code-block:: javascript
...
@ -204,7 +211,8 @@ Example 2 - Panel-specific code in the **openstack_dashboard** directory
------------------------------------------------------------------------
File tree:
::
.. code-block:: none
openstack_dashboard/static/dashboard/launch-instance/network/
├── network.help.html
@ -215,7 +223,8 @@ File tree:
Lines added to ``openstack_dashboard/enabled/_10_project.py``:
::
.. code-block:: python
LAUNCH_INST = 'dashboard/launch-instance/'
@ -232,7 +241,8 @@ Lines added to ``openstack_dashboard/enabled/_10_project.py``:
]
``network.spec.js``:
::
.. code-block:: javascript
...

View File

@ -16,11 +16,11 @@ to build the car, he must create the tool, too.
As a developer, if you are going to add a library named “foo”, the package
must adhere to the following standards:
- Be a free package created with free software.
- Include all tools that are required to build the package.
- Have an active and responsive upstream to maintain the package.
- Adhere to Filesystem Hierarchy Standards (FHS). A specific file system
layout is not required.
- Be a free package created with free software.
- Include all tools that are required to build the package.
- Have an active and responsive upstream to maintain the package.
- Adhere to Filesystem Hierarchy Standards (FHS). A specific file system
layout is not required.
Embedded copies not allowed
@ -146,16 +146,16 @@ maintainers. Some of the most important ones are:
- /usr is considered read only. Software must not write in /usr at
runtime. However, it is fine for a package post-installation script to write
in /usr. When this rule was not followed, distributions had to write many
tricks to convince Horizon to write in /var/lib only. For example,
distributions wrote symlinks to /var/lib/openstack-dashboard, or patched
the default local_settings.py to write the SECRET_KEY in /var.
tricks to convince Horizon to write in ``/var/lib`` only. For example,
distributions wrote symlinks to ``/var/lib/openstack-dashboard``, or patched
the default ``local_settings.py`` to write the ``SECRET_KEY`` in /var.
- Configuration must always be in /etc, no matter what. When this rule
was not followed, package maintainers had to place symlinks to
/etc/openstack-dashboard/local_settings in Red Hat based distributions
``/etc/openstack-dashboard/local_settings`` in Red Hat based distributions
instead of using directly
/usr/share/openstack-dashboard/openstack_dashboard/local/local_settings.py
``/usr/share/openstack-dashboard/openstack_dashboard/local/local_settings.py``
which Horizon expects. In Debian,the configuration file is named
/etc/openstack-dashboard/local_settings.py.
``/etc/openstack-dashboard/local_settings.py.``
Packaging Horizon
@ -168,29 +168,29 @@ Why we use XStatic
XStatic provides the following features that are not currently available
by default with systems like NPM and Grunt:
- Dependency checks: XStatic checks that dependencies, such as fonts
and JavaScript libs, are available in downstream distributions.
- Reusable components across projects: The XStatic system ensures
components are reusable by other packages, like Fuel.
- System-wide registry of static content: XStatic brings a system-wide
registry of components, so that it is easy to check if one is missing. For
example, it can detect if there is no egg-info, or a broken package
dependency exists.
- No embedded content: The XStatic system helps us avoid embedding files that
are already available in the distribution, for example, libjs-* or fonts-*
packages. It even provides a compatibility layer for distributions. Not
every distribution places static files in the same position in the file
system. If you are packaging an XStatic package for your distribution, make
sure that you are using the static files provided by that specific
distribution. Having put together an XStatic package is *no* guarantee to
get it into a distribution. XStatic provides only the abstraction layer to
use distribution provided static files.
- Package build systems are disconnected from the outside network (for
several reasons). Other packaging systems download dependencies directly
from the internet without verifying that the downloaded file is intact,
matches a provided checksum, etc. With these other systems, there is no way
to provide a mirror, a proxy or a cache, making builds even more unstable
when minor networking issues are encountered.
- Dependency checks: XStatic checks that dependencies, such as fonts
and JavaScript libs, are available in downstream distributions.
- Reusable components across projects: The XStatic system ensures
components are reusable by other packages, like Fuel.
- System-wide registry of static content: XStatic brings a system-wide
registry of components, so that it is easy to check if one is missing. For
example, it can detect if there is no egg-info, or a broken package
dependency exists.
- No embedded content: The XStatic system helps us avoid embedding files that
are already available in the distribution, for example, libjs-* or fonts-*
packages. It even provides a compatibility layer for distributions. Not
every distribution places static files in the same position in the file
system. If you are packaging an XStatic package for your distribution, make
sure that you are using the static files provided by that specific
distribution. Having put together an XStatic package is *no* guarantee to
get it into a distribution. XStatic provides only the abstraction layer to
use distribution provided static files.
- Package build systems are disconnected from the outside network (for
several reasons). Other packaging systems download dependencies directly
from the internet without verifying that the downloaded file is intact,
matches a provided checksum, etc. With these other systems, there is no way
to provide a mirror, a proxy or a cache, making builds even more unstable
when minor networking issues are encountered.
The previous features are critical requirements of the Horizon packaging
system. Any new system *must* keep these features. Although XStatic may mean
@ -203,11 +203,11 @@ Packaging Horizon for distributions
Horizon is a Python module. Preferably, it is installed at the default
location for python. In Fedora and openSUSE, this is
/usr/lib/python2.7/site-packages/horizon, and in Debian/Ubuntu it is
/usr/lib/python2.7/dist-packages/horizon.
``/usr/lib/python2.7/site-packages/horizon``, and in Debian/Ubuntu it is
``/usr/lib/python2.7/dist-packages/horizon``.
Configuration files should reside under /etc/openstack-dashboard. Policy
files should be created and modified there as well.
Configuration files should reside under ``/etc/openstack-dashboard``.
Policy files should be created and modified there as well.
It is expected that ``manage.py collectstatic`` will be run during package
build.

View File

@ -9,9 +9,9 @@ a convenient, reusable API for building data-driven displays and interfaces.
The core components of this API fall into three categories: ``DataTables``,
``Actions``, and ``Class-based Views``.
.. seealso::
.. seealso::
For a detailed API information check out the :ref:`ref-datatables`.
For a detailed API information check out the :ref:`ref-datatables`.
Tables
======
@ -26,13 +26,13 @@ Creating your own tables
Creating a table is fairly simple:
#. Create a subclass of :class:`~horizon.tables.DataTable`.
#. Define columns on it using :class:`~horizon.tables.Column`.
#. Create an inner ``Meta`` class to contain the special options for
this table.
#. Define any actions for the table, and add them to
:attr:`~horizon.tables.DataTableOptions.table_actions` or
:attr:`~horizon.tables.DataTableOptions.row_actions`.
#. Create a subclass of :class:`~horizon.tables.DataTable`.
#. Define columns on it using :class:`~horizon.tables.Column`.
#. Create an inner ``Meta`` class to contain the special options for
this table.
#. Define any actions for the table, and add them to
:attr:`~horizon.tables.DataTableOptions.table_actions` or
:attr:`~horizon.tables.DataTableOptions.row_actions`.
Examples of this can be found in any of the ``tables.py`` modules included
in the reference modules under ``horizon.dashboards``.
@ -80,14 +80,14 @@ take place; prior to data being loaded into the table, and after the data
is loaded. When you're using one of the pre-built class-based views for
working with your tables the pseudo-workflow looks like this:
#. The request enters view.
#. The table class is instantiated without data.
#. Any "preemptive" actions are checked to see if they should run.
#. Data is fetched and loaded into the table.
#. All other actions are checked to see if they should run.
#. If none of the actions have caused an early exit from the view,
the standard response from the view is returned (usually the
rendered table).
#. The request enters view.
#. The table class is instantiated without data.
#. Any "preemptive" actions are checked to see if they should run.
#. Data is fetched and loaded into the table.
#. All other actions are checked to see if they should run.
#. If none of the actions have caused an early exit from the view,
the standard response from the view is returned (usually the
rendered table).
The benefit of the multi-step table instantiation is that you can use
preemptive actions which don't need access to the entire collection of data
@ -262,10 +262,10 @@ functionality, communication with the server goes through AJAX in JSON format.
The javascript wrapper for inline editing allows each table cell that has
in-line editing available to:
#. Refresh itself with new data from the server.
#. Display in edit mode.
#. Send changed data to server.
#. Display validation errors.
#. Refresh itself with new data from the server.
#. Display in edit mode.
#. Send changed data to server.
#. Display validation errors.
There are basically 3 things that need to be defined in the table in order
to enable in-line editing.

View File

@ -89,7 +89,7 @@ Cons:
* Did I mention that setting it up is a pain?
Screenshot directory could be set through horizon.conf file, default value:
"./integration_tests_screenshots"
``./integration_tests_screenshots``
So what should I write?
-----------------------

View File

@ -8,9 +8,9 @@ One of the most challenging aspects of building a compelling user experience
is crafting complex multi-part workflows. Horizon's ``workflows`` module
aims to bring that capability within everyday reach.
.. seealso::
.. seealso::
For detailed API information refer to the :ref:`ref-workflows`.
For detailed API information refer to the :ref:`ref-workflows`.
Workflows
=========

View File

@ -592,6 +592,5 @@ What you've learned here is the fundamentals of how to write interfaces for
your own project based on the components horizon provides.
If you have feedback on how this tutorial could be improved, please feel free
to submit a bug against ``Horizon`` in `launchpad`_.
.. _launchpad: https://bugs.launchpad.net/horizon
to submit a bug against ``Horizon`` in
`launchpad <https://bugs.launchpad.net/horizon>`__.

View File

@ -296,6 +296,5 @@ snapshot to other API calls that require more complex forms to gather the
necessary information.
If you have feedback on how this tutorial could be improved, please feel free
to submit a bug against ``Horizon`` in `launchpad`_.
.. _launchpad: https://bugs.launchpad.net/horizon
to submit a bug against ``Horizon`` in
`launchpad <https://bugs.launchpad.net/horizon>`__.

View File

@ -241,16 +241,23 @@ class Column(html.HTMLElement):
List of scope and rule tuples to do policy checks on, the
composition of which is (scope, rule)
scope: service type managing the policy for action
rule: string representing the action to be checked
* scope: service type managing the policy for action
* rule: string representing the action to be checked
for a policy that requires a single rule check:
policy_rules should look like
"(("compute", "compute:create_instance"),)"
for a policy that requires multiple rule checks:
rules should look like
"(("identity", "identity:list_users"),
("identity", "identity:list_roles"))"
for a policy that requires a single rule check,
policy_rules should look like:
.. code-block:: none
"(("compute", "compute:create_instance"),)"
for a policy that requires multiple rule checks,
rules should look like:
.. code-block:: none
"(("identity", "identity:list_users"),
("identity", "identity:list_roles"))"
.. attribute:: help_text

View File

@ -156,18 +156,18 @@ class TestCase(horizon_helpers.TestCase):
It gives access to numerous additional features:
* A full suite of test data through various attached objects and
managers (e.g. ``self.servers``, ``self.user``, etc.). See the
docs for
:class:`~openstack_dashboard.test.test_data.utils.TestData`
for more information.
* The ``mox`` mocking framework via ``self.mox``.
* A set of request context data via ``self.context``.
* A ``RequestFactory`` class which supports Django's ``contrib.messages``
framework via ``self.factory``.
* A ready-to-go request object via ``self.request``.
* The ability to override specific time data controls for easier testing.
* Several handy additional assertion methods.
* A full suite of test data through various attached objects and
managers (e.g. ``self.servers``, ``self.user``, etc.). See the
docs for
:class:`~openstack_dashboard.test.test_data.utils.TestData`
for more information.
* The ``mox`` mocking framework via ``self.mox``.
* A set of request context data via ``self.context``.
* A ``RequestFactory`` class which supports Django's ``contrib.messages``
framework via ``self.factory``.
* A ready-to-go request object via ``self.request``.
* The ability to override specific time data controls for easier testing.
* Several handy additional assertion methods.
"""
# To force test failures when unmocked API calls are attempted, provide