<commit_before>import React, { Component } from 'react';
import ExpenseList from './ExpenseList.js';
import ExpenseForm from './ExpenseForm.js';
import LoadingBar from "./LoadingBar.js"
import {MDCSnackbar} from '@material/snackbar/dist/mdc.snackbar.js';

import '@material/fab/dist/mdc.fab.css';
import '@material/button/dist/mdc.button.css';
import '@material/toolbar/dist/mdc.toolbar.css';
import '@material/snackbar/dist/mdc.snackbar.css';
import '@material/card/dist/mdc.card.css';


import './App.css';

class App extends Component {
  constructor() {
    super();

    this.clientId = '826265862385-p41e559ccssujlfsf49ppmo0gktkf6co.apps.googleusercontent.com';
    this.spreadsheetId = "<KEY>";

    this.state = {
      signedIn: undefined,
      accounts: [],
      categories: [],
      expenses: [],
      processing: true,
      expense: {},
      currentMonth: undefined,
      previousMonth: undefined,
      showExpenseForm: false
    }

    this.handleExpenseSubmit = this.handleExpenseSubmit.bind(this);
    this.handleExpenseSelect = this.handleExpenseSelect.bind(this);
    this.handleExpenseCancel = this.handleExpenseCancel.bind(this);
    this.handleExpenseDelete = this.handleExpenseDelete.bind(this);
    this.handleExpenseChange = this.handleExpenseChange.bind(this);
    this.signedInChanged = this.signedInChanged.bind(this);
  }

  componentDidMount() {
    window.gapi.load('client:auth2', () => {
      window.gapi.client.init({
        discoveryDocs: ["https://sheets.googleapis.com/$discovery/rest?version=v4"],
        clientId: this.clientId,
        scope: "https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive.metadata.readonly"
      }).then(() => {
        window.gapi.auth2.getAuthInstance().isSignedIn.listen(this.signedInChanged);
        this.signedInChanged(window.gapi.auth2.getAuthInstance().isSignedIn.get());
      });
    });
  }

  signedInChanged(signedIn) {
    this.setState({ signedIn: signedIn });
    if (this.state.signedIn) {
      this.load();
    }
  }

  handleExpenseSubmit() {
    this.setState({ processing: true, showExpenseForm: false });
    const submitAction = (this.state.expense.id ? this.update : this.append).bind(this);
    submitAction(this.state.expense).then(
      response => {
        this.snackbar.show({ message: `Expense ${this.state.expense.id ? "updated" : "added"}!` });
        this.load();
      },
      response => {
        console.error('Something went wrong');
        console.error(response);
        this.setState({ loading: false });
      });
  }

  handleExpenseChange(attribute, value) {
    this.setState({ expense: Object.assign({}, this.state.expense, {[attribute]: value}) });
  }

  handleExpenseDelete(expense) {
    this.setState({ processing: true, showExpenseForm: false });
    const expenseRow = expense.id.substring(10);
    window.gapi.client.sheets.spreadsheets.batchUpdate({
      spreadsheetId: this.spreadsheetId, resource: {
      requests: [
        {
          "deleteDimension": {
            "range": {
              "sheetId": 0,
              "dimension": "ROWS",
              "startIndex": expenseRow - 1,
              "endIndex": expenseRow
            }
          }
        },
      ] }
    }).then(
      response => {
        this.snackbar.show({ message: "Expense deleted!" });
        this.load();
      },
      response => {
        console.error('Something went wrong');
        console.error(response);
        this.setState({ loading: false });
      });
  }

  handleExpenseSelect(expense) {
    this.setState({ expense: expense, showExpenseForm: true });
  }

  handleExpenseCancel() {
    this.setState({ showExpenseForm: false })
  }

