1%{-- 2 - Copyright 2016 SimplifyOps, Inc. (http://simplifyops.com) 3 - 4 - Licensed under the Apache License, Version 2.0 (the "License"); 5 - you may not use this file except in compliance with the License. 6 - You may obtain a copy of the License at 7 - 8 - http://www.apache.org/licenses/LICENSE-2.0 9 - 10 - Unless required by applicable law or agreed to in writing, software 11 - distributed under the License is distributed on an "AS IS" BASIS, 12 - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 - See the License for the specific language governing permissions and 14 - limitations under the License. 15 --}% 16 17<%@ page import="grails.util.Environment; rundeck.User; com.dtolabs.rundeck.server.authorization.AuthConstants" %> 18<html> 19<head> 20 <g:set var="ukey" value="${g.rkey()}" /> 21 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 22 <meta name="layout" content="base"/> 23 <meta name="tabpage" content="nodes"/> 24 <g:set var="projectName" value="${params.project ?: request.project}"></g:set> 25 <g:set var="projectLabel" value="${session.frameworkLabels?session.frameworkLabels[projectName]:projectName}"/> 26 <title><g:message code="gui.menu.Nodes"/> - <g:enc>${projectLabel}</g:enc></title> 27 <asset:javascript src="framework/nodes.js"/> 28 <g:if test="${grails.util.Environment.current==grails.util.Environment.DEVELOPMENT}"> 29 <asset:javascript src="nodeFiltersKOTest.js"/> 30 </g:if> 31 <g:embedJSON id="filterParamsJSON" 32 data="${[filterName: params.filterName, filter: query?.filter, filterAll: params.showall in ['true', true]]}"/> 33 <g:embedJSON id="pageParams" 34 data="${[pagingMax:params.int('max')?:20, project:params.project?:request.project]}"/> 35 36 <g:jsMessages code="Node,Node.plural"/> 37</head> 38<body> 39 40<g:if test="${session.user && User.findByLogin(session.user)?.nodefilters}"> 41 <g:set var="filterset" value="${User.findByLogin(session.user)?.nodefilters}"/> 42</g:if> 43<div id="nodesContent"> 44 <g:set var="run_authorized" value="${auth.adhocAllowedTest( action:AuthConstants.ACTION_RUN,project: params.project ?: request.project)}"/> 45 <g:set var="job_create_authorized" value="${auth.resourceAllowedTest(kind:'job', action: AuthConstants.ACTION_CREATE,project: params.project ?: request.project)}"/> 46 <g:render template="/common/messages"/> 47 48 <div class=" collapse" id="queryFilterHelp"> 49 <div class="help-block"> 50 <g:render template="/common/nodefilterStringHelp"/> 51 </div> 52 </div> 53 54 %{--Form for saving/deleting node filters--}% 55 56 <g:form class="form form-horizontal" useToken="true"> 57 <g:hiddenField name="project" value="${params.project}"/> 58 <g:render template="nodeFiltersHidden"/> 59 <g:render template="/common/queryFilterManagerModal" 60 model="${[rkey: ukey, filterName: filterName, filterset: filterset, 61 filterLinks: true, 62 formId: "${ukey}filter", 63 ko: true, 64 deleteActionSubmit: 'deleteNodeFilter', storeActionSubmit: 'storeNodeFilter']}"/> 65 </g:form> 66 67 <ul class="nav nav-tabs"> 68 <li class="active" id="tab_link_summary"> 69 <a href="#summary" data-toggle="tab"> 70 <g:message code="browse" /> 71 </a> 72 </li> 73 74 <li> 75 <span class="tabs-sibling tabs-sibling-compact form-inline"> 76 <div class="form-group "> 77 <span class="input-group" > 78 <g:render template="nodeFilterInputGroup" model="[filterset: filterset, filtvalue:filtvalue,filterName:filterName]"/> 79 80 81 </span> 82 83 </div> 84 </span> 85 86 </li> 87 <li id="tab_link_result" data-bind="visible: filterIsSet()||allcount()>=0"> 88 <a href="#result" data-toggle="tab" data-bind="visible: filterIsSet() "> 89 <g:message code="result" /> 90 <span data-bind="visible: allcount()>=0"> 91 <span data-bind="text: allcount" class="text-info">${total}</span> 92 <span data-bind="text: nodesTitle()">Node${1 != total ? 's' : ''}</span> 93 </span> 94 <span data-bind="visible: allcount()<0" class="text-muted">…</span> 95 96 </a> 97 <a href="#" data-bind="visible: !filterIsSet() "> 98 <g:message code="enter.a.filter" /> 99 </a> 100 </li> 101 <li data-bind="visible: filterIsSet()||allcount()>=0" class="pull-right"> 102 <span class="tabs-sibling tabs-sibling-compact "> 103 <div class=" btn-group pull-right "> 104 <button class="btn btn-default dropdown-toggle" data-toggle="dropdown"> 105 <g:message code="actions" /> <span class="caret"></span> 106 </button> 107 <ul class="dropdown-menu" role="menu"> 108 109 <li class="dropdown-header" data-bind="visible: filterName()"> 110 <g:message code="filter" /><span data-bind="text: filterNameDisplay()"></span> 111 </li> 112 <li data-bind="visible: canSaveFilter"> 113 <a href="#" 114 data-toggle="modal" 115 data-target="#saveFilterModal"> 116 <i class="glyphicon glyphicon-plus"></i> 117 <g:message code="save.filter.ellipsis" /> 118 </a> 119 </li> 120 <li data-bind="visible: canDeleteFilter"> 121 <a href="#" 122 class="textbtn textbtn-danger" 123 data-bind="click: deleteFilter"> 124 <i class="glyphicon glyphicon-remove"></i> 125 <g:message code="delete.this.filter.ellipsis" /> 126 </a> 127 </li> 128 <li data-bind="visible: canSetDefaultFilter"> 129 <a href="#" 130 class="textbtn textbtn-success" 131 data-bind="click: setDefaultFilter"> 132 <i class="glyphicon glyphicon-filter"></i> 133 <g:message code="set.as.default.filter" /> 134 </a> 135 </li> 136 <li data-bind="visible: canRemoveDefaultFilter"> 137 <a href="#" 138 class="textbtn textbtn-default" 139 data-bind="click: nodeSummary().removeDefault"> 140 <i class="glyphicon glyphicon-ban-circle"></i> 141 <g:message code="remove.default.filter" /> 142 </a> 143 </li> 144 <li class="divider" ></li> 145 <g:if test="${g.executionMode(is:'active',project:params.project)}"> 146 147 <li data-bind="visible: hasNodes()" class="${run_authorized?'':'disabled'}"> 148 <a href="#" data-bind="${run_authorized?'click: runCommand':''}" 149 title="${run_authorized ? '' : message(code:"not.authorized")}" 150 class="${run_authorized ? '' : 'has_tooltip'}" 151 data-placement="left" 152 > 153 <i class="glyphicon glyphicon-play"></i> 154 <span data-bind="messageTemplate: [total,nodesTitle]"><g:message code="run.a.command.on.count.nodes.ellipsis" /></span> 155 </a> 156 </li> 157 </g:if> 158 <g:else> 159 160 <li data-bind="visible: hasNodes()" class="disabled"> 161 <a href="#" 162 title="${g.message(code:'disabled.execution.run')}" 163 class="has_tooltip" 164 data-placement="left" 165 > 166 <i class="glyphicon glyphicon-play"></i> 167 <span data-bind="messageTemplate: [total,nodesTitle]"><g:message code="run.a.command.on.count.nodes.ellipsis" /></span> 168 </a> 169 </li> 170 </g:else> 171 172 <li class="${job_create_authorized?'':'disabled'}"> 173 <a href="#" data-bind="${job_create_authorized?'click: saveJob':''}" 174 title="${job_create_authorized?'':message(code:"not.authorized")}" 175 class="${job_create_authorized?'':'has_tooltip'}" 176 data-placement="left" 177 > 178 <i class="glyphicon glyphicon-plus"></i> 179 <span data-bind="messageTemplate: [total,nodesTitle]"><g:message code="create.a.job.for.count.nodes.ellipsis" /></span> 180 </a> 181 </li> 182 </ul> 183 </div> 184 </span> 185 </li> 186 </ul> 187 188 <div class="row row-space"> 189 <div class="col-sm-12"> 190 <div class="tab-content"> 191 <div class="tab-pane " id="result"> 192 <div class="row row-space"> 193 <div class="col-sm-12"> 194 195 <span data-bind="if: error()" class="text-danger"> 196 <i class="glyphicon glyphicon-warning-sign"></i> 197 <span data-bind="text: error()"></span> 198 </span> 199 <g:if test="${tagsummary}"> 200 <g:render template="tagsummary" 201 model="${[hidetop:!summaryOnly,tagsummary: tagsummary, link: [action: 'nodes', controller: 'framework', param: 'nodeIncludeTags']]}"/> 202 </g:if> 203 <g:elseif test="${tagsummary?.size() == 0}"> 204 %{--<span class="text-muted">no tags</span>--}% 205 </g:elseif> 206 207 </div> 208 <g:form class="form form-inline" action="adhoc" controller="framework" method="get" name="runform"> 209 <g:hiddenField name="project" value="${params.project ?: request.project}"/> 210 <g:render template="nodeFiltersHidden" model="${[params: params, query: query]}"/> 211 </g:form> 212 213 </div> 214 <div class=" clear matchednodes " id="nodelist" > 215 </div> 216 <div class="clear matchednodes" id="nodeview"> 217 <g:render template="allnodesKO" /> 218 </div> 219 </div> 220 <div class="tab-pane active" id="summary"> 221 222 <div class="row row-space"> 223 224 <div class="col-sm-5 col-sm-offset-1"> 225 <span class="text-uppercase text-muted small"><i class="glyphicon glyphicon-tags " ></i> <g:message code="resource.metadata.entity.tags" /></span> 226 <ul data-bind="foreach: nodeSummary().tags" class="list-unstyled"> 227 <li> 228 <node-filter-link params=" 229 filterkey: 'tags', 230 filterval: tag, 231 tag: tag 232 "> 233 </node-filter-link> 234 235 <span data-bind="text: count" class="text-muted"></span> 236 </li> 237 </ul> 238 <div data-bind="visible: !nodeSummary().tags"> 239 <g:message code="none" /> 240 </div> 241 </div> 242 243 <div class="col-sm-5"> 244 245 <span class="text-uppercase text-muted small"><i class="glyphicon glyphicon-filter " ></i> <g:message code="filters" /></span> 246 <ul class="list-unstyled"> 247 <li> 248 <a href="#" 249 class="nodefilterlink textbtn textbtn-default" data-node-filter=".*" 250 data-node-filter-all="true"> 251 <g:message code="all.nodes" /></a> 252 253 <span data-bind="text: nodeSummary().totalCount" class="text-info">...</span> 254 255 <div class="btn-group"> 256 <button type="button" 257 class="btn btn-default btn-sm btn-link dropdown-toggle" 258 title="Filter Actions" 259 data-toggle="dropdown" 260 aria-expanded="false"> 261 <span class="caret"></span> 262 </button> 263 <ul class="dropdown-menu" role="menu"> 264 <li data-bind="visible: '.*'!=$root.nodeSummary().defaultFilter()"> 265 <a href="#" 266 data-bind="click: $root.nodeSummary().setDefaultAll"> 267 268 <i class="glyphicon glyphicon-filter"></i> 269 <g:message code="set.all.nodes.as.default.filter" /> 270 </a> 271 </li> 272 <li data-bind="visible: '.*'==$root.nodeSummary().defaultFilter()"> 273 <a href="#" 274 data-bind="click: $root.nodeSummary().removeDefault"> 275 <i class="glyphicon glyphicon-ban-circle"></i> 276 <g:message code="remove.all.nodes.as.default.filter" /> 277 </a> 278 </li> 279 </ul> 280 </div> 281 </li> 282 283 <!-- ko foreach: nodeSummary().filters --> 284 <li> 285 <a 286 href="#" 287 class=" nodefilterlink textbtn textbtn-default" 288 data-bind="attr: { 289 'data-node-filter-name': name(), 290 'data-node-filter': filter(), 291 'title': filter(), 292 'href': $root.nodeSummary().linkForFilterName($data) 293 }, 294 295 " 296 > 297 <span data-bind="text: name"></span> 298 </a> 299 <div class="btn-group"> 300 <button type="button" 301 class="btn btn-default btn-sm btn-link dropdown-toggle" 302 title="Filter Actions" 303 data-toggle="dropdown" 304 aria-expanded="false"> 305 <span class="caret"></span> 306 </button> 307 <ul class="dropdown-menu" role="menu"> 308 <li> 309 <a href="#" 310 data-bind="click: $root.nodeSummary().deleteFilterConfirm"> 311 <i class="glyphicon glyphicon-remove"></i> 312 <g:message code="delete.this.filter.ellipsis" /> 313 </a> 314 </li> 315 <li data-bind="visible: name()!=$root.nodeSummary().defaultFilter()"> 316 <a href="#" 317 data-bind="click: $root.nodeSummary().setDefault"> 318 319 <i class="glyphicon glyphicon-filter"></i> 320 <g:message code="set.as.default.filter" /> 321 </a> 322 </li> 323 <li data-bind="visible: name()==$root.nodeSummary().defaultFilter()"> 324 <a href="#" 325 data-bind="click: $root.nodeSummary().removeDefault"> 326 <i class="glyphicon glyphicon-ban-circle"></i> 327 <g:message code="remove.default.filter" /> 328 </a> 329 </li> 330 </ul> 331 </div> 332 333 </li> 334 <!-- /ko --> 335 </ul> 336 <div data-bind="visible: !nodeSummary().filters"> 337 <g:message code="none" /> 338 </div> 339 340 </div> 341 </div> 342 </div> 343 </div> 344 </div> 345 </div> 346 347 348 349</div> 350</body> 351</html> 352