mirror of https://github.com/apache/lucene.git
SOLR-7558: Uber-patch for Angular JS admin UI
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1680118 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
685a9f2643
commit
a49a6b5dc4
|
@ -129,8 +129,9 @@ New Features
|
|||
http://localhost:8983/solr/techproducts/replication?command=restorestatus
|
||||
(Varun Thacker, noble, shalin)
|
||||
|
||||
* SOLR-7241, SOLR-7263, SOLR-7279: More functionality moving the Admin UI to Angular JS
|
||||
(Upayavira via Erick)
|
||||
* SOLR-7241, SOLR-7263, SOLR-7279, SOLR-7300, SOLR-7396, SOLR-7397, SOLR-7492:
|
||||
Admin UI - Refactoring using AngularJS. More functionality moving the Admin
|
||||
UI to Angular JS (Upayavira via Erick)
|
||||
|
||||
* SOLR-7372: Limit memory consumed by LRUCache with a new 'maxRamMB' config parameter.
|
||||
(yonik, shalin)
|
||||
|
|
|
@ -116,7 +116,7 @@ This file is generated by `grunt build`, do not edit it by hand.
|
|||
display: block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background: url('chosen-sprite.png') -42px 1px no-repeat;
|
||||
background: url('../../img/chosen-sprite.png') -42px 1px no-repeat;
|
||||
font-size: 1px;
|
||||
}
|
||||
.chosen-container-single .chosen-single abbr:hover {
|
||||
|
@ -137,7 +137,7 @@ This file is generated by `grunt build`, do not edit it by hand.
|
|||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('chosen-sprite.png') no-repeat 0px 2px;
|
||||
background: url('../../img/chosen-sprite.png') no-repeat 0px 2px;
|
||||
}
|
||||
.chosen-container-single .chosen-search {
|
||||
position: relative;
|
||||
|
@ -153,8 +153,8 @@ This file is generated by `grunt build`, do not edit it by hand.
|
|||
height: auto;
|
||||
outline: 0;
|
||||
border: 1px solid #aaa;
|
||||
background: white url('chosen-sprite.png') no-repeat 100% -20px;
|
||||
background: url('chosen-sprite.png') no-repeat 100% -20px;
|
||||
background: white url('../../img/chosen-sprite.png') no-repeat 100% -20px;
|
||||
background: url('../../img/chosen-sprite.png') no-repeat 100% -20px;
|
||||
font-size: 1em;
|
||||
font-family: sans-serif;
|
||||
line-height: normal;
|
||||
|
@ -300,7 +300,7 @@ This file is generated by `grunt build`, do not edit it by hand.
|
|||
display: block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background: url('chosen-sprite.png') -42px 1px no-repeat;
|
||||
background: url('../../img/chosen-sprite.png') -42px 1px no-repeat;
|
||||
font-size: 1px;
|
||||
}
|
||||
.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
|
||||
|
@ -436,8 +436,8 @@ This file is generated by `grunt build`, do not edit it by hand.
|
|||
}
|
||||
.chosen-rtl .chosen-search input[type="text"] {
|
||||
padding: 4px 5px 4px 20px;
|
||||
background: white url('chosen-sprite.png') no-repeat -30px -20px;
|
||||
background: url('chosen-sprite.png') no-repeat -30px -20px;
|
||||
background: white url('../../img/chosen-sprite.png') no-repeat -30px -20px;
|
||||
background: url('../../img/chosen-sprite.png') no-repeat -30px -20px;
|
||||
direction: rtl;
|
||||
}
|
||||
.chosen-rtl.chosen-container-single .chosen-single div b {
|
||||
|
@ -457,7 +457,7 @@ This file is generated by `grunt build`, do not edit it by hand.
|
|||
.chosen-container-multi .chosen-choices .search-choice .search-choice-close,
|
||||
.chosen-container .chosen-results-scroll-down span,
|
||||
.chosen-container .chosen-results-scroll-up span {
|
||||
background-image: url('chosen-sprite@2x.png') !important;
|
||||
background-image: url('../../img/chosen-sprite-2x.png') !important;
|
||||
background-size: 52px 37px !important;
|
||||
background-repeat: no-repeat !important;
|
||||
}
|
||||
|
|
|
@ -180,6 +180,12 @@ ul
|
|||
background-image: url( ../../img/loader-light.gif ) !important;
|
||||
}
|
||||
|
||||
.universal-loader {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
#wrapper
|
||||
{
|
||||
position: relative;
|
||||
|
|
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
#content #dataimport
|
||||
{
|
||||
background-image: url( ../../img/div.gif );
|
||||
background-position: 21% 0;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
|
||||
#content #dataimport #frame
|
||||
{
|
||||
float: right;
|
||||
width: 78%;
|
||||
}
|
||||
|
||||
#content #dataimport #form
|
||||
{
|
||||
float: left;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
#content #dataimport #form #navigation
|
||||
{
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
#content #dataimport #form #navigation a
|
||||
{
|
||||
background-image: url( ../../img/ico/status-offline.png );
|
||||
}
|
||||
|
||||
#content #dataimport #form #navigation .current a
|
||||
{
|
||||
background-image: url( ../../img/ico/status.png );
|
||||
}
|
||||
|
||||
#content #dataimport #form form
|
||||
{
|
||||
border-top: 1px solid #f0f0f0;
|
||||
margin-top: 10px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
#content #dataimport #form label
|
||||
{
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
#content #dataimport #form input,
|
||||
#content #dataimport #form select,
|
||||
#content #dataimport #form textarea
|
||||
{
|
||||
margin-bottom: 2px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#content #dataimport #form input
|
||||
{
|
||||
width: 98%;
|
||||
}
|
||||
|
||||
#content #dataimport #form button
|
||||
{
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#content #dataimport #form .execute span
|
||||
{
|
||||
background-image: url( ../../img/ico/document-import.png );
|
||||
}
|
||||
|
||||
#content #dataimport #form .refresh-status span
|
||||
{
|
||||
background-image: url( ../../img/ico/arrow-circle.png );
|
||||
}
|
||||
|
||||
#content #dataimport #form .refresh-status span.success
|
||||
{
|
||||
background-image: url( ../../img/ico/tick.png );
|
||||
}
|
||||
|
||||
#content #dataimport #form #start
|
||||
{
|
||||
float: left;
|
||||
width: 47%;
|
||||
}
|
||||
|
||||
#content #dataimport #form #rows
|
||||
{
|
||||
float: right;
|
||||
width: 47%;
|
||||
}
|
||||
|
||||
#content #dataimport #form .checkbox input
|
||||
{
|
||||
margin-bottom: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#content #dataimport #form #auto-refresh-status
|
||||
{
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#content #dataimport #form #auto-refresh-status a
|
||||
{
|
||||
background-image: url( ../../img/ico/ui-check-box-uncheck.png );
|
||||
background-position: 0 50%;
|
||||
color: #c0c0c0;
|
||||
display: block;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #dataimport #form #auto-refresh-status a.on,
|
||||
#content #dataimport #form #auto-refresh-status a:hover
|
||||
{
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#content #dataimport #form #auto-refresh-status a.on
|
||||
{
|
||||
background-image: url( ../../img/ico/ui-check-box.png );
|
||||
}
|
||||
|
||||
#content #dataimport #current_state
|
||||
{
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state .last_update,
|
||||
#content #dataimport #current_state .info
|
||||
{
|
||||
display: block;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state .last_update
|
||||
{
|
||||
color: #c0c0c0;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state .info
|
||||
{
|
||||
background-position: 0 1px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state .info .details span
|
||||
{
|
||||
# color: #c0c0c0;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state .info .abort-import
|
||||
{
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state .info .abort-import span
|
||||
{
|
||||
background-image: url( ../../img/ico/cross.png );
|
||||
}
|
||||
|
||||
#content #dataimport #current_state .info .abort-import.success span
|
||||
{
|
||||
background-image: url( ../../img/ico/tick.png );
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.indexing
|
||||
{
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.indexing .info
|
||||
{
|
||||
background-image: url( ../../img/ico/hourglass.png );
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.indexing .info .abort-import
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.success
|
||||
{
|
||||
background-color: #e6f3e6;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.success .info
|
||||
{
|
||||
background-image: url( ../../img/ico/tick-circle.png );
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.success .info strong
|
||||
{
|
||||
color: #080;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.aborted
|
||||
{
|
||||
background-color: #f3e6e6;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.aborted .info
|
||||
{
|
||||
background-image: url( ../../img/ico/slash.png );
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.aborted .info strong
|
||||
{
|
||||
color: #800;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.failure
|
||||
{
|
||||
background-color: #f3e6e6;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.failure .info
|
||||
{
|
||||
background-image: url( ../../img/ico/cross-button.png );
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.failure .info strong
|
||||
{
|
||||
color: #800;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.idle
|
||||
{
|
||||
background-color: #e6e6ff;
|
||||
}
|
||||
|
||||
#content #dataimport #current_state.idle .info
|
||||
{
|
||||
background-image: url( ../../img/ico/information.png );
|
||||
}
|
||||
|
||||
#content #dataimport #error
|
||||
{
|
||||
background-color: #f00;
|
||||
background-image: url( ../../img/ico/construction.png );
|
||||
background-position: 10px 50%;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
padding-left: 35px;
|
||||
}
|
||||
|
||||
#content #dataimport .block h2
|
||||
{
|
||||
border-color: #c0c0c0;
|
||||
padding-left: 5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#content #dataimport .block.hidden h2
|
||||
{
|
||||
border-color: #fafafa;
|
||||
}
|
||||
|
||||
#content #dataimport .block h2 a.toggle
|
||||
{
|
||||
background-image: url( ../../img/ico/toggle-small.png );
|
||||
background-position: 0 50%;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #dataimport .block.hidden h2 a.toggle
|
||||
{
|
||||
background-image: url( ../../img/ico/toggle-small-expand.png );
|
||||
}
|
||||
|
||||
#content #dataimport #config h2 a.r
|
||||
{
|
||||
background-position: 3px 50%;
|
||||
display: block;
|
||||
float: right;
|
||||
margin-left: 10px;
|
||||
padding-left: 24px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
#content #dataimport #config h2 a.reload_config
|
||||
{
|
||||
background-image: url( ../../img/ico/arrow-circle.png );
|
||||
}
|
||||
|
||||
#content #dataimport #config h2 a.reload_config.success
|
||||
{
|
||||
background-image: url( ../../img/ico/tick.png );
|
||||
}
|
||||
|
||||
#content #dataimport #config h2 a.reload_config.error
|
||||
{
|
||||
background-image: url( ../../img/ico/slash.png );
|
||||
}
|
||||
|
||||
#content #dataimport #config h2 a.debug_mode
|
||||
{
|
||||
background-image: url( ../../img/ico/hammer.png );
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
#content #dataimport #config.debug_mode h2 a.debug_mode
|
||||
{
|
||||
background-color: #ff0;
|
||||
background-image: url( ../../img/ico/hammer-screwdriver.png );
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#content #dataimport #config .content
|
||||
{
|
||||
padding: 5px 2px;
|
||||
}
|
||||
|
||||
#content #dataimport #dataimport_config .loader
|
||||
{
|
||||
background-position: 0 50%;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #dataimport #dataimport_config .formatted
|
||||
{
|
||||
border: 1px solid #fff;
|
||||
display: block;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
#content #dataimport .debug_mode #dataimport_config .editable
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #dataimport #dataimport_config .editable textarea
|
||||
{
|
||||
font-family: monospace;
|
||||
height: 120px;
|
||||
min-height: 60px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#content #dataimport #debug_response em
|
||||
{
|
||||
color: #c0c0c0;
|
||||
font-style: normal;
|
||||
}
|
|
@ -279,6 +279,7 @@ limitations under the License.
|
|||
#core-menu .logging a { background-image: url( ../../img/ico/inbox-document-text.png ); }
|
||||
#core-menu .plugins a { background-image: url( ../../img/ico/block.png ); }
|
||||
#core-menu .dataimport a { background-image: url( ../../img/ico/document-import.png ); }
|
||||
#core-menu .segments a { background-image: url( ../../img/ico/construction.png ); }
|
||||
|
||||
|
||||
#content #navigation
|
||||
|
|
|
@ -0,0 +1,500 @@
|
|||
/*
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
#content #replication
|
||||
{
|
||||
background-image: url( ../../img/div.gif );
|
||||
background-position: 21% 0;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
|
||||
#content #replication #frame
|
||||
{
|
||||
float: right;
|
||||
width: 78%;
|
||||
}
|
||||
|
||||
#content #replication #navigation
|
||||
{
|
||||
border-right: 0;
|
||||
float: left;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
#content #replication #error
|
||||
{
|
||||
background-color: #f00;
|
||||
background-image: url( ../../img/ico/construction.png );
|
||||
background-position: 10px 50%;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
padding-left: 35px;
|
||||
}
|
||||
|
||||
#content #replication .block
|
||||
{
|
||||
border-bottom: 1px solid #c0c0c0;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
#content #replication .block.last
|
||||
{
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
#content #replication .masterOnly,
|
||||
#content #replication .slaveOnly
|
||||
{
|
||||
}
|
||||
|
||||
#content #replication.master .masterOnly
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #replication.slave .slaveOnly
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #replication .replicating
|
||||
{
|
||||
}
|
||||
|
||||
#content #replication.replicating .replicating
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #replication #progress
|
||||
{
|
||||
padding-bottom: 80px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#content #replication #progress .info
|
||||
{
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#content #replication #progress #start
|
||||
{
|
||||
margin-left: 100px;
|
||||
border-left: 1px solid #c0c0c0;
|
||||
}
|
||||
|
||||
#content #replication #progress #bar
|
||||
{
|
||||
background-color: #f0f0f0;
|
||||
margin-left: 100px;
|
||||
margin-right: 100px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#content #replication #progress #bar #bar-info,
|
||||
#content #replication #progress #bar #eta
|
||||
{
|
||||
position: absolute;
|
||||
right: -100px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#content #replication #progress #bar #bar-info
|
||||
{
|
||||
border-left: 1px solid #f0f0f0;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
#content #replication #progress #eta .info
|
||||
{
|
||||
color: #c0c0c0;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
#content #replication #progress #speed
|
||||
{
|
||||
color: #c0c0c0;
|
||||
position: absolute;
|
||||
right: 100px;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#content #replication #progress #bar #done
|
||||
{
|
||||
background-color: #c0c0c0;
|
||||
box-shadow: 5px 5px 10px #c0c0c0;
|
||||
-moz-box-shadow: 5px 5px 10px #c0c0c0;
|
||||
-webkit-box-shadow: 5px 5px 10px #c0c0c0;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#content #replication #progress #bar #done .percent
|
||||
{
|
||||
font-weight: bold;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#content #replication #progress #bar #done #done-info
|
||||
{
|
||||
border-right: 1px solid #c0c0c0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
margin-top: 30px;
|
||||
text-align: right;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#content #replication #progress #bar #done #done-info .percent
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#content #replication .block .label,
|
||||
#content #replication #current-file .file,
|
||||
#content #replication #current-file .progress,
|
||||
#content #replication #iterations .iterations
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
#content #replication .block .label
|
||||
{
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#content #replication .block .label span
|
||||
{
|
||||
display: block;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #replication #current-file
|
||||
{
|
||||
border-top: 1px solid #f0f0f0;
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#content #replication #current-file .progress
|
||||
{
|
||||
color: #c0c0c0;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
#content #replication #iterations .label span
|
||||
{
|
||||
background-image: url( ../../img/ico/node-design.png );
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations li
|
||||
{
|
||||
background-position: 100% 50%;
|
||||
padding-right: 21px;
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations.expanded li
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations .latest
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations .replicated
|
||||
{
|
||||
color: #80c480;
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations ul:hover .replicated,
|
||||
#content #replication #iterations .iterations .replicated.latest
|
||||
{
|
||||
color: #080;
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations .replicated.latest
|
||||
{
|
||||
background-image: url( ../../img/ico/tick.png );
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations .failed
|
||||
{
|
||||
color: #c48080;
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations ul:hover .failed,
|
||||
#content #replication #iterations .iterations .failed.latest
|
||||
{
|
||||
color: #800;
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations .failed.latest
|
||||
{
|
||||
background-image: url( ../../img/ico/cross.png );
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations a
|
||||
{
|
||||
border-top: 1px solid #f0f0f0;
|
||||
margin-top: 2px;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations a span
|
||||
{
|
||||
background-position: 0 50%;
|
||||
color: #c0c0c0;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations a span.expand
|
||||
{
|
||||
background-image: url( ../../img/ico/chevron-small-expand.png );
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #replication #iterations .iterations a span.collapse
|
||||
{
|
||||
background-image: url( ../../img/ico/chevron-small.png );
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #replication #details table
|
||||
{
|
||||
margin-left: 20px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
#content #replication #details table th
|
||||
{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#content #replication.slave #details table .slaveOnly
|
||||
{
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
#content #replication #details table thead th
|
||||
{
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
#content #replication #details table thead th,
|
||||
#content #replication #details table tbody td
|
||||
{
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
#content #replication #details table thead td,
|
||||
#content #replication #details table thead th,
|
||||
#content #replication #details table tbody th,
|
||||
#content #replication #details table tbody td div
|
||||
{
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
#content #replication #details table tbody td,
|
||||
#content #replication #details table tbody th
|
||||
{
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
#content #replication #details table thead td
|
||||
{
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#content #replication #details table thead td span
|
||||
{
|
||||
background-image: url( ../../img/ico/clipboard-list.png );
|
||||
background-position: 0 50%;
|
||||
display: block;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #replication #details table tbody th
|
||||
{
|
||||
padding-right: 10px;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#content #replication #details table tbody .size
|
||||
{
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#content #replication #details table tbody .generation div
|
||||
{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#content #replication #details table tbody .diff div
|
||||
{
|
||||
background-color: #fcfcc9;
|
||||
padding-left: 1px;
|
||||
padding-right: 1px;
|
||||
}
|
||||
|
||||
#content #replication .settings .label span
|
||||
{
|
||||
background-image: url( ../../img/ico/hammer-screwdriver.png );
|
||||
}
|
||||
|
||||
#content #replication .settings ul,
|
||||
#content #replication .settings dl dt,
|
||||
#content #replication .settings dl dd
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
#content #replication .settings ul li
|
||||
{
|
||||
border-top: 1px solid #f0f0f0;
|
||||
padding-top: 3px;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
#content #replication .settings ul li:first-child
|
||||
{
|
||||
border-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#content #replication .settings dl dt
|
||||
{
|
||||
clear: left;
|
||||
margin-right: 5px;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
#content #replication .settings dl .ico
|
||||
{
|
||||
background-position: 0 50%;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #replication .settings dl .ico.ico-0
|
||||
{
|
||||
background-image: url( ../../img/ico/slash.png );
|
||||
}
|
||||
|
||||
#content #replication .settings dl .ico.ico-1
|
||||
{
|
||||
background-image: url( ../../img/ico/tick.png );
|
||||
}
|
||||
|
||||
#content #replication .timer
|
||||
{
|
||||
box-shadow: 5px 5px 10px #c0c0c0;
|
||||
-moz-box-shadow: 5px 5px 10px #c0c0c0;
|
||||
-webkit-box-shadow: 5px 5px 10px #c0c0c0;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#content #replication .timer p,
|
||||
#content #replication .timer small
|
||||
{
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #replication .timer p
|
||||
{
|
||||
background-image: url( ../../img/ico/clock-select-remain.png );
|
||||
background-position: 0 50%;
|
||||
}
|
||||
|
||||
#content #replication .timer p .approx
|
||||
{
|
||||
color: #c0c0c0;
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
#content #replication .timer p .tick
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#content #replication .timer small
|
||||
{
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
#content #replication #navigation button
|
||||
{
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#content #replication #navigation button.optional
|
||||
{
|
||||
}
|
||||
|
||||
#content #replication #navigation .replicate-now span
|
||||
{
|
||||
background-image: url( ../../img/ico/document-convert.png );
|
||||
}
|
||||
|
||||
#content #replication #navigation .abort-replication span
|
||||
{
|
||||
background-image: url( ../../img/ico/hand.png );
|
||||
}
|
||||
|
||||
#content #replication #navigation .disable-polling span
|
||||
{
|
||||
background-image: url( ../../img/ico/cross.png );
|
||||
}
|
||||
|
||||
#content #replication #navigation .enable-polling span
|
||||
{
|
||||
background-image: url( ../../img/ico/tick.png );
|
||||
}
|
||||
|
||||
#content #replication #navigation .disable-replication span
|
||||
{
|
||||
background-image: url( ../../img/ico/cross.png );
|
||||
}
|
||||
|
||||
#content #replication #navigation .enable-replication span
|
||||
{
|
||||
background-image: url( ../../img/ico/tick.png );
|
||||
}
|
||||
|
||||
#content #replication #navigation .refresh-status span
|
||||
{
|
||||
background-image: url( ../../img/ico/arrow-circle.png );
|
||||
}
|
|
@ -0,0 +1,567 @@
|
|||
/*
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
#content #schema-browser .loader
|
||||
{
|
||||
background-position: 0 50%;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #schema-browser.loaded
|
||||
{
|
||||
background-image: url( ../../img/div.gif );
|
||||
background-position: 21% 0;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
|
||||
#content #schema-browser #data
|
||||
{
|
||||
float: right;
|
||||
width: 78%;
|
||||
}
|
||||
|
||||
#content #schema-browser #related
|
||||
{
|
||||
float: left;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
#content #schema-browser #related select
|
||||
{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#content #schema-browser #related select optgroup
|
||||
{
|
||||
font-style: normal;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#content #schema-browser #related select option
|
||||
{
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
#content #schema-browser #related #f-df-t
|
||||
{
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
#content #schema-browser #related .ukf-dsf dt
|
||||
{
|
||||
}
|
||||
|
||||
#content #schema-browser #related dl
|
||||
{
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
#content #schema-browser #related dl dt,
|
||||
#content #schema-browser #related dl dd a
|
||||
{
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
#content #schema-browser #related dl dt
|
||||
{
|
||||
font-weight: bold;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
#content #schema-browser #related dl dd a
|
||||
{
|
||||
display: block;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
#content #schema-browser #related dl dd a:hover
|
||||
{
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
#content #schema-browser #related .field .field,
|
||||
#content #schema-browser #related .field .field a,
|
||||
#content #schema-browser #related .dynamic-field .dynamic-field,
|
||||
#content #schema-browser #related .dynamic-field .dynamic-field a,
|
||||
#content #schema-browser #related .type .type,
|
||||
#content #schema-browser #related .type .type a,
|
||||
#content #schema-browser #related .active,
|
||||
#content #schema-browser #related .active a
|
||||
{
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#content #schema-browser #related .copyfield,
|
||||
#content #schema-browser #related .copyfield a
|
||||
{
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#content #schema-browser #data
|
||||
{
|
||||
}
|
||||
|
||||
#content #schema-browser #data #index dt
|
||||
{
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options
|
||||
{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .head h2
|
||||
{
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .partial
|
||||
{
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .partial p
|
||||
{
|
||||
background-image: url( ../../img/ico/exclamation-button.png );
|
||||
background-position: 0 50%;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .options dt,
|
||||
#content #schema-browser #data #field .field-options .options dd
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .options dt
|
||||
{
|
||||
clear: left;
|
||||
margin-right: 5px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .flags
|
||||
{
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .flags thead td
|
||||
{
|
||||
color: #c0c0c0;
|
||||
padding-right: 5px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .flags tbody td,
|
||||
#content #schema-browser #data #field .field-options .flags th
|
||||
{
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .flags thead td,
|
||||
#content #schema-browser #data #field .field-options .flags tbody th
|
||||
{
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .flags thead th,
|
||||
#content #schema-browser #data #field .field-options .flags tbody td
|
||||
{
|
||||
border-left: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .flags tbody th,
|
||||
#content #schema-browser #data #field .field-options .flags tbody td
|
||||
{
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .flags tbody .check
|
||||
{
|
||||
background-color: #fafdfa;
|
||||
background-image: url( ../../img/ico/tick.png );
|
||||
background-position: 50% 50%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .flags tbody .check span
|
||||
{
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .flags tbody .text
|
||||
{
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer,
|
||||
#content #schema-browser #data #field .field-options .analyzer li,
|
||||
#content #schema-browser #data #field .field-options .analyzer ul,
|
||||
#content #schema-browser #data #field .field-options .analyzer ul li
|
||||
{
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer p,
|
||||
#content #schema-browser #data #field .field-options .analyzer dl
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer p
|
||||
{
|
||||
margin-right: 5px;
|
||||
text-align: right;
|
||||
width: 125px;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer p a
|
||||
{
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer p a.analysis
|
||||
{
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer p a.analysis span
|
||||
{
|
||||
background-image: url( ../../img/ico/question-white.png );
|
||||
background-position: 0 50%;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer p a.analysis:hover span
|
||||
{
|
||||
background-image: url( ../../img/ico/question.png );
|
||||
color: #008;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer a
|
||||
{
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer .toggle
|
||||
{
|
||||
background-image: url( ../../img/ico/chevron-small-expand.png );
|
||||
background-position: 100% 50%;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
padding-right: 21px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer .open .toggle
|
||||
{
|
||||
background-image: url( ../../img/ico/chevron-small.png );
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer li
|
||||
{
|
||||
border-top: 1px solid #f0f0f0;
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer ul
|
||||
{
|
||||
clear: left;
|
||||
margin-left: 55px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer .open ul
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer ul li
|
||||
{
|
||||
border-top: 1px solid #f8f8f8;
|
||||
margin-top: 5px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer ul p
|
||||
{
|
||||
color: #999;
|
||||
margin-right: 5px;
|
||||
text-align: right;
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer ul dd
|
||||
{
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer ul dd
|
||||
{
|
||||
background-image: url( ../../img/ico/document-list.png );
|
||||
background-position: 0 50%;
|
||||
color: #c0c0c0;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer ul dd.ico-0
|
||||
{
|
||||
background-image: url( ../../img/ico/slash.png );
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .field-options .analyzer ul dd.ico-1
|
||||
{
|
||||
background-image: url( ../../img/ico/tick.png );
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .head
|
||||
{
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .terminfo-holder
|
||||
{
|
||||
border-top: 1px solid #c0c0c0;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .terminfo-holder .trigger
|
||||
{
|
||||
float: left;
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .terminfo-holder .trigger button span
|
||||
{
|
||||
background-image: url( ../../img/ico/information.png );
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .terminfo-holder .status
|
||||
{
|
||||
border-left: 1px solid #f0f0f0;
|
||||
float: left;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .terminfo-holder.disabled .trigger button span
|
||||
{
|
||||
background-image: url( ../../img/ico/prohibition.png );
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .terminfo-holder.disabled .status
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .terminfo-holder .trigger .autoload
|
||||
{
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .terminfo-holder.loaded .trigger .autoload
|
||||
{
|
||||
background-image: url( ../../img/ico/ui-check-box-uncheck.png );
|
||||
background-position: 0 50%;
|
||||
color: #c0c0c0;
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .terminfo-holder .trigger .autoload:hover
|
||||
{
|
||||
color: #008;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .terminfo-holder .trigger .autoload.on
|
||||
{
|
||||
background-image: url( ../../img/ico/ui-check-box.png );
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .topterms-holder,
|
||||
#content #schema-browser #data #field .histogram-holder
|
||||
{
|
||||
border-left: 1px solid #f0f0f0;
|
||||
float: left;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .topterms-holder .head input
|
||||
{
|
||||
height: 18px;
|
||||
line-height: 16px;
|
||||
text-align: right;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .topterms-holder .head .max-holder
|
||||
{
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .topterms-holder .head .max-holder:hover .max
|
||||
{
|
||||
color: #008;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .topterms-holder .head #query_link
|
||||
{
|
||||
background-image: url( ../../img/ico/question-white.png );
|
||||
background-position: 0 50%;
|
||||
color: #c0c0c0;
|
||||
padding-left: 21px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .topterms-holder .head #query_link:hover
|
||||
{
|
||||
background-image: url( ../../img/ico/question.png );
|
||||
}
|
||||
|
||||
|
||||
#content #schema-browser #data #field .topterms-holder .head #query_link span
|
||||
{
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .topterms-holder .head #query_link:hover span
|
||||
{
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#content #schema-browser .topterms-holder li
|
||||
{
|
||||
border-top: 1px solid #999;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
/* possible overwrite with inline style */
|
||||
#content #schema-browser .topterms-holder li p
|
||||
{
|
||||
background-color: #999;
|
||||
color: #fff;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#content #schema-browser .topterms-holder li p span
|
||||
{
|
||||
display: block;
|
||||
padding-right: 2px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* possible overwrite with inline style */
|
||||
#content #schema-browser .topterms-holder li ul
|
||||
{
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
#content #schema-browser .topterms-holder li li
|
||||
{
|
||||
border-top: 0;
|
||||
margin-bottom: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#content #schema-browser .topterms-holder li li.odd
|
||||
{
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
#content #schema-browser .topterms-holder li li a
|
||||
{
|
||||
display: block;
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
#content #schema-browser .topterms-holder li li a:hover
|
||||
{
|
||||
background-color: #c0c0c0;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .histogram-holder ul
|
||||
{
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .histogram-holder li
|
||||
{
|
||||
margin-bottom: 2px;
|
||||
position: relative;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .histogram-holder li.odd
|
||||
{
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .histogram-holder li dl,
|
||||
#content #schema-browser #data #field .histogram-holder li dt
|
||||
{
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .histogram-holder li dl
|
||||
{
|
||||
background-color: #c0c0c0;
|
||||
min-width: 1px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .histogram-holder li dt
|
||||
{
|
||||
color: #a0a0a0;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
left: -25px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .histogram-holder li dt span
|
||||
{
|
||||
display: block;
|
||||
padding-right: 4px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .histogram-holder li dd
|
||||
{
|
||||
clear: left;
|
||||
float: left;
|
||||
margin-left: 2px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .histogram-holder li:hover dl
|
||||
{
|
||||
background-color: #b0b0b0;
|
||||
}
|
||||
|
||||
#content #schema-browser #data #field .histogram-holder li:hover dt
|
||||
{
|
||||
color: #333;
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
#content #segments .loader
|
||||
{
|
||||
background-position: 0 50%;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #segments .reload
|
||||
{
|
||||
background-image: url( ../../img/ico/arrow-circle.png );
|
||||
background-position: 50% 50%;
|
||||
display: block;
|
||||
height: 30px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
#content #segments .reload.loader
|
||||
{
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#content #segments .reload span
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#content #segments #result
|
||||
{
|
||||
width: 77%;
|
||||
}
|
||||
|
||||
#content #segments #result #response
|
||||
{
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
#content #segments .segments-holder ul {
|
||||
margin-left: 25px;
|
||||
}
|
||||
#content #segments .segments-holder li {
|
||||
margin-bottom: 2px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#content #segments .segments-holder li .tooltip {
|
||||
display: none;
|
||||
background: #C8C8C8;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
width:220px;
|
||||
height:120px;
|
||||
margin-left: 100%;
|
||||
opacity: .8;
|
||||
padding: 5px;
|
||||
border: 1px solid;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#content #segments .segments-holder li .tooltip .label {
|
||||
float: left;
|
||||
width: 20%;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#content #segments .segments-holder li:hover .tooltip {
|
||||
display:block;
|
||||
}
|
||||
|
||||
#content #segments .segments-holder li dl,
|
||||
#content #segments .segments-holder li dt {
|
||||
padding-bottom: 1px;
|
||||
padding-top: 1px;
|
||||
}
|
||||
#content #segments .segments-holder li dl {
|
||||
min-width: 1px;
|
||||
}
|
||||
#content #segments .segments-holder li dt {
|
||||
color: #a0a0a0;
|
||||
left: -45px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
#content #segments .segments-holder li dt div {
|
||||
display: block;
|
||||
padding-right: 4px;
|
||||
text-align: right;
|
||||
}
|
||||
#content #segments .segments-holder li dd {
|
||||
clear: left;
|
||||
float: left;
|
||||
margin-left: 2px;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#content #segments .segments-holder li dd div.deleted {
|
||||
background-color: #808080;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
#content #segments .segments-holder li dd div.live {
|
||||
background-color: #DDDDDD;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#content #segments .segments-holder li dd div.start {
|
||||
float: left;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
#content #segments .segments-holder li dd div.end {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.merge-candidate {
|
||||
background-color: #FFC9F9 !important;
|
||||
}
|
||||
|
||||
#content #segments .segments-holder li dd div.w5 {
|
||||
width: 20%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#content #segments #auto-refresh {
|
||||
margin-top: 4px;
|
||||
background-position: 50% 50%;
|
||||
display: block;
|
||||
height: 30px;
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
#content #segments #auto-refresh a {
|
||||
background-image: url( ../../img/ico/ui-check-box-uncheck.png );
|
||||
background-position: 0 50%;
|
||||
color: #c0c0c0;
|
||||
display: block;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
#content #segments #auto-refresh a.on,
|
||||
#content #segments #auto-refresh a:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#content #segments #auto-refresh a.on {
|
||||
background-image: url( ../../img/ico/ui-check-box.png );
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ limitations under the License.
|
|||
<link rel="stylesheet" type="text/css" href="css/angular/cloud.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/angular/cores.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/styles/dashboard.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/styles/dataimport.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/angular/dataimport.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/angular/files.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/angular/index.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/styles/java-properties.css?_=${version}">
|
||||
|
@ -37,8 +37,9 @@ limitations under the License.
|
|||
<link rel="stylesheet" type="text/css" href="css/angular/plugins.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/angular/documents.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/angular/query.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/styles/replication.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/styles/schema-browser.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/angular/replication.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/angular/schema-browser.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/angular/segments.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/angular/threads.css?_=${version}">
|
||||
<link rel="stylesheet" type="text/css" href="css/angular/chosen.css?_=${version}">
|
||||
|
||||
|
@ -53,6 +54,7 @@ limitations under the License.
|
|||
<script src="libs/angular-cookies.min.js"></script>
|
||||
<script src="libs/ngtimeago.js"></script>
|
||||
<script src="libs/highlight.js"></script>
|
||||
<script src="libs/d3.js"></script>
|
||||
<script src="js/angular/app.js"></script>
|
||||
<script src="js/angular/services.js"></script>
|
||||
<script src="js/angular/controllers/index.js"></script>
|
||||
|
@ -63,10 +65,14 @@ limitations under the License.
|
|||
<script src="js/angular/controllers/java-properties.js"></script>
|
||||
<script src="js/angular/controllers/core-overview.js"></script>
|
||||
<script src="js/angular/controllers/analysis.js"></script>
|
||||
<script src="js/angular/controllers/dataimport.js"></script>
|
||||
<script src="js/angular/controllers/documents.js"></script>
|
||||
<script src="js/angular/controllers/files.js"></script>
|
||||
<script src="js/angular/controllers/query.js"></script>
|
||||
<script src="js/angular/controllers/plugins.js"></script>
|
||||
<script src="js/angular/controllers/replication.js"></script>
|
||||
<script src="js/angular/controllers/schema-browser.js"></script>
|
||||
<script src="js/angular/controllers/segments.js"></script>
|
||||
|
||||
</head>
|
||||
<body ng-controller="MainController">
|
||||
|
@ -91,9 +97,7 @@ limitations under the License.
|
|||
|
||||
</div>
|
||||
|
||||
<div id="loading" class="header-message" loading-status-message>
|
||||
Loading...
|
||||
</div>
|
||||
<div id="loading" class="loader universal-loader" loading-status-message> </div>
|
||||
|
||||
<div id="connection-box" connection-message>
|
||||
<div id="connection-status-modal">
|
||||
|
@ -134,12 +138,12 @@ limitations under the License.
|
|||
</ul>
|
||||
</li>
|
||||
|
||||
<li id="cloud" class="global optional" ng-show="isCloudEnabled" ng-class="{active:page=='cloud'}"><p><a href="#/~cloud">Cloud</a></p>
|
||||
<li id="cloud" class="global optional" ng-show="isCloudEnabled" ng-class="{active:showingCloud}"><p><a href="#/~cloud">Cloud</a></p>
|
||||
<ul ng-show="showingCloud">
|
||||
<li class="tree" ng-class="{active:page=='cloud-tree'}"><a href="#/~cloud?view=tree">Tree</a></li>
|
||||
<li class="graph" ng-class="{active:page=='cloud-graph'}"><a href="#/~cloud">Graph</a></li>
|
||||
<li class="rgraph" ng-class="{active:page=='cloud-rgraph'}"><a href="#/~cloud?view=rgraph">Graph (Radial)</a></li>
|
||||
<li class="dump" ng-class="{active:page=='cloud-dump'}"><a href="#/~cloud">Dump</a></li>
|
||||
<li class="dump" ng-class="{active:page=='cloud-dump'}"><a ng-click="dumpCloud()">Dump</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
@ -175,6 +179,7 @@ limitations under the License.
|
|||
<li class="query" ng-class="{active:page=='query'}"><a href="#/{{currentCore.name}}/query"><span>Query</span></a></li>
|
||||
<li class="replication" ng-class="{active:page=='replication'}"><a href="#/{{currentCore.name}}/replication"><span>Replication</span></a></li>
|
||||
<li class="schema-browser" ng-class="{active:page=='schema-browser'}"><a href="#/{{currentCore.name}}/schema-browser"><span>Schema Browser</span></a></li>
|
||||
<li class="segments" ng-class="{active:page=='segments'}"><a href="#/{{currentCore.name}}/segments"><span>Segments info</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -67,6 +67,14 @@ solrAdminApp.config([
|
|||
templateUrl: 'partials/analysis.html',
|
||||
controller: 'AnalysisController'
|
||||
}).
|
||||
when('/:core/dataimport', {
|
||||
templateUrl: 'partials/dataimport.html',
|
||||
controller: 'DataImportController'
|
||||
}).
|
||||
when('/:core/dataimport/:handler*', {
|
||||
templateUrl: 'partials/dataimport.html',
|
||||
controller: 'DataImportController'
|
||||
}).
|
||||
when('/:core/documents', {
|
||||
templateUrl: 'partials/documents.html',
|
||||
controller: 'DocumentsController'
|
||||
|
@ -89,6 +97,26 @@ solrAdminApp.config([
|
|||
templateUrl: 'partials/query.html',
|
||||
controller: 'QueryController'
|
||||
}).
|
||||
when('/:core/replication', {
|
||||
templateUrl: 'partials/replication.html',
|
||||
controller: 'ReplicationController'
|
||||
}).
|
||||
when('/:core/dataimport', {
|
||||
templateUrl: 'partials/dataimport.html',
|
||||
controller: 'DataImportController'
|
||||
}).
|
||||
when('/:core/dataimport/:handler*', {
|
||||
templateUrl: 'partials/dataimport.html',
|
||||
controller: 'DataImportController'
|
||||
}).
|
||||
when('/:core/schema-browser', {
|
||||
templateUrl: 'partials/schema-browser.html',
|
||||
controller: 'SchemaBrowserController'
|
||||
}).
|
||||
when('/:core/segments', {
|
||||
templateUrl: 'partials/segments.html',
|
||||
controller: 'SegmentsController'
|
||||
}).
|
||||
otherwise({
|
||||
redirectTo: '/'
|
||||
});
|
||||
|
@ -110,6 +138,59 @@ solrAdminApp.config([
|
|||
}
|
||||
};
|
||||
})
|
||||
.filter('readableSeconds', function() {
|
||||
return function(input) {
|
||||
seconds = parseInt(input||0, 10);
|
||||
var minutes = Math.floor( seconds / 60 );
|
||||
var hours = Math.floor( minutes / 60 );
|
||||
|
||||
var text = [];
|
||||
if( 0 !== hours ) {
|
||||
text.push( hours + 'h' );
|
||||
seconds -= hours * 60 * 60;
|
||||
minutes -= hours * 60;
|
||||
}
|
||||
|
||||
if( 0 !== minutes ) {
|
||||
text.push( minutes + 'm' );
|
||||
seconds -= minutes * 60;
|
||||
}
|
||||
|
||||
if( 0 !== seconds ) {
|
||||
text.push( ( '0' + seconds ).substr( -2 ) + 's' );
|
||||
}
|
||||
return text.join(' ');
|
||||
};
|
||||
})
|
||||
.filter('number', function($locale) {
|
||||
return function(input) {
|
||||
var sep = {
|
||||
'de_CH' : '\'',
|
||||
'de' : '.',
|
||||
'en' : ',',
|
||||
'es' : '.',
|
||||
'it' : '.',
|
||||
'ja' : ',',
|
||||
'sv' : ' ',
|
||||
'tr' : '.',
|
||||
'_' : '' // fallback
|
||||
};
|
||||
|
||||
var browser = {};
|
||||
var match = $locale.id.match( /^(\w{2})([-_](\w{2}))?$/ );
|
||||
if (match[1]) {
|
||||
browser.language = match[1].toLowerCase();
|
||||
}
|
||||
if (match[1] && match[3]) {
|
||||
browser.locale = match[1] + '_' + match[3];
|
||||
}
|
||||
|
||||
var result= ( input || 0 ).toString().replace(/\B(?=(\d{3})+(?!\d))/g,
|
||||
sep[ browser.locale ] || sep[ browser.language ] || sep['_']);
|
||||
console.log(result);
|
||||
return result;
|
||||
};
|
||||
})
|
||||
.filter('orderObjectBy', function() {
|
||||
return function(items, field, reverse) {
|
||||
var filtered = [];
|
||||
|
@ -177,7 +258,7 @@ solrAdminApp.config([
|
|||
$rootScope.$broadcast('loadingStatusActive');
|
||||
}
|
||||
activeRequests++;
|
||||
config.timeout = 1000;
|
||||
config.timeout = 10000;
|
||||
return config || $q.when(config);
|
||||
};
|
||||
|
||||
|
@ -238,24 +319,29 @@ solrAdminApp.config([
|
|||
};
|
||||
});
|
||||
|
||||
var solrAdminControllers = angular.module('solrAdminControllers', []);
|
||||
|
||||
solrAdminApp.controller('MainController', function($scope, $routeParams, $rootScope, $location, Cores, Ping) {
|
||||
solrAdminApp.controller('MainController', function($scope, $route, $rootScope, $location, Cores, System, Ping) {
|
||||
$rootScope.hideException = function() {delete $rootScope.exception};
|
||||
$scope.refresh = function() {
|
||||
Cores.list(function(data) {
|
||||
var cores = [];
|
||||
for (key in data.status) {
|
||||
cores.push(data.status[key]);
|
||||
$scope.cores = [];
|
||||
var currentCoreName = $route.current.params.core;
|
||||
for (key in data.status) {
|
||||
var core = data.status[key];
|
||||
$scope.cores.push(core);
|
||||
if (core.name == currentCoreName) {
|
||||
$scope.currentCore = core;
|
||||
}
|
||||
}
|
||||
$scope.cores = cores;
|
||||
});
|
||||
System.get(function(data) {
|
||||
$scope.isCloudEnabledCloud = data.mode.match( /solrcloud/i )
|
||||
});
|
||||
};
|
||||
$scope.refresh();
|
||||
|
||||
$scope.resetMenu = function(page) {
|
||||
$scope.showingLogging = page.lastIndexOf("logging", 0) === 0;
|
||||
$scope.isCloudEnabled = true;
|
||||
$scope.showingCloud = page.lastIndexOf("cloud", 0) === 0;
|
||||
$scope.page = page;
|
||||
};
|
||||
|
@ -274,28 +360,94 @@ solrAdminApp.controller('MainController', function($scope, $routeParams, $rootSc
|
|||
|
||||
|
||||
|
||||
(function(window, angular, undefined) {
|
||||
'use strict';
|
||||
|
||||
angular.module('ngClipboard', []).
|
||||
provider('ngClip', function() {
|
||||
var self = this;
|
||||
this.path = '//cdnjs.cloudflare.com/ajax/libs/zeroclipboard/2.1.6/ZeroClipboard.swf';
|
||||
return {
|
||||
setPath: function(newPath) {
|
||||
self.path = newPath;
|
||||
},
|
||||
setConfig: function(config) {
|
||||
self.config = config;
|
||||
},
|
||||
$get: function() {
|
||||
return {
|
||||
path: self.path,
|
||||
config: self.config
|
||||
};
|
||||
}
|
||||
};
|
||||
}).
|
||||
run(['ngClip', function(ngClip) {
|
||||
var config = {
|
||||
swfPath: ngClip.path,
|
||||
trustedDomains: ["*"],
|
||||
allowScriptAccess: "always",
|
||||
forceHandCursor: true,
|
||||
};
|
||||
ZeroClipboard.config(angular.extend(config,ngClip.config || {}));
|
||||
}]).
|
||||
directive('clipCopy', ['ngClip', function (ngClip) {
|
||||
return {
|
||||
scope: {
|
||||
clipCopy: '&',
|
||||
clipClick: '&',
|
||||
clipClickFallback: '&'
|
||||
},
|
||||
restrict: 'A',
|
||||
link: function (scope, element, attrs) {
|
||||
// Bind a fallback function if flash is unavailable
|
||||
if (ZeroClipboard.isFlashUnusable()) {
|
||||
element.bind('click', function($event) {
|
||||
// Execute the expression with local variables `$event` and `copy`
|
||||
scope.$apply(scope.clipClickFallback({
|
||||
$event: $event,
|
||||
copy: scope.$eval(scope.clipCopy)
|
||||
}));
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the client object
|
||||
var client = new ZeroClipboard(element);
|
||||
if (attrs.clipCopy === "") {
|
||||
scope.clipCopy = function(scope) {
|
||||
return element[0].previousElementSibling.innerText;
|
||||
};
|
||||
}
|
||||
client.on( 'ready', function(readyEvent) {
|
||||
|
||||
client.on('copy', function (event) {
|
||||
var clipboard = event.clipboardData;
|
||||
clipboard.setData(attrs.clipCopyMimeType || 'text/plain', scope.$eval(scope.clipCopy));
|
||||
});
|
||||
|
||||
client.on( 'aftercopy', function(event) {
|
||||
if (angular.isDefined(attrs.clipClick)) {
|
||||
scope.$apply(scope.clipClick);
|
||||
}
|
||||
});
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
client.destroy();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
||||
})(window, window.angular);
|
||||
|
||||
|
||||
/* THE BELOW CODE IS TAKEN FROM js/scripts/app.js, AND STILL REQUIRES INTEGRATING
|
||||
|
||||
SolrDate = function( date )
|
||||
{
|
||||
// ["Sat Mar 03 11:00:00 CET 2012", "Sat", "Mar", "03", "11:00:00", "CET", "2012"]
|
||||
var parts = date.match( /^(\w+)\s+(\w+)\s+(\d+)\s+(\d+\:\d+\:\d+)\s+(\w+)\s+(\d+)$/ );
|
||||
|
||||
// "Sat Mar 03 2012 10:37:33"
|
||||
return new Date( parts[1] + ' ' + parts[2] + ' ' + parts[3] + ' ' + parts[6] + ' ' + parts[4] );
|
||||
}
|
||||
|
||||
// @todo clear timeouts
|
||||
|
||||
this.bind
|
||||
(
|
||||
'error',
|
||||
function( message, original_error )
|
||||
{
|
||||
alert( original_error.message );
|
||||
}
|
||||
);
|
||||
|
||||
// activate_core
|
||||
this.before
|
||||
(
|
||||
|
@ -362,12 +514,6 @@ var solr_admin = function( app_config )
|
|||
|
||||
this.core_regex_base = '^#\\/([\\w\\d-\\.]+)';
|
||||
|
||||
browser = {
|
||||
locale : null,
|
||||
language : null,
|
||||
country : null
|
||||
};
|
||||
|
||||
show_global_error = function( error )
|
||||
{
|
||||
var main = $( '#main' );
|
||||
|
@ -454,8 +600,6 @@ var solr_admin = function( app_config )
|
|||
}
|
||||
|
||||
var core_selector = $( '#core-selector' );
|
||||
core_selector.find( '#has-cores' ).toggle( has_cores );
|
||||
core_selector.find( '#has-no-cores' ).toggle( !has_cores );
|
||||
|
||||
if( has_cores )
|
||||
{
|
||||
|
@ -468,70 +612,10 @@ var solr_admin = function( app_config )
|
|||
cores_element.find( '.chzn-drop' )
|
||||
.css( 'width', ( selector_width - 2 ) + 'px' );
|
||||
}
|
||||
|
||||
this.check_for_init_failures( cores );
|
||||
};
|
||||
|
||||
this.remove_init_failures = function remove_init_failures()
|
||||
{
|
||||
$( '#init-failures' )
|
||||
.hide()
|
||||
.find( 'ul' )
|
||||
.empty();
|
||||
}
|
||||
|
||||
this.check_for_init_failures = function check_for_init_failures( cores )
|
||||
{
|
||||
if( !cores.initFailures )
|
||||
{
|
||||
this.remove_init_failures();
|
||||
return false;
|
||||
}
|
||||
|
||||
var failures = [];
|
||||
for( var core_name in cores.initFailures )
|
||||
{
|
||||
failures.push
|
||||
(
|
||||
'<li>' +
|
||||
'<strong>' + core_name.esc() + ':</strong>' + "\n" +
|
||||
cores.initFailures[core_name].esc() + "\n" +
|
||||
'</li>'
|
||||
);
|
||||
}
|
||||
|
||||
if( 0 === failures.length )
|
||||
{
|
||||
this.remove_init_failures();
|
||||
return false;
|
||||
}
|
||||
|
||||
$( '#init-failures' )
|
||||
.show()
|
||||
.find( 'ul' )
|
||||
.html( failures.join( "\n" ) );
|
||||
}
|
||||
|
||||
this.run = function()
|
||||
{
|
||||
var navigator_language = navigator.userLanguage || navigator.language;
|
||||
var language_match = navigator_language.match( /^(\w{2})([-_](\w{2}))?$/ );
|
||||
if( language_match )
|
||||
{
|
||||
if( language_match[1] )
|
||||
{
|
||||
browser.language = language_match[1].toLowerCase();
|
||||
}
|
||||
if( language_match[3] )
|
||||
{
|
||||
browser.country = language_match[3].toUpperCase();
|
||||
}
|
||||
if( language_match[1] && language_match[3] )
|
||||
{
|
||||
browser.locale = browser.language + '_' + browser.country
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax
|
||||
(
|
||||
{
|
||||
|
@ -619,113 +703,10 @@ var solr_admin = function( app_config )
|
|||
'<requestHandler name="/admin/" class="solr.admin.AdminHandlers" />'.esc() +
|
||||
'</code></pre></div>'
|
||||
);
|
||||
},
|
||||
complete : function()
|
||||
{
|
||||
loader.hide( this );
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
error : function()
|
||||
{
|
||||
},
|
||||
complete : function()
|
||||
{
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.convert_duration_to_seconds = function convert_duration_to_seconds( str )
|
||||
{
|
||||
var seconds = 0;
|
||||
var arr = new String( str || '' ).split( '.' );
|
||||
var parts = arr[0].split( ':' ).reverse();
|
||||
var parts_count = parts.length;
|
||||
|
||||
for( var i = 0; i < parts_count; i++ )
|
||||
{
|
||||
seconds += ( parseInt( parts[i], 10 ) || 0 ) * Math.pow( 60, i );
|
||||
}
|
||||
|
||||
// treat more or equal than .5 as additional second
|
||||
if( arr[1] && 5 <= parseInt( arr[1][0], 10 ) )
|
||||
{
|
||||
seconds++;
|
||||
}
|
||||
|
||||
return seconds;
|
||||
};
|
||||
|
||||
this.convert_seconds_to_readable_time = function convert_seconds_to_readable_time( seconds )
|
||||
{
|
||||
seconds = parseInt( seconds || 0, 10 );
|
||||
var minutes = Math.floor( seconds / 60 );
|
||||
var hours = Math.floor( minutes / 60 );
|
||||
|
||||
var text = [];
|
||||
if( 0 !== hours )
|
||||
{
|
||||
text.push( hours + 'h' );
|
||||
seconds -= hours * 60 * 60;
|
||||
minutes -= hours * 60;
|
||||
}
|
||||
|
||||
if( 0 !== minutes )
|
||||
{
|
||||
text.push( minutes + 'm' );
|
||||
seconds -= minutes * 60;
|
||||
}
|
||||
|
||||
if( 0 !== seconds )
|
||||
{
|
||||
text.push( ( '0' + seconds ).substr( -2 ) + 's' );
|
||||
}
|
||||
|
||||
return text.join( ' ' );
|
||||
};
|
||||
|
||||
this.format_json = function format_json( json_str )
|
||||
{
|
||||
if( JSON.stringify && JSON.parse )
|
||||
{
|
||||
json_str = JSON.stringify( JSON.parse( json_str ), undefined, 2 );
|
||||
}
|
||||
|
||||
return json_str.esc();
|
||||
};
|
||||
|
||||
this.format_number = function format_number( number )
|
||||
{
|
||||
var sep = {
|
||||
'de_CH' : '\'',
|
||||
'de' : '.',
|
||||
'en' : ',',
|
||||
'es' : '.',
|
||||
'it' : '.',
|
||||
'ja' : ',',
|
||||
'sv' : ' ',
|
||||
'tr' : '.',
|
||||
'_' : '' // fallback
|
||||
};
|
||||
|
||||
return ( number || 0 ).toString().replace
|
||||
(
|
||||
/\B(?=(\d{3})+(?!\d))/g,
|
||||
sep[ browser.locale ] || sep[ browser.language ] || sep['_']
|
||||
);
|
||||
};
|
||||
|
||||
check_fixed_menu = function check_fixed_menu()
|
||||
{
|
||||
$( '#wrapper' ).toggleClass( 'scroll', $( window ).height() < $( '#menu-wrapper' ).height() + $( '#header' ).height() + 40 );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
$.ajaxSetup( { cache: false } );
|
||||
var app = new solr_admin( app_config );
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
var dataimport_timeout = 2000;
|
||||
|
||||
solrAdminApp.controller('DataImportController',
|
||||
function($scope, $rootScope, $routeParams, $location, $timeout, $interval, $cookies, Mbeans, DataImport) {
|
||||
$scope.resetMenu("dataimport");
|
||||
|
||||
$scope.refresh = function () {
|
||||
Mbeans.info({core: $routeParams.core, cat: 'QUERYHANDLER'}, function (data) {
|
||||
var mbeans = data['solr-mbeans'][1];
|
||||
$scope.handlers = [];
|
||||
for (var key in mbeans) {
|
||||
if (mbeans[key]['class'] !== key && mbeans[key]['class'] === 'org.apache.solr.handler.dataimport.DataImportHandler') {
|
||||
$scope.handlers.push(key);
|
||||
}
|
||||
}
|
||||
$scope.hasHandlers = $scope.handlers.length > 0;
|
||||
|
||||
if (!$routeParams.handler) {
|
||||
$location.path("/" + $routeParams.core + "/dataimport/" + $scope.handlers[0]);
|
||||
} else {
|
||||
$scope.currentHandler = $routeParams.handler;
|
||||
}
|
||||
});
|
||||
|
||||
DataImport.config({core: $routeParams.core}, function (data) {
|
||||
$scope.config = data.config;
|
||||
$scope.entities = [];
|
||||
var xml = $.parseXML($scope.config);
|
||||
$('document > entity', xml).each(function (i, element) {
|
||||
$scope.entities.push($(element).attr('name'));
|
||||
});
|
||||
});
|
||||
|
||||
$scope.lastUpdate = "unknown";
|
||||
$scope.lastUpdateUTC = "";
|
||||
|
||||
$scope.refreshStatus();
|
||||
};
|
||||
|
||||
$scope.toggleDebug = function () {
|
||||
$scope.isDebugMode = !$scope.isDebugMode;
|
||||
$scope.showConfiguration = true;
|
||||
}
|
||||
|
||||
$scope.toggleConfiguration = function () {
|
||||
$scope.showConfiguration = !$scope.showConfiguration;
|
||||
}
|
||||
|
||||
$scope.toggleRawStatus = function () {
|
||||
$scope.showRawStatus = !$scope.showRawStatus;
|
||||
}
|
||||
|
||||
$scope.toggleRawDebug = function () {
|
||||
$scope.showRawDebug = !$scope.showRawDebug;
|
||||
}
|
||||
|
||||
$scope.reload = function () {
|
||||
DataImport.reload({core: $routeParams.core}, function () {
|
||||
$scope.reloaded = true;
|
||||
$timeout(function () {
|
||||
$scope.reloaded = false;
|
||||
}, 5000);
|
||||
$scope.refresh();
|
||||
});
|
||||
}
|
||||
|
||||
$scope.form = {
|
||||
command: "full-import",
|
||||
verbose: false,
|
||||
clean: true,
|
||||
commit: true,
|
||||
optimize: false,
|
||||
showDebug: false,
|
||||
custom: "",
|
||||
core: $routeParams.core
|
||||
};
|
||||
|
||||
$scope.submit = function () {
|
||||
var params = {};
|
||||
for (var key in $scope.form) {
|
||||
params[key] = $scope.form[key];
|
||||
}
|
||||
if (params.custom.length) {
|
||||
var customParams = $scope.form.custom.split("&");
|
||||
for (var i in customParams) {
|
||||
var parts = customParams[i].split("=");
|
||||
params[parts[0]] = parts[1];
|
||||
}
|
||||
}
|
||||
delete params.custom;
|
||||
|
||||
if (params.isDebugMode) {
|
||||
params.dataConfig = $scope.rawConfig;
|
||||
}
|
||||
delete params.showDebug;
|
||||
params.core = $routeParams.core;
|
||||
|
||||
DataImport.post(params, function (data) {
|
||||
$scope.rawResponse = JSON.stringify(data, null, 2);
|
||||
$scope.refreshStatus();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.abort = function () {
|
||||
$scope.isAborting = true;
|
||||
DataImport.abort({core: $routeParams.core}, function () {
|
||||
$timeout(function () {
|
||||
$scope.isAborting = false;
|
||||
$scope.refreshStatus();
|
||||
}, 4000);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.refreshStatus = function () {
|
||||
|
||||
console.log("Refresh Status");
|
||||
|
||||
$scope.isStatusLoading = true;
|
||||
DataImport.status({core: $routeParams.core}, function (data) {
|
||||
|
||||
var now = new Date();
|
||||
$scope.lastUpdate = now.toTimeString().split(' ').shift();
|
||||
$scope.lastUpdateUTC = now.toUTCString();
|
||||
var messages = data.statusMessages;
|
||||
var messagesCount = 0;
|
||||
for( var key in messages ) { messagesCount++; }
|
||||
|
||||
if (data.status == 'busy') {
|
||||
$scope.status = "indexing";
|
||||
|
||||
$scope.timeElapsed = data.statusMessages['Time Elapsed'];
|
||||
$scope.elapsedSeconds = parseSeconds($scope.timeElapsed);
|
||||
|
||||
var info = $scope.timeElapsed ? 'Indexing since ' + $scope.timeElapsed : 'Indexing ...';
|
||||
$scope.info = showInfo(messages, true, info, $scope.elapsedSeconds);
|
||||
|
||||
} else if (messages.RolledBack) {
|
||||
$scope.status = "failure";
|
||||
$scope.info = showInfo(messages, true);
|
||||
} else if (messages.Aborted) {
|
||||
$scope.status = "aborted";
|
||||
$scope.info = showInfo(messages, true, 'Aborting current Import ...');
|
||||
} else if (data.status == "idle" && messagesCount != 0) {
|
||||
$scope.status = "success";
|
||||
$scope.info = showInfo(messages, true);
|
||||
} else {
|
||||
$scope.status = "idle";
|
||||
$scope.info = showInfo(messages, false, 'No information available (idle)');
|
||||
}
|
||||
|
||||
delete data.$promise;
|
||||
delete data.$resolved;
|
||||
|
||||
$scope.rawStatus = JSON.stringify(data, null, 2);
|
||||
|
||||
$scope.isStatusLoading = false;
|
||||
$scope.statusUpdated = true;
|
||||
$timeout(function () {
|
||||
$scope.statusUpdated = false;
|
||||
}, dataimport_timeout / 2);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.updateAutoRefresh = function () {
|
||||
$scope.autorefresh = !$scope.autorefresh;
|
||||
$cookies.dataimport_autorefresh = $scope.autorefresh ? true : null;
|
||||
if ($scope.autorefresh) {
|
||||
$scope.refreshTimeout = $interval($scope.refreshStatus, dataimport_timeout);
|
||||
} else if ($scope.refreshTimeout) {
|
||||
$interval.cancel($scope.refreshTimeout);
|
||||
}
|
||||
$scope.refreshStatus();
|
||||
};
|
||||
|
||||
$scope.refresh();
|
||||
|
||||
});
|
||||
|
||||
var showInfo = function (messages, showFull, info_text, elapsed_seconds) {
|
||||
|
||||
var info = {};
|
||||
if (info_text) {
|
||||
info.text = info_text;
|
||||
} else {
|
||||
info.text = messages[''] || '';
|
||||
// format numbers included in status nicely
|
||||
/* @todo this pretty printing is hard to work out how to do in an Angularesque way:
|
||||
info.text = info.text.replace(/\d{4,}/g,
|
||||
function (match, position, string) {
|
||||
return app.format_number(parseInt(match, 10));
|
||||
}
|
||||
);
|
||||
*/
|
||||
|
||||
var time_taken_text = messages['Time taken'];
|
||||
info.timeTaken = parseSeconds(time_taken_text);
|
||||
}
|
||||
info.showDetails = false;
|
||||
|
||||
if (showFull) {
|
||||
if (!elapsed_seconds) {
|
||||
var time_taken_text = messages['Time taken'];
|
||||
elapsed_seconds = parseSeconds(time_taken_text);
|
||||
}
|
||||
|
||||
info.showDetails = true;
|
||||
|
||||
var document_config = {
|
||||
'Requests': 'Total Requests made to DataSource',
|
||||
'Fetched': 'Total Rows Fetched',
|
||||
'Skipped': 'Total Documents Skipped',
|
||||
'Processed': 'Total Documents Processed'
|
||||
};
|
||||
|
||||
info.docs = [];
|
||||
for (var key in document_config) {
|
||||
var value = parseInt(messages[document_config[key]], 10);
|
||||
var doc = {desc: document_config[key], name: key, value: value};
|
||||
if (elapsed_seconds && key != 'Skipped') {
|
||||
doc.speed = Math.round(value / elapsed_seconds);
|
||||
}
|
||||
info.docs.push(doc);
|
||||
}
|
||||
|
||||
var dates_config = {
|
||||
'Started': 'Full Dump Started',
|
||||
'Aborted': 'Aborted',
|
||||
'Rolledback': 'Rolledback'
|
||||
};
|
||||
|
||||
info.dates = [];
|
||||
for (var key in dates_config) {
|
||||
var value = messages[dates_config[key]];
|
||||
if (value) {
|
||||
value = value.replace(" ", "T")+".000Z";
|
||||
console.log(value);
|
||||
var date = {desc: dates_config[key], name: key, value: value};
|
||||
info.dates.push(date);
|
||||
}
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
var parseSeconds = function(time) {
|
||||
var seconds = 0;
|
||||
var arr = new String(time || '').split('.');
|
||||
var parts = arr[0].split(':').reverse();
|
||||
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
seconds += ( parseInt(parts[i], 10) || 0 ) * Math.pow(60, i);
|
||||
}
|
||||
|
||||
if (arr[1] && 5 <= parseInt(arr[1][0], 10)) {
|
||||
seconds++; // treat more or equal than .5 as additional second
|
||||
}
|
||||
return seconds;
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
solrAdminApp.controller('ReplicationController',
|
||||
function($scope, $rootScope, $routeParams, $interval, $timeout, Replication) {
|
||||
$scope.resetMenu("replication");
|
||||
|
||||
$scope.iterationCount = 1;
|
||||
|
||||
$scope.refresh = function() {
|
||||
Replication.details({core:$routeParams.core}, function(response) {
|
||||
if ($scope.interval) $interval.cancel($scope.interval);
|
||||
$scope.isSlave = (response.details.isSlave === 'true');
|
||||
if ($scope.isSlave) {
|
||||
$scope.progress = getProgressDetails(response.details.slave);
|
||||
$scope.iterations = getIterations(response.details.slave);
|
||||
$scope.versions = getSlaveVersions(response.details);
|
||||
$scope.settings = getSlaveSettings(response.details);
|
||||
if ($scope.settings.isReplicating) {
|
||||
$timeout($scope.refresh, 1000);
|
||||
} else if(!$scope.settings.isPollingDisabled && $scope.settings.pollInterval) {
|
||||
$scope.interval = $interval(function() {
|
||||
$scope.settings.tick--;
|
||||
}, 1000, $scope.settings.tick);
|
||||
$timeout($scope.refresh, 1000*(1+$scope.settings.tick));
|
||||
}
|
||||
} else {
|
||||
$scope.versions = getMasterVersions(response.details);
|
||||
}
|
||||
$scope.master = getMasterSettings(response.details, $scope.isSlave);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
$scope.execute = function(command) {
|
||||
Replication.command({core:$routeParams.core, command:command}, function(data){$scope.refresh()});
|
||||
}
|
||||
|
||||
$scope.showIterations = function() { $scope.iterationCount = 100000}; // limitTo should accept undefined, but doesn't work.
|
||||
$scope.hideIterations = function() { $scope.iterationCount = 1};
|
||||
|
||||
$scope.refresh();
|
||||
});
|
||||
|
||||
var getProgressDetails = function(progress) {
|
||||
|
||||
progress.timeRemaining = parseSeconds(progress.timeRemaining);
|
||||
progress.totalPercent = parseInt(progress.totalPercent);
|
||||
if (progress.totalPercent === 0) {
|
||||
progress.totalPercentWidth = "1px";
|
||||
} else {
|
||||
progress.totalPercentWidth = progress.totalPercent + "%";
|
||||
}
|
||||
progress.currentFileSizePercent = parseInt(progress.currentFileSizePercent);
|
||||
|
||||
if (!progress.indexReplicatedAtList) {
|
||||
progress.indexReplicatedAtList = [];
|
||||
}
|
||||
|
||||
if (!progress.replicationFailedAtList) {
|
||||
progress.replicationFailedAtList = [];
|
||||
}
|
||||
return progress;
|
||||
};
|
||||
|
||||
var getIterations = function(slave) {
|
||||
|
||||
var iterations = [];
|
||||
|
||||
var find = function(list, date) {
|
||||
return list.filter(function(e) {return e.date == date});
|
||||
};
|
||||
|
||||
for (var i in slave.indexReplicatedAtList) {
|
||||
var date = slave.indexReplicatedAtList[i];
|
||||
var iteration = {date:date, status:"replicated", latest: false};
|
||||
if (date == slave.indexReplicatedAt) {
|
||||
iteration.latest = true;
|
||||
}
|
||||
iterations.push(iteration);
|
||||
}
|
||||
|
||||
for (var i in slave.replicationFailedAtList) {
|
||||
var failedDate = slave.replicationFailedAtList[i];
|
||||
var matchingIterations = find(iterations, failedDate);
|
||||
if (matchingIterations) {
|
||||
iteration = matchingIterations[0];
|
||||
} else {
|
||||
iteration = {date: failedDate, latest:false};
|
||||
iterations.push(iteration);
|
||||
}
|
||||
iteration.status = "failed";
|
||||
if (failedDate == slave.replicationFailedAt) {
|
||||
iteration.latest = true;
|
||||
}
|
||||
}
|
||||
iterations.sort(function(a,b){ return a.date> b.date;}).reverse();
|
||||
return iterations;
|
||||
};
|
||||
|
||||
var getMasterVersions = function(data) {
|
||||
versions = {masterSearch:{}, master:{}};
|
||||
|
||||
versions.masterSearch.version = data.indexVersion;
|
||||
versions.masterSearch.generation = data.generation;
|
||||
versions.masterSearch.size = data.indexSize;
|
||||
|
||||
versions.master.version = data.master.replicableVersion || '-';
|
||||
versions.master.generation = data.master.replicableGeneration || '-';
|
||||
versions.master.size = '-';
|
||||
|
||||
return versions;
|
||||
};
|
||||
|
||||
var getSlaveVersions = function(data) {
|
||||
versions = {masterSearch: {}, master: {}, slave: {}};
|
||||
|
||||
versions.slave.version = data.indexVersion;
|
||||
versions.slave.generation = data.generation;
|
||||
versions.slave.size = data.indexSize;
|
||||
|
||||
versions.master.version = data.slave.masterDetails.replicableVersion || '-';
|
||||
versions.master.generation = data.slave.masterDetails.replicableGeneration || '-';
|
||||
versions.master.size = '-';
|
||||
|
||||
versions.masterSearch.version = data.slave.masterDetails.indexVersion;
|
||||
versions.masterSearch.generation = data.slave.masterDetails.generation;
|
||||
versions.masterSearch.size = data.slave.masterDetails.indexSize;
|
||||
|
||||
versions.changedVersion = data.indexVersion !== data.slave.masterDetails.indexVersion;
|
||||
versions.changedGeneration = data.generation !== data.slave.masterDetails.generation;
|
||||
|
||||
return versions;
|
||||
};
|
||||
|
||||
var parseDateToEpoch = function(date) {
|
||||
// ["Sat Mar 03 11:00:00 CET 2012", "Sat", "Mar", "03", "11:00:00", "CET", "2012"]
|
||||
var parts = date.match( /^(\w+)\s+(\w+)\s+(\d+)\s+(\d+\:\d+\:\d+)\s+(\w+)\s+(\d+)$/ );
|
||||
|
||||
// "Sat Mar 03 2012 10:37:33"
|
||||
var d = new Date( parts[1] + ' ' + parts[2] + ' ' + parts[3] + ' ' + parts[6] + ' ' + parts[4] );
|
||||
return d.getTime();
|
||||
}
|
||||
|
||||
var parseSeconds = function(time) {
|
||||
var seconds = 0;
|
||||
var arr = new String(time || '').split('.');
|
||||
var parts = arr[0].split(':').reverse();
|
||||
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
seconds += ( parseInt(parts[i], 10) || 0 ) * Math.pow(60, i);
|
||||
}
|
||||
|
||||
if (arr[1] && 5 <= parseInt(arr[1][0], 10)) {
|
||||
seconds++; // treat more or equal than .5 as additional second
|
||||
|
||||
}
|
||||
|
||||
return seconds;
|
||||
}
|
||||
|
||||
var getSlaveSettings = function(data) {
|
||||
var settings = {};
|
||||
settings.masterUrl = data.slave.masterUrl;
|
||||
settings.isPollingDisabled = data.slave.isPollingDisabled == 'true';
|
||||
settings.pollInterval = data.slave.pollInterval;
|
||||
settings.isReplicating = data.slave.isReplicating == 'true';
|
||||
settings.nextExecutionAt = data.slave.nextExecutionAt;
|
||||
|
||||
if(settings.isReplicating) {
|
||||
settings.isApprox = true;
|
||||
settings.tick = parseSeconds(settings.pollInterval);
|
||||
} else if (!settings.isPollingDisabled && settings.pollInterval) {
|
||||
if( settings.nextExecutionAt ) {
|
||||
settings.nextExecutionAtEpoch = parseDateToEpoch(settings.nextExecutionAt);
|
||||
settings.currentTime = parseDateToEpoch(data.slave.currentDate);
|
||||
|
||||
if( settings.nextExecutionAtEpoch > settings.currentTime) {
|
||||
settings.isApprox = false;
|
||||
settings.tick = ( settings.nextExecutionAtEpoch - settings.currentTime) / 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
|
||||
var getMasterSettings = function(details, isSlave) {
|
||||
var master = {};
|
||||
var masterData = isSlave ? details.slave.masterDetails.master : details.master;
|
||||
master.replicationEnabled = masterData.replicationEnabled == "true";
|
||||
master.replicateAfter = masterData.replicateAfter.join(", ");
|
||||
|
||||
if (masterData.confFiles) {
|
||||
master.files = [];
|
||||
var confFiles = masterData.confFiles.split(',');
|
||||
for (var i=0; i<confFiles.length; i++) {
|
||||
var file = confFiles[i];
|
||||
var short = file;
|
||||
var title = file;
|
||||
if (file.indexOf(":")>=0) {
|
||||
title = file.replace(':', ' » ');
|
||||
var parts = file.split(':');
|
||||
if (isSlave) {
|
||||
short = parts[1];
|
||||
} else {
|
||||
short = parts[0];
|
||||
}
|
||||
}
|
||||
master.files.push({title:title, name:short});
|
||||
}
|
||||
}
|
||||
return master;
|
||||
}
|
|
@ -0,0 +1,432 @@
|
|||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
var cookie_schema_browser_autoload = 'schema-browser_autoload';
|
||||
|
||||
solrAdminApp.controller('SchemaBrowserController',
|
||||
function($scope, $routeParams, $location, $cookies, Luke) {
|
||||
$scope.resetMenu("schema-browser");
|
||||
|
||||
$scope.refresh = function () {
|
||||
Luke.schema({core: $routeParams.core}, function (schema) {
|
||||
Luke.index({core: $routeParams.core}, function (index) {
|
||||
|
||||
var data = mergeIndexAndSchemaData(index, schema.schema);
|
||||
|
||||
$scope.fieldsAndTypes = getFieldsAndTypes(data);
|
||||
$scope.is = {};
|
||||
|
||||
var search = $location.search();
|
||||
leftbar = {};
|
||||
$scope.isField = $scope.isDynamicField = $scope.isType = false;
|
||||
if (search.field) {
|
||||
$scope.selectedType = "Field";
|
||||
$scope.is.field = true;
|
||||
$scope.name = search.field;
|
||||
leftbar.fields = [$scope.name];
|
||||
var field = data.fields[$scope.name];
|
||||
leftbar.types = [field.type];
|
||||
if (field.dynamicBase) leftbar.dynamicFields = [field.dynamicBase];
|
||||
if (field.copySources && field.copySources.length>0) leftbar.copyFieldSources = field.copySources.sort();
|
||||
if (field.copyDests && field.copyDests.length>0) leftbar.copyFieldDests = field.copyDests.sort();
|
||||
$scope.fieldOrType = "field=" + $scope.name;
|
||||
} else if (search["dynamic-field"]) {
|
||||
$scope.selectedType = "Dynamic Field";
|
||||
$scope.is.dynamicField = true;
|
||||
$scope.name = search["dynamic-field"];
|
||||
leftbar.dynamicFields = [$scope.name];
|
||||
leftbar.types = [data.dynamic_fields[$scope.name].type];
|
||||
$scope.fieldOrType = "dynamic-field=" + $scope.name;
|
||||
} else if (search.type) {
|
||||
$scope.selectedType = "Type";
|
||||
$scope.is.type = true;
|
||||
$scope.name = search.type;
|
||||
leftbar.types = [$scope.name];
|
||||
leftbar.fields = filterFields("fields", data, $scope.name);
|
||||
leftbar.dynamicFields = filterFields("dynamic_fields", data, $scope.name);
|
||||
$scope.fieldOrType = "type=" + $scope.name;
|
||||
}
|
||||
$scope.leftbar = leftbar;
|
||||
$scope.core = $routeParams.core;
|
||||
$scope.defaultSearchField = data.default_search_field;
|
||||
$scope.uniqueKeyField = data.unique_key_field;
|
||||
$scope.isDefaultSearchField = ($scope.selectedType == "Field" && $scope.name == $scope.defaultSearchField);
|
||||
$scope.isUniqueKeyField = ($scope.selectedType == "Field" && $scope.name == $scope.uniqueKeyField);
|
||||
|
||||
$scope.display = getFieldProperties(index, $routeParams.core, $scope.is, $scope.name);
|
||||
$scope.analysis = getAnalysisInfo(data, $scope.is, $scope.name);
|
||||
|
||||
$scope.isAutoload = $cookies[cookie_schema_browser_autoload] == "true";
|
||||
if ($scope.isAutoload) {
|
||||
$scope.toggleTerms();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
$scope.refresh();
|
||||
|
||||
$scope.selectFieldOrType = function() {
|
||||
$location.search($scope.fieldOrType);
|
||||
}
|
||||
|
||||
$scope.toggleAnalyzer = function(analyzer) {
|
||||
analyzer.show = !analyzer.show;
|
||||
}
|
||||
|
||||
$scope.loadTermInfo = function() {
|
||||
var params = {fl: $scope.name, core: $routeParams.core};
|
||||
if ($scope.topTermsCount) {
|
||||
params.numTerms = $scope.topTermsCount;
|
||||
}
|
||||
$scope.isLoadingTerms = true;
|
||||
Luke.field(params, function (data) {
|
||||
$scope.isLoadingTerms = false;
|
||||
$scope.termInfo = getTermInfo(data.fields[$scope.name]);
|
||||
if (!$scope.topTermsCount) {
|
||||
$scope.topTermsCount = $scope.termInfo.termCount;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.toggleTerms = function() {
|
||||
$scope.showTerms = !$scope.showTerms;
|
||||
|
||||
if ($scope.showTerms) {
|
||||
$scope.loadTermInfo();
|
||||
}
|
||||
}
|
||||
|
||||
$scope.loadAllTerms = function() {
|
||||
$scope.topTermsCount = $scope.termInfo.maxTerms;
|
||||
$scope.loadTermInfo();
|
||||
}
|
||||
|
||||
$scope.toggleAutoload = function() {
|
||||
$scope.isAutoload = !$scope.isAutoload;
|
||||
$cookies[cookie_schema_browser_autoload] = $scope.isAutoload;
|
||||
console.log("cookie: " + $cookies[cookie_schema_browser_autoload]);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
var getFieldsAndTypes = function(data) {
|
||||
var fieldsAndTypes = [];
|
||||
for (var field in data.fields) {
|
||||
fieldsAndTypes.push({
|
||||
group: "Fields",
|
||||
value: "field=" + field,
|
||||
label: field
|
||||
});
|
||||
}
|
||||
for (var field in data.dynamic_fields) {
|
||||
fieldsAndTypes.push({
|
||||
group: "Dynamic Fields",
|
||||
value: "dynamic-field=" + field,
|
||||
label: field
|
||||
});
|
||||
}
|
||||
for (var type in data.types) {
|
||||
fieldsAndTypes.push({
|
||||
group: "Types",
|
||||
value: "type=" + type,
|
||||
label: type
|
||||
});
|
||||
}
|
||||
return fieldsAndTypes;
|
||||
};
|
||||
|
||||
var filterFields = function(type, data, name) {
|
||||
var fields = [];
|
||||
for (var i in data.types[name].fields) {
|
||||
var field = data.types[name].fields[i];
|
||||
if (data[type][field]) {
|
||||
fields.push(field)
|
||||
}
|
||||
}
|
||||
return fields.sort();
|
||||
}
|
||||
|
||||
var mergeIndexAndSchemaData = function(index, schema) {
|
||||
|
||||
var data = {
|
||||
default_search_field: null,
|
||||
unique_key_field: null,
|
||||
key: {},
|
||||
fields: {},
|
||||
dynamic_fields: {},
|
||||
types: {},
|
||||
relations: {
|
||||
f_df: {},
|
||||
f_t: {},
|
||||
df_f: {},
|
||||
df_t: {},
|
||||
t_f: {},
|
||||
t_df: {}
|
||||
}
|
||||
};
|
||||
|
||||
data.fields = index.fields;
|
||||
|
||||
data.key = index.info.key;
|
||||
|
||||
data.default_search_field = schema.defaultSearchField;
|
||||
data.unique_key_field = schema.uniqueKeyField;
|
||||
|
||||
data.dynamic_fields = schema.dynamicFields;
|
||||
data.types = schema.types;
|
||||
|
||||
for (var field in schema.fields) {
|
||||
data.fields[field] =
|
||||
$.extend({}, data.fields[field], schema.fields[field]);
|
||||
}
|
||||
|
||||
for (var field in data.fields) {
|
||||
var copy_dests = data.fields[field].copyDests;
|
||||
for (var i in copy_dests) {
|
||||
var copy_dest = copy_dests[i];
|
||||
if (!data.fields[copy_dest]) {
|
||||
data.fields[copy_dest] = {
|
||||
partial: true,
|
||||
copySources: []
|
||||
};
|
||||
}
|
||||
|
||||
if (data.fields[copy_dest].partial) {
|
||||
data.fields[copy_dest].copySources.push(field);
|
||||
}
|
||||
}
|
||||
|
||||
var copy_sources = data.fields[field].copySources;
|
||||
for (var i in copy_sources) {
|
||||
var copy_source = copy_sources[i];
|
||||
if (!data.fields[copy_source]) {
|
||||
data.fields[copy_source] = {
|
||||
partial: true,
|
||||
copyDests: []
|
||||
};
|
||||
}
|
||||
|
||||
if (data.fields[copy_source].partial) {
|
||||
data.fields[copy_source].copyDests.push(field);
|
||||
}
|
||||
}
|
||||
|
||||
data.relations.f_t[field] = data.fields[field].type;
|
||||
|
||||
if (!data.relations.t_f[data.fields[field].type]) {
|
||||
data.relations.t_f[data.fields[field].type] = [];
|
||||
}
|
||||
data.relations.t_f[data.fields[field].type].push(field);
|
||||
|
||||
if (data.fields[field].dynamicBase) {
|
||||
data.relations.f_df[field] = data.fields[field].dynamicBase;
|
||||
|
||||
if (!data.relations.df_f[data.fields[field].dynamicBase]) {
|
||||
data.relations.df_f[data.fields[field].dynamicBase] = [];
|
||||
}
|
||||
data.relations.df_f[data.fields[field].dynamicBase].push(field);
|
||||
}
|
||||
}
|
||||
|
||||
for (var dynamic_field in data.dynamic_fields) {
|
||||
data.relations.df_t[dynamic_field] = data.dynamic_fields[dynamic_field].type;
|
||||
|
||||
if (!data.relations.t_df[data.dynamic_fields[dynamic_field].type]) {
|
||||
data.relations.t_df[data.dynamic_fields[dynamic_field].type] = [];
|
||||
}
|
||||
data.relations.t_df[data.dynamic_fields[dynamic_field].type].push(dynamic_field);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
var getFieldProperties = function(data, core, is, field) {
|
||||
|
||||
var display = {};
|
||||
|
||||
display.partialState = is.field && !!data.fields[field].partial;
|
||||
|
||||
display.columns = [];
|
||||
display.rows = [];
|
||||
var allFlags = "";
|
||||
|
||||
var addRow = function(name, flags) {
|
||||
if (flags[0]!='(') {
|
||||
display.rows.push({name:name, flags:flags});
|
||||
for (var i in flags) {
|
||||
if (flags[i]!="-" && allFlags.indexOf(flags[i])<0) {
|
||||
allFlags+=flags[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
display.rows.push({name:name, comment:flags});
|
||||
}
|
||||
}
|
||||
|
||||
// Identify the rows for our field property table
|
||||
if (is.field && data.fields[field]) {
|
||||
if (data.fields[field].flags) {
|
||||
addRow('Properties', data.fields[field].flags);
|
||||
}
|
||||
if (data.fields[field].schema) {
|
||||
addRow('Schema', data.fields[field].schema);
|
||||
}
|
||||
if (data.fields[field].index) {
|
||||
addRow('Index', data.fields[field].index);
|
||||
}
|
||||
display.docs = data.fields[field].docs;
|
||||
display.docsUrl = "#/" + core + "/query?q=" + field + ":[* TO *]";
|
||||
display.distinct = data.fields[field].distinct;
|
||||
display.positionIncrementGap = data.fields[field].positionIncrementGap;
|
||||
display.similarity = data.fields[field].similarity;
|
||||
} else if (is.dynamicField && data.dynamic_fields[field] && data.dynamic_fields[field].flags) {
|
||||
addRow('Properties', data.dynamic_fields[field].flags);
|
||||
}
|
||||
|
||||
// identify columns in field property table:
|
||||
for (var key in data.info.key) {
|
||||
if (allFlags.indexOf(key)>=0) {
|
||||
display.columns.push({key: key, name: data.info.key[key]});
|
||||
}
|
||||
}
|
||||
|
||||
// identify rows and cell values in field property table:
|
||||
for (var i in display.rows) {
|
||||
var row = display.rows[i];
|
||||
row.cells = [];
|
||||
|
||||
for (var j in display.columns) {
|
||||
var flag = display.columns[j].key;
|
||||
row.cells.push({key: flag, value: row.flags.indexOf(flag)>=0});
|
||||
}
|
||||
}
|
||||
|
||||
return display;
|
||||
};
|
||||
|
||||
var getAnalysisInfo = function(data, is, name) {
|
||||
|
||||
var analysis = {};
|
||||
|
||||
if (is.field) {
|
||||
var type = data.relations.f_t[name];
|
||||
analysis.query = "analysis.fieldname=" + name;
|
||||
}
|
||||
else if (is.dynamicField) {
|
||||
var type = data.relations.df_t[name];
|
||||
analysis.query = "analysis.fieldtype=" + type;
|
||||
}
|
||||
else if (is.type) {
|
||||
var type = name;
|
||||
analysis.query = "analysis.fieldtype=" + name;
|
||||
}
|
||||
|
||||
var processComponentType = function (label, key, componentTypeData) {
|
||||
if (componentTypeData) {
|
||||
var components = [];
|
||||
console.dir(componentTypeData);
|
||||
for (var componentName in componentTypeData) {
|
||||
console.log(componentName);
|
||||
var componentData = componentTypeData[componentName];
|
||||
var component = {className: componentData.className, args:[]};
|
||||
if (componentData.args) {
|
||||
for (var argName in componentData.args) {
|
||||
var argValue = componentData.args[argName];
|
||||
if (argValue == "1" || argValue == "true") {
|
||||
component.args.push({name: argName, booleanValue:true});
|
||||
} else if (argValue == "0" || argValue == "false") {
|
||||
component.args.push({name: argName, booleanValue:false});
|
||||
} else {
|
||||
component.args.push({name: argName, value:argValue});
|
||||
}
|
||||
}
|
||||
}
|
||||
components.push(component);
|
||||
}
|
||||
return {label: label, key: key, components: components};
|
||||
} else {
|
||||
return {label: label, key: key};
|
||||
}
|
||||
}
|
||||
|
||||
var buildAnalyzer = function (analyzerData) {
|
||||
var analyzer = {};
|
||||
analyzer.className = analyzerData.className;
|
||||
analyzer.componentTypes = [];
|
||||
if (analyzerData.tokenizer) {
|
||||
analyzer.componentTypes.push(processComponentType("Char Filters", "charFilters", analyzerData.charFilters));
|
||||
analyzer.componentTypes.push(processComponentType("Tokenizer", "tokenizer", {tokenizer: analyzerData.tokenizer}));
|
||||
analyzer.componentTypes.push(processComponentType("Token Filters", "tokenFilters", analyzerData.filters));
|
||||
}
|
||||
return analyzer;
|
||||
}
|
||||
|
||||
analysis.data = data.types[type];
|
||||
if (analysis.data) {
|
||||
analysis.analyzers = [
|
||||
{key: "index", name: "Index", detail: buildAnalyzer(analysis.data.indexAnalyzer)},
|
||||
{key: "query", name: "Query", detail: buildAnalyzer(analysis.data.queryAnalyzer)}
|
||||
];
|
||||
}
|
||||
return analysis;
|
||||
}
|
||||
|
||||
var getTermInfo = function(data) {
|
||||
|
||||
var termInfo = {};
|
||||
if (data && data.topTerms) {
|
||||
termInfo.topTerms = [];
|
||||
|
||||
var currentGroup = {count: 0}
|
||||
for (var i = 0; i < data.topTerms.length; i += 2) {
|
||||
var count = data.topTerms[i + 1];
|
||||
if (currentGroup.count != count) {
|
||||
currentGroup = {count: count, terms: []};
|
||||
termInfo.topTerms.push(currentGroup);
|
||||
}
|
||||
currentGroup.terms.push(data.topTerms[i]);
|
||||
}
|
||||
termInfo.termCount = data.topTerms.length / 2;
|
||||
termInfo.maxTerms = data.distinct;
|
||||
}
|
||||
|
||||
if(data && data.histogram) {
|
||||
termInfo.histogram = [];
|
||||
termInfo.histogramMax = 0;
|
||||
for (var i = 0; i < data.histogram.length; i += 2) {
|
||||
termInfo.histogram.push({key: data.histogram[i], value: data.histogram[i + 1]});
|
||||
termInfo.histogramMax = Math.max(termInfo.histogramMax, data.histogram[i + 1]);
|
||||
}
|
||||
}
|
||||
return termInfo;
|
||||
};
|
||||
|
||||
/*
|
||||
var get_width = function get_width()
|
||||
{
|
||||
return $( this ).width();
|
||||
}
|
||||
|
||||
var max_width = 10 + Math.max.apply( Math, $( 'p', topterms_table_element ).map( get_width ).get() );
|
||||
topterms:
|
||||
p { width: {{maxWidth}}px !important; }
|
||||
ul { margin-left: {{max_width + 5 }}px !important; }
|
||||
|
||||
var max_width = 10 + Math.max.apply( Math, $( 'dt', histogram_holder_element ).map( get_width ).get() );
|
||||
histogram_holder:
|
||||
ul { margin-left: {{maxWidth}}px !important; }
|
||||
li dt { left: {{-maxWidth}}px !important; width: {{maxWidth}}px !important; }
|
||||
*/
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
var MB_FACTOR = 1024*1024;
|
||||
|
||||
solrAdminApp.controller('SegmentsController', function($scope, $routeParams, $interval, Segments) {
|
||||
$scope.resetMenu("segments");
|
||||
|
||||
$scope.refresh = function() {
|
||||
|
||||
Segments.get({core: $routeParams.core}, function(data) {
|
||||
var segments = data.segments;
|
||||
|
||||
var segmentSizeInBytesMax = getLargestSegmentSize(segments);
|
||||
$scope.segmentMB = Math.floor(segmentSizeInBytesMax / MB_FACTOR);
|
||||
$scope.xaxis = calculateXAxis(segmentSizeInBytesMax);
|
||||
|
||||
$scope.documentCount = 0;
|
||||
$scope.deletionCount = 0;
|
||||
|
||||
$scope.segments = [];
|
||||
for (var name in segments) {
|
||||
var segment = segments[name];
|
||||
|
||||
var segmentSizeInBytesLog = Math.log(segment.sizeInBytes);
|
||||
var segmentSizeInBytesMaxLog = Math.log(segmentSizeInBytesMax);
|
||||
|
||||
segment.totalSize = Math.floor((segmentSizeInBytesLog / segmentSizeInBytesMaxLog ) * 100);
|
||||
|
||||
segment.deletedDocSize = Math.floor((segment.delCount / (segment.delCount + segment.totalSize)) * segment.totalSize);
|
||||
if (segment.delDocSize <= 0.001) delete segment.deletedDocSize;
|
||||
|
||||
segment.aliveDocSize = segment.totalSize - segment.deletedDocSize;
|
||||
|
||||
$scope.segments.push(segment);
|
||||
|
||||
$scope.documentCount += segment.size;
|
||||
$scope.deletionCount += segment.delCount;
|
||||
}
|
||||
$scope.deletionsPercentage = calculateDeletionsPercentage($scope.documentCount, $scope.deletionCount);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.toggleAutoRefresh = function() {
|
||||
$scope.autorefresh = !$scope.autorefresh;
|
||||
if ($scope.autorefresh) {
|
||||
$scope.interval = $interval($scope.refresh, 1000);
|
||||
} else if ($scope.interval) {
|
||||
$interval.cancel($scope.interval);
|
||||
}
|
||||
};
|
||||
$scope.refresh();
|
||||
});
|
||||
|
||||
var calculateXAxis = function(segmentInBytesMax) {
|
||||
var steps = [];
|
||||
var log = Math.log(segmentInBytesMax);
|
||||
|
||||
for (var j=0, step=log/4; j<3; j++, step+=log/4) {
|
||||
steps.push({pos:j, value:Math.floor((Math.pow(Math.E, step))/MB_FACTOR)})
|
||||
}
|
||||
return steps;
|
||||
};
|
||||
|
||||
var getLargestSegmentSize = function(segments) {
|
||||
var max = 0;
|
||||
for (var name in segments) {
|
||||
max = Math.max(max, segments[name].sizeInBytes);
|
||||
}
|
||||
return max;
|
||||
};
|
||||
|
||||
var calculateDeletionsPercentage = function(docCount, delCount) {
|
||||
if (docCount == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
var percent = delCount / docCount * 100;
|
||||
return Math.round(percent * 100) / 100;
|
||||
}
|
||||
};
|
|
@ -67,8 +67,9 @@ solrAdminServices.factory('System',
|
|||
}])
|
||||
.factory('Replication',
|
||||
['$resource', function($resource) {
|
||||
return $resource('/solr/:core/replication', {'wt':'json', core: "@core", 'command': 'details', '_':Date.now()}, {
|
||||
"details": {params: {command: "details"}}
|
||||
return $resource('/solr/:core/replication', {'wt':'json', core: "@core", '_':Date.now()}, {
|
||||
"details": {params: {command: "details"}},
|
||||
"command": {params: {}}
|
||||
});
|
||||
}])
|
||||
.factory('CoreSystem',
|
||||
|
@ -106,8 +107,21 @@ solrAdminServices.factory('System',
|
|||
.factory('Luke',
|
||||
['$resource', function($resource) {
|
||||
return $resource('/solr/:core/admin/luke', {core: '@core', wt:'json', _:Date.now()}, {
|
||||
"index": {params: {numTerms: 0}},
|
||||
"schema": {params: {show:'schema'}},
|
||||
"index": {params: {show:'index', numTerms: 0}}
|
||||
"field": {},
|
||||
"fields": {params: {show:'schema'}, interceptor: {
|
||||
response: function(response) {
|
||||
var fieldsAndTypes = [];
|
||||
for (var field in response.data.schema.fields) {
|
||||
fieldsAndTypes.push({group: "Fields", label: field, value: "fieldname=" + field});
|
||||
}
|
||||
for (var type in response.data.schema.types) {
|
||||
fieldsAndTypes.push({group: "Types", label: type, value: "fieldtype=" + type});
|
||||
}
|
||||
return fieldsAndTypes;
|
||||
}
|
||||
}}
|
||||
});
|
||||
}])
|
||||
.factory('Analysis',
|
||||
|
@ -116,6 +130,19 @@ solrAdminServices.factory('System',
|
|||
"field": {params: {"analysis.showmatch": true}}
|
||||
});
|
||||
}])
|
||||
.factory('DataImport',
|
||||
['$resource', function($resource) {
|
||||
return $resource('/solr/:core/dataimport', {core: '@core', indent:'on', wt:'json', _:Date.now()}, {
|
||||
"config": {params: {command: "show-config"}, transformResponse: function(data) {
|
||||
return {config: data};
|
||||
}},
|
||||
"status": {params: {command: "status"}},
|
||||
"reload": {params: {command: "reload-config"}},
|
||||
"post": {method: "POST",
|
||||
headers: {'Content-type': 'application/x-www-form-urlencoded'},
|
||||
transformRequest: function(data) { return $.param(data) }}
|
||||
});
|
||||
}])
|
||||
.factory('Ping',
|
||||
['$resource', function($resource) {
|
||||
return $resource('/solr/:core/admin/ping', {wt:'json', core: '@core', ts:Date.now(), _:Date.now()}, {
|
||||
|
@ -127,6 +154,7 @@ solrAdminServices.factory('System',
|
|||
['$resource', function($resource) {
|
||||
return $resource('/solr/:core/admin/mbeans', {'wt':'json', core: '@core', '_':Date.now()}, {
|
||||
stats: {params: {stats: true}},
|
||||
info: {},
|
||||
reference: {
|
||||
params: {wt: "xml", stats: true}, transformResponse: function (data) {
|
||||
return {reference: data}
|
||||
|
@ -161,11 +189,11 @@ solrAdminServices.factory('System',
|
|||
}).success(callback);
|
||||
}
|
||||
}}
|
||||
])
|
||||
.factory('Segments',
|
||||
['$resource', function($resource) {
|
||||
return $resource('/solr/:core/admin/segments', {'wt':'json', core: '@core', _:Date.now()}, {
|
||||
get: {}
|
||||
});
|
||||
}
|
||||
]);
|
||||
/*
|
||||
http://localhost:8983/solr/techproducts/admin/mbeans?cat=QUERYHANDLER&wt=json&_=1419614354276
|
||||
PING:
|
||||
http://localhost:8983/solr/techproducts/admin/ping?wt=json&ts=1419614393324&_=1419614393325
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ limitations under the License.
|
|||
<li class="settings-holder clearfix">
|
||||
<div class="settings clearfix">
|
||||
<label for="type_or_name">Analyse Fieldname / FieldType:</label>
|
||||
<select id="type_or_name" ng-model="fieldOrType" ng-options="f.value as f.label group by f.group for f in fieldsAndTypes"></select>
|
||||
<select chosen id="type_or_name" ng-model="fieldOrType" ng-options="f.value as f.label group by f.group for f in fieldsAndTypes"></select>
|
||||
|
||||
<a id="tor_schema" href="#"><span>Schema Browser</span> </a>
|
||||
|
||||
|
|
|
@ -17,15 +17,15 @@ limitations under the License.
|
|||
<div id="cloud" class="clearfix">
|
||||
|
||||
<div id="frame">
|
||||
{{here}}
|
||||
|
||||
<div id="tree-content" class="content clearfix" ng-show="showTree">
|
||||
<jstree class="tree" on-select="showTreeLink(url)" config="jstree" data="tree" id="tree"></jstree>
|
||||
<jstree class="tree" on-select="showTreeLink(url)" id="tree"></jstree>
|
||||
|
||||
<div id="file-content" class="clearfix">
|
||||
|
||||
<div id="prop" ng-show="znode.prop && showData">
|
||||
<ul>
|
||||
<li ng-class:"odd:$odd" ng-repeat="(key, prop) in znode.prop">
|
||||
<li ng-class="{odd:$odd}" ng-repeat="(key, prop) in znode.prop">
|
||||
<dl class="clearfix">
|
||||
<dt>{{ key }}</dt>
|
||||
<dd>{{ prop }}</dd>
|
||||
|
|
|
@ -33,7 +33,7 @@ limitations under the License.
|
|||
<dt>Last Modified:</dt>
|
||||
<dd class="value">{{index.lastModified | timeago}}</dd>
|
||||
|
||||
<dt>Num Docs:</dt>
|
||||
<dt class="index_num-docs">Num Docs:</dt>
|
||||
<dd class="value">{{index.numDocs}}</dd>
|
||||
|
||||
<dt class="index_max-doc">Max Doc:</dt>
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<div id="dataimport" class="clearfix">
|
||||
|
||||
<div ng-show="!hasHandlers">Sorry, no dataimport-handler defined!</div>
|
||||
<div id="frame" ng-show="hasHandlers">
|
||||
|
||||
<div id="error" ng-show="error"></div>
|
||||
|
||||
<div id="current_state" class="{{status}}">
|
||||
|
||||
<p class="last_update">Last Update: <abbr title="{{lastUpdateUTC}}">{{lastUpdate}}</abbr></p>
|
||||
<div class="info">
|
||||
|
||||
<strong>{{info.text}}<span ng-show="info.timeTaken"> (Duration: {{info.timeTaken | readableSeconds }})</span>
|
||||
</strong>
|
||||
<div class="details" ng-show="info.showDetails">
|
||||
<div class="docs">
|
||||
<span ng-repeat="doc in info.docs">
|
||||
<abbr style="display:inline" title="{{ doc.desc }}">{{ doc.name }}</abbr>: {{doc.value | number}}<!-- remove whitespace!
|
||||
--><span style="display:inline" ng-show="doc.speed">{{ doc.speed | number}}/s</span><!-- remove whitespace!
|
||||
--><span style="display:inline" ng-show="!$last">, </span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="dates">
|
||||
<span ng-repeat="date in info.dates">
|
||||
<abbr title="{{ date.desc }}">{{ date.name }}</abbr>:
|
||||
<abbr class="time">{{ date.value | timeago }}</abbr>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="abort-import" ng-class="{warn:!isAborting, success: isAborting}" ng-click="abort()" ng-show="isRunning">
|
||||
<span ng-show="isAborting">Aborting Import</span>
|
||||
<span ng-show="!isAborting">Abort Import</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="block" id="raw_output" >
|
||||
|
||||
<h2>
|
||||
<a class="toggle" ng-click="toggleRawStatus()"><span>Raw Status-Output</span></a>
|
||||
</h2>
|
||||
|
||||
<div class="message-container" ng-show="showRawStatus">
|
||||
<div class="message"></div>
|
||||
</div>
|
||||
|
||||
<div class="content" ng-show="showRawStatus">
|
||||
|
||||
<div id="raw_output_container"><pre class="syntax language-json"><code ng-bind-html="rawStatus | highlight:'json' | unsafe"></code></pre></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="block" id="config" ng-class="{debug_mode:isDebugMode}">
|
||||
|
||||
<h2 class="clearfix">
|
||||
<a class="toggle" ng-click="toggleConfiguration()"><span>Configuration</span></a>
|
||||
<a class="r reload_config" ng-class="{success:reloaded}" ng-click="reload()" title="Reload Configuration">Reload</a>
|
||||
<a class="r debug_mode" ng-click="toggleDebug()">Debug-Mode</a>
|
||||
</h2>
|
||||
|
||||
<div class="message-container" ng-show="showConfiguration">
|
||||
<div class="message"></div>
|
||||
</div>
|
||||
|
||||
<div class="content" ng-show="showConfiguration">
|
||||
<div id="dataimport_config">
|
||||
|
||||
<div class="formatted" ng-show="!isDebugMode">
|
||||
|
||||
<pre class="syntax language-xml"><code ng-bind-html="config | highlight:'xml'| unsafe"></code></pre>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="editable" ng-show="isDebugMode">
|
||||
|
||||
<textarea>{{config}}</textarea>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="block" id="debug_response" ng-show="form.showDebug">
|
||||
|
||||
<h2>
|
||||
<a class="toggle" ng-click="toggleRawDebug()"><span>Raw Debug-Response</span></a>
|
||||
</h2>
|
||||
|
||||
<div class="message-container" ng-show="showRawDebug">
|
||||
<div class="message"></div>
|
||||
</div>
|
||||
|
||||
<div class="content" ng-show="showRawDebug">
|
||||
<span ng-show="true">
|
||||
<em>No Request executed</em>
|
||||
</span>
|
||||
<span ng-show="false">
|
||||
<pre class="syntax language-json"><code ng-bind-html="rawResponse | highlight:'xml' | unsafe"></code></pre>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="form" ng-show="hasHandlers">
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
<ul>
|
||||
<li ng-class="{current: currentHandler == handler}" ng-repeat="handler in handlers">
|
||||
<a href="#/{{form.core}}/dataimport/{{handler}}">{{handler}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<form action="#" method="get">
|
||||
|
||||
<label for="command">
|
||||
<a rel="help">Command</a>
|
||||
</label>
|
||||
<select name="command" id="command" ng-model="form.command">
|
||||
<option>full-import</option>
|
||||
<option>delta-import</option>
|
||||
</select>
|
||||
|
||||
<label for="verbose" class="checkbox">
|
||||
<input type="checkbox" name="verbose" id="verbose" ng-model="form.verbose">
|
||||
Verbose
|
||||
</label>
|
||||
|
||||
<label for="clean" class="checkbox">
|
||||
<input type="checkbox" name="clean" id="clean" ng-model="form.clean">
|
||||
Clean
|
||||
</label>
|
||||
|
||||
<label for="commit" class="checkbox">
|
||||
<input type="checkbox" name="commit" id="commit" ng-model="form.commit">
|
||||
Commit
|
||||
</label>
|
||||
|
||||
<label for="optimize" class="checkbox">
|
||||
<input type="checkbox" name="optimize" id="optimize" ng-model="form.optimize">
|
||||
Optimize
|
||||
</label>
|
||||
|
||||
<label for="debug" class="checkbox">
|
||||
<input type="checkbox" name="debug" id="debug" ng-model="form.showDebug">
|
||||
Debug
|
||||
</label>
|
||||
|
||||
<label for="entity">
|
||||
<a rel="help">Entity</a>
|
||||
</label>
|
||||
<select ng-model="form.entity" id="entity">
|
||||
<option value=""></option>
|
||||
<option ng-repeat="entity in entities">{{entity}}</option>
|
||||
</select>
|
||||
|
||||
<label for="start">
|
||||
<a rel="help">Start</a>,
|
||||
<a rel="help">Rows</a>
|
||||
</label>
|
||||
<div class="clearfix">
|
||||
<input type="text" id="start" placeholder="0" ng-model="form.start">
|
||||
<input type="text" id="rows" placeholder="10" ng-model="form.rows">
|
||||
</div>
|
||||
|
||||
<label for="custom_parameters">
|
||||
<a rel="help">Custom Parameters</a>
|
||||
</label>
|
||||
<input type="text" id="custom_parameters" ng-model="form.custom" placeholder="key1=val1&key2=val2">
|
||||
</form>
|
||||
<button class="execute" type="submit" ng-click="submit()">
|
||||
<span ng-show="isDebugMode">Execute with this Configuration →</span>
|
||||
<span ng-show="!isDebugMode">Execute</span>
|
||||
</button>
|
||||
<button class="refresh-status" ng-click="refreshStatus()" ng-class="{loader: isStatusLoading, success: statusUpdated}"><span>Refresh Status</span></button>
|
||||
|
||||
<p id="auto-refresh-status"><a ng-click="updateAutoRefresh()" ng-class="{on:autorefresh}">Auto-Refresh Status</a></p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -0,0 +1,118 @@
|
|||
<!--
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<div id="documents" class="clearfix">
|
||||
<div id="form">
|
||||
<form>
|
||||
<label for="qt">
|
||||
<a rel="help">Request-Handler (qt)</a>
|
||||
</label>
|
||||
<input ng-model="handler" type="text" id="qt" value="/update" title="Request handler in solrconfig.xml.">
|
||||
<label for="document-type">
|
||||
<a rel="help">Document Type</a>
|
||||
</label>
|
||||
|
||||
<div><select ng-model="type" id="document-type" ng-change="changeDocumentType()" placeholder="The type of the document field">
|
||||
<!-- TODO: support the Builder -->
|
||||
<option value="csv">CSV</option>
|
||||
<option value="wizard">Document Builder</option>
|
||||
<option value="upload">File Upload</option>
|
||||
<option value="json">JSON</option>
|
||||
<option value="solr">Solr Command (raw XML or JSON)</option>
|
||||
<option value="xml">XML</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="document-container">
|
||||
<div id="wizard" ng-show="type=='wizard'">
|
||||
<div id="wizard-fields">
|
||||
<div><span class="description">Field</span>: <select ng-model="fieldName" id="wiz-field-select" name="wiz-field-select"
|
||||
ng-options="field for field in fields"></select>
|
||||
</div>
|
||||
<div><span id="wiz-field-data"><span class="description">Field Data</span>:</span>
|
||||
<textarea ng-model="fieldData"
|
||||
id="wizard-doc"
|
||||
name="wizard-doc"
|
||||
rows="10"
|
||||
cols="40"
|
||||
placeholder="Enter your field text here and then click 'Add Field' to add the field to the document.">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wizard-add"><a ng-click="addWizardField()" id="add-field-href"><img border="0" src="./img/ico/plus-button.png"/>Add
|
||||
Field</a></div>
|
||||
</div>
|
||||
<label for="document">
|
||||
<a rel="help">Document(s)</a>
|
||||
</label>
|
||||
<textarea ng-show="type!='upload'" ng-model="document" name="document" id="document" title="The Document" rows="10"
|
||||
cols="70" placeholder="{{placeholder}}"></textarea>
|
||||
|
||||
<div id="file-upload" ng-show="type=='upload'">
|
||||
<input type="file" id="the-file" name="the-file" file-model="fileUpload"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="advanced">
|
||||
<!-- TODO: only show for JSON/XML-->
|
||||
<div id="attribs">
|
||||
<div id="upload-only" ng-show="type=='upload'">
|
||||
<label for="erh-params"><!-- TODO: cleaner way to do this? -->
|
||||
<a rel="help">Extracting Req. Handler Params</a>
|
||||
</label>
|
||||
<input ng-model="literalParams" type="text" id="erh-params" value="&literal.id=change.me"
|
||||
title="Extracting Request Handler Parameters" size="50">
|
||||
</div>
|
||||
<div id="general-attribs">
|
||||
<label for="commitWithin">
|
||||
<a rel="help">Commit Within</a>
|
||||
</label>
|
||||
<input type="text" ng-model="commitWithin" id="commitWithin" value="1000" title="Commit Within (ms)">
|
||||
<label for="overwrite">
|
||||
<a rel="help">Overwrite</a>
|
||||
</label>
|
||||
<input ng-model="overwrite" type="text" id="overwrite" value="true" title="Overwrite">
|
||||
</div>
|
||||
<!-- Boost is json only, since the XML has it embedded -->
|
||||
<div id="json-only" ng-show="type=='json'">
|
||||
<label for="boost">
|
||||
<a rel="help">Boost</a>
|
||||
</label>
|
||||
<input ng-model="boost" type="text" id="boost" value="1.0" title="Document Boost">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" ng-click="submit()" id="submit">Submit Document</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="result">
|
||||
<div id="response" ng-show="response">
|
||||
<div>
|
||||
<span class="description">Status: </span>{{ responseStatus }}
|
||||
</div>
|
||||
<div>
|
||||
<span class="description">Response:</span>
|
||||
<pre class="syntax language-json"><code ng-bind-html="response | highlight:'json' | unsafe"></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<div id="files" class="clearfix">
|
||||
|
||||
<div id="frame">
|
||||
|
||||
<div id="tree-holder">
|
||||
|
||||
<jstree class="tree" on-select="showTreeLink(data)" data="tree" id="tree"></jstree>
|
||||
|
||||
</div>
|
||||
<div id="file-content" class="clearfix">
|
||||
|
||||
<div class="top clearfix">
|
||||
|
||||
<a id="url" class="address-bar" href="{{url}}" ng-show="url">{{url}}</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="view-file">
|
||||
|
||||
<div class="response" ng-show="content">
|
||||
<pre class="syntax language-{{lang}}"><code ng-bind-html="content | highlight:lang | unsafe"></code></pre>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -25,6 +25,7 @@ limitations under the License.
|
|||
<tr>
|
||||
<th class="time">Time (<span>{{timezone}}</span>)</th>
|
||||
<th class="level">Level</th>
|
||||
<th class="core">Core</th>
|
||||
<th class="logger">Logger</th>
|
||||
<th class="message">Message</th>
|
||||
</tr>
|
||||
|
@ -33,6 +34,7 @@ limitations under the License.
|
|||
<tr ng-click="toggleRow(event)" class="{{event.trace ? 'has-trace': ''}} {{'level-'+event.level.toLowerCase()}}">
|
||||
<td class="span"><a><span>{{ timezone == "UTC" ? event.utc_time : event.local_time }}</span></a></td>
|
||||
<td class="level span"><a><span>{{ event.level }} {{event.showTrace}}</span></span></a></td>
|
||||
<td class="span"><a><span>{{ event.core }}</span></a></td>
|
||||
<td class="span"><a><span><abbr title="{{event.logger}}">{{event.loggerBase}}</abbr></span></a></td>
|
||||
<td class="message span"><a><span>{{ event.message }}</span></a></td>
|
||||
</tr>
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<div id="plugins" class="clearfix">
|
||||
|
||||
<div id="frame">
|
||||
<ul>
|
||||
<li class="entry" ng-class="{changed: plugin.changed}" ng-repeat="plugin in type.plugins">
|
||||
<a ng-click="selectPlugin(plugin)">
|
||||
<span>{{ plugin.name }}</span>
|
||||
</a>
|
||||
<ul class="detail" ng-show="plugin.open">
|
||||
<li ng-repeat="(key, value) in plugin.properties" ng-class="{odd: $odd}">
|
||||
<dl class="clearfix">
|
||||
<dt>{{ key }}:</dt>
|
||||
<!--<dd ng-repeat="v in value">{{v}}</dd><!-- is AN ARRAY!!-->
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="stats clearfix" ng-show="plugin.stats">
|
||||
<span>stats:</span>
|
||||
<ul>
|
||||
<li ng-repeat="(key, value) in plugin.stats" ng-class="{odd: $odd}">
|
||||
<dl class="clearfix">
|
||||
<dt>{{key}}:</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="navigation" class="clearfix">
|
||||
|
||||
<ul>
|
||||
<li ng-repeat="type in types" class="{{type.lower}}">
|
||||
<a ng-click="selectPluginType(type)" rel="{{type.name}}">{{type.name}}
|
||||
<span ng-show="type.changes">{{type.changes}}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="PLUGINCHANGES"><a ng-click="startRecording()">Watch Changes</a></li>
|
||||
<li class="RELOAD"><a ng-click="refresh()">Refresh Values</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="recording" ng-show="isRecording">
|
||||
<div class="wrapper clearfix">
|
||||
|
||||
<p class="loader">Watching for Changes</p>
|
||||
<button class="primary" ng-click="stopRecording()">Stop & Show Changes</button>
|
||||
|
||||
</div>
|
||||
<div id="blockUI"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -0,0 +1,239 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<div id="replication" class="clearfix" ng-class="{replicating:settings.isReplicating}">
|
||||
|
||||
<div id="frame">
|
||||
|
||||
<div id="error" ng-show="progress.ERROR">{{ progress.ERROR }}</div>
|
||||
|
||||
<div class="replicating block" ng-show="settings.isReplicating">
|
||||
|
||||
<div id="progress">
|
||||
|
||||
<div id="start"><div class="info">
|
||||
|
||||
<span>{{progress.replicationStartTime}}</span>
|
||||
|
||||
</div></div>
|
||||
|
||||
<div id="speed"><div class="info">
|
||||
|
||||
<span>5.1 MB</span>/s
|
||||
|
||||
</div></div>
|
||||
|
||||
<div id="bar">
|
||||
|
||||
<div id="bar-info"><div class="info">
|
||||
|
||||
<div class="files"><span>{{progress.numFilesToDownload}}</span> File<span ng-show="progress.numFilesToDownload>1">s</span></div>
|
||||
<div class="size"><span>{{progress.bytesToDownload}}</span></div>
|
||||
|
||||
</div></div>
|
||||
|
||||
<div id="eta"><div class="info">
|
||||
|
||||
ETA: <span>{{progress.timeRemaining | readableSeconds }}</span>
|
||||
|
||||
</div></div>
|
||||
|
||||
<div id="done" style="width: {{progress.totalPercentWidth}}">
|
||||
|
||||
<div class="percent">
|
||||
|
||||
<span>{{progress.totalPercent}}</span>%
|
||||
|
||||
</div>
|
||||
|
||||
<div id="done-info"><div class="info">
|
||||
|
||||
<div class="files"><span>{{progress.numFilesDownloaded}}</span> File<span ng-show="progress.numFilesDownloaded>1">s</span></div>
|
||||
<div class="size"><span>{{progress.bytesDownloaded}}</span></div>
|
||||
|
||||
</div></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="current-file" class="clearfix">
|
||||
|
||||
<div class="label"><span class="loader">Current File:</span></div>
|
||||
<div class="file">{{progress.currentFile}}</div>
|
||||
<div class="progress">
|
||||
<span class="done">{{progress.currentFileSizeDownloaded}}</span> / <span class="total">{{progress.currentFileSize}}</span> [<span class="percent">{{progress.currentFileSizePercent}}</span>%]
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="iterations" class="slaveOnly block clearfix" ng-show="isSlave">
|
||||
|
||||
<div class="label"><span class="">Iterations:</span></div>
|
||||
<div class="iterations" ng-show="iterations && showIterations">
|
||||
<ul>
|
||||
<li class="{{iteration.status}}" ng-class="{latest:iteration.latest}" ng-repeat="iteration in iterations |limitTo:iterationCount">{{iteration.date}}</li>
|
||||
</ul>
|
||||
<span ng-show="iterations.length>1">
|
||||
<a ng-show="iterationCount==1" ng-click="showIterations()"><span class="expand">Show all Iterations</span></a>
|
||||
<a ng-show="iterationCount>1" ng-click="hideIterations()"><span class="collapse">Hide past Iterations</span></a>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="details" class="block clearfix">
|
||||
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
|
||||
<thead>
|
||||
|
||||
<tr>
|
||||
|
||||
<td><span>Index</span></td>
|
||||
<th>Version</th>
|
||||
<th><abbr title="Generation">Gen</abbr></th>
|
||||
<th>Size</th>
|
||||
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tr class="masterSearch">
|
||||
|
||||
<th>Master (Searching)</th>
|
||||
<td class="version" ng-class="{diff:versions.changedVersion}">
|
||||
<div>{{versions.masterSearch.version}}</div>
|
||||
</td>
|
||||
<td class="generation" ng-class="{diff:versions.changedGeneration}">
|
||||
<div>{{versions.masterSearch.generation}}</div>
|
||||
</td>
|
||||
<td class="size">
|
||||
<div>{{versions.masterSearch.size}}</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="master">
|
||||
|
||||
<th>Master (Replicable)</th>
|
||||
<td class="version" ng-class="{diff:versions.changedVersion}">
|
||||
<div>{{versions.master.version}}</div>
|
||||
</td>
|
||||
<td class="generation" ng-class="{diff:versions.changedGeneration}">
|
||||
<div>{{versions.master.generation}}</div>
|
||||
</td>
|
||||
<td class="size">
|
||||
<div>{{versions.master.size}}</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="slave slaveOnly" ng-show="isSlave">
|
||||
|
||||
<th>Slave (Searching)</th>
|
||||
<td class="version" ng-class="{diff:versions.changedVersion}">
|
||||
<div>{{versions.slave.version}}</div>
|
||||
</td>
|
||||
<td class="generation" ng-class="{diff:versions.changedGeneration}">
|
||||
<div>{{versions.slave.generation}}</div>
|
||||
</td>
|
||||
<td class="size">
|
||||
<div>{{versions.slave.size}}</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="settings" class="settings block clearfix slaveOnly" ng-show="isSlave">
|
||||
|
||||
<div class="label"><span>Settings:</span></div>
|
||||
<ul>
|
||||
<li class="masterUrl" ng-show="settings.masterUrl">
|
||||
<dl class="clearfix">
|
||||
<dt>master url:</dt>
|
||||
<dd>{{settings.masterUrl}}</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="isPollingDisabled"><dl class="clearfix">
|
||||
<dt>polling enable:</dt>
|
||||
<dd class="ico" ng-class="{'ico-0':settings.isPollingDisabled, 'ico-1':!settings.isPollingDisabled}">
|
||||
<span ng-show="settings.pollInterval">(interval: {{settings.pollInterval}})</span>
|
||||
</dd>
|
||||
</dl></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="master-settings" class="settings block clearfix">
|
||||
|
||||
<div class="label"><span>Settings (Master):</span></div>
|
||||
<ul>
|
||||
<li class="replicationEnabled"><dl class="clearfix">
|
||||
<dt>replication enable:</dt>
|
||||
<dd class="ico" ng-class="{'ico-0':!master.replicationEnabled, 'ico-1':master.replicationEnabled}"> </dd>
|
||||
</dl></li>
|
||||
<li class="replicateAfter"><dl class="clearfix">
|
||||
<dt>replicateAfter:</dt>
|
||||
<dd>{{master.replicateAfter}}</dd>
|
||||
</dl></li>
|
||||
<li class="confFiles" ng-show="master.files"><dl class="clearfix">
|
||||
<dt>confFiles:</dt>
|
||||
<dd><span ng-repeat="file in master.files"><attr title="{{file.title}}">{{file.name}}</attr>{{ $last ? '' :', '}}</span></dd>
|
||||
</dl></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
<div class="timer" ng-show="isSlave && !settings.isPollingDisabled &&!settings.isReplicating">
|
||||
|
||||
<p>Next Run: <span class="approx" ng-show="settings.isApprox">~</span><span class="tick">{{settings.tick | readableSeconds}}</span></p>
|
||||
<small ng-show="settings.nextExecutionAt">{{settings.nextExecutionAt}}</small>
|
||||
</div>
|
||||
|
||||
<button class="refresh-status" ng-click="refresh()"><span>Refresh Status</span></button>
|
||||
|
||||
<div class="slaveOnly" ng-show="isSlave">
|
||||
<button class="optional replicate-now primary" ng-click="execute('fetchindex')" ng-show="!settings.isReplicating"><span>Replicate now</span></button>
|
||||
<button class="optional abort-replication warn" ng-click="execute('abortfetch')" ng-show="settings.isReplicating"><span>Abort Replication</span></button>
|
||||
|
||||
<button class="optional disable-polling" ng-click="execute('disablepoll')" ng-show="!settings.isPollingDisabled"><span>Disable Polling</span></button>
|
||||
<button class="optional enable-polling" ng-click="execute('enablepoll')" ng-show="settings.isPollingDisabled"><span>Enable Polling</span></button>
|
||||
</div>
|
||||
|
||||
<div class="masterOnly" ng-show="!isSlave">
|
||||
<button class="optional disable-replication warn" ng-click="execute('disablereplication')" ng-show="master.replicationEnabled"><span>Disable Replication</span></button>
|
||||
<button class="optional enable-replication warn" ng-click="execute('enablereplication')" ng-show="!master.replicationEnabled"><span>Enable Replication</span></button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -0,0 +1,206 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<div id="schema-browser" class="loaded">
|
||||
|
||||
<div class="clearfix">
|
||||
|
||||
<div id="data">
|
||||
|
||||
<div id="field">
|
||||
|
||||
<div class="field-options">
|
||||
|
||||
<div class="block head">
|
||||
<h2>
|
||||
<span class="type">{{selectedType}}</span>:
|
||||
<span class="name">{{name}}</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="partial" ng-show="partialState">
|
||||
|
||||
<p>Because your Index is empty, we do not have enough Information about this Field</p>
|
||||
|
||||
</div>
|
||||
|
||||
<dl class="options clearfix">
|
||||
|
||||
<dt class="field-type">Field-Type:</dt>
|
||||
<dd class="field-type">{{analysis.data.className}}</dd>
|
||||
|
||||
<dt class="similarity" ng-show="display.similarity">Similarity:</dt>
|
||||
<dd class="similarity" ng-show="display.similarity">{{ display.similarity.details }} ({{ similarity.className }}) </dd>
|
||||
|
||||
<dt class="position-increment-gap" ng-show="display.positionIncrementGap"><abbr title="Position Increment Gap">PI Gap</abbr>:</dt>
|
||||
<dd class="position-increment-gap" ng-show="display.positionIncrementGap">{{ display.positionIncrementGap }}</dd>
|
||||
|
||||
<dt class="docs" ng-show="display.docs">Docs:</dt>
|
||||
<dd class="docs" ng-show="display.docs"><a href="{{display.docsUrl}}">{{display.docs | number}}</a></dd>
|
||||
|
||||
<dt class="distinct" ng-show="display.distinct">Distinct:</dt>
|
||||
<dd class="distinct" ng-show="display.distinct">{{display.distinct}}</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
<table class="flags" cellspacing="0" cellpadding="0" border="0">
|
||||
|
||||
<thead>
|
||||
|
||||
<tr>
|
||||
|
||||
<td>Flags:</td>
|
||||
<th ng-repeat="key in display.columns">{{key.name}}</th>
|
||||
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr ng-repeat="row in display.rows track by row.name">
|
||||
<th>{{row.name}}</th>
|
||||
<td colspan="2" class="text" ng-show="row.comment">{{row.comment}}</td>
|
||||
<td ng-repeat="cell in row.cells"
|
||||
ng-class="{'check':cell.value}">
|
||||
<span ng-show="cell.value">√</span>
|
||||
<span ng-show="!cell.value"> </span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
<ul class="analyzer">
|
||||
<li class="clearfix {{analyzer.key}}" ng-class="{open: analyzer.show}" ng-repeat="analyzer in analysis.analyzers">
|
||||
|
||||
<p><a class="analysis" ng-href="#/{{core}}/analysis?{{analysis.query}}"><span>{{analyzer.name}} Analyzer:</span></a></p>
|
||||
<dl>
|
||||
<dt><a ng-click="toggleAnalyzer(analyzer)" class="toggle">{{analyzer.detail.className}}</a></dt>
|
||||
</dl>
|
||||
<ul ng-show="analyzer.show">
|
||||
<li class="clearfix {{componentType.key}} data" ng-repeat="componentType in analyzer.detail.componentTypes" ng-show="componentType.components">
|
||||
<p>{{componentType.label}}:</p>
|
||||
<dl>
|
||||
<dt ng-repeat-start="component in componentType.components">{{component.className}}</dt>
|
||||
<dd ng-repeat-end ng-repeat="arg in component.args"
|
||||
ng-class="{'ico-1': arg.booleanValue, 'ico-0': arg.booleanValue==false}">
|
||||
{{arg.name}}<span ng-show="arg.value">: {{arg.value}}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="terminfo-holder loaded clearfix" ng-class="{disabled: noTermData}" ng-show="is.field">
|
||||
|
||||
<div class="trigger">
|
||||
|
||||
<button class="submit" ng-click="toggleTerms()"><span ng-class="{loader:isLoadingTerms}">Load Term Info</span></button>
|
||||
|
||||
<a ng-show="showTerms" ng-click="toggleAutoload()" ng-class="{on:isAutoload}" class="autoload" title="Automatically load Term Info?"><span>Autoload</span></a>
|
||||
|
||||
</div>
|
||||
|
||||
<p ng-show="showTerms && noTerms" class="status">Sorry, no Term Info available :(</p>
|
||||
|
||||
<div ng-show="showTerms && termInfo.topTerms" class="topterms-holder">
|
||||
|
||||
<form>
|
||||
<p class="head">
|
||||
<input type="text" ng-model="topTermsCount" ng-change="loadTermInfo()">
|
||||
<a class="max-holder" ng-click="loadAllTopTerms()" title="Load all Top-Terms">/<span class="max">{{termInfo.maxTerms | number}}</span></a> Top-Terms:
|
||||
<a id="query_link" href="#/{{core}}/query?q={{name}}:[* TO *]"><span>Query</span> </a>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<ul>
|
||||
<li class="clearfix" ng-repeat="countGroup in termInfo.topTerms">
|
||||
<p><span>{{countGroup.count}}</span></p>
|
||||
<ul>
|
||||
<li ng-repeat="term in countGroup.terms" ng-class="{odd:$odd}"><a href="#/{{core}}/query?q={{name}}:{{term}}">{{term}}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div ng-show="showTerms && termInfo.histogram" class="histogram-holder">
|
||||
|
||||
<p class="head">Histogram:</p>
|
||||
<ul>
|
||||
<li ng-repeat="row in termInfo.histogram" ng-class="{odd:$odd}">
|
||||
<dl class="clearfix" style="width: {{(( row.value / termInfo.histogramMax ) * 100 )}}%;">
|
||||
<dt><span>{{ row.key | number}}</span></dt>
|
||||
<dd><span>{{ row.value | number }}</span></dd>
|
||||
</dl>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="related">
|
||||
<select id="type_or_name"
|
||||
ng-model="fieldOrType"
|
||||
chosen
|
||||
data-placeholder="Please select ..."
|
||||
ng-change="selectFieldOrType()"
|
||||
ng-options="f.value as f.label group by f.group for f in fieldsAndTypes"></select>
|
||||
|
||||
<dl id="f-df-t">
|
||||
|
||||
<dt class="field" ng-class="{active: selectedType=='Field'}" ng-show="leftbar.fields">Field</dt>
|
||||
<dd class="field" ng-class="{active: selectedType=='Field'}" ng-repeat="field in leftbar.fields"><a href="#/{{core}}/schema-browser?field={{field}}">{{field}}</a></dd>
|
||||
|
||||
<dt class="copyfield" ng-show="leftbar.copyFieldSources">Copied from</dt>
|
||||
<dd class="copyfield" ng-repeat="field in leftbar.copyFieldSources"><a href="#/{{core}}/schema-browser?field={{field}}">{{field}}</a></dd>
|
||||
|
||||
<dt class="copyfield" ng-show="leftbar.copyFieldDests">Copied to</dt>
|
||||
<dd class="copyfield" ng-repeat="field in leftbar.copyFieldDests"><a href="#/{{core}}/schema-browser?field={{field}}">{{field}}</a></dd>
|
||||
|
||||
<dt class="dynamic-field" ng-class="{active: selectedType=='Dynamic Field'}" ng-show="leftbar.dynamicFields">Dynamic Field {{dynamicFields}} / {{dynamicFields.length()}}</dt>
|
||||
<dd class="dynamic-field" ng-class="{active: selectedType=='Dynamic Field'}" ng-repeat="field in leftbar.dynamicFields"><a href="#/{{core}}/schema-browser?dynamic-field={{field}}">{{field}}</a></dd>
|
||||
|
||||
<dt class="type" ng-class="{active: selectedType=='Type'}" ng-show="leftbar.types">Type</dt>
|
||||
<dd class="type" ng-class="{active: selectedType=='Type'}" ng-repeat="type in leftbar.types"><a href="#/{{core}}/schema-browser?type={{type}}">{{type}}</a></dd>
|
||||
|
||||
</dl>
|
||||
|
||||
<dl class="ukf-dsf">
|
||||
|
||||
<dt class="unique-key-field" ng-class="{active: isUniqueKeyField}" ng-show="uniqueKeyField">Unique Key Field</dt>
|
||||
<dd class="unique-key-field" ng-class="{active: isUniqueKeyField}"><a ng-href="#/{{core}}/schema-browser?field={{uniqueKeyField}}">{{uniqueKeyField}}</a></dd>
|
||||
|
||||
<dt class="default-search-field" ng-class="{active: isDefaultSearchField}" ng-show="defaultSearchField">Default Search Field</dt>
|
||||
<dd class="default-search-field" ng-class="{active: isDefaultSearchField}"><a ng-href="#/{{core}}/schema-browser?field={{defaultSearchField}}">{{defaultSearchField}}</a></dd>
|
||||
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -0,0 +1,99 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<div id="segments">
|
||||
<div class="clearfix">
|
||||
|
||||
<div class="block fieldlist" id="statistics">
|
||||
|
||||
<h2><span>Segments</span></h2>
|
||||
<p id="auto-refresh"><a ng-click="toggleAutoRefresh()" ng-class="{on:autorefresh}">Auto-Refresh</a></p>
|
||||
<a class="reload" ng-click="refresh()"><span>reload</span></a>
|
||||
|
||||
<div class="message-container">
|
||||
<div class="message"></div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
|
||||
<div id="result">
|
||||
|
||||
<div id="response">
|
||||
|
||||
<div class="segments-holder">
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<dl class="clearfix" style="width:100%;">
|
||||
<dt>
|
||||
<div>Size</div>
|
||||
</dt>
|
||||
<dd>
|
||||
<div class="start">0</div>
|
||||
<div class="w5" ng-repeat="x in xaxis">
|
||||
<span ng-show="x>0.001">{{x.value}}</span>
|
||||
<span ng-hide="x>0.001"> </span>
|
||||
</div>
|
||||
<div class="end">{{segmentMB | number}} MB</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li ng-repeat="segment in segments">
|
||||
<dl class="clearfix" ng-style="{width: segment.totalSize+'%'}">
|
||||
<dt>
|
||||
<div>{{ segment.name }}</div>
|
||||
</dt>
|
||||
<dd>
|
||||
<div class="live" ng-class="{'merge-candidate':segment.mergeCandidate}"
|
||||
ng-style="{width: segment.aliveDocSize+'%'}"> </div>
|
||||
<div class="tooltip">
|
||||
<div>Segment <b>{{segment.name}}</b>:</div>
|
||||
<div class="label">#docs:</div>
|
||||
<div>{{ segment.size | number }}</div>
|
||||
<div class="label">#dels:</div>
|
||||
<div>{{ segment.delCount | number }}</div>
|
||||
<div class="label">size:</div>
|
||||
<div>{{ segment.sizeInBytes | number }} bytes</div>
|
||||
<div class="label">age:</div>
|
||||
<div>{{ segment.age }}</div>
|
||||
<div class="label">source:</div>
|
||||
<div>{{ segment.source }}</div>
|
||||
</div>
|
||||
<div class="deleted" ng-show="segment.deletedDocSize"
|
||||
style="width: {{ segment.deletedDocSize }}%; margin-left:{{ segment.aliveDocSize}}%;">
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<dl>
|
||||
<dt></dt>
|
||||
<dd>Deletions: {{ deletionsPercentage }}%</dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
Loading…
Reference in New Issue