<commit_before>'use strict'

import { h, Component } from 'preact';
import LogoutButton from '../components/LogoutButton.js';
import Realtime from '../components/Realtime.js';
import DatePicker from '../components/DatePicker.js';
import Sidebar from '../components/Sidebar.js';
import SiteSwitcher from '../components/SiteSwitcher.js';
import SiteSettings from '../components/SiteSettings.js';
import Gearwheel from '../components/Gearwheel.js';
import Table from '../components/Table.js';
import Chart from '../components/Chart.js';
import { bind } from 'decko';
import Client from '../lib/client.js';

class Dashboard extends Component {
  constructor(props) {
    super(props)

    // TODO: Update state after adding / deleting site
    // TODO: Update endpoints to take site ID parameter
    this.state = {
      before: 0,
      after: 0,
      isPublic: document.cookie.indexOf('auth') < 0,
      site: { id: 0 },
      sites: [],
      settingsOpen: false,
      addingNewSite: false,
    }
  }

  componentDidMount() {
    this.fetchSites()
  }

  @bind 
  fetchSites() {
    Client.request(`sites`)
    .then((data) => { 
      // TODO: Account for no sites here
      // TODO: Get selected site from localstorage
      this.setState({
        sites: data, 
        site: data[0] 
      })
    })
  }

  @bind
  changeDateRange(s) {
    this.setState({ 
      before: s.before, 
      after: s.after 
    })
  }

  @bind 
  showSiteSettings(site) {
    site = site && site.id == 0 ? site : this.state.site;
    this.setState({ 
      settingsOpen: true, 
      site: site,
      previousSite: this.state.site,
    })
  }

  @bind
  closeSiteSettings() {
    this.setState({
      settingsOpen: false, 

      // switch back to previous site if we were showing site settings to add a new site
      site: this.state.site.id > 0 ? this.state.site : this.state.previousSite,
    })
  }

  @bind 
  changeSelectedSite(site) {
    this.setState({
      site: site,
      previousSite: this.state.site,
    })
  }

  @bind
  updateSite(site) {
    let updated = false;
    let newSites = this.state.sites.map((s) => {
      if(s.id != site.id) {
        return s;
      }

      updated = true;
      return site;
    })

    if(!updated) {
      newSites.push(site);
    }

    this.setState({sites: newSites, site: site})
  }

  @bind 
  deleteSite(site) {
    let newSites = this.state.sites.filter((s) => (s.id != site.id))
    this.setState({ sites: newSites, site: newSites[0] })
  }

  render(props, state) {
    // only show logout link if this dashboard is not public
    let logoutMenuItem = state.isPublic ? '' : (
      <li class="signout"><span class="spacer">&middot;</span><LogoutButton onSuccess={props.onLogout} /></li>
    );

    return (
  <div class="app-page ">
     <div class="wrapper animated fadeInUp delayed_02s">

      <header class="section">
        <nav class="main-nav">
            <ul>
              <li class="logo"><a href="/">Fathom</a></li>
              <SiteSwitcher sites={state.sites} selectedSite={state.site} onChange={this.changeSelectedSite} onAdd={this.showSiteSettings} showAdd={!state.isPublic}/>
              <Gearwheel onClick={this.showSiteSettings} visible={!state.isPublic} />
              <li class="visitors"><Realtime siteId={state.site.id} /></li>
          </ul>
        </nav>
      </header>

      <section class="section">
        <nav class="date-nav">
          <DatePicker onChange={this.changeDateRange} />
        </nav>

        <div class="boxes">
          <Sidebar siteId={state.site.id} before={state.before} after={state.after} />

          <div class="boxes-col">
            <div class="box box-graph">
              <Chart siteId={state.site.id} before={state.before} after={state.after}  />
            </div>
            <div class="box box-pages">
              <Table endpoint="stats/pages" headers={["Top pages", "Views", "Uniques"]} siteId={state.site.id} before={state.before} after={state.after} />
            </div>
            <div class="box box-referrers">
              <Table endpoint="stats/referrers" headers={["Top referrers", "Views", "Uniques"]} siteId={state.site.id} before={state.before} after={state.after} showHostname="true" />
            </div>
          </div>
        </div>

        <div class="footer hide-on-mobile">
          <p>Use <strong>the arrow keys</strong> to cycle through date ranges.</p>
        </div>
      </section>

      <footer class="section"></footer>

    </div>
    <SiteSettings visible={state.settingsOpen} onClose={this.closeSiteSettings} onUpdate={this.updateSite} onDelete={this.deleteSite} site={state.site} />
  </div>
  )}
}

export default Dashboard
<commit_msg>make things work when there are no sites yet<commit_after>'use strict'

