ソースを参照

Ajax requests to reset or invalidate are now handled.
Style updates including handling for smaller device screens.
Better handling of file list update when filtered.

Andrew Collington 10 年 前
コミット
ec18756f51
1 ファイル変更152 行追加113 行削除
  1. 152 113
      index.php

+ 152 - 113
index.php

@@ -32,7 +32,13 @@ class OpCacheService
         if (!empty($_SERVER['HTTP_X_REQUESTED_WITH'])
         if (!empty($_SERVER['HTTP_X_REQUESTED_WITH'])
             && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'
             && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'
         ) {
         ) {
-            echo json_encode($self->getData(@$_GET['section'] ?: null));
+            if ((isset($_GET['reset']))) {
+                echo '{ "success": "' . ($self->resetCache() ? 'yes' : 'no') . '" }';
+            } else if ((isset($_GET['invalidate']))) {
+                echo '{ "success": "' . ($self->resetCache($_GET['invalidate']) ? 'yes' : 'no') . '" }';
+            } else {
+                echo json_encode($self->getData(@$_GET['section'] ?: null));
+            }
             exit;
             exit;
         } else if ((isset($_GET['reset']))) {
         } else if ((isset($_GET['reset']))) {
             $self->resetCache();
             $self->resetCache();
@@ -212,9 +218,17 @@ $opcache = OpCacheService::init();
         nav > ul > li > a {
         nav > ul > li > a {
             display: block;
             display: block;
             margin: 0 10px;
             margin: 0 10px;
-            padding: 20px 40px;
+            padding: 15px 30px;
             border: 1px solid transparent;
             border: 1px solid transparent;
             border-bottom-color: #ccc;
             border-bottom-color: #ccc;
+            text-decoration: none;
+        }
+        nav > ul > li > a:hover {
+            background-color: #f4f4f4;
+            text-decoration: underline;
+        }
+        nav > ul > li > a.active:hover {
+            background-color: initial;
         }
         }
         nav > ul > li > a[data-for].active {
         nav > ul > li > a[data-for].active {
             border: 1px solid #ccc;
             border: 1px solid #ccc;
@@ -222,7 +236,7 @@ $opcache = OpCacheService::init();
             border-top: 3px solid #6ca6ef;
             border-top: 3px solid #6ca6ef;
         }
         }
         #resetCache, #toggleRealtime {
         #resetCache, #toggleRealtime {
-            background-position: 15px 50%;
+            background-position: 5px 50%;
             background-repeat: no-repeat;
             background-repeat: no-repeat;
             background-color: transparent;
             background-color: transparent;
         }
         }