  onExpenseNew() {
    const now = new Date();
    this.setState({
      showExpenseForm: true,
      expense: {
        amount: 0,
        description: '',
        date: `${now.getFullYear()}-${now.getMonth() < 9 ? "0" + (now.getMonth() + 1) : now.getMonth() + 1}-${now.getDate() < 10 ? "0" + now.getDate() : now.getDate()}`,
        category: this.state.categories[0],
        account: this.state.accounts[0]
      }
    })
  }

  parseExpense(value, index) {
    const dateParts = value[0].split("/");
    return {
      id: `Expenses!A${index + 2}`,
      date: `20${dateParts[2]}-${dateParts[1].length === 1 ? "0" + dateParts[1] : dateParts[1]}-${dateParts[0].length === 1 ? "0" + dateParts[0] : dateParts[0]}`,
      description: value[1],
      category: value[3],
      amount: value[4].replace(',', ''),
      account: value[2],
    };
  }

  formatExpense(expense) {
    return [
      `=DATE(${expense.date.substr(0, 4)}, ${expense.date.substr(5, 2)}, ${expense.date.substr(-2)})`,
      expense.description,
      expense.account,
      expense.category,
      expense.amount,
    ];
  }

  append(expense) {
    return window.gapi.client.sheets.spreadsheets.values.append({
      spreadsheetId: this.spreadsheetId, range: "Expenses!A1", valueInputOption: "USER_ENTERED", insertDataOption: "INSERT_ROWS",
      values: [this.formatExpense(expense)]
    });
  }

  update(expense) {
    return window.gapi.client.sheets.spreadsheets.values.update({
      spreadsheetId: this.spreadsheetId, range: expense.id, valueInputOption: "USER_ENTERED",
      values: [this.formatExpense(expense)]
    });
  }

  load() {
    window.gapi.client.sheets.spreadsheets.values
      .batchGet({ spreadsheetId: this.spreadsheetId, ranges: ["Data!A2:A50", "Data!E2:E50", "Expenses!A2:F", "Current!H1", "Previous!H1"] })
      .then(response => {
        const accounts = response.result.valueRanges[0].values.map(items => items[0]);
        const categories = response.result.valueRanges[1].values.map(items => items[0]);
        this.setState({
          accounts: accounts,
          categories: categories,
          expenses: (response.result.valueRanges[2].values || []).map(this.parseExpense).reverse(),
          processing: false,
          currentMonth: response.result.valueRanges[3].values[0][0],
          previousMonth: response.result.valueRanges[4].values[0][0],
        });
      });
  }