import { h, Component } from 'preact';
import LogoutButton from '../components/LogoutButton.js';
import Realtime from '../components/Realtime.js';
import DatePicker from '../components/DatePicker.js';
import Sidebar from '../components/Sidebar.js';
import SiteSwitcher from '../components/SiteSwitcher.js';
import SiteSettings from '../components/SiteSettings.js';
import Gearwheel from '../components/Gearwheel.js';
import Table from '../components/Table.js';
import Chart from '../components/Chart.js';
import { bind } from 'decko';
import Client from '../lib/client.js';

const defaultSite = { id: 0, name: "" }

class Dashboard extends Component {
  constructor(props) {
    super(props)

    // TODO: Update state after adding / deleting site
    // TODO: Update endpoints to take site ID parameter
    this.state = {
      before: 0,
      after: 0,
      isPublic: document.cookie.indexOf('auth') < 0,
      site: defaultSite,
      sites: [],
      settingsOpen: false,
      addingNewSite: false,
    }
  }

  componentDidMount() {
    this.fetchSites()
  }

  @bind 
  fetchSites() {
    Client.request(`sites`)
    .then((data) => { 
      // TODO: Account for no sites here
      // TODO: Get selected site from localstorage
      this.setState({
        sites: data, 
        site: data.length > 0 ? data[0] : defaultSite,
      })
    })
  }

  @bind
  changeDateRange(s) {
    this.setState({ 
      before: s.before, 
      after: s.after 
    })
  }

  @bind 
  showSiteSettings(site) {
    site = site && site.id == 0 ? site : this.state.site;
    this.setState({ 
      settingsOpen: true, 
      site: site,
      previousSite: this.state.site,
    })
  }

  @bind
  closeSiteSettings() {
    this.setState({
      settingsOpen: false, 

      // switch back to previous site if we were showing site settings to add a new site
      site: this.state.site.id > 0 ? this.state.site : this.state.previousSite,
    })
  }

  @bind 
  changeSelectedSite(site) {
    this.setState({
      site: site,
      previousSite: this.state.site,
    })
  }

  @bind
  updateSite(site) {
    let updated = false;
    let newSites = this.state.sites.map((s) => {
      if(s.id != site.id) {
        return s;
      }

      updated = true;
      return site;
    })

    if(!updated) {
      newSites.push(site);
    }

    this.setState({sites: newSites, site: site})
  }

  @bind 
  deleteSite(site) {
    let newSites = this.state.sites.filter((s) => (s.id != site.id))
    let newSelectedSite = newSites.length > 0 ? newSites[0] : defaultSite;
    this.setState({ 
      sites: newSites, 
      site: newSelectedSite 
    })
  }

  render(props, state) {
    // only show logout link if this dashboard is not public
    let logoutMenuItem = state.isPublic ? '' : (
      <li class="signout"><span class="spacer">&middot;</span><LogoutButton onSuccess={props.onLogout} /></li>
    );

    return (
  <div class="app-page ">
     <div class="wrapper animated fadeInUp delayed_02s">

      <header class="section">
        <nav class="main-nav">
            <ul>
              <li class="logo"><a href="/">Fathom</a></li>
              <SiteSwitcher sites={state.sites} selectedSite={state.site} onChange={this.changeSelectedSite} onAdd={this.showSiteSettings} showAdd={!state.isPublic}/>
              <Gearwheel onClick={this.showSiteSettings} visible={!state.isPublic} />
              <li class="visitors"><Realtime siteId={state.site.id} /></li>
          </ul>
        </nav>
      </header>

      <section class="section">
        <nav class="date-nav">
          <DatePicker onChange={this.changeDateRange} />
        </nav>

        <div class="boxes">
          <Sidebar siteId={state.site.id} before={state.before} after={state.after} />

          <div class="boxes-col">
            <div class="box box-graph">
              <Chart siteId={state.site.id} before={state.before} after={state.after}  />
            </div>
            <div class="box box-pages">
              <Table endpoint="stats/pages" headers={["Top pages", "Views", "Uniques"]} siteId={state.site.id} before={state.before} after={state.after} />
            </div>
            <div class="box box-referrers">
              <Table endpoint="stats/referrers" headers={["Top referrers", "Views", "Uniques"]} siteId={state.site.id} before={state.before} after={state.after} showHostname="true" />
            </div>
          </div>
        </div>

        <div class="footer hide-on-mobile">
          <p>Use <strong>the arrow keys</strong> to cycle through date ranges.</p>
        </div>
      </section>

      <footer class="section"></footer>

    </div>
    <SiteSettings visible={state.settingsOpen} onClose={this.closeSiteSettings} onUpdate={this.updateSite} onDelete={this.deleteSite} site={state.site} />
  </div>
  )}
}

export default Dashboard

{'fraction_non_alphanumeric': 0.15125701225846666, 'fraction_numerical': 0.0022854768335757326, 'mean_word_length': 2.4956427015250546, 'pattern_counts': {'":': 0, '<': 109, '<?xml version=': 0, '>': 117, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2468269', 'n_tokens_mistral': 3026, 'n_tokens_neox': 2931, 'n_words': 683}