@@ -269,12 +283,40 @@ $opcache = OpCacheService::init();
         table { margin: 0 0 1em 0; border-collapse: collapse; border-color: #fff; width: 100%; }
         table { margin: 0 0 1em 0; border-collapse: collapse; border-color: #fff; width: 100%; }
         table caption { text-align: left; font-size: 1.5em; }
         table caption { text-align: left; font-size: 1.5em; }
         table tr { background-color: #99D0DF; border-color: #fff; }
         table tr { background-color: #99D0DF; border-color: #fff; }
-        table th { text-align: left; padding: 6px; background-color: #0BA0C8; color: #fff; border-color: #fff; }
+        table th { text-align: left; padding: 6px; background-color: #0BA0C8; color: #fff; border-color: #fff; font-weight: normal; }
         table td { padding: 4px 6px; line-height: 1.4em; vertical-align: top; border-color: #fff; }
         table td { padding: 4px 6px; line-height: 1.4em; vertical-align: top; border-color: #fff; }
         table tr:nth-child(odd) { background-color: #EFFEFF; }
         table tr:nth-child(odd) { background-color: #EFFEFF; }
         table tr:nth-child(even) { background-color: #E0ECEF; }
         table tr:nth-child(even) { background-color: #E0ECEF; }
         td.pathname { width: 70%; }
         td.pathname { width: 70%; }
+        .metainfo { font-size: 80%; }
 
 
+        @media screen and (max-width: 750px) {
+            #info { margin-right:auto; }
+            nav > ul {
+                border-bottom: 0;
+            }
+            nav > ul > li {
+                display: block;
+                margin: 0;
+            }
+            nav > ul > li > a {
+                display: block;
+                margin: 0 10px;
+                padding: 10px 0 10px 30px;
+                border: 0;
+            }
+            nav > ul > li > a[data-for].active {
+                border-bottom-color: #ccc;
+            }
+            #counts {
+                position:relative;
+                display:block;
+                width:100%;
+            }
+        }
+        @media screen and (max-width: 550px) {
+            #frmFilter { width: 100%; }
+        }
     </style>
     </style>
 </head>
 </head>
 
 
@@ -285,7 +327,7 @@ $opcache = OpCacheService::init();
         <li><a data-for="overview" href="#overview" class="active">Overview</a></li>
         <li><a data-for="overview" href="#overview" class="active">Overview</a></li>
         <li><a data-for="files" href="#files">File usage</a></li>
         <li><a data-for="files" href="#files">File usage</a></li>
         <li><a href="?reset=1" id="resetCache" onclick="return confirm('Are you sure you want to reset the cache?');">Reset cache</a></li>
         <li><a href="?reset=1" id="resetCache" onclick="return confirm('Are you sure you want to reset the cache?');">Reset cache</a></li>
-        <li><a href="#" id="toggleRealtime">Enable real-time update of stats</a></li>
+        <li><a href="#" id="toggleRealtime">Enable real-time update</a></li>
     </ul>
     </ul>
 </nav>
 </nav>
 
 
@@ -307,9 +349,72 @@ $opcache = OpCacheService::init();
     </div>
     </div>
 </div>
 </div>
 
 
+<script type="text/javascript">
+    var realtime = false;
+
+    $(function(){
+        function updateStatus() {
+            $.ajax({
+                url: "#",
+                dataType: "json",
+                cache: false,
+                success: function(data) {
+                    opstate = data;
+                    overviewCountsObj.setState({
+                        data : opstate.overview
+                    });
+                    generalInfoObj.setState({
+                        version : opstate.version,
+                        start : opstate.overview.readable.start_time,
+                        reset : opstate.overview.readable.last_restart_time
+                    });
+                    filesObj.setState({
+                        data : opstate.files,
+                        count_formatted : opstate.overview.readable.num_cached_scripts,
+                        count : opstate.overview.num_cached_scripts
+                    });
+                    $('#frmFilter').trigger('keyup');
+                }
+            });
+        }
+        $('#toggleRealtime').click(function(){
+            if (realtime === false) {
+                realtime = setInterval(function(){updateStatus()}, 5000);
+                $(this).text('Disable real-time update');
+            } else {
+                clearInterval(realtime);
+                realtime = false;
+                $(this).text('Enable real-time update');
+            }
+        });
+        $('nav a[data-for]').click(function(){
+            $('#tabs > div').hide();
+            $('#' + $(this).data('for')).show();
+            $('nav a[data-for]').removeClass('active');
+            $(this).addClass('active');
+            return false;
+        });
+        $(document).on('paint', '#filelist table tbody', function(event, params) {
+            var trs = $('tr:visible', $(this));
+            trs.filter(':odd').css({backgroundColor:'#E0ECEF'})
+               .end().filter(':even').css({backgroundColor:'#EFFEFF'});
+            filesObj.setState({showing: trs.length});
+        });
+        $('#frmFilter').bind('keyup', function(event){
+            $('span.pathname').each(function(index){
+                if ($(this).text().toLowerCase().indexOf($('#frmFilter').val().toLowerCase()) == -1) {
+                    $(this).closest('tr').hide();
+                } else {
+                    $(this).closest('tr').show();
+                }
+            });
+            $('#filelist table tbody').trigger('paint');
+        });
+    });
+</script>
+
 <script type="text/jsx">
 <script type="text/jsx">
     var opstate = <?php echo json_encode($opcache->getData()); ?>;
     var opstate = <?php echo json_encode($opcache->getData()); ?>;
-    var realtime = false;
 
 
     var OverviewCounts = React.createClass({
     var OverviewCounts = React.createClass({
         getInitialState: function() {
         getInitialState: function() {
@@ -433,51 +538,47 @@ $opcache = OpCacheService::init();
         getInitialState: function() {
         getInitialState: function() {
             return {
             return {
                 data : opstate.files,
                 data : opstate.files,
-                count_formatted : opstate.overview.readable.num_cached_scripts,
-                count : opstate.overview.num_cached_scripts
+                showing: null
             };
             };
         },
         },
+        handleInvalidate: function(e) {
+            e.preventDefault();
+            if (realtime) {
+                $.get('#', { invalidate: e.currentTarget.getAttribute('data-file') }, function(data) {
+                    console.log('success: ' + data.success);
+                }, 'json');
+            } else {
+                window.location.href = e.currentTarget.href;
+            }
+        },
         render: function() {
         render: function() {
-            var fileNodes = this.state.data.map(function (file) {
+            var fileNodes = this.state.data.map(function(file) {
                 var invalidated;
                 var invalidated;
-                console.log(file);
                 if (file.timestamp == 0) {
                 if (file.timestamp == 0) {
-                    invalidated = <span>
-                        <i className="invalid">has been invalidated</i>
-                    </span>;
+                    invalidated = <span><i className="invalid metainfo">has been invalidated</i></span>;
                 }
                 }
+                var details = 'hits: ' + file.readable.hits + ', memory: ' 
+                    + file.readable.memory_consumption + ', last used: ' + file.last_used;
                 return (
                 return (
                     <tr>
                     <tr>
-                        <td className="pathname">
-                            <p>{file.full_path}</p>
-                            <?php if ($opcache->getOption('allow_invalidate') && function_exists('opcache_invalidate')): ?>
-                            <p><a href="?invalidate={file.full_path}">Force file invalidation</a></p>
-                            <?php endif; ?>
-                        </td>
                         <td>
                         <td>
-                            <p>
-                                <span>hits: {file.readable.hits},</span>
-                                <span>memory: {file.readable.memory_consumption}</span>
-                                <br />
-                                <span>last used: {file.last_used}</span>
+                            <div>
+                                <span className="pathname">{file.full_path}</span><br/>
+                                <span className="metainfo">{details}</span>
+                                <?php if ($opcache->getOption('allow_invalidate') && function_exists('opcache_invalidate')): ?>
+                                <span>,&nbsp;</span><a className="metainfo" href={'?invalidate=' + file.full_path} data-file={file.full_path} onClick={this.handleInvalidate}>force file invalidation</a>
+                                <?php endif; ?>
                                 {invalidated}
                                 {invalidated}
-                            </p>
+                            </div>
                         </td>
                         </td>
                     </tr>
                     </tr>
                 );
                 );
-            });
+            }.bind(this));
             return (
             return (
                 <div>
                 <div>
-                    <h3>{this.state.count_formatted} file{this.state.count == 1 ? '' : 's'} cached
-                        <span id="filterShowing"></span>
-                    </h3>
+                    <FilesListed showing={this.state.showing} />
                     <table>
                     <table>
-                        <thead>
-                            <tr>
-                                <th>Script</th>
-                                <th>Details</th>
-                            </tr>
-                        </thead>
+                        <thead><tr><th>Script</th></tr></thead>
                         <tbody>{fileNodes}</tbody>
                         <tbody>{fileNodes}</tbody>
                     </table>
                     </table>
                 </div>
                 </div>
@@ -485,89 +586,27 @@ $opcache = OpCacheService::init();
         }
         }
     });
     });
 
 
+    var FilesListed = React.createClass({
+        getInitialState: function() {
+            return {
+                formatted : opstate.overview.readable.num_cached_scripts,
+                total     : opstate.overview.num_cached_scripts
+            };
+        },
+        render: function() {
+            var display = this.state.formatted + ' file' + (this.state.total == 1 ? '' : 's') + ' cached';
+            if (this.props.showing !== null && this.props.showing != 0 && this.props.showing != this.state.total) {
+                display += ', ' + this.props.showing + ' showing due to filter';
+            }
+            return (<h3>{display}</h3>);
+        }
+    })
+
     var overviewCountsObj = React.render(<OverviewCounts/>, document.getElementById('counts'));
     var overviewCountsObj = React.render(<OverviewCounts/>, document.getElementById('counts'));
     var generalInfoObj = React.render(<GeneralInfo/>, document.getElementById('generalInfo'));
     var generalInfoObj = React.render(<GeneralInfo/>, document.getElementById('generalInfo'));
     var filesObj = React.render(<Files/>, document.getElementById('filelist'));
     var filesObj = React.render(<Files/>, document.getElementById('filelist'));
     React.render(<Directives/>, document.getElementById('directives'));
     React.render(<Directives/>, document.getElementById('directives'));
     React.render(<Functions/>, document.getElementById('functions'));
     React.render(<Functions/>, document.getElementById('functions'));
-
-    $(function() {
-        function updateStatus() {
-            $.ajax({
-                url: "#",
-                dataType: "json",
-                cache: false,
-                success: function(data) {
-                    opstate = data;
-                    overviewCountsObj.setState({
-                        data : opstate.overview
-                    });
-                    generalInfoObj.setState({
-                        version : opstate.version,
-                        start : opstate.overview.readable.start_time,
-                        reset : opstate.overview.readable.last_restart_time
-                    });
-                    filesObj.setState({
-                        data : opstate.files,
-                        count_formatted : opstate.overview.readable.num_cached_scripts,
-                        count : opstate.overview.num_cached_scripts
-                    });
-                }
-            });
-        }
-        $('#toggleRealtime').click(function(){
-            if (realtime === false) {
-                realtime = setInterval(function(){updateStatus()}, 5000);
-                $(this).text('Disable real-time update of stats');
-            } else {
-                clearInterval(realtime);
-                realtime = false;
-                $(this).text('Enable real-time update of stats');
-            }
-        });
-        $('nav a[data-for]').click(function(){
-            $('#tabs > div').hide();
-            $('#' + $(this).data('for')).show();
-            $('nav a[data-for]').removeClass('active');
-            $(this).addClass('active');
-            return false;
-        });
-    });
-</script>
-
-<script type="text/javascript">
-    $(function(){
-        $('span.showmore span.button').click(function(){
-            if ($(this).next().is(":visible")) {
-                $(this).next().hide();
-                $(this).css('padding-top', '0').text('…');
-            } else {
-                $(this).next().show();
-                $(this).css('padding-top', '2px').text('«');
-            }
-        });
-        $('.container table').bind('paint', function(event, params) {
-            var trs = $('tr:visible', $(this)).not(':first');
-            trs.removeClass('odd even')
-                .filter(':odd').addClass('odd')
-                .end()
-                .filter(':even').addClass('even');
-            $('#filterShowing').text(($('#frmFilter').val().length
-                ? trs.length + ' showing due to filter'
-                : ''
-            ));
-        });
-        $('#frmFilter').bind('keyup', function(event){
-            $('td.pathname p').each(function(index){
-                if ($(this).text().toLowerCase().indexOf($('#frmFilter').val().toLowerCase()) == -1) {
-                    $(this).closest('tr').hide();
-                } else {
-                    $(this).closest('tr').show();
-                }
-            });
-            $('.container table').trigger('paint');
-        });
-    });
 </script>
 </script>
 
 
 </body>
 </body>