  render() {
    return (
      <div>
        <header className="mdc-toolbar mdc-toolbar--fixed">
          <div className="mdc-toolbar__row">
            <section className="mdc-toolbar__section mdc-toolbar__section--align-start">
              <span className="mdc-toolbar__title">Expenses</span>
            </section>
            <section className="mdc-toolbar__section mdc-toolbar__section--align-end" role="toolbar">
              { this.state.signedIn === false && <a className="material-icons mdc-toolbar__icon" aria-label="Sign in" alt="Sign in" onClick={(e) => { e.preventDefault(); window.gapi.auth2.getAuthInstance().signIn(); }}>perm_identity</a> }
              { this.state.signedIn && <a className="material-icons mdc-toolbar__icon" aria-label="Sign out" alt="Sign out" onClick={(e) => { e.preventDefault(); window.gapi.auth2.getAuthInstance().signOut(); }}>exit_to_app</a> }
            </section>
          </div>
        </header>
        <div className="toolbar-adjusted-content">
          {this.state.signedIn === undefined && <LoadingBar />}
          {this.state.signedIn === false && <div className="center"><button className="mdc-button sign-in" aria-label="Sign in" onClick={() => { window.gapi.auth2.getAuthInstance().signIn(); }}>Sign In</button></div>}
          {this.state.signedIn && this.renderBody()}<commit_msg>Limit display to last 15 expenses<commit_after>import React, { Component } from 'react';
import ExpenseList from './ExpenseList.js';
import ExpenseForm from './ExpenseForm.js';
import LoadingBar from "./LoadingBar.js"
import {MDCSnackbar} from '@material/snackbar/dist/mdc.snackbar.js';

import '@material/fab/dist/mdc.fab.css';
import '@material/button/dist/mdc.button.css';
import '@material/toolbar/dist/mdc.toolbar.css';
import '@material/snackbar/dist/mdc.snackbar.css';
import '@material/card/dist/mdc.card.css';


import './App.css';

class App extends Component {
  constructor() {
    super();

    this.clientId = '826265862385-p41e559ccssujlfsf49ppmo0gktkf6co.apps.googleusercontent.com';
    this.spreadsheetId = "<KEY>";

    this.state = {
      signedIn: undefined,
      accounts: [],
      categories: [],
      expenses: [],
      processing: true,
      expense: {},
      currentMonth: undefined,
      previousMonth: undefined,
      showExpenseForm: false
    }

    this.handleExpenseSubmit = this.handleExpenseSubmit.bind(this);
    this.handleExpenseSelect = this.handleExpenseSelect.bind(this);
    this.handleExpenseCancel = this.handleExpenseCancel.bind(this);
    this.handleExpenseDelete = this.handleExpenseDelete.bind(this);
    this.handleExpenseChange = this.handleExpenseChange.bind(this);
    this.signedInChanged = this.signedInChanged.bind(this);
  }

  componentDidMount() {
    window.gapi.load('client:auth2', () => {
      window.gapi.client.init({
        discoveryDocs: ["https://sheets.googleapis.com/$discovery/rest?version=v4"],
        clientId: this.clientId,
        scope: "https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive.metadata.readonly"
      }).then(() => {
        window.gapi.auth2.getAuthInstance().isSignedIn.listen(this.signedInChanged);
        this.signedInChanged(window.gapi.auth2.getAuthInstance().isSignedIn.get());
      });
    });
  }

  signedInChanged(signedIn) {
    this.setState({ signedIn: signedIn });
    if (this.state.signedIn) {
      this.load();
    }
  }

  handleExpenseSubmit() {
    this.setState({ processing: true, showExpenseForm: false });
    const submitAction = (this.state.expense.id ? this.update : this.append).bind(this);
    submitAction(this.state.expense).then(
      response => {
        this.snackbar.show({ message: `Expense ${this.state.expense.id ? "updated" : "added"}!` });
        this.load();
      },
      response => {
        console.error('Something went wrong');
        console.error(response);
        this.setState({ loading: false });
      });
  }

  handleExpenseChange(attribute, value) {
    this.setState({ expense: Object.assign({}, this.state.expense, {[attribute]: value}) });
  }

  handleExpenseDelete(expense) {
    this.setState({ processing: true, showExpenseForm: false });
    const expenseRow = expense.id.substring(10);
    window.gapi.client.sheets.spreadsheets.batchUpdate({
      spreadsheetId: this.spreadsheetId, resource: {
      requests: [
        {
          "deleteDimension": {
            "range": {
              "sheetId": 0,
              "dimension": "ROWS",
              "startIndex": expenseRow - 1,
              "endIndex": expenseRow
            }
          }
        },
      ] }
    }).then(
      response => {
        this.snackbar.show({ message: "Expense deleted!" });
        this.load();
      },
      response => {
        console.error('Something went wrong');
        console.error(response);
        this.setState({ loading: false });
      });
  }

  handleExpenseSelect(expense) {
    this.setState({ expense: expense, showExpenseForm: true });
  }

  handleExpenseCancel() {
    this.setState({ showExpenseForm: false })
  }

  onExpenseNew() {
    const now = new Date();
    this.setState({
      showExpenseForm: true,
      expense: {
        amount: 0,
        description: '',
        date: `${now.getFullYear()}-${now.getMonth() < 9 ? "0" + (now.getMonth() + 1) : now.getMonth() + 1}-${now.getDate() < 10 ? "0" + now.getDate() : now.getDate()}`,
        category: this.state.categories[0],
        account: this.state.accounts[0]
      }
    })
  }

  parseExpense(value, index) {
    const dateParts = value[0].split("/");
    return {
      id: `Expenses!A${index + 2}`,
      date: `20${dateParts[2]}-${dateParts[1].length === 1 ? "0" + dateParts[1] : dateParts[1]}-${dateParts[0].length === 1 ? "0" + dateParts[0] : dateParts[0]}`,
      description: value[1],
      category: value[3],
      amount: value[4].replace(',', ''),
      account: value[2],
    };
  }

  formatExpense(expense) {
    return [
      `=DATE(${expense.date.substr(0, 4)}, ${expense.date.substr(5, 2)}, ${expense.date.substr(-2)})`,
      expense.description,
      expense.account,
      expense.category,
      expense.amount,
    ];
  }

  append(expense) {
    return window.gapi.client.sheets.spreadsheets.values.append({
      spreadsheetId: this.spreadsheetId, range: "Expenses!A1", valueInputOption: "USER_ENTERED", insertDataOption: "INSERT_ROWS",
      values: [this.formatExpense(expense)]
    });
  }

  update(expense) {
    return window.gapi.client.sheets.spreadsheets.values.update({
      spreadsheetId: this.spreadsheetId, range: expense.id, valueInputOption: "USER_ENTERED",
      values: [this.formatExpense(expense)]
    });
  }

  load() {
    window.gapi.client.sheets.spreadsheets.values
      .batchGet({ spreadsheetId: this.spreadsheetId, ranges: ["Data!A2:A50", "Data!E2:E50", "Expenses!A2:F", "Current!H1", "Previous!H1"] })
      .then(response => {
        const accounts = response.result.valueRanges[0].values.map(items => items[0]);
        const categories = response.result.valueRanges[1].values.map(items => items[0]);
        this.setState({
          accounts: accounts,
          categories: categories,
          expenses: (response.result.valueRanges[2].values || []).map(this.parseExpense).reverse().slice(0, 15),
          processing: false,
          currentMonth: response.result.valueRanges[3].values[0][0],
          previousMonth: response.result.valueRanges[4].values[0][0],
        });
      });
  }

  render() {
    return (
      <div>
        <header className="mdc-toolbar mdc-toolbar--fixed">
          <div className="mdc-toolbar__row">
            <section className="mdc-toolbar__section mdc-toolbar__section--align-start">
              <span className="mdc-toolbar__title">Expenses</span>
            </section>
            <section className="mdc-toolbar__section mdc-toolbar__section--align-end" role="toolbar">
              { this.state.signedIn === false && <a className="material-icons mdc-toolbar__icon" aria-label="Sign in" alt="Sign in" onClick={(e) => { e.preventDefault(); window.gapi.auth2.getAuthInstance().signIn(); }}>perm_identity</a> }
              { this.state.signedIn && <a className="material-icons mdc-toolbar__icon" aria-label="Sign out" alt="Sign out" onClick={(e) => { e.preventDefault(); window.gapi.auth2.getAuthInstance().signOut(); }}>exit_to_app</a> }
            </section>
          </div>
        </header>
        <div className="toolbar-adjusted-content">
          {this.state.signedIn === undefined && <LoadingBar />}
          {this.state.signedIn === false && <div className="center"><button className="mdc-button sign-in" aria-label="Sign in" onClick={() => { window.gapi.auth2.getAuthInstance().signIn(); }}>Sign In</button></div>}
          {this.state.signedIn && this.renderBody()}
{'fraction_non_alphanumeric': 0.1636424506193505, 'fraction_numerical': 0.011985269501171745, 'mean_word_length': 3.0064377682403434, 'pattern_counts': {'":': 12, '<': 51, '<?xml version=': 0, '>': 71, 'https://': 6, 'lorem ipsum': 0, 'www.': 4, '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': '851930', 'n_tokens_mistral': 4762, 'n_tokens_neox': 4680, 'n_words': 735}