Get dashboard working and upgrade bootstrap. Note: the bootstrap fixes will be coming in the followup CL
This commit is contained in:
parent
79f39697fe
commit
524705b88c
18 changed files with 429 additions and 260 deletions
|
@ -25,6 +25,9 @@ class DynamicRegistrationComponent(BaseComponent):
|
||||||
logger.debug('Registering new build component+worker with realm %s', realm)
|
logger.debug('Registering new build component+worker with realm %s', realm)
|
||||||
return realm
|
return realm
|
||||||
|
|
||||||
|
def kind(self):
|
||||||
|
return 'registration'
|
||||||
|
|
||||||
|
|
||||||
class EnterpriseManager(BaseManager):
|
class EnterpriseManager(BaseManager):
|
||||||
""" Build manager implementation for the Enterprise Registry. """
|
""" Build manager implementation for the Enterprise Registry. """
|
||||||
|
@ -82,5 +85,7 @@ class EnterpriseManager(BaseManager):
|
||||||
if build_component in self.ready_components:
|
if build_component in self.ready_components:
|
||||||
self.ready_components.remove(build_component)
|
self.ready_components.remove(build_component)
|
||||||
|
|
||||||
|
self.unregister_component(build_component)
|
||||||
|
|
||||||
def num_workers(self):
|
def num_workers(self):
|
||||||
return len(self.all_components)
|
return len(self.all_components)
|
||||||
|
|
|
@ -271,8 +271,6 @@ class EphemeralBuilderManager(BaseManager):
|
||||||
|
|
||||||
def build_component_disposed(self, build_component, timed_out):
|
def build_component_disposed(self, build_component, timed_out):
|
||||||
logger.debug('Calling build_component_disposed.')
|
logger.debug('Calling build_component_disposed.')
|
||||||
|
|
||||||
# TODO make it so that I don't have to unregister the component if it timed out
|
|
||||||
self.unregister_component(build_component)
|
self.unregister_component(build_component)
|
||||||
|
|
||||||
@coroutine
|
@coroutine
|
||||||
|
|
|
@ -70,7 +70,8 @@ class BuilderServer(object):
|
||||||
|
|
||||||
@controller_app.route('/status')
|
@controller_app.route('/status')
|
||||||
def status():
|
def status():
|
||||||
(running_count, available_count) = server._queue.get_metrics()
|
metrics = server._queue.get_metrics(require_transaction=False)
|
||||||
|
(running_count, available_not_running_count, available_count) = metrics
|
||||||
|
|
||||||
workers = [component for component in server._current_components
|
workers = [component for component in server._current_components
|
||||||
if component.kind() == 'builder']
|
if component.kind() == 'builder']
|
||||||
|
@ -80,7 +81,7 @@ class BuilderServer(object):
|
||||||
'running_local': server._job_count,
|
'running_local': server._job_count,
|
||||||
'running_total': running_count,
|
'running_total': running_count,
|
||||||
'workers': len(workers),
|
'workers': len(workers),
|
||||||
'job_total': available_count
|
'job_total': available_count + running_count
|
||||||
}
|
}
|
||||||
|
|
||||||
return json.dumps(data)
|
return json.dumps(data)
|
||||||
|
|
|
@ -6,6 +6,12 @@ from util.morecollections import AttrDict
|
||||||
|
|
||||||
MINIMUM_EXTENSION = timedelta(seconds=20)
|
MINIMUM_EXTENSION = timedelta(seconds=20)
|
||||||
|
|
||||||
|
class NoopWith:
|
||||||
|
def __enter__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
pass
|
||||||
|
|
||||||
class WorkQueue(object):
|
class WorkQueue(object):
|
||||||
def __init__(self, queue_name, transaction_factory,
|
def __init__(self, queue_name, transaction_factory,
|
||||||
|
@ -49,21 +55,32 @@ class WorkQueue(object):
|
||||||
def _item_by_id_for_update(self, queue_id):
|
def _item_by_id_for_update(self, queue_id):
|
||||||
return db_for_update(QueueItem.select().where(QueueItem.id == queue_id)).get()
|
return db_for_update(QueueItem.select().where(QueueItem.id == queue_id)).get()
|
||||||
|
|
||||||
def update_metrics(self):
|
def get_metrics(self, require_transaction=True):
|
||||||
if self._reporter is None:
|
guard = self._transaction_factory(db) if require_transaction else NoopWith()
|
||||||
return
|
with guard:
|
||||||
|
|
||||||
with self._transaction_factory(db):
|
|
||||||
now = datetime.utcnow()
|
now = datetime.utcnow()
|
||||||
name_match_query = self._name_match_query()
|
name_match_query = self._name_match_query()
|
||||||
|
|
||||||
running_query = self._running_jobs(now, name_match_query)
|
running_query = self._running_jobs(now, name_match_query)
|
||||||
running_count = running_query.distinct().count()
|
running_count = running_query.distinct().count()
|
||||||
|
|
||||||
available_query = self._available_jobs_not_running(now, name_match_query, running_query)
|
available_query = self._available_jobs(now, name_match_query)
|
||||||
available_count = available_query.select(QueueItem.queue_name).distinct().count()
|
available_count = available_query.select(QueueItem.queue_name).distinct().count()
|
||||||
|
|
||||||
self._reporter(self._currently_processing, running_count, running_count + available_count)
|
available_not_running_query = self._available_jobs_not_running(now, name_match_query,
|
||||||
|
running_query)
|
||||||
|
available_not_running_count = (available_not_running_query.select(QueueItem.queue_name)
|
||||||
|
.distinct().count())
|
||||||
|
|
||||||
|
return (running_count, available_not_running_count, available_count)
|
||||||
|
|
||||||
|
def update_metrics(self):
|
||||||
|
if self._reporter is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
(running_count, available_not_running_count, available_count) = self.get_metrics()
|
||||||
|
self._reporter(self._currently_processing, running_count,
|
||||||
|
running_count + available_not_running_count)
|
||||||
|
|
||||||
def put(self, canonical_name_list, message, available_after=0, retries_remaining=5):
|
def put(self, canonical_name_list, message, available_after=0, retries_remaining=5):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -50,10 +50,6 @@ class SuperUserRegistryStatus(ApiResource):
|
||||||
@verify_not_prod
|
@verify_not_prod
|
||||||
def get(self):
|
def get(self):
|
||||||
""" Returns the status of the registry. """
|
""" Returns the status of the registry. """
|
||||||
if app.config.get('DEBUGGING', False):
|
|
||||||
return {
|
|
||||||
'status': 'ready'
|
|
||||||
}
|
|
||||||
|
|
||||||
# If there is no conf/stack volume, then report that status.
|
# If there is no conf/stack volume, then report that status.
|
||||||
if not CONFIG_PROVIDER.volume_exists():
|
if not CONFIG_PROVIDER.volume_exists():
|
||||||
|
|
|
@ -47,9 +47,12 @@ def ps():
|
||||||
}
|
}
|
||||||
json_string = json.dumps(data)
|
json_string = json.dumps(data)
|
||||||
yield 'data: %s\n\n' % json_string
|
yield 'data: %s\n\n' % json_string
|
||||||
time.sleep(0.25)
|
time.sleep(1)
|
||||||
|
|
||||||
|
try:
|
||||||
return Response(generator(), mimetype="text/event-stream")
|
return Response(generator(), mimetype="text/event-stream")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ LOCAL_DIRECTORY = 'static/ldn/'
|
||||||
|
|
||||||
EXTERNAL_JS = [
|
EXTERNAL_JS = [
|
||||||
'code.jquery.com/jquery.js',
|
'code.jquery.com/jquery.js',
|
||||||
'netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js',
|
'netdna.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js',
|
||||||
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js',
|
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js',
|
||||||
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-route.min.js',
|
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-route.min.js',
|
||||||
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-sanitize.min.js',
|
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-sanitize.min.js',
|
||||||
|
@ -19,7 +19,7 @@ EXTERNAL_JS = [
|
||||||
|
|
||||||
EXTERNAL_CSS = [
|
EXTERNAL_CSS = [
|
||||||
'netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.css',
|
'netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.css',
|
||||||
'netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.no-icons.min.css',
|
'netdna.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css',
|
||||||
'fonts.googleapis.com/css?family=Source+Sans+Pro:400,700',
|
'fonts.googleapis.com/css?family=Source+Sans+Pro:400,700',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -705,5 +705,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.realtime-area-chart, .realtime-line-chart {
|
.realtime-area-chart, .realtime-line-chart {
|
||||||
display: inline-block;
|
margin: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rickshaw_graph {
|
||||||
|
overflow: hidden;
|
||||||
|
padding-bottom: 40px;
|
||||||
}
|
}
|
|
@ -4972,3 +4972,9 @@ i.slack-icon {
|
||||||
left: 16px;
|
left: 16px;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chart-col h4, .chart-col h5 {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="config-setup-tool-element">
|
<div class="config-setup-tool-element">
|
||||||
<div class="quay-spinner" ng-if="!config"></div>
|
<div class="cor-loader" ng-if="!config"></div>
|
||||||
<div ng-show="config && config['SUPER_USERS']">
|
<div ng-show="config && config['SUPER_USERS']">
|
||||||
<form id="configform" name="configform">
|
<form id="configform" name="configform">
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Authentication for the registry can be handled by either the registry itself or LDAP.
|
Authentication for the registry can be handled by either the registry itself or LDAP.
|
||||||
External authentication providers (such as Github) can be used on top of this choice.
|
External authentication providers (such as GitHub) can be used on top of this choice.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -339,20 +339,20 @@
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- /Authentication -->
|
</div> <!-- /Authentication -->
|
||||||
|
|
||||||
<!-- Github Authentication -->
|
<!-- GitHub Authentication -->
|
||||||
<div class="co-panel">
|
<div class="co-panel">
|
||||||
<div class="co-panel-heading">
|
<div class="co-panel-heading">
|
||||||
<i class="fa fa-github"></i> Github (Enterprise) Authentication
|
<i class="fa fa-github"></i> GitHub (Enterprise) Authentication
|
||||||
</div>
|
</div>
|
||||||
<div class="co-panel-body">
|
<div class="co-panel-body">
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
If enabled, users can use Github or Github Enterprise to authenticate to the registry.
|
If enabled, users can use GitHub or GitHub Enterprise to authenticate to the registry.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<strong>Note:</strong> A registered Github (Enterprise) OAuth application is required.
|
<strong>Note:</strong> A registered GitHub (Enterprise) OAuth application is required.
|
||||||
View instructions on how to
|
View instructions on how to
|
||||||
<a href="https://coreos.com/docs/enterprise-registry/github-auth/" target="_blank">
|
<a href="https://coreos.com/docs/enterprise-registry/github-app/" target="_blank">
|
||||||
Create an OAuth Application in GitHub
|
Create an OAuth Application in GitHub
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -360,21 +360,21 @@
|
||||||
|
|
||||||
<div class="co-checkbox">
|
<div class="co-checkbox">
|
||||||
<input id="ftghl" type="checkbox" ng-model="config.FEATURE_GITHUB_LOGIN">
|
<input id="ftghl" type="checkbox" ng-model="config.FEATURE_GITHUB_LOGIN">
|
||||||
<label for="ftghl">Enable Github Authentication</label>
|
<label for="ftghl">Enable GitHub Authentication</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="config-table" ng-if="config.FEATURE_GITHUB_LOGIN">
|
<table class="config-table" ng-if="config.FEATURE_GITHUB_LOGIN">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Github:</td>
|
<td>GitHub:</td>
|
||||||
<td>
|
<td>
|
||||||
<select ng-model="mapped.GITHUB_LOGIN_KIND">
|
<select ng-model="mapped.GITHUB_LOGIN_KIND">
|
||||||
<option value="hosted">Github.com</option>
|
<option value="hosted">GitHub.com</option>
|
||||||
<option value="enterprise">Github Enterprise</option>
|
<option value="enterprise">GitHub Enterprise</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ng-if="mapped.GITHUB_LOGIN_KIND == 'enterprise'">
|
<tr ng-if="mapped.GITHUB_LOGIN_KIND == 'enterprise'">
|
||||||
<td>Github Endpoint:</td>
|
<td>GitHub Endpoint:</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="config-string-field"
|
<span class="config-string-field"
|
||||||
binding="config.GITHUB_LOGIN_CONFIG.GITHUB_ENDPOINT"
|
binding="config.GITHUB_LOGIN_CONFIG.GITHUB_ENDPOINT"
|
||||||
|
@ -382,7 +382,7 @@
|
||||||
pattern="{{ GITHUB_REGEX }}">
|
pattern="{{ GITHUB_REGEX }}">
|
||||||
</span>
|
</span>
|
||||||
<div class="help-text">
|
<div class="help-text">
|
||||||
The Github Enterprise endpoint. Must start with http:// or https://.
|
The GitHub Enterprise endpoint. Must start with http:// or https://.
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -402,7 +402,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- /Github Authentication -->
|
</div> <!-- /GitHub Authentication -->
|
||||||
|
|
||||||
<!-- Google Authentication -->
|
<!-- Google Authentication -->
|
||||||
<div class="co-panel">
|
<div class="co-panel">
|
||||||
|
@ -471,20 +471,20 @@
|
||||||
</div> <!-- /Build Support -->
|
</div> <!-- /Build Support -->
|
||||||
|
|
||||||
|
|
||||||
<!-- Github Trigger -->
|
<!-- GitHub Trigger -->
|
||||||
<div class="co-panel" ng-if="config.FEATURE_BUILD_SUPPORT" style="margin-top: 20px;">
|
<div class="co-panel" ng-if="config.FEATURE_BUILD_SUPPORT" style="margin-top: 20px;">
|
||||||
<div class="co-panel-heading">
|
<div class="co-panel-heading">
|
||||||
<i class="fa fa-github"></i> Github (Enterprise) Build Triggers
|
<i class="fa fa-github"></i> GitHub (Enterprise) Build Triggers
|
||||||
</div>
|
</div>
|
||||||
<div class="co-panel-body">
|
<div class="co-panel-body">
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
If enabled, users can setup Github or Github Enterprise triggers to invoke Registry builds.
|
If enabled, users can setup GitHub or GitHub Enterprise triggers to invoke Registry builds.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<strong>Note:</strong> A registered Github (Enterprise) OAuth application (<strong>separate from Github Authentication</strong>) is required.
|
<strong>Note:</strong> A registered GitHub (Enterprise) OAuth application (<strong>separate from GitHub Authentication</strong>) is required.
|
||||||
View instructions on how to
|
View instructions on how to
|
||||||
<a href="https://coreos.com/docs/enterprise-registry/github-auth/" target="_blank">
|
<a href="https://coreos.com/docs/enterprise-registry/github-app/" target="_blank">
|
||||||
Create an OAuth Application in GitHub
|
Create an OAuth Application in GitHub
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -492,21 +492,21 @@
|
||||||
|
|
||||||
<div class="co-checkbox">
|
<div class="co-checkbox">
|
||||||
<input id="ftgb" type="checkbox" ng-model="config.FEATURE_GITHUB_BUILD">
|
<input id="ftgb" type="checkbox" ng-model="config.FEATURE_GITHUB_BUILD">
|
||||||
<label for="ftgb">Enable Github Triggers</label>
|
<label for="ftgb">Enable GitHub Triggers</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="config-table" ng-if="config.FEATURE_GITHUB_BUILD">
|
<table class="config-table" ng-if="config.FEATURE_GITHUB_BUILD">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Github:</td>
|
<td>GitHub:</td>
|
||||||
<td>
|
<td>
|
||||||
<select ng-model="mapped.GITHUB_TRIGGER_KIND">
|
<select ng-model="mapped.GITHUB_TRIGGER_KIND">
|
||||||
<option value="hosted">Github.com</option>
|
<option value="hosted">GitHub.com</option>
|
||||||
<option value="enterprise">Github Enterprise</option>
|
<option value="enterprise">GitHub Enterprise</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ng-if="mapped.GITHUB_TRIGGER_KIND == 'enterprise'">
|
<tr ng-if="mapped.GITHUB_TRIGGER_KIND == 'enterprise'">
|
||||||
<td>Github Endpoint:</td>
|
<td>GitHub Endpoint:</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="config-string-field"
|
<span class="config-string-field"
|
||||||
binding="config.GITHUB_TRIGGER_CONFIG.GITHUB_ENDPOINT"
|
binding="config.GITHUB_TRIGGER_CONFIG.GITHUB_ENDPOINT"
|
||||||
|
@ -514,7 +514,7 @@
|
||||||
pattern="{{ GITHUB_REGEX }}">
|
pattern="{{ GITHUB_REGEX }}">
|
||||||
</span>
|
</span>
|
||||||
<div class="help-text">
|
<div class="help-text">
|
||||||
The Github Enterprise endpoint. Must start with http:// or https://.
|
The GitHub Enterprise endpoint. Must start with http:// or https://.
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -534,7 +534,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- /Github Trigger -->
|
</div> <!-- /GitHub Trigger -->
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<!-- Save Bar -->
|
<!-- Save Bar -->
|
||||||
|
|
|
@ -1,39 +1,75 @@
|
||||||
<div class="ps-usage-graph-element">
|
<div class="ps-usage-graph-element">
|
||||||
<div quay-show="Features.BUILD_SUPPORT" ng-if="data.build && data.build.job_total">
|
<!-- Build Charts -->
|
||||||
Build Workers:
|
<div quay-show="Features.BUILD_SUPPORT">
|
||||||
|
<div class="alert alert-warning" ng-if="data.build && data.build.job_total == null">
|
||||||
|
Cannot load build system status. Please restart your container.
|
||||||
|
</div>
|
||||||
|
<div ng-if="data.build && data.build.job_total >= 0">
|
||||||
|
<div class="col-md-6 chart-col">
|
||||||
|
<h4>Build Queue</h4>
|
||||||
|
<h5>
|
||||||
|
Running Jobs: {{ data.build.running_total }} | Total Jobs: {{ data.build.job_total }}
|
||||||
|
</h5>
|
||||||
<div class="realtime-area-chart"
|
<div class="realtime-area-chart"
|
||||||
data="[data.build.job_total, data.build.running_total]"
|
data="[data.build.job_total, data.build.running_total]"
|
||||||
labels="['Queued Build Jobs', 'Running Build Jobs']"
|
labels="['Queued Build Jobs', 'Running Build Jobs']"
|
||||||
colors="['rgb(157, 194, 211)', 'rgb(56, 122, 163)']"
|
colors="['rgb(157, 194, 211)', 'rgb(56, 122, 163)']"
|
||||||
counter="counter"></div>
|
counter="counter"
|
||||||
|
minimum="-10"
|
||||||
|
maximum="auto"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 chart-col">
|
||||||
|
<h4>Local Build Workers</h4>
|
||||||
|
<h5>
|
||||||
|
Local Workers: {{ data.build.workers }} | Working: {{ data.build.running_local }}
|
||||||
|
</h5>
|
||||||
<div class="realtime-area-chart"
|
<div class="realtime-area-chart"
|
||||||
data="[data.build.job_total, data.build.workers, data.build.running_local]"
|
data="[data.build.job_total, data.build.workers, data.build.running_local]"
|
||||||
labels="['Queued Build Jobs', 'Build Workers (local)', 'Running Build Jobs (local)']"
|
labels="['Queued Build Jobs', 'Build Workers (local)', 'Running Build Jobs (local)']"
|
||||||
colors="['rgb(157, 194, 211)', 'rgb(161, 208, 93)', 'rgb(210, 237, 130)']"
|
colors="['rgb(157, 194, 211)', 'rgb(161, 208, 93)', 'rgb(210, 237, 130)']"
|
||||||
counter="counter"></div>
|
counter="counter"
|
||||||
|
minimum="-10"
|
||||||
|
maximum="auto"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
CPU:
|
<!-- CPU, Memory and Network -->
|
||||||
|
<div class="col-md-4 chart-col">
|
||||||
|
<h4>CPU Usage %</h4>
|
||||||
<div class="realtime-line-chart" data="data.count.cpu" counter="counter"
|
<div class="realtime-line-chart" data="data.count.cpu" counter="counter"
|
||||||
label-template="CPU #{x} %"></div>
|
label-template="CPU #{x} %"
|
||||||
|
minimum="-10" maximum="110"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
Process Count:
|
<div class="col-md-4 chart-col">
|
||||||
|
<h4>Process Count</h4>
|
||||||
<div class="realtime-line-chart" data="data.count.processes" counter="counter"
|
<div class="realtime-line-chart" data="data.count.processes" counter="counter"
|
||||||
label-template="Process Count"></div>
|
label-template="Process Count"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
Virtual Memory:
|
<div class="col-md-4 chart-col">
|
||||||
|
<h4>Virtual Memory %</h4>
|
||||||
<div class="realtime-line-chart" data="data.count.virtual_mem[2]" counter="counter"
|
<div class="realtime-line-chart" data="data.count.virtual_mem[2]" counter="counter"
|
||||||
label-template="Virtual Memory %"></div>
|
label-template="Virtual Memory %"
|
||||||
|
minimum="-10" maximum="110"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
Swap Memory:
|
<div class="col-md-4 chart-col">
|
||||||
|
<h4>Swap Memory</h4>
|
||||||
<div class="realtime-line-chart" data="data.count.swap_mem[3]" counter="counter"
|
<div class="realtime-line-chart" data="data.count.swap_mem[3]" counter="counter"
|
||||||
label-template="Swap Memory %"></div>
|
label-template="Swap Memory %"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
Network Connections:
|
<div class="col-md-4 chart-col">
|
||||||
|
<h4>Network Connections</h4>
|
||||||
<div class="realtime-line-chart" data="data.count.connections" counter="counter"
|
<div class="realtime-line-chart" data="data.count.connections" counter="counter"
|
||||||
label-template="Network Connection Count"></div>
|
label-template="Network Connection Count"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
Network Usage:
|
<div class="col-md-4 chart-col">
|
||||||
|
<h4>Network Usage (Bytes)</h4>
|
||||||
<div class="realtime-line-chart" data="data.count.network" labels="['Bytes In', 'Bytes Out']" counter="counter"></div>
|
<div class="realtime-line-chart" data="data.count.network" labels="['Bytes In', 'Bytes Out']" counter="counter"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -1,3 +1,6 @@
|
||||||
<div class="realtime-area-chart-element">
|
<div class="realtime-area-chart-element">
|
||||||
<div class="chart" style="width: 450px; height: 250px;"></div>
|
<div ng-show="counter >= 1">
|
||||||
|
<div class="chart"></div>
|
||||||
|
</div>
|
||||||
|
<div class="cor-loader-inline" ng-if="counter < 1"></div>
|
||||||
</div>
|
</div>
|
|
@ -1,3 +1,6 @@
|
||||||
<div class="realtime-line-chart-element">
|
<div class="realtime-line-chart-element">
|
||||||
<div class="chart" style="width: 450px; height: 250px;"></div>
|
<div ng-show="counter >= 1">
|
||||||
|
<div class="chart"></div>
|
||||||
|
</div>
|
||||||
|
<div class="cor-loader-inline" ng-if="counter < 1"></div>
|
||||||
</div>
|
</div>
|
196
static/js/app.js
196
static/js/app.js
|
@ -6602,178 +6602,6 @@ quayApp.directive('locationView', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
quayApp.directive('realtimeAreaChart', function () {
|
|
||||||
var directiveDefinitionObject = {
|
|
||||||
priority: 0,
|
|
||||||
templateUrl: '/static/directives/realtime-area-chart.html',
|
|
||||||
replace: false,
|
|
||||||
transclude: false,
|
|
||||||
restrict: 'C',
|
|
||||||
scope: {
|
|
||||||
'data': '=data',
|
|
||||||
'labels': '=labels',
|
|
||||||
'colors': '=colors',
|
|
||||||
'counter': '=counter'
|
|
||||||
},
|
|
||||||
controller: function($scope, $element) {
|
|
||||||
var graph = null;
|
|
||||||
var series = [];
|
|
||||||
var palette = new Rickshaw.Color.Palette( { scheme: 'spectrum14' } );
|
|
||||||
var colors = $scope.colors || [];
|
|
||||||
|
|
||||||
var setupGraph = function() {
|
|
||||||
for (var i = 0; i < $scope.labels.length; ++i) {
|
|
||||||
series.push({
|
|
||||||
name: $scope.labels[i],
|
|
||||||
color: i >= colors.length ? palette.color(): $scope.colors[i],
|
|
||||||
stroke: 'rgba(0,0,0,0.15)',
|
|
||||||
data: []
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
graph = new Rickshaw.Graph( {
|
|
||||||
element: $element.find('.chart')[0],
|
|
||||||
renderer: 'area',
|
|
||||||
stroke: true,
|
|
||||||
series: series,
|
|
||||||
min: 0
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var refresh = function(data) {
|
|
||||||
if (!data || $scope.counter < 0) { return; }
|
|
||||||
if (!graph) {
|
|
||||||
setupGraph();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < $scope.data.length; ++i) {
|
|
||||||
series[i].data.push(
|
|
||||||
{'x': $scope.counter, 'y': $scope.data[i] }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
hoverDetail = new Rickshaw.Graph.HoverDetail({
|
|
||||||
graph: graph,
|
|
||||||
xFormatter: function(x) {
|
|
||||||
return x.toString();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
graph.renderer.unstack = true;
|
|
||||||
graph.render();
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.$watch('counter', function() {
|
|
||||||
refresh($scope.data_raw);
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$watch('data', function(data) {
|
|
||||||
$scope.data_raw = data;
|
|
||||||
refresh($scope.data_raw);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return directiveDefinitionObject;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
quayApp.directive('realtimeLineChart', function () {
|
|
||||||
var directiveDefinitionObject = {
|
|
||||||
priority: 0,
|
|
||||||
templateUrl: '/static/directives/realtime-line-chart.html',
|
|
||||||
replace: false,
|
|
||||||
transclude: false,
|
|
||||||
restrict: 'C',
|
|
||||||
scope: {
|
|
||||||
'data': '=data',
|
|
||||||
'labels': '=labels',
|
|
||||||
'counter': '=counter',
|
|
||||||
'labelTemplate': '@labelTemplate'
|
|
||||||
},
|
|
||||||
controller: function($scope, $element) {
|
|
||||||
var graph = null;
|
|
||||||
var hoverDetail = null;
|
|
||||||
var series = [];
|
|
||||||
var counter = 0;
|
|
||||||
var palette = new Rickshaw.Color.Palette( { scheme: 'spectrum14' } );
|
|
||||||
|
|
||||||
var setupGraph = function() {
|
|
||||||
graph = new Rickshaw.Graph({
|
|
||||||
element: $element.find('.chart')[0],
|
|
||||||
renderer: 'line',
|
|
||||||
series: series,
|
|
||||||
min: 'auto',
|
|
||||||
padding: {
|
|
||||||
'top': 0.1,
|
|
||||||
'left': 0.01,
|
|
||||||
'right': 0.01,
|
|
||||||
'bottom': 0.1
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
hoverDetail = new Rickshaw.Graph.HoverDetail({
|
|
||||||
graph: graph,
|
|
||||||
xFormatter: function(x) {
|
|
||||||
return x.toString();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var refresh = function(data) {
|
|
||||||
if (!data) { return; }
|
|
||||||
if (!graph) {
|
|
||||||
setupGraph();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data == 'number') {
|
|
||||||
data = [data];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope.labels) {
|
|
||||||
data = data.slice(0, $scope.labels.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (series.length == 0){
|
|
||||||
for (var i = 0; i < data.length; ++i) {
|
|
||||||
var title = $scope.labels ? $scope.labels[i] : $scope.labelTemplate.replace('{x}', i + 1);
|
|
||||||
series.push({
|
|
||||||
'color': palette.color(),
|
|
||||||
'data': [],
|
|
||||||
'name': title
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
counter++;
|
|
||||||
|
|
||||||
for (var i = 0; i < data.length; ++i) {
|
|
||||||
var arr = series[i].data;
|
|
||||||
arr.push({
|
|
||||||
'x': counter,
|
|
||||||
'y': data[i]
|
|
||||||
})
|
|
||||||
|
|
||||||
if (arr.length > 10) {
|
|
||||||
series[i].data = arr.slice(arr.length - 10, arr.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graph.render();
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.$watch('counter', function(counter) {
|
|
||||||
refresh($scope.data_raw);
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$watch('data', function(data) {
|
|
||||||
$scope.data_raw = data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return directiveDefinitionObject;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
quayApp.directive('psUsageGraph', function () {
|
quayApp.directive('psUsageGraph', function () {
|
||||||
var directiveDefinitionObject = {
|
var directiveDefinitionObject = {
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
@ -6782,18 +6610,40 @@ quayApp.directive('psUsageGraph', function () {
|
||||||
transclude: false,
|
transclude: false,
|
||||||
restrict: 'C',
|
restrict: 'C',
|
||||||
scope: {
|
scope: {
|
||||||
|
'isEnabled': '=isEnabled'
|
||||||
},
|
},
|
||||||
controller: function($scope, $element) {
|
controller: function($scope, $element) {
|
||||||
$scope.counter = -1;
|
$scope.counter = -1;
|
||||||
$scope.data = null;
|
$scope.data = null;
|
||||||
|
|
||||||
var source = new EventSource('/realtime/ps');
|
var source = null;
|
||||||
|
|
||||||
|
var connect = function() {
|
||||||
|
if (source) { return; }
|
||||||
|
source = new EventSource('/realtime/ps');
|
||||||
source.onmessage = function(e) {
|
source.onmessage = function(e) {
|
||||||
$scope.$apply(function() {
|
$scope.$apply(function() {
|
||||||
$scope.counter++;
|
$scope.counter++;
|
||||||
$scope.data = JSON.parse(e.data);
|
$scope.data = JSON.parse(e.data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var disconnect = function() {
|
||||||
|
if (!source) { return; }
|
||||||
|
source.close();
|
||||||
|
source = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$watch('isEnabled', function(value) {
|
||||||
|
if (value) {
|
||||||
|
connect();
|
||||||
|
} else {
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on("$destroy", disconnect);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return directiveDefinitionObject;
|
return directiveDefinitionObject;
|
||||||
|
|
|
@ -17,6 +17,11 @@ function SuperUserAdminCtrl($scope, $timeout, ApiService, Features, UserService,
|
||||||
$scope.pollChannel = null;
|
$scope.pollChannel = null;
|
||||||
$scope.logsScrolled = false;
|
$scope.logsScrolled = false;
|
||||||
$scope.csrf_token = encodeURIComponent(window.__token);
|
$scope.csrf_token = encodeURIComponent(window.__token);
|
||||||
|
$scope.dashboardActive = false;
|
||||||
|
|
||||||
|
$scope.setDashboardActive = function(active) {
|
||||||
|
$scope.dashboardActive = active;
|
||||||
|
};
|
||||||
|
|
||||||
$scope.configurationSaved = function() {
|
$scope.configurationSaved = function() {
|
||||||
$scope.requiresRestart = true;
|
$scope.requiresRestart = true;
|
||||||
|
|
|
@ -307,10 +307,10 @@ angular.module("core-config-setup", ['angularFileUpload'])
|
||||||
if (!value) { return; }
|
if (!value) { return; }
|
||||||
|
|
||||||
ApiService.scGetConfig().then(function(resp) {
|
ApiService.scGetConfig().then(function(resp) {
|
||||||
$scope.config = resp['config'];
|
$scope.config = resp['config'] || {};
|
||||||
initializeMappedLogic($scope.config);
|
initializeMappedLogic($scope.config);
|
||||||
$scope.mapped['$hasChanges'] = false;
|
$scope.mapped['$hasChanges'] = false;
|
||||||
});
|
}, ApiService.errorDisplay('Could not load config'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -270,9 +270,18 @@ angular.module("core-ui", [])
|
||||||
'tabActive': '@tabActive',
|
'tabActive': '@tabActive',
|
||||||
'tabTitle': '@tabTitle',
|
'tabTitle': '@tabTitle',
|
||||||
'tabTarget': '@tabTarget',
|
'tabTarget': '@tabTarget',
|
||||||
'tabInit': '&tabInit'
|
'tabInit': '&tabInit',
|
||||||
|
'tabShown': '&tabShown',
|
||||||
|
'tabHidden': '&tabHidden'
|
||||||
},
|
},
|
||||||
controller: function($rootScope, $scope, $element) {
|
controller: function($rootScope, $scope, $element) {
|
||||||
|
$element.find('a[data-toggle="tab"]').on('hidden.bs.tab', function (e) {
|
||||||
|
$scope.tabHidden({});
|
||||||
|
});
|
||||||
|
|
||||||
|
$element.find('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||||
|
$scope.tabShown({});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return directiveDefinitionObject;
|
return directiveDefinitionObject;
|
||||||
|
@ -297,6 +306,236 @@ angular.module("core-ui", [])
|
||||||
return directiveDefinitionObject;
|
return directiveDefinitionObject;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.directive('realtimeAreaChart', function () {
|
||||||
|
var directiveDefinitionObject = {
|
||||||
|
priority: 0,
|
||||||
|
templateUrl: '/static/directives/realtime-area-chart.html',
|
||||||
|
replace: false,
|
||||||
|
transclude: false,
|
||||||
|
restrict: 'C',
|
||||||
|
scope: {
|
||||||
|
'data': '=data',
|
||||||
|
'labels': '=labels',
|
||||||
|
'colors': '=colors',
|
||||||
|
'counter': '=counter'
|
||||||
|
},
|
||||||
|
controller: function($scope, $element) {
|
||||||
|
var graph = null;
|
||||||
|
var series = [];
|
||||||
|
var palette = new Rickshaw.Color.Palette( { scheme: 'spectrum14' } );
|
||||||
|
var colors = $scope.colors || [];
|
||||||
|
|
||||||
|
var setupGraph = function() {
|
||||||
|
for (var i = 0; i < $scope.labels.length; ++i) {
|
||||||
|
series.push({
|
||||||
|
name: $scope.labels[i],
|
||||||
|
color: i >= colors.length ? palette.color(): $scope.colors[i],
|
||||||
|
stroke: 'rgba(0,0,0,0.15)',
|
||||||
|
data: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
element: $element.find('.chart')[0],
|
||||||
|
renderer: 'area',
|
||||||
|
stroke: true,
|
||||||
|
series: series,
|
||||||
|
min: 0,
|
||||||
|
padding: {
|
||||||
|
'top': 0.3,
|
||||||
|
'left': 0,
|
||||||
|
'right': 0,
|
||||||
|
'bottom': 0.3
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($scope.minimum != null) {
|
||||||
|
options['min'] = $scope.minimum == 'auto' ? 'auto' : $scope.minimum * 1;
|
||||||
|
} else {
|
||||||
|
options['min'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($scope.maximum != null) {
|
||||||
|
options['max'] = $scope.maximum == 'auto' ? 'auto' : $scope.maximum * 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
graph = new Rickshaw.Graph(options);
|
||||||
|
|
||||||
|
xaxes = new Rickshaw.Graph.Axis.Time({
|
||||||
|
graph: graph,
|
||||||
|
timeFixture: new Rickshaw.Fixtures.Time.Local()
|
||||||
|
});
|
||||||
|
|
||||||
|
yaxes = new Rickshaw.Graph.Axis.Y({
|
||||||
|
graph: graph,
|
||||||
|
tickFormat: Rickshaw.Fixtures.Number.formatKMBT
|
||||||
|
});
|
||||||
|
|
||||||
|
hoverDetail = new Rickshaw.Graph.HoverDetail({
|
||||||
|
graph: graph,
|
||||||
|
xFormatter: function(x) {
|
||||||
|
return new Date(x * 1000).toString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var refresh = function(data) {
|
||||||
|
if (!data || $scope.counter < 0) { return; }
|
||||||
|
if (!graph) {
|
||||||
|
setupGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
var timecode = new Date().getTime() / 1000;
|
||||||
|
for (var i = 0; i < $scope.data.length; ++i) {
|
||||||
|
var arr = series[i].data;
|
||||||
|
arr.push(
|
||||||
|
{'x': timecode, 'y': $scope.data[i] }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (arr.length > 10) {
|
||||||
|
series[i].data = arr.slice(arr.length - 10, arr.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
graph.renderer.unstack = true;
|
||||||
|
graph.update();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$watch('counter', function() {
|
||||||
|
refresh($scope.data_raw);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$watch('data', function(data) {
|
||||||
|
$scope.data_raw = data;
|
||||||
|
refresh($scope.data_raw);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return directiveDefinitionObject;
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
.directive('realtimeLineChart', function () {
|
||||||
|
var directiveDefinitionObject = {
|
||||||
|
priority: 0,
|
||||||
|
templateUrl: '/static/directives/realtime-line-chart.html',
|
||||||
|
replace: false,
|
||||||
|
transclude: false,
|
||||||
|
restrict: 'C',
|
||||||
|
scope: {
|
||||||
|
'data': '=data',
|
||||||
|
'labels': '=labels',
|
||||||
|
'counter': '=counter',
|
||||||
|
'labelTemplate': '@labelTemplate',
|
||||||
|
'minimum': '@minimum',
|
||||||
|
'maximum': '@maximum'
|
||||||
|
},
|
||||||
|
controller: function($scope, $element) {
|
||||||
|
var graph = null;
|
||||||
|
var xaxes = null;
|
||||||
|
var yaxes = null;
|
||||||
|
var hoverDetail = null;
|
||||||
|
var series = [];
|
||||||
|
var counter = 0;
|
||||||
|
var palette = new Rickshaw.Color.Palette( { scheme: 'spectrum14' } );
|
||||||
|
|
||||||
|
var setupGraph = function() {
|
||||||
|
var options = {
|
||||||
|
element: $element.find('.chart')[0],
|
||||||
|
renderer: 'line',
|
||||||
|
series: series,
|
||||||
|
padding: {
|
||||||
|
'top': 0.3,
|
||||||
|
'left': 0,
|
||||||
|
'right': 0,
|
||||||
|
'bottom': 0.3
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($scope.minimum != null) {
|
||||||
|
options['min'] = $scope.minimum == 'auto' ? 'auto' : $scope.minimum * 1;
|
||||||
|
} else {
|
||||||
|
options['min'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($scope.maximum != null) {
|
||||||
|
options['max'] = $scope.maximum == 'auto' ? 'auto' : $scope.maximum * 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
graph = new Rickshaw.Graph(options);
|
||||||
|
xaxes = new Rickshaw.Graph.Axis.Time({
|
||||||
|
graph: graph,
|
||||||
|
timeFixture: new Rickshaw.Fixtures.Time.Local()
|
||||||
|
});
|
||||||
|
|
||||||
|
yaxes = new Rickshaw.Graph.Axis.Y({
|
||||||
|
graph: graph,
|
||||||
|
tickFormat: Rickshaw.Fixtures.Number.formatKMBT
|
||||||
|
});
|
||||||
|
|
||||||
|
hoverDetail = new Rickshaw.Graph.HoverDetail({
|
||||||
|
graph: graph,
|
||||||
|
xFormatter: function(x) {
|
||||||
|
return new Date(x * 1000).toString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var refresh = function(data) {
|
||||||
|
if (data == null) { return; }
|
||||||
|
if (!graph) {
|
||||||
|
setupGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof data == 'number') {
|
||||||
|
data = [data];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($scope.labels) {
|
||||||
|
data = data.slice(0, $scope.labels.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (series.length == 0){
|
||||||
|
for (var i = 0; i < data.length; ++i) {
|
||||||
|
var title = $scope.labels ? $scope.labels[i] : $scope.labelTemplate.replace('{x}', i + 1);
|
||||||
|
series.push({
|
||||||
|
'color': palette.color(),
|
||||||
|
'data': [],
|
||||||
|
'name': title
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
var timecode = new Date().getTime() / 1000;
|
||||||
|
|
||||||
|
for (var i = 0; i < data.length; ++i) {
|
||||||
|
var arr = series[i].data;
|
||||||
|
arr.push({
|
||||||
|
'x': timecode,
|
||||||
|
'y': data[i]
|
||||||
|
})
|
||||||
|
|
||||||
|
if (arr.length > 10) {
|
||||||
|
series[i].data = arr.slice(arr.length - 10, arr.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
graph.update();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$watch('counter', function(counter) {
|
||||||
|
refresh($scope.data_raw);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$watch('data', function(data) {
|
||||||
|
$scope.data_raw = data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return directiveDefinitionObject;
|
||||||
|
})
|
||||||
|
|
||||||
.directive('corStepBar', function() {
|
.directive('corStepBar', function() {
|
||||||
var directiveDefinitionObject = {
|
var directiveDefinitionObject = {
|
||||||
priority: 4,
|
priority: 4,
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
tab-target="#users" tab-init="loadUsers()">
|
tab-target="#users" tab-init="loadUsers()">
|
||||||
<i class="fa fa-group"></i>
|
<i class="fa fa-group"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="cor-tab" tab-title="Dashboard" tab-target="#dashboard">
|
<span class="cor-tab" tab-title="Dashboard" tab-target="#dashboard"
|
||||||
|
tab-shown="setDashboardActive(true)" tab-hidden="setDashboardActive(false)">
|
||||||
<i class="fa fa-tachometer"></i>
|
<i class="fa fa-tachometer"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="cor-tab" tab-title="Container Usage" tab-target="#usage-counter" tab-init="getUsage()">
|
<span class="cor-tab" tab-title="Container Usage" tab-target="#usage-counter" tab-init="getUsage()">
|
||||||
|
@ -47,7 +48,7 @@
|
||||||
|
|
||||||
<!-- Dashboard tab -->
|
<!-- Dashboard tab -->
|
||||||
<div id="dashboard" class="tab-pane">
|
<div id="dashboard" class="tab-pane">
|
||||||
<div class="ps-usage-graph" is-enabled="true"></div>
|
<div class="ps-usage-graph" is-enabled="dashboardActive"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Debugging tab -->
|
<!-- Debugging tab -->
|
||||||
|
|
Reference in a new issue