Add docs to about page
This commit adds a script that will convert RST files to basic HTML templates. The about page is also adjusted to assume that this tool will be run and that documentation templates will be available. Addresses-Spec: https://review.openstack.org/#/c/437175/ Change-Id: I0d3fa68be351177af39228d34c682f48f75ac10d
This commit is contained in:
parent
9ea5721d51
commit
01bc37c241
@ -204,6 +204,17 @@ performed to upgrade the database to the latest revision:
|
||||
|
||||
Now it should be some revision number other than `None`.
|
||||
|
||||
(Optional) Generate About Page Content
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The RefStack About page is populated with HTML templates generated from
|
||||
our RST documentation files. If you want this information displayed, then
|
||||
run the following command from the root of the project.
|
||||
|
||||
``./tools/convert-docs.py -o ./refstack-ui/app/components/about/templates ./doc/source/*.rst``
|
||||
|
||||
Ignore any unknown directive errors.
|
||||
|
||||
Start RefStack
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -41,7 +41,9 @@
|
||||
}).
|
||||
state('about', {
|
||||
url: '/about',
|
||||
templateUrl: '/components/about/about.html'
|
||||
templateUrl: '/components/about/about.html',
|
||||
controller: 'AboutController as ctrl'
|
||||
|
||||
}).
|
||||
state('guidelines', {
|
||||
url: '/guidelines',
|
||||
|
@ -226,3 +226,26 @@ a.glyphicon {
|
||||
.modal-body .row {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.about-sidebar {
|
||||
width: 20%;
|
||||
float: left;
|
||||
padding-right: 2px;
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
.about-content {
|
||||
width: 80%;
|
||||
float: left;
|
||||
padding-left: 5%;
|
||||
|
||||
}
|
||||
|
||||
.about-option {
|
||||
padding: 5px 5px 5px 10px;
|
||||
}
|
||||
|
||||
.about-active {
|
||||
background: #f2f2f2;
|
||||
border-left: 2px solid orange;
|
||||
}
|
@ -1,31 +1,13 @@
|
||||
<h1>RefStack Documentation</h1>
|
||||
|
||||
<p>RefStack is a source of tools for interoperability testing of OpenStack clouds.</p>
|
||||
<p>To learn more about RefStack, visit the links below.</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<a href="http://github.com/openstack/refstack/blob/master/README.rst#refstack"
|
||||
target="_blank"
|
||||
</a>
|
||||
<strong>About RefStack</strong>
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://github.com/openstack/refstack/blob/master/doc/source/uploading_private_results.rst#how-to-upload-test-results-to-refstack"
|
||||
target="_blank"
|
||||
</a>
|
||||
<strong>How to upload test results to RefStack</strong>
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://github.com/openstack/refstack/blob/master/doc/source/vendor_product.rst#vendor-and-product-management"
|
||||
target="_blank"
|
||||
</a>
|
||||
<strong>Vendor and product management</strong>
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://github.com/openstack/refstack/blob/master/doc/source/test_result_management.rst#test-result-management"
|
||||
target="_blank"
|
||||
</a>
|
||||
<strong>Test result management</strong>
|
||||
</li>
|
||||
</ol>
|
||||
<hr>
|
||||
<div class="about-sidebar">
|
||||
<div ng-repeat="(key, data) in ctrl.options | arrayConverter | orderBy: 'order'">
|
||||
<a><div class="about-option"
|
||||
ng-click="ctrl.selectOption(data.id)"
|
||||
ng-class="{ 'about-active': ctrl.selected === data.id }">
|
||||
{{data.title}}
|
||||
</div></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="about-content">
|
||||
<div ng-include src="ctrl.template"></div>
|
||||
</div>
|
||||
|
85
refstack-ui/app/components/about/aboutController.js
Normal file
85
refstack-ui/app/components/about/aboutController.js
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('refstackApp')
|
||||
.controller('AboutController', AboutController);
|
||||
|
||||
AboutController.$inject = ['$location'];
|
||||
|
||||
/**
|
||||
* RefStack About Controller
|
||||
* This controller handles the about page and the multiple templates
|
||||
* associated to the page.
|
||||
*/
|
||||
function AboutController($location) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.selectOption = selectOption;
|
||||
ctrl.getHash = getHash;
|
||||
|
||||
ctrl.options = {
|
||||
'about' : {
|
||||
'title': 'About RefStack',
|
||||
'template': 'components/about/templates/README.html',
|
||||
'order': 1
|
||||
},
|
||||
'uploading-your-results': {
|
||||
'title': 'Uploading Your Results',
|
||||
'template': 'components/about/templates/' +
|
||||
'uploading_private_results.html',
|
||||
'order': 2
|
||||
},
|
||||
'managing-results': {
|
||||
'title': 'Managing Results',
|
||||
'template': 'components/about/templates/' +
|
||||
'test_result_management.html',
|
||||
'order': 3
|
||||
},
|
||||
'vendors-and-products': {
|
||||
'title': 'Vendors and Products',
|
||||
'template': 'components/about/templates/vendor_product.html',
|
||||
'order': 4
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Given an option key, mark it as selected and set the corresponding
|
||||
* template and URL hash.
|
||||
*/
|
||||
function selectOption(key) {
|
||||
ctrl.selected = key;
|
||||
ctrl.template = ctrl.options[key].template;
|
||||
$location.hash(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hash in the URL and select it if possible.
|
||||
*/
|
||||
function getHash() {
|
||||
var hash = $location.hash();
|
||||
if (hash && hash in ctrl.options) {
|
||||
ctrl.selectOption(hash);
|
||||
}
|
||||
else {
|
||||
ctrl.selectOption('about');
|
||||
}
|
||||
}
|
||||
|
||||
ctrl.getHash();
|
||||
}
|
||||
})();
|
@ -40,6 +40,7 @@
|
||||
<script src="shared/header/headerController.js"></script>
|
||||
<script src="shared/alerts/alertModalFactory.js"></script>
|
||||
<script src="shared/alerts/confirmModalFactory.js"></script>
|
||||
<script src="components/about/aboutController.js"></script>
|
||||
<script src="components/guidelines/guidelinesController.js"></script>
|
||||
<script src="components/results/resultsController.js"></script>
|
||||
<script src="components/results-report/resultsReportController.js"></script>
|
||||
|
@ -58,6 +58,49 @@ describe('Refstack controllers', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('AboutController', function () {
|
||||
var $location, ctrl;
|
||||
|
||||
beforeEach(inject(function ($controller, _$location_) {
|
||||
$location = _$location_;
|
||||
ctrl = $controller('AboutController', {});
|
||||
ctrl.options = {
|
||||
'about' : {
|
||||
'title': 'About RefStack',
|
||||
'template': 'about-template'
|
||||
},
|
||||
'option1' : {
|
||||
'title': 'Option One',
|
||||
'template': 'template-1'
|
||||
}
|
||||
};
|
||||
}));
|
||||
|
||||
it('should have a function to select an option',
|
||||
function () {
|
||||
ctrl.selectOption('option1');
|
||||
expect(ctrl.selected).toBe('option1');
|
||||
expect(ctrl.template).toBe('template-1');
|
||||
expect($location.hash()).toBe('option1');
|
||||
});
|
||||
|
||||
it('should have a function to get the URL hash and select it',
|
||||
function () {
|
||||
// Test existing option.
|
||||
$location.url('/about#option1');
|
||||
ctrl.getHash();
|
||||
expect(ctrl.selected).toBe('option1');
|
||||
expect(ctrl.template).toBe('template-1');
|
||||
|
||||
// Test nonexistent option.
|
||||
$location.url('/about#foobar');
|
||||
ctrl.getHash();
|
||||
expect(ctrl.selected).toBe('about');
|
||||
expect(ctrl.template).toBe('about-template');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('GuidelinesController', function () {
|
||||
var ctrl;
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
SQLAlchemy>=0.8.3
|
||||
alembic==0.5.0
|
||||
beaker==1.6.5.post1
|
||||
beautifulsoup4
|
||||
cryptography>=1.0,!=1.3.0 # BSD/Apache-2.0
|
||||
docutils>=0.11
|
||||
oslo.config>=1.6.0 # Apache-2.0
|
||||
oslo.db>=1.4.1 # Apache-2.0
|
||||
oslo.log>=3.11.0
|
||||
|
75
tools/convert-docs.py
Executable file
75
tools/convert-docs.py
Executable file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2017 IBM, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Convert RST files to basic HTML. The primary use case is to provide a way
|
||||
to display RefStack documentation on the RefStack website.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import glob
|
||||
import os
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from docutils.core import publish_file
|
||||
|
||||
|
||||
def extract_body(html):
|
||||
"""Extract the content of the body tags of an HTML string."""
|
||||
soup = BeautifulSoup(html, "html.parser")
|
||||
return ''.join(['%s' % str(a) for a in soup.body.contents])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Convert RST files to basic HTML template files.'
|
||||
)
|
||||
parser.add_argument('files',
|
||||
metavar='file',
|
||||
nargs='+',
|
||||
help='RST file(s) to be converted to HTML templates.')
|
||||
parser.add_argument('-o', '--output_dir',
|
||||
required=False,
|
||||
help='The directory where template files should be '
|
||||
'output to. Defaults to the current directory.')
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.output_dir:
|
||||
output_dir = args.output_dir
|
||||
# If the output directory doesn't exist, create it.
|
||||
if not os.path.exists(output_dir):
|
||||
try:
|
||||
os.makedirs(output_dir)
|
||||
except OSError:
|
||||
if not os.path.isdir(output_dir):
|
||||
raise
|
||||
else:
|
||||
output_dir = os.getcwd()
|
||||
|
||||
for path in args.files:
|
||||
for file in glob.glob(path):
|
||||
base_file = os.path.splitext(os.path.basename(file))[0]
|
||||
|
||||
# Calling publish_file will also print to stdout. Destination path
|
||||
# is set to /dev/null to suppress this.
|
||||
html = publish_file(source_path=file,
|
||||
destination_path='/dev/null',
|
||||
writer_name='html',)
|
||||
body = extract_body(html)
|
||||
|
||||
output_file = os.path.join(output_dir, base_file + ".html")
|
||||
with open(output_file, "w") as template_file:
|
||||
template_file.write(body)
|
Loading…
x
Reference in New Issue
Block a user