Unit tests, fixes, and cleanup
This commit is contained in:
parent
402f319283
commit
0321b7128b
50 changed files with 56672 additions and 250 deletions
|
|
@ -20,8 +20,8 @@ indent_size = 4
|
|||
indent_style = tab
|
||||
tab_width = 8
|
||||
|
||||
# CHTML: 2-space indents
|
||||
[**/*.chtml]
|
||||
# jinja html: 2-space indents
|
||||
[**/*.html.j2]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ def get_options():
|
|||
# parser.add_option('--pdb', action='store_true',
|
||||
# help='drop into pdb on error')
|
||||
parser.add_option('--user', '-u', help='fake login as user')
|
||||
parser.add_option('--time', '-t', type="float", help='mock time as value')
|
||||
parser.add_option('-o', '--config-option', help='override config option',
|
||||
action='append', metavar='NAME=VALUE')
|
||||
opts, args = parser.parse_args()
|
||||
|
|
@ -189,6 +190,17 @@ def main():
|
|||
override_load_config(options.config_option)
|
||||
if options.user:
|
||||
fake_login(options.user)
|
||||
if options.time:
|
||||
from unittest import mock
|
||||
import datetime
|
||||
dt = datetime.datetime.fromtimestamp(options.time)
|
||||
mock.patch('time.time', return_value=options.time).start()
|
||||
# mocking datetime is tricky, can't mock the c object directly
|
||||
# and can't mock the datetime class globally without breaking other code
|
||||
# so we just mock the handlers import of it
|
||||
my_datetime = mock.patch.object(kojiweb_handlers.kojiweb.util, 'datetime', wraps=datetime).start()
|
||||
my_datetime.datetime.now.return_value = dt
|
||||
|
||||
# koji.add_file_logger('koji', 'fakeweb.log')
|
||||
httpd = make_server('', 8000, application)
|
||||
print("Serving kojiweb on http://localhost:8000 ...")
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ Koji is comprised of several components:
|
|||
koji-hub via XML-RPC.
|
||||
|
||||
- **koji-web** is a set of scripts that run in mod\_wsgi and use the
|
||||
Cheetah templating engine to provide an web interface to Koji.
|
||||
Jinja templating engine to provide an web interface to Koji.
|
||||
koji-web exposes a lot of information and also provides a means for
|
||||
certain operations, such as cancelling builds.
|
||||
- **koji** is a CLI written in Python that provides many hooks into Koji.
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ and communicates with koji-hub via XML-RPC.
|
|||
|
||||
Koji-Web
|
||||
--------
|
||||
koji-web is a set of scripts that run in mod_wsgi and use the Cheetah
|
||||
koji-web is a set of scripts that run in mod_wsgi and use the Jinja
|
||||
templating engine to provide a web interface to Koji. It acts as a client to
|
||||
koji-hub providing a visual interface to perform a limited amount of
|
||||
administration. koji-web exposes a lot of information and also provides a means
|
||||
|
|
|
|||
|
|
@ -895,7 +895,7 @@ The following command will test your login to the hub:
|
|||
Koji Web - Interface for the Masses
|
||||
===================================
|
||||
|
||||
Koji-web is a set of scripts that run in mod_wsgi and use the Cheetah
|
||||
Koji-web is a set of scripts that run in mod_wsgi and use the Jinja
|
||||
templating engine to provide an web interface to Koji. koji-web exposes a lot
|
||||
of information and also provides a means for certain operations, such as
|
||||
cancelling builds.
|
||||
|
|
|
|||
|
|
@ -565,16 +565,16 @@ can be turned on in ``/etc/kojid/kojid.conf``.
|
|||
Koji-Web
|
||||
--------
|
||||
|
||||
koji-web is a set of scripts that run in mod\_wsgi and use the Cheetah
|
||||
koji-web is a set of scripts that run in mod\_wsgi and use the Jinja
|
||||
templating engine to provide a web interface to Koji. It acts as a
|
||||
client to koji-hub providing a visual interface to perform a limited
|
||||
amount of administration. koji-web exposes a lot of information and also
|
||||
provides a means for certain operations, such as cancelling builds.
|
||||
|
||||
The web pages are derived from Cheetah templates, the syntax of which
|
||||
The web pages are derived from Jinja templates, the syntax of which
|
||||
you can read up on
|
||||
`here <http://cheetahtemplate.org/users_guide/>`__. These
|
||||
templates are the ``chtml`` files sitting in ``www/kojiweb``. You'll
|
||||
`here <https://jinja.palletsprojects.com/>`__. These
|
||||
templates are the ``html.j2`` files sitting in ``www/kojiweb``. You'll
|
||||
notice quickly that these templates are referencing variables, but where
|
||||
do they come from?
|
||||
|
||||
|
|
@ -582,26 +582,12 @@ The ``www/kojiweb/index.py`` file provides them. There are several
|
|||
functions named after the templates they support, and in each one a
|
||||
dictionary called ``values`` is populated. This is how data is gathered
|
||||
about the task, build, archive, or whatever the page is about. Take your
|
||||
time with ``taskinfo.chtml`` in particular, as the conditionals there
|
||||
time with ``taskinfo.html.j2`` in particular, as the conditionals there
|
||||
have gotten quite long. If you are adding a new task to Koji, you will
|
||||
need to extend this at a minimum. A new type of build task would require
|
||||
this, and possibly another that is specific to viewing the archived
|
||||
information about the build. (taskinfo vs. buildinfo)
|
||||
|
||||
If your web page needs to display the contents of a list or dictionary,
|
||||
use the ``$printMap`` function to help with that. It is often sensible
|
||||
to define a function that easily prints options and values in a
|
||||
dictionary. An example of this is in taskinfo.chtml.
|
||||
|
||||
::
|
||||
|
||||
#def printOpts($opts)
|
||||
#if $opts
|
||||
<strong>Options:</strong><br/>
|
||||
$printMap($opts, ' ')
|
||||
#end if
|
||||
#end def
|
||||
|
||||
Finally, if you need to expand the drop-down menus of "method" types
|
||||
when searching for tasks in the WebUI, you will need to add them to the
|
||||
``_TASKS`` list in ``www/kojiweb/index.py``. Add values where
|
||||
|
|
|
|||
|
|
@ -289,6 +289,7 @@ Requires: python%{python3_pkgversion}-%{name} = %{version}-%{release}
|
|||
Requires: python%{python3_pkgversion}-librepo
|
||||
Requires: python%{python3_pkgversion}-multilib
|
||||
Requires: python%{python3_pkgversion}-cheetah
|
||||
# cheetah required for backwards compatibility in wrapperRPM task
|
||||
%else
|
||||
Requires: python2-%{name} = %{version}-%{release}
|
||||
Requires: python2-multilib
|
||||
|
|
@ -359,7 +360,7 @@ Requires: httpd
|
|||
Requires: python%{python3_pkgversion}-mod_wsgi
|
||||
Requires: mod_auth_gssapi
|
||||
Requires: python%{python3_pkgversion}-psycopg2
|
||||
Requires: python%{python3_pkgversion}-cheetah
|
||||
Requires: python%{python3_pkgversion}-jinja2
|
||||
Requires: python%{python3_pkgversion}-%{name} = %{version}-%{release}
|
||||
Provides: %{name}-web-code = %{version}-%{release}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ try:
|
|||
from unittest import mock
|
||||
except ImportError:
|
||||
import mock
|
||||
import json
|
||||
import koji
|
||||
|
||||
from koji.xmlrpcplus import Fault
|
||||
from koji.xmlrpcplus import Fault, DateTime
|
||||
|
||||
|
||||
class BaseFakeClientSession(koji.ClientSession):
|
||||
|
|
@ -22,9 +23,11 @@ class BaseFakeClientSession(koji.ClientSession):
|
|||
self._calls = []
|
||||
for call in calls:
|
||||
method = call['methodName']
|
||||
args, kwargs = koji.decode_args(call['params'])
|
||||
args, kwargs = koji.decode_args(*call['params'])
|
||||
try:
|
||||
result = self._callMethod(method, args, kwargs)
|
||||
# multicall wraps non-fault results in a singleton
|
||||
result = (result,)
|
||||
ret.append(result)
|
||||
except Fault as fault:
|
||||
if strict:
|
||||
|
|
@ -58,6 +61,12 @@ class FakeClientSession(BaseFakeClientSession):
|
|||
key = self._munge([call['method'], call['args'], call['kwargs']])
|
||||
self._calldata.setdefault(key, []).append(call)
|
||||
|
||||
def load(self, filename):
|
||||
# load from json file
|
||||
with open(filename, 'rt') as fp:
|
||||
data = json.load(fp, object_hook=decode_data)
|
||||
self.load_calls(data)
|
||||
|
||||
def _callMethod(self, name, args, kwargs=None, retry=True):
|
||||
if self.multicall:
|
||||
return super(FakeClientSession, self)._callMethod(name, args,
|
||||
|
|
@ -103,6 +112,12 @@ class RecordingClientSession(BaseFakeClientSession):
|
|||
def get_calls(self):
|
||||
return self._calldata
|
||||
|
||||
def dump(self, filename):
|
||||
with open(filename, 'wt') as fp:
|
||||
# json.dump(self._calldata, fp, indent=4, sort_keys=True)
|
||||
json.dump(self._calldata, fp, indent=4, sort_keys=True, default=encode_data)
|
||||
self._calldata = []
|
||||
|
||||
def _callMethod(self, name, args, kwargs=None, retry=True):
|
||||
if self.multicall:
|
||||
return super(RecordingClientSession, self)._callMethod(name, args,
|
||||
|
|
@ -128,3 +143,24 @@ class RecordingClientSession(BaseFakeClientSession):
|
|||
'faultString': str(e)}
|
||||
call['fault'] = err
|
||||
raise
|
||||
|
||||
|
||||
def encode_data(value):
|
||||
"""Encode data for json"""
|
||||
if isinstance(value, DateTime):
|
||||
return {'__type': 'DateTime', 'value': value.value}
|
||||
else:
|
||||
raise TypeError('Unknown type for json encoding')
|
||||
|
||||
|
||||
def decode_data(value):
|
||||
"""Decode data encoded for json"""
|
||||
if isinstance(value, dict):
|
||||
_type = value.get('__type')
|
||||
if _type == 'DateTime':
|
||||
return DateTime(value['value'])
|
||||
#else
|
||||
return value
|
||||
|
||||
|
||||
# the end
|
||||
|
|
|
|||
56146
tests/test_www/data/pages_calls.json
Normal file
56146
tests/test_www/data/pages_calls.json
Normal file
File diff suppressed because one or more lines are too long
207
tests/test_www/test_pages.py
Normal file
207
tests/test_www/test_pages.py
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
from __future__ import absolute_import
|
||||
import inspect
|
||||
import json
|
||||
try:
|
||||
from unittest import mock
|
||||
except ImportError:
|
||||
import mock
|
||||
import os
|
||||
import six
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from six.moves import StringIO
|
||||
|
||||
import koji
|
||||
from koji_cli.lib import watch_tasks
|
||||
from koji_cli.commands import anon_handle_watch_task
|
||||
from koji.util import dslice
|
||||
from ..test_cli.fakeclient import FakeClientSession, RecordingClientSession, encode_data
|
||||
from .loadwebindex import webidx
|
||||
from kojiweb.util import FieldStorageCompat
|
||||
|
||||
|
||||
class TestPages(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# recording session used across tests in recording mode
|
||||
cls.cfile = os.path.dirname(__file__) + f'/data/pages_calls.json'
|
||||
cls.recording = False
|
||||
cls.rsession = RecordingClientSession('http://localhost/kojihub', {})
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if cls.recording:
|
||||
# save recorded calls
|
||||
cls.rsession.dump(cls.cfile)
|
||||
|
||||
def setUp(self):
|
||||
self.environ = {
|
||||
'koji.options': {
|
||||
'SiteName': 'test',
|
||||
'KojiFilesURL': 'http://server.local/files',
|
||||
'KojiHubURL': 'http://server.local/kojihub',
|
||||
'KojiGreeting': 'Welcome to Koji Web',
|
||||
'LoginDisabled': True,
|
||||
'Tasks': [],
|
||||
'ToplevelTasks': [],
|
||||
'ParentTasks': [],
|
||||
'MBS_WEB_URL': None,
|
||||
},
|
||||
'koji.currentUser': None,
|
||||
'SCRIPT_FILENAME': webidx.__file__, # close enough
|
||||
'SCRIPT_NAME': '',
|
||||
'SERVER_PORT': '80',
|
||||
'SERVER_NAME': 'server.local',
|
||||
'wsgi.url_scheme': 'http',
|
||||
'koji.headers': [],
|
||||
}
|
||||
self.get_server = mock.patch.object(webidx, "_getServer").start()
|
||||
self._assertLogin = mock.patch.object(webidx, "_assertLogin").start()
|
||||
self.server = None # set up setup_server
|
||||
|
||||
# mock time so that call args are reproduced
|
||||
self.time = mock.patch('time.time').start()
|
||||
self.time.return_value = 1735707600.0
|
||||
|
||||
def __get_server(env):
|
||||
return self.server
|
||||
|
||||
self.get_server.side_effect = __get_server
|
||||
self.setup_server()
|
||||
|
||||
def setup_server(self):
|
||||
if self.recording:
|
||||
self.server = self.rsession
|
||||
else:
|
||||
self.server = FakeClientSession('SERVER', {})
|
||||
self.server.load(self.cfile)
|
||||
return self.server
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
# Show long diffs in error output...
|
||||
maxDiff = None
|
||||
|
||||
CALLS = [
|
||||
['index', ''],
|
||||
['packages', ''],
|
||||
['packages', 'prefix=m&order=package_name&inherited=1&blocked=1'],
|
||||
['packages', 'start=50&order=package_name&inherited=1&blocked=1'],
|
||||
['builds', ''],
|
||||
['builds', 'start=50&order=-build_id'],
|
||||
['builds', 'prefix=d&order=-build_id'],
|
||||
['builds', 'state=4&prefix=d&order=-build_id'],
|
||||
['builds', 'type=image&prefix=d&order=-build_id'],
|
||||
['tasks', ''],
|
||||
['tasks', 'state=all&view=tree&order=-id&method=all'],
|
||||
['tasks', 'state=failed&view=tree&order=-id&method=all'],
|
||||
['tasks', 'view=flat&state=failed&order=-id&method=all'],
|
||||
['tasks', 'method=buildArch&view=flat&state=failed&order=-id'],
|
||||
['tasks', 'owner=mikem&view=flat&state=failed&order=-id&method=buildArch'],
|
||||
['tags', ''],
|
||||
['tags', 'start=50&order=name'],
|
||||
['buildtargets', ''],
|
||||
['buildtargets', 'order=-id'],
|
||||
['users', ''],
|
||||
['users', 'prefix=m&order=name'],
|
||||
['hosts', ''],
|
||||
['hosts', 'ready=yes&channel=all&state=all&order=name&arch=all'],
|
||||
['hosts', 'channel=appliance&ready=all&state=all&order=name&arch=all'],
|
||||
['hosts', 'arch=x86_64&channel=appliance&ready=all&state=all&order=name'],
|
||||
['reports', ''],
|
||||
['packagesbyuser', ''],
|
||||
['buildsbyuser', ''],
|
||||
['rpmsbyhost', ''],
|
||||
['tasksbyuser', ''],
|
||||
['tasksbyhost', ''],
|
||||
['buildsbystatus', ''],
|
||||
['buildsbytarget', ''],
|
||||
['clusterhealth', ''],
|
||||
['search', ''],
|
||||
['search', 'terms=k*&type=package&match=glob'],
|
||||
['api', ''],
|
||||
['userinfo', 'userID=1'],
|
||||
['activesession', ''],
|
||||
['archiveinfo', 'archiveID=202'],
|
||||
['buildinfo', 'buildID=628'],
|
||||
['rpminfo', 'rpmID=6608'],
|
||||
['buildrootinfo', 'buildrootID=966'],
|
||||
['buildinfo', 'buildID=574'],
|
||||
['buildrootinfo', 'buildrootID=934'],
|
||||
['repoinfo', 'repoID=2580'],
|
||||
['buildroots', 'repoID=2580'],
|
||||
['buildroots', 'state=3&repoID=2580&order=id'],
|
||||
['buildtargetedit', 'targetID=107&a='],
|
||||
['buildtargetinfo', 'targetID=107'],
|
||||
['taskinfo', 'taskID=14330'],
|
||||
['channelinfo', 'channelID=1'],
|
||||
#['channelinfo', 'channelID=MISSING'],
|
||||
['taginfo', 'tagID=798'],
|
||||
['externalrepoinfo', 'extrepoID=1'],
|
||||
['fileinfo', 'rpmID=6608&filename=/etc/koji.conf'],
|
||||
['hostinfo', 'hostID=1'],
|
||||
['hostedit', 'hostID=1&a='],
|
||||
['notificationcreate', 'a='],
|
||||
['notificationedit', 'notificationID=1&a='],
|
||||
['packageinfo', 'packageID=306'],
|
||||
['recentbuilds', ''],
|
||||
['recentbuilds', 'package=1'],
|
||||
['repoinfo', 'repoID=88'],
|
||||
['rpminfo', 'rpmID=6608'],
|
||||
['rpmlist', 'buildrootID=657&type=component'],
|
||||
['taginfo', 'tagID=2'],
|
||||
['tagedit', 'tagID=2&a='],
|
||||
['tagparent', 'tagID=2&parentID=1&action=edit&a='],
|
||||
['taginfo', 'tagID=2090'],
|
||||
['userinfo', 'userID=1'],
|
||||
['taskinfo', 'taskID=1'],
|
||||
['archivelist', 'buildrootID=363&type=built'],
|
||||
['buildinfo', 'buildID=422'],
|
||||
['archiveinfo', 'archiveID=130'],
|
||||
['archivelist', 'buildrootID=345&type=built'],
|
||||
['buildinfo', 'buildID=612'],
|
||||
['buildroots', ''],
|
||||
['buildroots', 'start=50&order=id'],
|
||||
#['builds', 'start=50&order=id'],
|
||||
]
|
||||
|
||||
def prep_handler(self, method, query):
|
||||
"""Takes method name and query string, returns handler and data"""
|
||||
# based loosely on publisher prep_handler
|
||||
self.environ['QUERY_STRING'] = query
|
||||
self.environ['koji.method'] = method
|
||||
self.environ['SCRIPT_NAME'] = method
|
||||
handler = getattr(webidx, method)
|
||||
fs = FieldStorageCompat(self.environ)
|
||||
self.environ['koji.form'] = fs
|
||||
# even though we have curated urls, we need to filter args for some cases, e.g. search
|
||||
args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
|
||||
inspect.getfullargspec(handler)
|
||||
if not varkw:
|
||||
data = dslice(fs.data, args, strict=False)
|
||||
else:
|
||||
data = fs.data.copy()
|
||||
return handler, data
|
||||
|
||||
def test_web_handlers(self):
|
||||
"""Test a bunch of web handlers"""
|
||||
for method, query in self.CALLS:
|
||||
handler, data = self.prep_handler(method, query)
|
||||
|
||||
result = handler(self.environ, **data)
|
||||
|
||||
# result should be a string containing the rendered template
|
||||
self.assertIsInstance(result, str)
|
||||
# none of these should return the error template
|
||||
self.assertNotIn(r'<h4>Error</h4>', result)
|
||||
# all except recentbuilds (rss) should render the header and footer
|
||||
if method != 'recentbuilds':
|
||||
self.assertIn(r'<div id="header">', result)
|
||||
self.assertIn(r'<div id="mainNav">', result)
|
||||
self.assertIn(r'<p id="footer">', result)
|
||||
|
||||
|
||||
# the end
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
#set _PASSTHROUGH = ['userID']
|
||||
|
||||
|
|
@ -14,7 +15,7 @@
|
|||
<th><a href="activesession?order={{ util.toggleOrder('id') }}{{ util.passthrough_except('order') }}">Logout?</a> {{ util.sortImage('id') }}</th>
|
||||
</tr>
|
||||
#for act in activesess
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td>{{ act.id }}</td>
|
||||
<td>{{ act.hostip }}</td>
|
||||
<td>{{ act.authtype }}</td>
|
||||
|
|
@ -24,3 +25,5 @@
|
|||
</tr>
|
||||
#endfor
|
||||
</table>
|
||||
|
||||
#include "includes/footer.html.j2"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#set _PASSTHROUGH = ['archiveID', 'fileOrder', 'fileStart', 'buildrootOrder', 'buildrootStart']
|
||||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
<h4>Information for archive <a href="archiveinfo?archiveID={{ archive.id }}">{{ archive.filename }}</a></h4>
|
||||
|
||||
<table>
|
||||
|
|
@ -92,7 +93,7 @@
|
|||
<th><a href="archiveinfo?fileOrder={{ util.toggleOrder('size', 'fileOrder') }}{{ util.passthrough_except('fileOrder', 'fileStart') }}#filelist">Size</a> {{ util.sortImage('size', 'fileOrder') }}</th>
|
||||
</tr>
|
||||
#for file in files
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="fileinfo?archiveID={{ archive.id }}&filename={{ file.name|urlencode }}">{{ file.name }}</a></td><td><span title="{{ util.formatThousands(file.size) }}">{{ util.formatNatural(file.size) }}</span></td>
|
||||
</tr>
|
||||
#endfor
|
||||
|
|
@ -132,7 +133,7 @@
|
|||
<th><a href="archiveinfo?buildrootOrder={{ util.toggleOrder('state', 'buildrootOrder') }}{{ util.passthrough_except('buildrootOrder', 'buildrootStart') }}#buildrootlist">State</a> {{ util.sortImage('state', 'buildrootOrder') }}</th>
|
||||
</tr>
|
||||
#for buildroot in buildroots
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="buildrootinfo?buildrootID={{ buildroot.id }}">{{ util.brLabel(buildroot) }}</a></td>
|
||||
<td>{{ util.formatTime(buildroot.create_event_time) }}</td>
|
||||
<td>{{ util.imageTag(util.brStateName(buildroot.state)) }}</td>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
#macro getID()
|
||||
#if type == 'image'
|
||||
|
|
@ -50,7 +51,7 @@ buildrootID={{ buildroot.id }}
|
|||
</tr>
|
||||
#if (archives |length) > 0
|
||||
#for archive in archives
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="archiveinfo?archiveID={{ archive.id }}">{{ archive.filename }}</a></td>
|
||||
<td>{{ archive.type_name }}</td>
|
||||
#if type == 'component'
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<th>Release</th><td>{{ build.release }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Epoch</th><td>{{ build.epoch }}</td>
|
||||
<th>Epoch</th><td>{{ build.epoch if build.epoch is not none else '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
#if build.draft
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#set _PASSTHROUGH = ['repoID', 'order', 'state']
|
||||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Buildroots in repo <a href="repoinfo?repoID={{ repoID }}">{{ repoID }}</a></h4>
|
||||
|
||||
|
|
@ -26,7 +27,7 @@
|
|||
#if (buildrootPages |length) > 1
|
||||
<form class="pageJump" action="">
|
||||
Page:
|
||||
<select onchange="javascript: window.location = 'builds?start=' + this.value * {{ buildrootRange }} + '{{ util.passthrough_except() }}';">
|
||||
<select onchange="javascript: window.location = 'buildroots?start=' + this.value * {{ buildrootRange }} + '{{ util.passthrough_except() }}';">
|
||||
#for pageNum in buildrootPages
|
||||
<option value="{{ pageNum }}"{{ ' selected' if pageNum == buildrootCurrentPage else '' }}>{{ pageNum + 1 }}</option>
|
||||
#endfor
|
||||
|
|
@ -34,13 +35,13 @@
|
|||
</form>
|
||||
#endif
|
||||
#if buildrootStart > 0
|
||||
<a href="builds?start={{ buildrootStart - buildrootRange }}{{ util.passthrough_except() }}"><<<</a>
|
||||
<a href="buildroots?start={{ buildrootStart - buildrootRange }}{{ util.passthrough_except() }}"><<<</a>
|
||||
#endif
|
||||
#if totalBuildroots != 0
|
||||
<strong>Buildroots {{ buildrootStart + 1 }} through {{ buildrootStart + buildrootCount }} of {{ totalBuildroots }}</strong>
|
||||
#endif
|
||||
#if buildrootStart + buildrootCount < totalBuildroots
|
||||
<a href="builds?start={{ buildrootStart + buildrootRange }}{{ util.passthrough_except() }}">>>></a>
|
||||
<a href="buildroots?start={{ buildrootStart + buildrootRange }}{{ util.passthrough_except() }}">>>></a>
|
||||
#endif
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -53,7 +54,7 @@
|
|||
</tr>
|
||||
#if (buildroots |length) > 0
|
||||
#for buildroot in buildroots
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="buildrootinfo?buildrootID={{ buildroot.id }}">{{ buildroot.id }}</a></td>
|
||||
<td><a href="repoinfo?repoID={{ buildroot.repo_id }}">{{ buildroot.repo_id }}</a></td>
|
||||
<td><a href="taskinfo?taskID={{ buildroot.task_id }}">{{ buildroot.task_id }}</a></td>
|
||||
|
|
@ -72,7 +73,7 @@
|
|||
#if (buildrootPages |length) > 1
|
||||
<form class="pageJump" action="">
|
||||
Page:
|
||||
<select onchange="javascript: window.location = 'builds?start=' + this.value * {{ buildrootRange }} + '{{ util.passthrough_except() }}';">
|
||||
<select onchange="javascript: window.location = 'buildroots?start=' + this.value * {{ buildrootRange }} + '{{ util.passthrough_except() }}';">
|
||||
#for pageNum in buildrootPages
|
||||
<option value="{{ pageNum }}"{{ ' selected' if pageNum == buildrootCurrentPage else '' }}>{{ pageNum + 1 }}</option>
|
||||
#endfor
|
||||
|
|
@ -80,13 +81,13 @@
|
|||
</form>
|
||||
#endif
|
||||
#if buildrootStart > 0
|
||||
<a href="builds?start={{ buildrootStart - buildrootRange }}{{ util.passthrough_except() }}"><<<</a>
|
||||
<a href="buildroots?start={{ buildrootStart - buildrootRange }}{{ util.passthrough_except() }}"><<<</a>
|
||||
#endif
|
||||
#if totalBuildroots != 0
|
||||
<strong>Buildroots {{ buildrootStart + 1 }} through {{ buildrootStart + buildrootCount }} of {{ totalBuildroots }}</strong>
|
||||
#endif
|
||||
#if buildrootStart + buildrootCount < totalBuildroots
|
||||
<a href="builds?start={{ buildrootStart + buildrootRange }}{{ util.passthrough_except() }}">>>></a>
|
||||
<a href="buildroots?start={{ buildrootStart + buildrootRange }}{{ util.passthrough_except() }}">>>></a>
|
||||
#endif
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#set _PASSTHROUGH = ['userID', 'tagID', 'packageID', 'order', 'prefix', 'state', 'inherited', 'latest', 'type']
|
||||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
#macro getDescription()
|
||||
#if latest
|
||||
|
|
@ -142,7 +143,7 @@ in tag <a href="taginfo?tagID={{ tag.id }}">{{ tag.name }}</a>
|
|||
</tr>
|
||||
#if (builds |length) > 0
|
||||
#for build in builds
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td>{{ build.build_id }}</td>
|
||||
<td><a href="buildinfo?buildID={{ build.build_id }}">{{ koji.buildLabel(build) }}</a></td>
|
||||
#if tag
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#endmacro
|
||||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Builds by Target{{ ' in the last %i days' % days if days != -1 else '' }}</h4>
|
||||
<table class="data-list">
|
||||
|
|
@ -59,7 +60,7 @@
|
|||
</tr>
|
||||
#if (targets |length) > 0
|
||||
#for target in targets
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="buildtargetinfo?name={{ target.name|urlencode }}">{{ target.name }}</a></td>
|
||||
<td width="{{ graphWidth + 5 }}"><img src={{ util.themePath('images/1px.gif') }} width="{{ increment * target.builds }}" height="15" class="graphrow" alt="graph row"/></td>
|
||||
<td>{{ target.builds }}</td>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Builds by User</h4>
|
||||
<table class="data-list">
|
||||
|
|
@ -33,7 +34,7 @@
|
|||
</tr>
|
||||
#if (userBuilds |length) > 0
|
||||
#for userBuild in userBuilds
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="userinfo?userID={{ userBuild.id }}">{{ userBuild.name }}</a></td>
|
||||
<td width="{{ graphWidth + 5 }}"><img src="{{ util.themePath('images/1px.gif') }}" width="{{ increment * userBuild.builds }}" height="15" class="graphrow" alt="graph row"/></td>
|
||||
<td>{{ userBuild.builds }}</td>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Build Targets</h4>
|
||||
<table class="data-list">
|
||||
|
|
@ -32,7 +33,7 @@
|
|||
</tr>
|
||||
#if (targets |length) > 0
|
||||
#for target in targets
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td>{{ target.id }}</td>
|
||||
<td><a href="buildtargetinfo?targetID={{ target.id }}">{{ target.name }}</a></td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Information for channel <a href="channelinfo?channelID={{ channel.id }}">{{ channel.name }}</a></h4>
|
||||
|
||||
|
|
@ -11,7 +12,7 @@
|
|||
<th>ID</th><td>{{ channel.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description</th><td>{{ channel.description }}</td>
|
||||
<th>Description</th><td>{{ channel.description or '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
#set enabled = channel.enabled and 'yes' or 'no'
|
||||
|
|
@ -21,7 +22,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Comment</th><td>{{ channel.comment }}</td>
|
||||
<th>Comment</th><td>{{ channel.comment or '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Active Tasks</th><td><a href="tasks?view=flat&channelID={{ channel.id }}">{{ taskCount }}</a></td>
|
||||
|
|
@ -37,7 +38,7 @@
|
|||
<th>Ready</th>
|
||||
</tr>
|
||||
#for host in hosts
|
||||
<tr class="{{ util.rowToggle }}({{ self }})">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="hostinfo?hostID={{ host.id }}">{{ host.name }}</a></td>
|
||||
<td class="{{ host.enabled |string |lower }}">{{ util.imageTag('yes') if host.enabled else util.imageTag('no') }}</td>
|
||||
<td class="{{ host.ready |string |lower }}">{{ util.imageTag('yes') if host.ready else util.imageTag('no') }}</td>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
#set epoch = (rpm.epoch != None and str(rpm.epoch) + ':' or '')
|
||||
<th>RPM</th><td><a href="rpminfo?rpmID={{ rpm.id }}">{{ rpm.name }}-{{ epoch }}{{ rpm.version }}-{{ rpm.release }}{{ rpm.arch }}.rpm</a></td>
|
||||
<th>RPM</th><td><a href="rpminfo?rpmID={{ rpm.id }}">{{ rpm.name }}-{{ epoch }}{{ rpm.version }}-{{ rpm.release }}.{{ rpm.arch }}.rpm</a></td>
|
||||
</tr>
|
||||
#elif archive
|
||||
<tr>
|
||||
|
|
|
|||
|
|
@ -27,15 +27,15 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<td><textarea name="description" rows="6" cols="50">{{ host.description }}</textarea></td>
|
||||
<td><textarea name="description" rows="6" cols="50">{{ host.description or '' }}</textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Comment</th>
|
||||
<td><textarea name="comment" rows="2" cols="50">{{ host.comment }}</textarea></td>
|
||||
<td><textarea name="comment" rows="2" cols="50">{{ host.comment or '' }}</textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Enabled?</th>
|
||||
<td><input type="checkbox" name="enabled" value="yes" {{ 'checked="checked"' if host.enabled else '' }}/>
|
||||
<td><input type="checkbox" name="enabled" value="yes"{{ ' checked' if host.enabled else '' }}/>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Channels</th>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Information for host <a href="hostinfo?hostID={{ host.id }}">{{ host.name }}</a></h4>
|
||||
|
||||
|
|
@ -20,10 +21,10 @@
|
|||
<th>Task Load</th><td><a href="tasks?hostID={{ host.id }}">{{ '%.2f' % host.task_load }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description</th><td class="usertext">{{ host.description }}</td>
|
||||
<th>Description</th><td class="usertext">{{ host.description or '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Comment</th><td class="usertext">{{ host.comment }}</td>
|
||||
<th>Comment</th><td class="usertext">{{ host.comment or '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
#set enabled = host.enabled and 'yes' or 'no'
|
||||
|
|
@ -66,7 +67,7 @@
|
|||
<th>Buildroot</th><th>Created</th><th>State</th>
|
||||
</tr>
|
||||
#for buildroot in buildroots
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="buildrootinfo?buildrootID={{ buildroot.id }}">{{ buildroot.tag_name }}-{{ buildroot.id }}-{{ buildroot.repo_id }}</a></td>
|
||||
<td>{{ util.formatTime(buildroot.create_event_time) }}</td>
|
||||
<td>{{ util.imageTag(util.brStateName(buildroot.state)) }}</td>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ in {{ channel }} channel
|
|||
#set _PASSTHROUGH = ['state', 'order', 'ready', 'channel', 'arch']
|
||||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>{{ headerState(state) }} {{ headerReady(ready) }} {{ headerArch(arch) }} {{ headerChannel(channel) }}</h4>
|
||||
<table class="data-list">
|
||||
|
|
@ -119,7 +120,7 @@ in {{ channel }} channel
|
|||
</tr>
|
||||
#if (hosts |length) > 0
|
||||
#for host in hosts
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td>{{ host.id }}</td>
|
||||
<td><a href="hostinfo?hostID={{ host.id }}">{{ host.name }}</a></td>
|
||||
<td>{{ host.arches }}</td>
|
||||
|
|
|
|||
|
|
@ -23,19 +23,19 @@
|
|||
<form action="search" id="headerSearch">
|
||||
<input type="hidden" name="match" value="glob"/>
|
||||
<select name="type">
|
||||
<option {{ toggleSelected("", type, "package") }} value="package">Packages</option>
|
||||
<option {{ toggleSelected("", type, "build") }} value="build">Builds</option>
|
||||
<option {{ toggleSelected("", type, "tag") }} value="tag">Tags</option>
|
||||
<option {{ toggleSelected("", type, "target") }} value="target">Build Targets</option>
|
||||
<option {{ toggleSelected("", type, "user") }} value="user">Users</option>
|
||||
<option {{ toggleSelected("", type, "host") }} value="host">Hosts</option>
|
||||
<option {{ toggleSelected("", type, "rpm") }} value="rpm">RPMs</option>
|
||||
{% if mavenEnabled %}
|
||||
<option {{ toggleSelected("", type, "maven") }} value="maven">Maven Artifacts</option>
|
||||
{% endif %}
|
||||
{% if winEnabled %}
|
||||
<option {{ toggleSelected("", type, "win") }} value="win">Windows Artifacts</option>
|
||||
{% endif %}
|
||||
<option {{ toggleSelected(type, "package") }} value="package">Packages</option>
|
||||
<option {{ toggleSelected(type, "build") }} value="build">Builds</option>
|
||||
<option {{ toggleSelected(type, "tag") }} value="tag">Tags</option>
|
||||
<option {{ toggleSelected(type, "target") }} value="target">Build Targets</option>
|
||||
<option {{ toggleSelected(type, "user") }} value="user">Users</option>
|
||||
<option {{ toggleSelected(type, "host") }} value="host">Hosts</option>
|
||||
<option {{ toggleSelected(type, "rpm") }} value="rpm">RPMs</option>
|
||||
{%- if mavenEnabled %}
|
||||
<option {{ toggleSelected(type, "maven") }} value="maven">Maven Artifacts</option>
|
||||
{%- endif %}
|
||||
{%- if winEnabled %}
|
||||
<option {{ toggleSelected(type, "win") }} value="win">Windows Artifacts</option>
|
||||
{%- endif %}
|
||||
</select>
|
||||
<input type="text" name="terms" title="You can use glob expressions here (e.g. 'bash-*')" value="{{ terms }}"/>
|
||||
<input type="submit" value="Search"/>
|
||||
|
|
@ -62,14 +62,15 @@
|
|||
|
||||
<span id="loginInfo">
|
||||
{{ date_str }}
|
||||
{% if not LoginDisabled %}
|
||||
{%- if not LoginDisabled %}
|
||||
|
|
||||
{% if currentUser %}
|
||||
{%- if currentUser %}
|
||||
{{ greeting }}, <a href="userinfo?userID={{ currentUser.id }}">{{ currentUser.name }}</a> | <a href="logout">logout</a>
|
||||
{% else %}
|
||||
{%- else %}
|
||||
<a href="login">login</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
</span>
|
||||
|
||||
<div id="content">
|
||||
|
||||
|
|
|
|||
11
www/kojiweb/includes/macros.html.j2
Normal file
11
www/kojiweb/includes/macros.html.j2
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{%- set TOGGLE = cycler('row-odd', 'row-even') %}
|
||||
|
||||
{%- macro rowToggle(loop=None) %}
|
||||
{%- if loop is not none %}
|
||||
{{- loop.cycle('row-odd', 'row-even') }}
|
||||
{%- else %}
|
||||
{# use the global one #}
|
||||
{{- TOGGLE.next() }}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<div class="pageHeader">{{ welcomeMessage }}</div>
|
||||
|
||||
|
|
@ -15,7 +16,7 @@
|
|||
<th>State</th>
|
||||
</tr>
|
||||
#for build in builds
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
#set stateName = util.stateName(build.state)
|
||||
<td>{{ build.build_id }}</td>
|
||||
<td><a href="buildinfo?buildID={{ build.build_id }}">{{ build.nvr }}</a></td>
|
||||
|
|
@ -49,7 +50,7 @@
|
|||
</tr>
|
||||
#for task in tasks
|
||||
#set scratch = util.taskScratchClass(task)
|
||||
<tr class="{{ util.rowToggle() }} {{ scratch }}">
|
||||
<tr class="{{ rowToggle(loop) }} {{ scratch }}">
|
||||
#set state = util.taskState(task.state)
|
||||
<td>{{ task.id }}</td>
|
||||
<td><a href="taskinfo?taskID={{ task.id }}" class="task{{ state }}" title="{{ state }}">{{ koji.taskLabel(task) }}</a></td>
|
||||
|
|
@ -108,7 +109,7 @@
|
|||
<th><a href="index?packageOrder={{ util.toggleOrder('blocked', 'packageOrder') }}{{ util.passthrough('buildOrder', 'buildStart', 'taskOrder', 'taskStart') }}#packagelist">Included?</a> {{ util.sortImage('blocked', 'packageOrder') }}</th>
|
||||
</tr>
|
||||
#for package in packages
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="packageinfo?packageID={{ package.package_id }}">{{ package.package_name }}</a></td>
|
||||
<td><a href="taginfo?tagID={{ package.tag_id }}">{{ package.tag_name }}</a></td>
|
||||
#set included = package.blocked and 'no' or 'yes'
|
||||
|
|
@ -137,7 +138,7 @@
|
|||
<th></th>
|
||||
</tr>
|
||||
#for notif in notifs
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td>{{ notif.package.name if notif.package else 'all' }}</td>
|
||||
<td>{{ notif.tag.name if notif.tag else 'all' }}</td>
|
||||
<td>{{ 'success only' if notif.success_only else 'all' }}</td>
|
||||
|
|
|
|||
|
|
@ -386,7 +386,7 @@ def index(environ, packageOrder='package_name', packageStart=None):
|
|||
|
||||
values['koji'] = koji
|
||||
|
||||
return _genHTML(environ, 'index.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'index.html.j2')
|
||||
|
||||
|
||||
def notificationedit(environ, notificationID):
|
||||
|
|
@ -432,7 +432,7 @@ def notificationedit(environ, notificationID):
|
|||
tags = server.listTags(queryOpts={'order': 'name'})
|
||||
values['tags'] = tags
|
||||
|
||||
return _genHTML(environ, 'notificationedit.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'notificationedit.html.j2')
|
||||
|
||||
|
||||
def notificationcreate(environ):
|
||||
|
|
@ -477,7 +477,7 @@ def notificationcreate(environ):
|
|||
tags = server.listTags(queryOpts={'order': 'name'})
|
||||
values['tags'] = tags
|
||||
|
||||
return _genHTML(environ, 'notificationedit.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'notificationedit.html.j2')
|
||||
|
||||
|
||||
def notificationdelete(environ, notificationID):
|
||||
|
|
@ -640,7 +640,7 @@ def tasks(environ, owner=None, state='active', view='tree', method='all', hostID
|
|||
values['S'] = SafeValue
|
||||
values['koji'] = koji
|
||||
|
||||
return _genHTML(environ, 'tasks.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'tasks.html.j2')
|
||||
|
||||
|
||||
def taskinfo(environ, taskID):
|
||||
|
|
@ -800,7 +800,7 @@ def taskinfo(environ, taskID):
|
|||
values['koji'] = koji
|
||||
values['S'] = SafeValue
|
||||
|
||||
return _genHTML(environ, 'taskinfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'taskinfo.html.j2')
|
||||
|
||||
|
||||
def taskstatus(environ, taskID):
|
||||
|
|
@ -937,7 +937,7 @@ def tags(environ, start=None, order=None, childID=None):
|
|||
else:
|
||||
values['childID'] = int(childID)
|
||||
|
||||
return _genHTML(environ, 'tags.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'tags.html.j2')
|
||||
|
||||
|
||||
_PREFIX_CHARS = [chr(char) for char in list(range(48, 58)) + list(range(97, 123))]
|
||||
|
|
@ -980,7 +980,7 @@ def packages(environ, tagID=None, userID=None, order='package_name', start=None,
|
|||
|
||||
values['chars'] = _PREFIX_CHARS
|
||||
|
||||
return _genHTML(environ, 'packages.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'packages.html.j2')
|
||||
|
||||
|
||||
def packageinfo(environ, packageID, tagOrder='name', tagStart=None, buildOrder='-completion_time',
|
||||
|
|
@ -1004,7 +1004,7 @@ def packageinfo(environ, packageID, tagOrder='name', tagStart=None, buildOrder='
|
|||
start=buildStart, dataName='builds', prefix='build',
|
||||
order=buildOrder)
|
||||
|
||||
return _genHTML(environ, 'packageinfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'packageinfo.html.j2')
|
||||
|
||||
|
||||
def taginfo(environ, tagID, all='0', packageOrder='package_name', packageStart=None,
|
||||
|
|
@ -1020,7 +1020,7 @@ def taginfo(environ, tagID, all='0', packageOrder='package_name', packageStart=N
|
|||
values['tagID'] = tag['id']
|
||||
if 'revoke_event' in tag:
|
||||
values['delete_ts'] = server.getEvent(tag['revoke_event'])['ts']
|
||||
return _genHTML(environ, 'taginfo_deleted.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'taginfo_deleted.html.j2')
|
||||
|
||||
all = int(all)
|
||||
|
||||
|
|
@ -1068,7 +1068,7 @@ def taginfo(environ, tagID, all='0', packageOrder='package_name', packageStart=N
|
|||
allPerms = dict([(perm['id'], perm['name']) for perm in permList])
|
||||
values['allPerms'] = allPerms
|
||||
|
||||
return _genHTML(environ, 'taginfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'taginfo.html.j2')
|
||||
|
||||
|
||||
def tagcreate(environ):
|
||||
|
|
@ -1104,7 +1104,7 @@ def tagcreate(environ):
|
|||
values['tag'] = None
|
||||
values['permissions'] = server.getAllPerms()
|
||||
|
||||
return _genHTML(environ, 'tagedit.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'tagedit.html.j2')
|
||||
|
||||
|
||||
def tagedit(environ, tagID):
|
||||
|
|
@ -1134,7 +1134,7 @@ def tagedit(environ, tagID):
|
|||
params['maven_support'] = bool('maven_support' in form)
|
||||
params['maven_include_all'] = bool('maven_include_all' in form)
|
||||
|
||||
server.editTag(tag['id'], **params)
|
||||
server.editTag2(tag['id'], **params)
|
||||
|
||||
_redirect(environ, 'taginfo?tagID=%i' % tag['id'])
|
||||
elif 'cancel' in form:
|
||||
|
|
@ -1147,7 +1147,7 @@ def tagedit(environ, tagID):
|
|||
values['tag'] = tag
|
||||
values['permissions'] = server.getAllPerms()
|
||||
|
||||
return _genHTML(environ, 'tagedit.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'tagedit.html.j2')
|
||||
|
||||
|
||||
def tagdelete(environ, tagID):
|
||||
|
|
@ -1213,7 +1213,7 @@ def tagparent(environ, tagID, parentID, action):
|
|||
'tag %i has tag %i listed as a parent more than once' %
|
||||
(tag['id'], parent['id']))
|
||||
|
||||
return _genHTML(environ, 'tagparent.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'tagparent.html.j2')
|
||||
elif action == 'remove':
|
||||
data = server.getInheritanceData(tag['id'])
|
||||
for datum in data:
|
||||
|
|
@ -1242,7 +1242,7 @@ def externalrepoinfo(environ, extrepoID):
|
|||
values['extRepo'] = extRepo
|
||||
values['repoTags'] = repoTags
|
||||
|
||||
return _genHTML(environ, 'externalrepoinfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'externalrepoinfo.html.j2')
|
||||
|
||||
|
||||
def buildinfo(environ, buildID):
|
||||
|
|
@ -1390,7 +1390,7 @@ def buildinfo(environ, buildID):
|
|||
|
||||
values['pathinfo'] = pathinfo
|
||||
values['koji'] = koji
|
||||
return _genHTML(environ, 'buildinfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'buildinfo.html.j2')
|
||||
|
||||
|
||||
def builds(environ, userID=None, tagID=None, packageID=None, state=None, order='-build_id',
|
||||
|
|
@ -1478,7 +1478,7 @@ def builds(environ, userID=None, tagID=None, packageID=None, state=None, order='
|
|||
values['chars'] = _PREFIX_CHARS
|
||||
values['koji'] = koji
|
||||
|
||||
return _genHTML(environ, 'builds.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'builds.html.j2')
|
||||
|
||||
|
||||
def users(environ, order='name', start=None, prefix=None):
|
||||
|
|
@ -1498,7 +1498,7 @@ def users(environ, order='name', start=None, prefix=None):
|
|||
|
||||
values['chars'] = _PREFIX_CHARS
|
||||
|
||||
return _genHTML(environ, 'users.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'users.html.j2')
|
||||
|
||||
|
||||
def userinfo(environ, userID, packageOrder='package_name', packageStart=None,
|
||||
|
|
@ -1526,7 +1526,7 @@ def userinfo(environ, userID, packageOrder='package_name', packageStart=None,
|
|||
start=buildStart, dataName='builds', prefix='build',
|
||||
order=buildOrder, pageSize=10)
|
||||
|
||||
return _genHTML(environ, 'userinfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'userinfo.html.j2')
|
||||
|
||||
|
||||
# headers shown in rpminfo and buildinfo pages
|
||||
|
|
@ -1589,7 +1589,7 @@ def rpminfo(environ, rpmID, fileOrder='name', fileStart=None, buildrootOrder='-i
|
|||
values['koji'] = koji
|
||||
values['time'] = time # TODO rework template so it doesn't need this
|
||||
|
||||
return _genHTML(environ, 'rpminfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'rpminfo.html.j2')
|
||||
|
||||
|
||||
def archiveinfo(environ, archiveID, fileOrder='name', fileStart=None, buildrootOrder='-id',
|
||||
|
|
@ -1635,7 +1635,7 @@ def archiveinfo(environ, archiveID, fileOrder='name', fileStart=None, buildrootO
|
|||
|
||||
values['koji'] = koji
|
||||
|
||||
return _genHTML(environ, 'archiveinfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'archiveinfo.html.j2')
|
||||
|
||||
|
||||
def fileinfo(environ, filename, rpmID=None, archiveID=None):
|
||||
|
|
@ -1670,7 +1670,7 @@ def fileinfo(environ, filename, rpmID=None, archiveID=None):
|
|||
|
||||
values['file'] = file
|
||||
|
||||
return _genHTML(environ, 'fileinfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'fileinfo.html.j2')
|
||||
|
||||
|
||||
def cancelbuild(environ, buildID):
|
||||
|
|
@ -1752,9 +1752,9 @@ def hosts(environ, state='enabled', start=None, order='name', ready='all', chann
|
|||
# Paginate after retrieving last update info so we can sort on it
|
||||
kojiweb.util.paginateList(values, hosts, start, 'hosts', 'host', order)
|
||||
|
||||
values['zip'] = zip # TODO FIXME
|
||||
values['zip'] = zip # TODO avoid passing this in
|
||||
|
||||
return _genHTML(environ, 'hosts.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'hosts.html.j2')
|
||||
|
||||
|
||||
def hostinfo(environ, hostID=None, userID=None):
|
||||
|
|
@ -1800,7 +1800,7 @@ def hostinfo(environ, hostID=None, userID=None):
|
|||
else:
|
||||
values['perms'] = []
|
||||
|
||||
return _genHTML(environ, 'hostinfo.html.j2', jinja=2)
|
||||
return _genHTML(environ, 'hostinfo.html.j2')
|
||||
|
||||
|
||||
def hostedit(environ, hostID):
|
||||
|
|
@ -1850,7 +1850,7 @@ def hostedit(environ, hostID):
|
|||
values['allChannels'] = allChannels
|
||||
values['hostChannels'] = server.listChannels(hostID=host['id'])
|
||||
|
||||
return _genHTML(environ, 'hostedit.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'hostedit.html.j2')
|
||||
|
||||
|
||||
def disablehost(environ, hostID):
|
||||
|
|
@ -1900,7 +1900,7 @@ def channelinfo(environ, channelID):
|
|||
values['enabled_hosts'] = len([h for h in hosts if h['enabled']])
|
||||
values['ready_hosts'] = len([h for h in hosts if h['ready']])
|
||||
|
||||
return _genHTML(environ, 'channelinfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'channelinfo.html.j2')
|
||||
|
||||
|
||||
def buildrootinfo(environ, buildrootID):
|
||||
|
|
@ -1925,7 +1925,7 @@ def buildrootinfo(environ, buildrootID):
|
|||
values['buildroot'] = buildroot
|
||||
values['koji'] = koji
|
||||
|
||||
return _genHTML(environ, template, jinja=True)
|
||||
return _genHTML(environ, template)
|
||||
|
||||
|
||||
def rpmlist(environ, type, buildrootID=None, imageID=None, start=None, order='nvr'):
|
||||
|
|
@ -1980,7 +1980,7 @@ def rpmlist(environ, type, buildrootID=None, imageID=None, start=None, order='nv
|
|||
values['type'] = type
|
||||
values['order'] = order
|
||||
|
||||
return _genHTML(environ, 'rpmlist.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'rpmlist.html.j2')
|
||||
|
||||
|
||||
def archivelist(environ, type, buildrootID=None, imageID=None, start=None, order='filename'):
|
||||
|
|
@ -2027,7 +2027,7 @@ def archivelist(environ, type, buildrootID=None, imageID=None, start=None, order
|
|||
values['type'] = type
|
||||
values['order'] = order
|
||||
|
||||
return _genHTML(environ, 'archivelist.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'archivelist.html.j2')
|
||||
|
||||
|
||||
def buildtargets(environ, start=None, order='name'):
|
||||
|
|
@ -2043,7 +2043,7 @@ def buildtargets(environ, start=None, order='name'):
|
|||
else:
|
||||
values['perms'] = []
|
||||
|
||||
return _genHTML(environ, 'buildtargets.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'buildtargets.html.j2')
|
||||
|
||||
|
||||
def buildtargetinfo(environ, targetID=None, name=None):
|
||||
|
|
@ -2073,7 +2073,7 @@ def buildtargetinfo(environ, targetID=None, name=None):
|
|||
else:
|
||||
values['perms'] = []
|
||||
|
||||
return _genHTML(environ, 'buildtargetinfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'buildtargetinfo.html.j2')
|
||||
|
||||
|
||||
def buildtargetedit(environ, targetID):
|
||||
|
|
@ -2113,7 +2113,7 @@ def buildtargetedit(environ, targetID):
|
|||
values['target'] = target
|
||||
values['tags'] = tags
|
||||
|
||||
return _genHTML(environ, 'buildtargetedit.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'buildtargetedit.html.j2')
|
||||
|
||||
|
||||
def buildtargetcreate(environ):
|
||||
|
|
@ -2173,7 +2173,7 @@ def reports(environ):
|
|||
values['loggedInUser'] = True
|
||||
else:
|
||||
values['loggedInUser'] = False
|
||||
return _genHTML(environ, 'reports.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'reports.html.j2')
|
||||
|
||||
|
||||
def buildsbyuser(environ, start=None, order='-builds'):
|
||||
|
|
@ -2201,7 +2201,7 @@ def buildsbyuser(environ, start=None, order='-builds'):
|
|||
values['increment'] = graphWidth / maxBuilds
|
||||
kojiweb.util.paginateList(values, users, start, 'userBuilds', 'userBuild', order)
|
||||
|
||||
return _genHTML(environ, 'buildsbyuser.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'buildsbyuser.html.j2')
|
||||
|
||||
|
||||
def rpmsbyhost(environ, start=None, order=None, hostArch=None, rpmArch=None):
|
||||
|
|
@ -2246,7 +2246,7 @@ def rpmsbyhost(environ, start=None, order=None, hostArch=None, rpmArch=None):
|
|||
values['increment'] = graphWidth / maxRPMs
|
||||
kojiweb.util.paginateList(values, hosts, start, 'hosts', 'host', order)
|
||||
|
||||
return _genHTML(environ, 'rpmsbyhost.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'rpmsbyhost.html.j2')
|
||||
|
||||
|
||||
def packagesbyuser(environ, start=None, order=None):
|
||||
|
|
@ -2276,7 +2276,7 @@ def packagesbyuser(environ, start=None, order=None):
|
|||
values['increment'] = graphWidth / maxPackages
|
||||
kojiweb.util.paginateList(values, users, start, 'users', 'user', order)
|
||||
|
||||
return _genHTML(environ, 'packagesbyuser.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'packagesbyuser.html.j2')
|
||||
|
||||
|
||||
def tasksbyhost(environ, start=None, order='-tasks', hostArch=None):
|
||||
|
|
@ -2314,7 +2314,7 @@ def tasksbyhost(environ, start=None, order='-tasks', hostArch=None):
|
|||
values['increment'] = graphWidth / maxTasks
|
||||
kojiweb.util.paginateList(values, hosts, start, 'hosts', 'host', order)
|
||||
|
||||
return _genHTML(environ, 'tasksbyhost.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'tasksbyhost.html.j2')
|
||||
|
||||
|
||||
def tasksbyuser(environ, start=None, order='-tasks'):
|
||||
|
|
@ -2343,7 +2343,7 @@ def tasksbyuser(environ, start=None, order='-tasks'):
|
|||
values['increment'] = graphWidth / maxTasks
|
||||
kojiweb.util.paginateList(values, users, start, 'users', 'user', order)
|
||||
|
||||
return _genHTML(environ, 'tasksbyuser.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'tasksbyuser.html.j2')
|
||||
|
||||
|
||||
def buildsbystatus(environ, days='7'):
|
||||
|
|
@ -2382,7 +2382,7 @@ def buildsbystatus(environ, days='7'):
|
|||
values['maxBuilds'] = maxBuilds
|
||||
values['increment'] = graphWidth / maxBuilds
|
||||
|
||||
return _genHTML(environ, 'buildsbystatus.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'buildsbystatus.html.j2')
|
||||
|
||||
|
||||
def buildsbytarget(environ, days='7', start=None, order='-builds'):
|
||||
|
|
@ -2422,7 +2422,7 @@ def buildsbytarget(environ, days='7', start=None, order='-builds'):
|
|||
values['maxBuilds'] = maxBuilds
|
||||
values['increment'] = graphWidth / maxBuilds
|
||||
|
||||
return _genHTML(environ, 'buildsbytarget.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'buildsbytarget.html.j2')
|
||||
|
||||
|
||||
def _filter_hosts_by_arch(hosts, arch):
|
||||
|
|
@ -2482,7 +2482,7 @@ def clusterhealth(environ, arch='__all__'):
|
|||
values['arches'] = sorted(arches)
|
||||
values['graphWidth'] = graphWidth
|
||||
values['channels'] = sorted(channels, key=lambda x: x['name'])
|
||||
return _genHTML(environ, 'clusterhealth.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'clusterhealth.html.j2')
|
||||
|
||||
|
||||
def recentbuilds(environ, user=None, tag=None, package=None):
|
||||
|
|
@ -2553,7 +2553,7 @@ def recentbuilds(environ, user=None, tag=None, package=None):
|
|||
values['koji'] = koji
|
||||
|
||||
environ['koji.headers'].append(['Content-Type', 'text/xml'])
|
||||
return _genHTML(environ, 'recentbuilds.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'recentbuilds.html.j2')
|
||||
|
||||
|
||||
_infoURLs = {'package': 'packageinfo?packageID=%(id)i',
|
||||
|
|
@ -2630,9 +2630,9 @@ def search(environ, start=None, order=None):
|
|||
else:
|
||||
typeLabel = '%ss' % type
|
||||
values['typeLabel'] = typeLabel
|
||||
return _genHTML(environ, 'search.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'search.html.j2')
|
||||
else:
|
||||
return _genHTML(environ, 'search.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'search.html.j2')
|
||||
|
||||
|
||||
def api(environ):
|
||||
|
|
@ -2647,7 +2647,7 @@ def api(environ):
|
|||
except koji.GenericError:
|
||||
values['koji_version'] = "Can't determine (older then 1.23)"
|
||||
|
||||
return _genHTML(environ, 'api.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'api.html.j2')
|
||||
|
||||
|
||||
def watchlogs(environ, taskID):
|
||||
|
|
@ -2700,7 +2700,7 @@ def repoinfo(environ, repoID):
|
|||
values['numBuildroots'] = num_buildroots
|
||||
values['state_name'] = kojiweb.util.repoState(repo_info['state'])
|
||||
values['create_time'] = kojiweb.util.formatTimeLong(repo_info['create_ts'])
|
||||
return _genHTML(environ, 'repoinfo.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'repoinfo.html.j2')
|
||||
|
||||
|
||||
def activesession(environ, start=None, order=None):
|
||||
|
|
@ -2718,10 +2718,12 @@ def activesession(environ, start=None, order=None):
|
|||
for a in activesess:
|
||||
a['lengthSession'] = kojiweb.util.formatTimestampDifference(
|
||||
a['start_time'], current_timestamp, in_days=True)
|
||||
else:
|
||||
activesess = []
|
||||
|
||||
kojiweb.util.paginateList(values, activesess, start, 'activesess', order=order)
|
||||
|
||||
return _genHTML(environ, 'activesession.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'activesession.html.j2')
|
||||
|
||||
|
||||
def activesessiondelete(environ, sessionID):
|
||||
|
|
@ -2752,4 +2754,4 @@ def buildroots(environ, repoID=None, order='id', start=None, state=None):
|
|||
|
||||
values['koji'] = koji
|
||||
|
||||
return _genHTML(environ, 'buildroots.html.j2', jinja=True)
|
||||
return _genHTML(environ, 'buildroots.html.j2')
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<th>Success Only?</th>
|
||||
<td><input type="checkbox" name="success_only" value="yes"{{ ' checked="checked"' if notif and notif.success_only else '' }}/></td>
|
||||
<td><input type="checkbox" name="success_only" value="yes"{{ ' checked' if notif and notif.success_only else '' }}/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Information for package <a href="packageinfo?packageID={{ package.id }}">{{ package.name }}</a></h4>
|
||||
|
||||
|
|
@ -44,7 +45,7 @@
|
|||
<th><a href="packageinfo?buildOrder={{ util.toggleOrder('state', 'buildOrder') }}{{ util.passthrough('packageID', 'tagOrder', 'tagStart') }}#buildlist">State</a> {{ util.sortImage('state', 'buildOrder') }}</th>
|
||||
</tr>
|
||||
#for build in builds
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="buildinfo?buildID={{ build.build_id }}">{{ build.nvr }}</a></td>
|
||||
<td class="user-{{ build.owner_name }}"><a href="userinfo?userID={{ build.owner_id }}">{{ build.owner_name }}</a></td>
|
||||
<td>{{ util.formatTime(build.completion_ts) }}</td>
|
||||
|
|
@ -99,12 +100,12 @@
|
|||
<th><a href="packageinfo?tagOrder={{ util.toggleOrder('extra_arches', 'tagOrder') }}{{ util.passthrough('packageID', 'buildOrder', 'buildStart') }}#taglist">Extra Arches</a> {{ util.sortImage('extra_arches', 'tagOrder') }}</th>
|
||||
</tr>
|
||||
#for tag in tags
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="taginfo?tagID={{ tag.id }}">{{ tag.name }}</a></td>
|
||||
<td><a href="userinfo?userID={{ tag.owner_id }}">{{ tag.owner_name }}</a></td>
|
||||
#set included = tag.blocked and 'no' or 'yes'
|
||||
<td>{{ util.imageTag(included) }}</td>
|
||||
<td>{{ tag.extra_arches }}</td>
|
||||
<td>{{ tag.extra_arches or '' }}</td>
|
||||
</tr>
|
||||
#endfor
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#set _PASSTHROUGH = ['userID', 'tagID', 'order', 'prefix', 'inherited', 'blocked']
|
||||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
#macro getDescription()
|
||||
Packages
|
||||
|
|
@ -93,7 +94,7 @@ owned by <a href="userinfo?userID={{ user.id }}">{{ user.name }}</a>
|
|||
</tr>
|
||||
#if (packages |length) > 0
|
||||
#for package in packages
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td>{{ package.package_id }}</td>
|
||||
<td><a href="packageinfo?packageID={{ package.package_id }}">{{ package.package_name }}</a></td>
|
||||
#if tag or user
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Packages by User</h4>
|
||||
<table class="data-list">
|
||||
|
|
@ -33,7 +34,7 @@
|
|||
</tr>
|
||||
#if (users |length) > 0
|
||||
#for user in users
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="userinfo?userID={{ user.id }}">{{ user.name }}</a></td>
|
||||
<td width="{{ graphWidth + 5 }}"><img src="{{ util.themePath('images/1px.gif') }}" width="{{ increment * user.packages }}" height="15" class="graphrow" alt="graph row"/></td>
|
||||
<td>{{ user.packages }}</td>
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
#macro linkURL()
|
||||
#set query = []
|
||||
#if tag
|
||||
#set _tmp = query.append('tagID=%i' % (tag.id|urlencode))
|
||||
#set _tmp = query.append('tagID=%s' % (tag.id|urlencode))
|
||||
#endif
|
||||
#if user
|
||||
#set _tmp = query.append('userID=%i' % (user.id|urlencode))
|
||||
#set _tmp = query.append('userID=%s' % (user.id|urlencode))
|
||||
#endif
|
||||
#if package
|
||||
#set _tmp = query.append('packageID=%i' % (package.id|urlencode))
|
||||
#set _tmp = query.append('packageID=%s' % (package.id|urlencode))
|
||||
#endif
|
||||
#if query
|
||||
{{ '%s/%s?%s' % (weburl, 'builds', '&'.join(query)) }}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@
|
|||
{% endif %}
|
||||
<tr><th>State</th><td class="repo{{ state_name }}">{{ state_name }}</td></tr>
|
||||
<tr><th>Event</th><td>{{ repo.create_event }} ({{ create_time }})</td></tr>
|
||||
{% if state_name != 'DELETED' %}
|
||||
{%- if state_name != 'deleted' %}
|
||||
<tr><th>URL</th><td><a href="{{ url }}">repodata</a></td></tr>
|
||||
<tr><th>Repo json</th><td><a href="{{ repo_json }}">repo.json</a></td></tr>
|
||||
{% endif %}
|
||||
{%- endif %}
|
||||
<tr><th>Dist repo?</th><td class="{{ repo.dist | lower }}">{{ repo.dist }}</td></tr>
|
||||
<tr><th>Number of buildroots: </th><td><a href="buildroots?repoID={{ repo.id }}">{{ numBuildroots }}</a></td></tr>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#set _PASSTHROUGH = ['rpmID', 'fileOrder', 'fileStart', 'buildrootOrder', 'buildrootStart']
|
||||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
#set epoch = (rpm.epoch|string + ':' if rpm.epoch != None else '')
|
||||
<h4>Information for RPM <a href="rpminfo?rpmID={{ rpm.id }}">{{ rpm.name }}-{{ epoch }}{{ rpm.version }}-{{ rpm.release }}.{{rpm.arch}}.rpm</a></h4>
|
||||
|
||||
|
|
@ -32,7 +33,7 @@
|
|||
<th>Release</th><td>{{ rpm.release }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Epoch</th><td>{{ rpm.epoch }}</td>
|
||||
<th>Epoch</th><td>{{ rpm.epoch if rpm.epoch is not none else '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Arch</th><td>{{ rpm.arch }}</td>
|
||||
|
|
@ -255,7 +256,7 @@
|
|||
<th align="right"><a href="rpminfo?fileOrder={{ util.toggleOrder('size', 'fileOrder') }}{{ util.passthrough_except('fileOrder', 'fileStart') }}#filelist">Size</a> {{ util.sortImage('size', 'fileOrder') }}</th>
|
||||
</tr>
|
||||
#for file in files
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="fileinfo?rpmID={{ rpm.id }}&filename={{ file.name|urlencode }}">{{ file.name }}</a></td><td align="right"><span title="{{ util.formatThousands(file.size) }}">{{ util.formatNatural(file.size) }}</span></td>
|
||||
</tr>
|
||||
#endfor
|
||||
|
|
@ -298,7 +299,7 @@
|
|||
<th><a href="rpminfo?buildrootOrder={{ util.toggleOrder('state', 'buildrootOrder') }}{{ util.passthrough_except('buildrootOrder', 'buildrootStart') }}#buildrootlist">State</a> {{ util.sortImage('state', 'buildrootOrder') }}</th>
|
||||
</tr>
|
||||
#for buildroot in buildroots
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="buildrootinfo?buildrootID={{ buildroot.id }}">{{ util.brLabel(buildroot) }}</a></td>
|
||||
<td>{{ util.formatTime(buildroot.create_event_time) }}</td>
|
||||
<td>{{ util.imageTag(util.brStateName(buildroot.state)) }}</td>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
#macro getID()
|
||||
#if type == 'image'
|
||||
|
|
@ -60,7 +61,7 @@ colspan="2"
|
|||
</tr>
|
||||
#if (rpms |length) > 0
|
||||
#for rpm in rpms
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
#set epoch = (rpm.epoch|string + ':' if rpm.epoch != None else '')
|
||||
<td>{{ util.formatRPM(rpm) }}</td>
|
||||
#if type in ['component', 'image']
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>{{ rpmArch + ' ' if rpmArch else '' }}RPMs by Host{{ ' (%s)' % hostArch if hostArch else '' }}</h4>
|
||||
<table class="data-list">
|
||||
|
|
@ -67,7 +68,7 @@
|
|||
</tr>
|
||||
#if (hosts |length) > 0
|
||||
#for host in hosts
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="hostinfo?hostID={{ host.id }}">{{ host.name }}</a></td>
|
||||
<td width="{{ graphWidth + 5 }}"><img src="{{ util.themePath('images/1px.gif') }}" width="{{ increment * host.rpms }}" height="15" class="graphrow" alt="graph row"/></td>
|
||||
<td>{{ host.rpms }}</td>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{% include "includes/header.html.j2" %}
|
||||
{% from 'includes/macros.html.j2' import rowToggle %}
|
||||
|
||||
|
||||
<h4>Search</h4>
|
||||
|
|
@ -19,18 +20,18 @@
|
|||
<option {{ toggleSelected(type, "user") }} value="user">Users</option>
|
||||
<option {{ toggleSelected(type, "host") }} value="host">Hosts</option>
|
||||
<option {{ toggleSelected(type, "rpm") }} value="rpm">RPMs</option>
|
||||
{% if mavenEnabled %}
|
||||
{%- if mavenEnabled %}
|
||||
<option {{ toggleSelected(type, "maven") }} value="maven">Maven Artifacts</option>
|
||||
{% endif %}
|
||||
{% if winEnabled %}
|
||||
{%- endif %}
|
||||
{%- if winEnabled %}
|
||||
<option {{ toggleSelected(type, "win") }} value="win">Windows Artifacts</option>
|
||||
{% endif %}
|
||||
{%- endif %}
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
{% if match is not defined %}
|
||||
{% set match='glob' %}
|
||||
{% endif %}
|
||||
{%- if match is not defined %}
|
||||
{%- set match='glob' %}
|
||||
{%- endif %}
|
||||
<input type="radio" name="match" value="glob" {{ toggleSelected(match, "glob", True) }} id="radioglob"/><abbr title="? will match any single character, * will match any sequence of zero or more characters" id="abbrglob">glob</abbr>
|
||||
<input type="radio" name="match" value="regexp" {{ toggleSelected(match, "regexp", True) }} id="radioregexp"/><abbr title="full POSIX regular expressions" id="abbrregexp">regexp</abbr>
|
||||
<input type="radio" name="match" value="exact" {{ toggleSelected(match, "exact", True) }} id="radioexact"/><abbr title="exact matches only" id="abbrexact">exact</abbr>
|
||||
|
|
@ -49,43 +50,43 @@
|
|||
<table class="data-list">
|
||||
<tr>
|
||||
<td class="paginate" colspan="2">
|
||||
{% if resultPages|length > 1 %}
|
||||
{%- if resultPages|length > 1 %}
|
||||
<form class="pageJump" action="">
|
||||
Page:
|
||||
<select onchange="javascript: window.location = 'search?start=' + this.value * {{ resultRange }} + '{{ passthrough('order', 'terms', 'type', 'match') }}';">
|
||||
{% for pageNum in resultPages %}
|
||||
<option value="{{ pageNum }}"{{ 'selected' if pageNum == resultCurrentPage else '' }}>{{ pageNum + 1 }}</option>
|
||||
<option value="{{ pageNum }}"{{ ' selected' if pageNum == resultCurrentPage else '' }}>{{ pageNum + 1 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if resultStart > 0 %}
|
||||
{%- endif %}
|
||||
{%- if resultStart > 0 %}
|
||||
<a href="search?start={{ resultStart - resultRange }}{{ passthrough('order', 'terms', 'type', 'match') }}"><<<</a>
|
||||
{% endif %}
|
||||
{% if totalResults %}
|
||||
{%- endif %}
|
||||
{%- if totalResults %}
|
||||
<strong>Results {{ resultStart + 1 }} through {{ resultStart + resultCount }} of {{ totalResults }}</strong>
|
||||
{% endif %}
|
||||
{% if resultStart + resultCount < totalResults %}
|
||||
{%- endif %}
|
||||
{%- if resultStart + resultCount < totalResults %}
|
||||
<a href="search?start={{ resultStart + resultRange }}{{ passthrough('order', 'terms', 'type', 'match') }}">>>></a>
|
||||
{% endif %}
|
||||
{%- endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="list-header">
|
||||
<th><a href="search?order={{ toggleOrder('id') }}{{ passthrough('terms', 'type', 'match') }}">ID</a> {{ sortImage('id') }}</th>
|
||||
<th><a href="search?order={{ toggleOrder('name') }}{{ passthrough('terms', 'type', 'match') }}">Name</a> {{ sortImage('name') }}</th>
|
||||
</tr>
|
||||
{% if results %}
|
||||
{% for result in results %}
|
||||
<tr class="{{ rowToggle() }}">
|
||||
{%- if results %}
|
||||
{%- for result in results %}
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td>{{ result.id }}</td>
|
||||
<td><a href="{{ infoURL % result }}">{{ result.name }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{%- endfor %}
|
||||
{%- else %}
|
||||
<tr class="row-odd">
|
||||
<td colspan="2">No search results</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{%- endif %}
|
||||
<tr>
|
||||
<td class="paginate" colspan="2">
|
||||
{% if resultPages|length > 1 %}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<th>Locked</th>
|
||||
<td><input type="checkbox" name="locked" value="yes" {{ 'checked="checked"' if tag and tag.locked else '' }}/></td>
|
||||
<td><input type="checkbox" name="locked" value="yes"{{ ' checked' if tag and tag.locked else '' }}/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Permission</th>
|
||||
|
|
@ -41,11 +41,11 @@
|
|||
#if mavenEnabled
|
||||
<tr>
|
||||
<th>Maven Support?</th>
|
||||
<td><input type="checkbox" name="maven_support" value="yes" {{ 'checked="checked"' if tag and tag.maven_support else '' }}>
|
||||
<td><input type="checkbox" name="maven_support" value="yes"{{ 'checked' if tag and tag.maven_support else '' }}>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Include All Maven Builds?</th>
|
||||
<td><input type="checkbox" name="maven_include_all" value="yes" {{ 'checked="checked"' if tag and tag.maven_include_all else '' }}>
|
||||
<td><input type="checkbox" name="maven_include_all" value="yes"{{ ' checked' if tag and tag.maven_include_all else '' }}>
|
||||
</tr>
|
||||
#endif
|
||||
<tr>
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
<span class="root">{{ tag.name }}</span>
|
||||
#set numParents = (inheritance |length)
|
||||
#set iter = 0
|
||||
#set all_depths = []
|
||||
#set all_depths = [0]
|
||||
#set TRUNC_DEPTH = 7
|
||||
<ul>
|
||||
#for parent in inheritance
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
#set nextDepth = (loop.nextitem.currdepth if not loop.last else 1)
|
||||
#set depth = parent.currdepth
|
||||
#set _junk = all_depths.append(depth)
|
||||
## ^ TODO FIXME
|
||||
## ^ TODO refactor to avoid this
|
||||
#if depth == TRUNC_DEPTH and not all
|
||||
<li><span class="treeBranch"><span class="treeToggle treeLabel">...</span></span></li>
|
||||
<li class="hidden">
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
<li>
|
||||
#endif
|
||||
#set _junk = tagsByChild[parent.child_id].pop()
|
||||
## ^ TODO FIXME
|
||||
## ^ TODO refactor to avoid this
|
||||
<span class="treeBranch">
|
||||
<span class="treeLabel">
|
||||
<a href="taginfo?tagID={{ parent.parent_id }}">{{ parent.name }}</a>
|
||||
|
|
@ -134,7 +134,7 @@
|
|||
<td>
|
||||
#if (srcTargets |length)
|
||||
#for target in srcTargets
|
||||
<a href="buildtargetinfo?name={{ quote(target.name) }}">{{ target.name }}</a><br/>
|
||||
<a href="buildtargetinfo?name={{ target.name|urlencode }}">{{ target.name }}</a><br/>
|
||||
#endfor
|
||||
#else
|
||||
No build targets
|
||||
|
|
@ -146,7 +146,7 @@
|
|||
<td>
|
||||
#if (destTargets |length)
|
||||
#for target in destTargets
|
||||
<a href="buildtargetinfo?name={{ quote(target.name) }}">{{ target.name }}</a><br/>
|
||||
<a href="buildtargetinfo?name={{ target.name|urlencode }}">{{ target.name }}</a><br/>
|
||||
#endfor
|
||||
#else
|
||||
No build targets
|
||||
|
|
@ -168,7 +168,7 @@
|
|||
#for key in tag['extra']
|
||||
<tr>
|
||||
<th>{{ key }}</th>
|
||||
<td>{{ pprint.pformat(tag.extra[key]) }}</td>
|
||||
<td>{{ tag.extra[key]|pprint }}</td>
|
||||
</tr>
|
||||
#endfor
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -34,19 +34,19 @@
|
|||
<tr>
|
||||
<th>Max Depth</th>
|
||||
<td>
|
||||
<input type="text" name="maxdepth" value="{{ inheritanceData.maxdepth if inheritanceData else '' }}"/>
|
||||
<input type="text" name="maxdepth" value="{{ inheritanceData.maxdepth if inheritanceData and inheritanceData.maxdepth is not none else '' }}"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Intransitive</th>
|
||||
<td>
|
||||
<input type="checkbox" name="intransitive" value="yes" {{ 'checked="checked"' if inheritanceData and inheritanceData.intransitive else '' }}/>
|
||||
<input type="checkbox" name="intransitive" value="yes"{{ ' checked' if inheritanceData and inheritanceData.intransitive else '' }}/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Packages Only</th>
|
||||
<td>
|
||||
<input type="checkbox" name="noconfig" value="yes" {{ 'checked="checked"' if inheritanceData and inheritanceData.noconfig else '' }}/>
|
||||
<input type="checkbox" name="noconfig" value="yes"{{ ' checked' if inheritanceData and inheritanceData.noconfig else '' }}/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Tags</h4>
|
||||
<table class="data-list">
|
||||
|
|
@ -10,7 +11,7 @@
|
|||
Page:
|
||||
<select onchange="javascript: window.location = 'tags?start=' + this.value * {{ tagRange }} + '{{ passthrough('userID', 'tagID', 'order', 'childID') }}';">
|
||||
#for pageNum in tagPages
|
||||
<option value="{{ pageNum }}"{{ 'selected' if pageNum == tagCurrentPage else '' }}>{{ pageNum + 1 }}</option>
|
||||
<option value="{{ pageNum }}"{{ ' selected' if pageNum == tagCurrentPage else '' }}>{{ pageNum + 1 }}</option>
|
||||
#endfor
|
||||
</select>
|
||||
</form>
|
||||
|
|
@ -32,7 +33,7 @@
|
|||
</tr>
|
||||
#if tags | length > 0
|
||||
#for tag in tags
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td>{{ tag.id }}</td>
|
||||
<td><a href="taginfo?tagID={{ tag.id }}{{ passthrough('childID') }}">{{ tag.name }}</a></td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
|
||||
#macro printChildren(taskID, childMap)
|
||||
#set iter = 0
|
||||
#set children = childMap[taskID|string]
|
||||
#if children
|
||||
<ul>
|
||||
#for child in children
|
||||
#set iter = iter + 1
|
||||
#if iter < children|length
|
||||
#if not loop.last
|
||||
<li class="sibling">
|
||||
#else
|
||||
<li>
|
||||
|
|
@ -60,10 +58,12 @@ None
|
|||
#elif key in ('build_target', 'target_info')
|
||||
<a href="buildtargetinfo?targetID={{ value['id'] }}">{{ value['name'] }}</a>
|
||||
#elif key in ('repo_info', 'oldrepo', 'repo')
|
||||
#if key == 'repo' and value is sequence and value is not string
|
||||
#if value is mapping
|
||||
<a href="repoinfo?repoID={{ value.id }}">{{ value.id }}</a> ({{ koji.formatTimeLong(value.create_ts) }})
|
||||
#elif value is sequence and value is not string
|
||||
{{ value|join(sep) }}
|
||||
#else
|
||||
<a href="repoinfo?repoID={{ value.id }}">{{ value.id }}</a> ({{ koji.formatTimeLong(value.create_ts) }})
|
||||
{{ value }}
|
||||
#endif
|
||||
#elif key == 'task_list'
|
||||
#for task in params['task_list']
|
||||
|
|
@ -71,20 +71,27 @@ None
|
|||
{{ printMap(task, S(' ')) }}
|
||||
#endfor
|
||||
#elif value is mapping
|
||||
##{{ sep.join(['%s=%s' % ((n == '' and "''" or n), v) for n, v in value.items()])
|
||||
{{ value }} TODO FIXME
|
||||
{{ printSimpleMap(value, sep) }}
|
||||
#elif value is sequence and value is not string
|
||||
## XXX this logic doesn't quite convert
|
||||
{{ value|join(sep) }}
|
||||
#else
|
||||
{{ value }}
|
||||
#endif
|
||||
#endmacro
|
||||
|
||||
{%- macro printSimpleMap(value, sep) %}
|
||||
{%- for name, value in value|dictsort -%}
|
||||
{{- '%s=%s' % ("''" if name == '' else name, value) -}}
|
||||
{{- sep if not loop.last else '' -}}
|
||||
{%- endfor -%}
|
||||
{%- endmacro %}
|
||||
|
||||
#macro printProperties(props)
|
||||
##{{ ', '.join([v is not None and '%s=%s' % (n, v) or n|string for n, v in props.items() ]) }}
|
||||
TODO FIXME
|
||||
{{ props | pprint }}
|
||||
## TODO this needs refactoring, but for now we simply port the logic
|
||||
{%- for name, value in props|dictsort -%}
|
||||
{{- name if value is none else '%s=%s' % (name, value) -}}
|
||||
{{- ', ' if not loop.last else '' -}}
|
||||
{%- endfor -%}
|
||||
#endmacro
|
||||
|
||||
|
||||
|
|
@ -155,9 +162,7 @@ None
|
|||
#set end_ts = task.completion_ts
|
||||
#endif
|
||||
#if not end_ts
|
||||
##set end_ts = koji.util.parseTime(koji.util.encode_datetime(datetime.datetime.utcnow()))
|
||||
#set end_ts = koji.time.time()
|
||||
## XXX is this right?
|
||||
#endif
|
||||
<tr>
|
||||
<th title="From task's creation">Total time</th>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
|
||||
#macro printChildren(taskID, childMap)
|
||||
#set iter = 0
|
||||
#set children = childMap[taskID|string]
|
||||
#if children
|
||||
<ul>
|
||||
#for child in children
|
||||
#set iter = iter + 1
|
||||
#if iter < children|length
|
||||
#if not loop.last
|
||||
<li class="sibling">
|
||||
#else
|
||||
<li>
|
||||
|
|
@ -37,6 +35,7 @@ All
|
|||
#set _PASSTHROUGH = ['owner', 'state', 'view', 'method', 'hostID', 'channelID', 'order']
|
||||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
#macro getDescription()
|
||||
{{ headerPrefix(state) }}
|
||||
|
|
@ -96,23 +95,15 @@ in channel <a href="channelinfo?channelID={{ channel.id }}">{{ channel.name }}</
|
|||
<select name="method" class="filterlist" onchange="javascript: window.location = 'tasks?method=' + this.value + '{{ util.passthrough_except('method') }}';">
|
||||
<option value="all" {{ util.toggleSelected(method, 'all') }}>all</option>
|
||||
#for task_type in alltasks
|
||||
#if task_type in ('maven', 'buildMaven') and not mavenEnabled
|
||||
## XXX continue
|
||||
#elif task_type in ('winbuild', 'vmExec') and not winEnabled
|
||||
## XXX continue
|
||||
#elif task_type == 'wrapperRPM' and not (mavenEnabled or winEnabled)
|
||||
## XXX continue
|
||||
#else
|
||||
<option value="{{ task_type }}" {{ 'selected' if method == task_type else '' }}>{{ task_type }}</option>
|
||||
#endif
|
||||
#endfor
|
||||
</select>
|
||||
</td><td>
|
||||
<strong>View</strong>:
|
||||
</td><td>
|
||||
<select name="view" class="filterlist" onchange="javascript: window.location = 'tasks?view=' + this.value + '{{ util.passthrough_except('view') }}';">
|
||||
<option value="tree" {{ util.toggleSelected(view, 'tree') }} {{ 'disabled="disabled"' if not treeEnabled else '' }}>tree</option>
|
||||
<option value="toplevel" {{ util.toggleSelected(view, 'toplevel') }} {{ 'disabled="disabled"' if not toplevelEnabled else '' }}>toplevel</option>
|
||||
<option value="tree" {{ util.toggleSelected(view, 'tree') }}{{ ' disabled' if not treeEnabled else '' }}>tree</option>
|
||||
<option value="toplevel" {{ util.toggleSelected(view, 'toplevel') }}{{ ' disabled' if not toplevelEnabled else '' }}>toplevel</option>
|
||||
<option value="flat" {{ util.toggleSelected(view, 'flat') }}>flat</option>
|
||||
</select>
|
||||
</td></tr>
|
||||
|
|
@ -165,7 +156,7 @@ in channel <a href="channelinfo?channelID={{ channel.id }}">{{ channel.name }}</
|
|||
</tr>
|
||||
#if tasks
|
||||
#for task in tasks
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
#set taskState = util.taskState(task.state)
|
||||
<td>{{ task.id }}</td>
|
||||
<td{{ S(' class="tree"') if treeDisplay else '' }}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Tasks by Host{{ ' (%s)' % hostArch if hostArch else '' }}</h4>
|
||||
<table class="data-list">
|
||||
|
|
@ -50,7 +51,7 @@
|
|||
</tr>
|
||||
#if (hosts |length) > 0
|
||||
#for host in hosts
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="hostinfo?hostID={{ host.id }}">{{ host.name }}</a></td>
|
||||
<td width="{{ graphWidth + 5 }}"><img src="{{ util.themePath('images/1px.gif') }}" width="{{ increment * host.tasks }}" height="15" class="graphrow" alt="graph row"/></td>
|
||||
<td>{{ host.tasks }}</td>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Tasks by User</h4>
|
||||
<table class="data-list">
|
||||
|
|
@ -33,7 +34,7 @@
|
|||
</tr>
|
||||
#if (users |length) > 0
|
||||
#for user in users
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="userinfo?userID={{ user.id }}">{{ user.name }}</a></td>
|
||||
<td width="{{ graphWidth + 5 }}"><img src="{{ util.themePath('images/1px.gif') }}" width="{{ increment * user.tasks }}" height="15" class="graphrow" alt="graph row"/></td>
|
||||
<td>{{ user.tasks }}</td>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Information for user <a href="userinfo?userID={{ user.id }}">{{ user.name }}</a></h4>
|
||||
|
||||
|
|
@ -45,10 +46,10 @@
|
|||
<th><a href="userinfo?packageOrder={{ util.toggleOrder('blocked', 'packageOrder') }}{{ util.passthrough('userID', 'buildOrder', 'buildStart') }}#packagelist">Included?</a> {{ util.sortImage('blocked', 'packageOrder') }}</th>
|
||||
</tr>
|
||||
#for package in packages
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td><a href="packageinfo?packageID={{ package.package_id }}">{{ package.package_name }}</a></td>
|
||||
<td><a href="taginfo?tagID={{ package.tag_id }}">{{ package.tag_name }}</a></td>
|
||||
<td class="{{ package.blocked|lower }}">{{ util.imageTag('no') if package.blocked else util.imageTag('yes') }}</td>
|
||||
<td class="{{ (not package.blocked)|lower }}">{{ util.imageTag('no') if package.blocked else util.imageTag('yes') }}</td>
|
||||
</tr>
|
||||
#endfor
|
||||
</table>
|
||||
|
|
@ -89,7 +90,7 @@
|
|||
<th><a href="userinfo?buildOrder={{ util.toggleOrder('state', 'buildOrder') }}{{ util.passthrough('userID', 'packageOrder', 'packageStart') }}#buildlist">State</a> {{ util.sortImage('state', 'buildOrder') }}</th>
|
||||
</tr>
|
||||
#for build in builds
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
#set stateName = util.stateName(build.state)
|
||||
<td><a href="buildinfo?buildID={{ build.build_id }}">{{ build.nvr }}</a></td>
|
||||
<td>{{ util.formatTime(build.completion_ts) }}</td>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "includes/header.html.j2"
|
||||
# from "includes/macros.html.j2" import rowToggle
|
||||
|
||||
<h4>Users {{ ' starting with "%s"' % prefix if prefix else '' }}</h4>
|
||||
<table class="data-list">
|
||||
|
|
@ -27,7 +28,7 @@
|
|||
Page:
|
||||
<select onchange="javascript: window.location = 'users?start=' + this.value * {{ userRange }} + '{{ util.passthrough('order', 'prefix') }}';">
|
||||
#for pageNum in userPages
|
||||
<option value="{{ pageNum }}"{{ 'selected' if pageNum == userCurrentPage else '' }}>{{ pageNum + 1 }}</option>
|
||||
<option value="{{ pageNum }}"{{ ' selected' if pageNum == userCurrentPage else '' }}>{{ pageNum + 1 }}</option>
|
||||
#endfor
|
||||
</select>
|
||||
</form>
|
||||
|
|
@ -52,7 +53,7 @@
|
|||
</tr>
|
||||
#if users |length > 0
|
||||
#for user in users
|
||||
<tr class="{{ util.rowToggle() }}">
|
||||
<tr class="{{ rowToggle(loop) }}">
|
||||
<td>{{ user.id }}</td>
|
||||
<td><a href="userinfo?userID={{ user.name }}">{{ user.name }}</a></td>
|
||||
<td><a href="packages?userID={{ user.name }}">view</a></td>
|
||||
|
|
@ -72,7 +73,7 @@
|
|||
Page:
|
||||
<select onchange="javascript: window.location = 'users?start=' + this.value * {{ userRange }} + '{{ util.passthrough('order', 'prefix') }}';">
|
||||
#for pageNum in userPages
|
||||
<option value="{{ pageNum }}"{{ 'selected' if pageNum == userCurrentPage else '' }}>{{ pageNum + 1 }}</option>
|
||||
<option value="{{ pageNum }}"{{ ' selected' if pageNum == userCurrentPage else '' }}>{{ pageNum + 1 }}</option>
|
||||
#endfor
|
||||
</select>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ class Dispatcher(object):
|
|||
environ['koji.values'].setdefault('mavenEnabled', False)
|
||||
environ['koji.values'].setdefault('winEnabled', False)
|
||||
# import pdb; pdb.set_trace()
|
||||
result = _genHTML(environ, 'error.html.j2', jinja=True)
|
||||
result = _genHTML(environ, 'error.html.j2')
|
||||
result = self._tobytes(result)
|
||||
headers = [
|
||||
('Allow', 'GET, POST, HEAD'),
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import urllib
|
|||
from collections.abc import Mapping
|
||||
from functools import wraps
|
||||
from socket import error as socket_error
|
||||
from threading import local
|
||||
from urllib.parse import parse_qs
|
||||
from xml.parsers.expat import ExpatError
|
||||
|
||||
|
|
@ -68,7 +69,6 @@ def _initValues(environ, title='Build System Info', pageID='summary'):
|
|||
values['themePath'] = themePath
|
||||
values['toggleOrder'] = toggleOrder
|
||||
values['toggleSelected'] = toggleSelected
|
||||
values['rowToggle'] = rowToggle
|
||||
values['sortImage'] = sortImage
|
||||
values['passthrough'] = passthrough
|
||||
values['passthrough_except'] = passthrough_except
|
||||
|
|
@ -138,10 +138,25 @@ def safe_return(func):
|
|||
return _safe
|
||||
|
||||
|
||||
TEMPLATES = {}
|
||||
# threadlocal cache
|
||||
JINJA_CACHE = local()
|
||||
|
||||
|
||||
def _genHTML(environ, fileName, jinja=True):
|
||||
def get_jinja_env(dirpath):
|
||||
if hasattr(JINJA_CACHE, 'env'):
|
||||
return JINJA_CACHE.env
|
||||
# otherwise
|
||||
env = jinja2.Environment(
|
||||
loader=jinja2.FileSystemLoader(dirpath),
|
||||
autoescape=True,
|
||||
line_statement_prefix='#', # for ease of porting Cheetah templates
|
||||
line_comment_prefix='##'
|
||||
)
|
||||
JINJA_CACHE.env = env
|
||||
return env
|
||||
|
||||
|
||||
def _genHTML(environ, fileName):
|
||||
reqdir = os.path.dirname(environ['SCRIPT_FILENAME'])
|
||||
if os.getcwd() != reqdir:
|
||||
os.chdir(reqdir)
|
||||
|
|
@ -168,18 +183,9 @@ def _genHTML(environ, fileName, jinja=True):
|
|||
else:
|
||||
environ['koji.values']['LoginDisabled'] = False
|
||||
|
||||
if jinja:
|
||||
# TODO clean up and optimize
|
||||
env = jinja2.Environment(
|
||||
loader=jinja2.FileSystemLoader(reqdir),
|
||||
autoescape=True,
|
||||
line_statement_prefix='#', # for ease of porting Cheetah templates
|
||||
line_comment_prefix='##'
|
||||
)
|
||||
template = env.get_template(fileName)
|
||||
return template.render(**environ['koji.values'])
|
||||
else:
|
||||
raise NotImplementedError('no more Cheetah')
|
||||
env = get_jinja_env(reqdir)
|
||||
template = env.get_template(fileName)
|
||||
return template.render(**environ['koji.values'])
|
||||
|
||||
|
||||
def _truncTime():
|
||||
|
|
@ -264,8 +270,15 @@ class FieldCompat:
|
|||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
# compat with jinja 2.x
|
||||
try:
|
||||
pass_context = jinja2.pass_context
|
||||
except AttributeError:
|
||||
pass_context = jinja2.contextfunction
|
||||
# (all our uses are functions, not filters)
|
||||
|
||||
@jinja2.pass_context
|
||||
|
||||
@pass_context
|
||||
def toggleOrder(context, sortKey, orderVar='order'):
|
||||
"""Toggle order for jinja templates"""
|
||||
value = context.get(orderVar)
|
||||
|
|
@ -308,7 +321,7 @@ def toggleSelected(var, option, checked=False):
|
|||
|
||||
|
||||
@safe_return
|
||||
@jinja2.pass_context
|
||||
@pass_context
|
||||
def sortImage(context, sortKey, orderVar='order'):
|
||||
"""jinja version"""
|
||||
orderVal = context.get(orderVar)
|
||||
|
|
@ -331,7 +344,7 @@ def _sortImage(orderVal, sortKey, orderVar):
|
|||
|
||||
|
||||
@safe_return
|
||||
@jinja2.pass_context
|
||||
@pass_context
|
||||
def passthrough(context, *varnames, prefix='&', invert=False):
|
||||
if invert:
|
||||
_PASSTHROUGH = context.get('_PASSTHROUGH', None)
|
||||
|
|
@ -357,7 +370,7 @@ def _passthrough(data, prefix='&'):
|
|||
The prefix value (default '&') is prepended if any values were found
|
||||
"""
|
||||
result = []
|
||||
for var in data:
|
||||
for var in sorted(data):
|
||||
value = data[var]
|
||||
if value is not None:
|
||||
if isinstance(value, str):
|
||||
|
|
@ -374,7 +387,7 @@ def _passthrough(data, prefix='&'):
|
|||
return ''
|
||||
|
||||
|
||||
@jinja2.pass_context
|
||||
@pass_context
|
||||
def passthrough_except(context, *exclude, prefix='&'):
|
||||
"""
|
||||
Construct a string suitable for use as URL
|
||||
|
|
@ -387,7 +400,7 @@ def passthrough_except(context, *exclude, prefix='&'):
|
|||
"""
|
||||
# note that we have to pass context ourselves here
|
||||
# the decorator only works when called directly from the template
|
||||
return passthrough(context, *exclude, prefix='&', invert=True)
|
||||
return passthrough(context, *exclude, prefix=prefix, invert=True)
|
||||
|
||||
|
||||
def sortByKeyFuncNoneGreatest(key):
|
||||
|
|
@ -719,21 +732,6 @@ def formatRPM(rpminfo, link=True):
|
|||
return label
|
||||
|
||||
|
||||
@jinja2.pass_context
|
||||
def rowToggle(context):
|
||||
# XXX avoid modifying context
|
||||
rowNum = getattr(context, '_rowNum', 0) + 1
|
||||
context._rowNum = rowNum
|
||||
return _rowToggle(rowNum)
|
||||
|
||||
|
||||
def _rowToggle(rowNum):
|
||||
if rowNum % 2:
|
||||
return 'row-odd'
|
||||
else:
|
||||
return 'row-even'
|
||||
|
||||
|
||||
def taskScratchClass(task_object):
|
||||
""" Return a css class indicating whether or not this task is a scratch
|
||||
build.
|
||||
|
|
@ -798,7 +796,7 @@ def escapeHTML(value):
|
|||
|
||||
|
||||
@safe_return
|
||||
@jinja2.pass_context
|
||||
@pass_context
|
||||
def authToken(context, first=False, form=False):
|
||||
token = context.get('authToken', None)
|
||||
return _authToken(token, first, form)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue