<commit_before>function toggleSuite(suiteId) {
    toggleElement(suiteId, ['keyword', 'suite', 'test']);
}

function toggleTest(testId) {
    toggleElement(testId, ['keyword']);
}

function toggleKeyword(kwId) {
    toggleElement(kwId, ['keyword', 'message']);
}

function addElements(elems, templateName, target){
    for (var i in elems) {
        $.tmpl(templateName, elems[i]).appendTo(target);
    }
}

function toggleElement(elementId, childrenNames) {
    var childElement = $("#"+elementId+"_children");
    childElement.toggle();
    populateChildren(elementId, childElement, childrenNames);
    var foldingButton = $('#'+elementId+'_foldingbutton');
    foldingButton.text(foldingButton.text() == '+' ? '-' : '+');
}

function populateChildren(elementId, childElement, childrenNames) {
    if (!childElement.hasClass("populated")) {
        var element = window.testdata.find(elementId);
        element.callWhenChildrenReady(drawCallback(element, childElement, childrenNames));
        childElement.addClass("populated");
    }
}

function drawCallback(element, childElement, childrenNames) {
    return function () {
        $.map(childrenNames, function (childName) {
            addElements(element[childName + 's'](), childName + 'Template', childElement);
        });
    }
}

function expandRecursively(){
    if (!window.elementsToExpand.length)
        return;
    var element = window.elementsToExpand.pop();
    if (element == undefined || elementHiddenByUser(element.id)) {
        window.elementsToExpand = [];
        return;
    }
    expandElement(element);
    element.callWhenChildrenReady( function () {
        var children = element.children();
        for (var i = children.length-1; i >= 0; i--) {
            if (window.expandDecider(children[i]))
                window.elementsToExpand.push(children[i]);
        }
        if (window.elementsToExpand.length)
            setTimeout(expandRecursively, 0);
    });
}

function expandElement(element) {
    var childElement = $("#" + element.id + "_children");
    childElement.show();
    populateChildren(element.id, childElement, element.childrenNames);
    $('#'+element.id+'_foldingbutton').text('-');
}

function elementHiddenByUser(elementId) {
    var domElement = $("#"+elementId);
    return !domElement.is(":visible");
}

function expandAllChildren(elementId) {
    window.elementsToExpand = [window.testdata.find(elementId)];
    window.expandDecider = function() {return true;};
    expandRecursively();
}

function expandCriticalFailed(element) {
    if (element.status == "FAIL") {
        window.elementsToExpand = [element];
        window.expandDecider = function(e) {return e.status == "FAIL" && (e.isCritical === undefined || e.isCritical);};
        expandRecursively();
    }
}

function expandSuite(suite) {
    if (suite.status == "PASS")
        expandElement(suite);
    else
        expandCriticalFailed(suite);
}
<commit_msg>backout animation change - not the cause of the current problem<commit_after>function toggleSuite(suiteId) {
    toggleElement(suiteId, ['keyword', 'suite', 'test']);
}

function toggleTest(testId) {
    toggleElement(testId, ['keyword']);
}

function toggleKeyword(kwId) {
    toggleElement(kwId, ['keyword', 'message']);
}

function addElements(elems, templateName, target){
    for (var i in elems) {
        $.tmpl(templateName, elems[i]).appendTo(target);
    }
}

function toggleElement(elementId, childrenNames) {
    var childElement = $("#"+elementId+"_children");
    childElement.toggle(100);
    populateChildren(elementId, childElement, childrenNames);
    var foldingButton = $('#'+elementId+'_foldingbutton');
    foldingButton.text(foldingButton.text() == '+' ? '-' : '+');
}

function populateChildren(elementId, childElement, childrenNames) {
    if (!childElement.hasClass("populated")) {
        var element = window.testdata.find(elementId);
        element.callWhenChildrenReady(drawCallback(element, childElement, childrenNames));
        childElement.addClass("populated");
    }
}

function drawCallback(element, childElement, childrenNames) {
    return function () {
        $.map(childrenNames, function (childName) {
            addElements(element[childName + 's'](), childName + 'Template', childElement);
        });
    }
}

function expandRecursively(){
    if (!window.elementsToExpand.length)
        return;
    var element = window.elementsToExpand.pop();
    if (element == undefined || elementHiddenByUser(element.id)) {
        window.elementsToExpand = [];
        return;
    }
    expandElement(element);
    element.callWhenChildrenReady( function () {
        var children = element.children();
        for (var i = children.length-1; i >= 0; i--) {
            if (window.expandDecider(children[i]))
                window.elementsToExpand.push(children[i]);
        }
        if (window.elementsToExpand.length)
            setTimeout(expandRecursively, 0);
    });
}

function expandElement(element) {
    var childElement = $("#" + element.id + "_children");
    childElement.show(100);
    populateChildren(element.id, childElement, element.childrenNames);
    $('#'+element.id+'_foldingbutton').text('-');
}

function elementHiddenByUser(elementId) {
    var domElement = $("#"+elementId);
    return !domElement.is(":visible");
}

function expandAllChildren(elementId) {
    window.elementsToExpand = [window.testdata.find(elementId)];
    window.expandDecider = function() {return true;};
    expandRecursively();
}

function expandCriticalFailed(element) {
    if (element.status == "FAIL") {
        window.elementsToExpand = [element];
        window.expandDecider = function(e) {return e.status == "FAIL" && (e.isCritical === undefined || e.isCritical);};
        expandRecursively();
    }
}

function expandSuite(suite) {
    if (suite.status == "PASS")
        expandElement(suite);
    else
        expandCriticalFailed(suite);
}
<|endoftext|>


<commit_before>
'use strict'

import gutil from 'gulp-util'
// import path from 'path'
// import runSequence from 'run-sequence'
// import iff from 'gulp-if'
// import gutil from 'gulp-util'
// import debug from 'gulp-debug'

import AbstractTaskLoader from '../../abstract-task-loader'
// import config from '../../config'
// import utils from '../../utils'

class UnitTestTaskLoader extends AbstractTaskLoader {

  constructor (phase) {
    super(phase)
    this.name = 'unit-test'
    this.phase = phase
  }

  registerTask (gulp) {
    super.registerTask(gulp)

    // // let run = runSequence.use(gulp) // needed to bind to the correct gulp object (alternative is to pass gulp to runSequence as first argument)

    // let karmaConfigFilePath = path.resolve('karma.conf.js')

    // let options = {
    //   path: karmaConfigFilePath,
    //   singleRun: true
    // }

    gulp.task(this.name, false, (callback) => {
      gutil.log(gutil.colors.green('Execute unit tests'))
    //   return utils.getKarmaServer(options, callback)
    })

    // // options.singleRun = false
    // // gulp.task('test-unit-watch', 'Execute all unit tests continuously (watches files)', (callback) => {
    // //   return utils.getKarmaServer(options, callback)
    // // })

    // // gulp.task('prepare-test-unit', 'Do all the necessary preparatory work for the test-unit task', () => {
    // //   return run([
    // //     'clean',
    // //     'ts-lint',
    // //     'check-js-style',
    // //     'check-js-quality'
    // //   ], [
    // //     'scripts-typescript',
    // //     'scripts-javascript'
    // //   ])
    // // })
  }
}

module.exports = new UnitTestTaskLoader('test')
<commit_msg>Add basic test support via Jasmine and Karma:<commit_after>
'use strict'

import gutil from 'gulp-util'
import path from 'path'
// import runSequence from 'run-sequence'
// import iff from 'gulp-if'
// import gutil from 'gulp-util'
// import debug from 'gulp-debug'

import AbstractTaskLoader from '../../abstract-task-loader'
// import config from '../../config'
import utils from '../../utils'

class UnitTestTaskLoader extends AbstractTaskLoader {

  constructor (phase) {
    super(phase)
    this.name = 'unit-test'
    this.phase = phase
  }

  registerTask (gulp) {
    super.registerTask(gulp)

    // let run = runSequence.use(gulp) // needed to bind to the correct gulp object (alternative is to pass gulp to runSequence as first argument)

    let karmaConfigFilePath = path.resolve('karma.conf.js')

    let options = {
      path: karmaConfigFilePath,
      singleRun: true
    }
    console.log(`TEST OPTIONS: ${JSON.stringify(options)}`)

    gulp.task(this.name, false, (callback) => {
      gutil.log(gutil.colors.green('Execute unit tests'))
      return utils.getKarmaServer(options, callback)
    })

    // options.singleRun = false
    // gulp.task('test-unit-watch', 'Execute all unit tests continuously (watches files)', (callback) => {
    //   return utils.getKarmaServer(options, callback)
    // })

    // gulp.task('prepare-test-unit', 'Do all the necessary preparatory work for the test-unit task', () => {
    //   return run([
    //     'clean',
    //     'ts-lint',
    //     'check-js-style',
    //     'check-js-quality'
    //   ], [
    //     'scripts-typescript',
    //     'scripts-javascript'
    //   ])
    // })
  }
}

module.exports = new UnitTestTaskLoader('test')
<|endoftext|>


<commit_before>import _ from 'lodash'

const Checkin = require('mongoose').model('Checkin')

function checkinsByMember(checkins) {
  let byMember = _.groupBy(checkins, 'memberName')

  byMember = _.map(byMember, (checkins, name) => {
    return {
      name,
      checkins,
    }
  })

  byMember = _.sortBy(byMember, (member) => {
    return -member.checkins.length
  })

  return byMember
}

export default async (req, res) => {
  const checkins = await Checkin.where({}).sort('-createdAt')
  const memberCheckins = checkinsByMember(checkins)
  res.render('checkins/list.jade', { checkins, memberCheckins })
}
<commit_msg>Only show last 500 checkins.<commit_after>import _ from 'lodash'

const Checkin = require('mongoose').model('Checkin')

//function checkinsByMember(checkins) {
  //let byMember = _.groupBy(checkins, 'memberName')

  //byMember = _.map(byMember, (checkins, name) => {
    //return {
      //name,
      //checkins,
    //}
  //})

  //byMember = _.sortBy(byMember, (member) => {
    //return -member.checkins.length
  //})

  //return byMember
//}

export default async (req, res) => {
  const checkins = await Checkin.where({}).sort('-createdAt').limit(500)
  //const memberCheckins = checkinsByMember(checkins)
  res.render('checkins/list.jade', { checkins })//, memberCheckins
}
<|endoftext|>


<commit_before>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-present Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import PropTypes from 'prop-types';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import { Modal, Button, FormControl, Table } from 'react-bootstrap';
import TextEditor from '../../components/TextEditor';
import User from '../../components/User';
import s from './Course.css';
import { addStudyEntity } from '../../actions/study_entities';
import { subscribeUser, unsubscribeUser } from '../../actions/courses';

class Course extends React.Component {
  static contextTypes = {
    store: PropTypes.any.isRequired,
    fetch: PropTypes.func.isRequired,
  };

  static propTypes = {
    title: PropTypes.string.isRequired,
    course: PropTypes.shape({
      id: PropTypes.string.isRequired,
      title: PropTypes.string.isRequired,
      studyEntities: PropTypes.arrayOf(
        PropTypes.shape({
          id: PropTypes.string,
          title: PropTypes.string,
        }),
      ),
      users: PropTypes.arrayOf(
        PropTypes.shape({
          id: PropTypes.string,
          email: PropTypes.string,
        }),
      ),
    }).isRequired,
  };

  constructor(props) {
    super(props);
    this.state = {
      studyEntityBody: '',
      showModal: false,
      showModalSubscribe: false,
      studyEntityName: '',
      studyEntities: [],
      subscribedUsersList: [],
    };
    this.handleChangeBody = this.handleChangeBody.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.addStEn = this.addStEn.bind(this);
    this.openStEn = this.openStEn.bind(this);
    this.closeStEn = this.closeStEn.bind(this);
    this.openSubs = this.openSubs.bind(this);
    this.closeSubs = this.closeSubs.bind(this);
  }

  componentWillMount() {
    this.setState({
      studyEntities: this.context.store.getState().course.studyEntities,
      subscribedUsersList: this.props.course.users,
    });
  }

  componentDidMount() {
    this.context.store.subscribe(() => {
      this.setState({
        studyEntities: this.context.store.getState().course.studyEntities,
      });
    });
    this.updateUsers();
  }

  async updateUsers() {
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `{users
          { id, email }
        }`,
      }),
    });
    const { data } = await resp.json();
    this.setState({ users: data.users });
  }

  handleChange(event) {
    this.setState({ studyEntityName: event.target.value });
  }

  handleChangeBody(val) {
    this.setState({ studyEntityBody: val });
  }

  closeStEn() {
    this.setState({ showModal: false });
  }

  openStEn() {
    this.setState({ showModal: true });
  }

  closeSubs() {
    this.setState({ showModalSubscribe: false });
  }

  openSubs() {
    this.setState({ showModalSubscribe: true });
  }

  async subscribeUser(user) {
    this.state.subscribedUsersList.push(user);
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `mutation  subscribe($id: String, $courseId: String){
          subscribeUser(
            id: $id,
            courseId: $courseId)
            { id }
        }`,
        variables: {
          id: user.id,
          courseId: this.props.course.id,
        },
      }),
    });
    const { data } = await resp.json();
    this.context.store.dispatch(subscribeUser(data.subscribeUser));
    this.setState({
      subscribedUsersList: this.state.subscribedUsersList,
    });
  }

  async unsubscribeUser(user) {
    const i = this.state.subscribedUsersList.indexOf(user);
    this.state.subscribedUsersList.splice(i, 1);
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `mutation  unsubscribe($id: String, $courseId: String){
          unsubscribeUser(
            id: $id,
            courseId: $courseId)
            { id }
        }`,
        variables: {
          id: user.id,
          courseId: this.props.course.id,
        },
      }),
    });
    const { data } = await resp.json();
    this.context.store.dispatch(unsubscribeUser(data.unsubscribeUser));

    this.setState({
      subscribedUsersList: this.state.subscribedUsersList,
    });
  }

  async addStEn() {
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `mutation create($courseId: String, $title: String, $body: String){
          createStudyEntity(
            title: $title,
            courseId: $courseId,
            body: $body)
          { id, title }
        }`,
        variables: {
          title: this.state.studyEntityName,
          courseId: this.props.course.id,
          body: this.state.studyEntityBody,
        },
      }),
    });
    const { data } = await resp.json();
    this.context.store.dispatch(addStudyEntity(data.createStudyEntity));
    this.closeStEn();
  }

  render() {
    const studyEntitiesList = [];
    for (let i = 0; i < this.state.studyEntities.length; i += 1) {
      studyEntitiesList.push(

            {this.state.studyEntities[i].title}

,
      );
    }

    const usersList = [];
    for (let i = 0; this.state.users && i < this.state.users.length; i += 1) {
      // const email = this.state.users[i].email;
      const { id } = this.state.users[i];
      if (!this.state.subscribedUsersList.find(user => user.id === id)) {
        usersList.push(

              <Button
                bsStyle="primary"
                role="link"
                onClick={() => this.subscribeUser(this.state.users[i])}
              >
                <User user={this.state.users[i]} link={false} />
              </Button>

,
        );
      }
    }
    const subscribedUsersList = this.state.subscribedUsersList.map(user => (

          <Button
            bsStyle="primary"
            role="link"
            onClick={() => this.unsubscribeUser(user)}
          >
            <User user={user} link={false} />
          </Button>

    ));
    return (

{this.props.title}

{studyEntitiesList}

        <Button bsStyle="primary" onClick={this.openStEn}>
          Add study entity
        </Button>
        <Modal show={this.state.showModal} onHide={this.closeStEn}>
          <Modal.Header closeButton>
            <Modal.Title>Modal heading</Modal.Title>
          </Modal.Header>
          <Modal.Body>

Course name

            <FormControl
              type="text"
              value={this.state.studyEntityName}
              onChange={this.handleChange}
            />

              <TextEditor
                value={this.state.studyEntityBody}
                onChange={this.handleChangeBody}
              />

          </Modal.Body>
          <Modal.Footer>
            <Button onClick={this.addStEn}>Add study entity</Button>
            <Button onClick={this.closeStEn}>Close</Button>
          </Modal.Footer>
        </Modal>
        <Button bsStyle="primary" onClick={this.openSubs}>
          Subscribe user
        </Button>
        <Modal show={this.state.showModalSubscribe} onHide={this.closeSubs}>
          <Modal.Header closeButton>
            <Modal.Title>Modal heading</Modal.Title>
          </Modal.Header>
          <Modal.Body>

Subscribed

                      User email

{subscribedUsersList}

Unsubscribed

                      User email

{usersList}

          </Modal.Body>
          <Modal.Footer>
            <Button onClick={this.closeSubs}>Close</Button>
          </Modal.Footer>
        </Modal>

    );
  }
}

export default withStyles(s)(Course);
<commit_msg>refactor 'Course.js'<commit_after>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-present Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import PropTypes from 'prop-types';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import { Modal, Button, FormControl, Table } from 'react-bootstrap';
import TextEditor from '../../components/TextEditor';
import User from '../../components/User';
import s from './Course.css';
import { addStudyEntity } from '../../actions/study_entities';
import { subscribeUser, unsubscribeUser } from '../../actions/courses';

const StudyEntitiesList = ({ studyEntities, course }) => (

    {studyEntities.map(se => (

        <a href={`/courses/${course.id}/${se.id}`}>{se.title}

    ))}

);

StudyEntitiesList.propTypes = {
  studyEntities: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.string,
      title: PropTypes.string,
    }),
  ).isRequired,
  course: PropTypes.shape({
    id: PropTypes.string.isRequired,
    title: PropTypes.string.isRequired,
    studyEntities: PropTypes.arrayOf(
      PropTypes.shape({
        id: PropTypes.string,
        title: PropTypes.string,
      }),
    ),
  }).isRequired,
};

const UsersList = ({ usersList, onClick }) =>
  usersList.map(user => (

        <Button bsStyle="primary" role="link" onClick={() => onClick(user)}>
          <User user={user} link={false} />
        </Button>

  ));

const ModalSubscribe = ({
  isShowed,
  onCloseClick,
  subscribedUsers,
  unsubscribedUsers,
}) => (
  <Modal show={isShowed} onHide={onCloseClick}>
    <Modal.Header closeButton>
      <Modal.Title>Modal heading</Modal.Title>
    </Modal.Header>
    <Modal.Body>

Subscribed

                User email

{subscribedUsers}

Unsubscribed

                User email

{unsubscribedUsers}

    </Modal.Body>
    <Modal.Footer>
      <Button onClick={onCloseClick}>Close</Button>
    </Modal.Footer>
  </Modal>
);

ModalSubscribe.propTypes = {
  isShowed: PropTypes.bool.isRequired,
  onCloseClick: PropTypes.func.isRequired,
  subscribedUsers: PropTypes.element.isRequired,
  unsubscribedUsers: PropTypes.element.isRequired,
};

const ModalStudyEntity = ({
  isShowed,
  state,
  onInputChange,
  onEditorChange,
  onSubmitClick,
  onCloseClick,
}) => (
  <Modal show={isShowed} onHide={onCloseClick}>
    <Modal.Header closeButton>
      <Modal.Title>Modal heading</Modal.Title>
    </Modal.Header>
    <Modal.Body>

Course name

      <FormControl
        type="text"
        value={state.studyEntityName}
        onChange={onInputChange}
      />

        <TextEditor value={state.studyEntityBody} onChange={onEditorChange} />

    </Modal.Body>
    <Modal.Footer>
      <Button onClick={onSubmitClick}>Add study entity</Button>
      <Button onClick={onCloseClick}>Close</Button>
    </Modal.Footer>
  </Modal>
);

ModalStudyEntity.propTypes = {
  isShowed: PropTypes.bool.isRequired,
  state: PropTypes.shape({ studyEntityName: PropTypes.string.isRequired })
    .isRequired,
  onInputChange: PropTypes.func.isRequired,
  onEditorChange: PropTypes.func.isRequired,
  onSubmitClick: PropTypes.func.isRequired,
  onCloseClick: PropTypes.func.isRequired,
};

class Course extends React.Component {
  static contextTypes = {
    store: PropTypes.any.isRequired,
    fetch: PropTypes.func.isRequired,
  };

  static propTypes = {
    title: PropTypes.string.isRequired,
    course: PropTypes.shape({
      id: PropTypes.string.isRequired,
      title: PropTypes.string.isRequired,
      studyEntities: PropTypes.arrayOf(
        PropTypes.shape({
          id: PropTypes.string,
          title: PropTypes.string,
        }),
      ),
      users: PropTypes.arrayOf(
        PropTypes.shape({
          id: PropTypes.string,
          email: PropTypes.string,
        }),
      ),
    }).isRequired,
  };

  constructor(props) {
    super(props);
    this.state = {
      studyEntityBody: '',
      showModal: false,
      showModalSubscribe: false,
      studyEntityName: '',
      studyEntities: [],
      subscribedUsersList: [],
    };
    this.handleChangeBody = this.handleChangeBody.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.addStEn = this.addStEn.bind(this);
    this.openStEn = this.openStEn.bind(this);
    this.closeStEn = this.closeStEn.bind(this);
    this.openSubs = this.openSubs.bind(this);
    this.closeSubs = this.closeSubs.bind(this);
  }

  componentWillMount() {
    this.setState({
      studyEntities: this.context.store.getState().course.studyEntities,
      subscribedUsersList: this.props.course.users,
    });
  }

  componentDidMount() {
    this.context.store.subscribe(() => {
      this.setState({
        studyEntities: this.context.store.getState().course.studyEntities,
      });
    });
    this.updateUsers();
  }

  async updateUsers() {
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `{users
          { id, email }
        }`,
      }),
    });
    const { data } = await resp.json();
    this.setState({ users: data.users });
  }

  handleChange(event) {
    this.setState({ studyEntityName: event.target.value });
  }

  handleChangeBody(val) {
    this.setState({ studyEntityBody: val });
  }

  closeStEn() {
    this.setState({ showModal: false });
  }

  openStEn() {
    this.setState({ showModal: true });
  }

  closeSubs() {
    this.setState({ showModalSubscribe: false });
  }

  openSubs() {
    this.setState({ showModalSubscribe: true });
  }

  async subscribeUser(user) {
    this.state.subscribedUsersList.push(user);
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `mutation  subscribe($id: String, $courseId: String){
          subscribeUser(
            id: $id,
            courseId: $courseId)
            { id }
        }`,
        variables: {
          id: user.id,
          courseId: this.props.course.id,
        },
      }),
    });
    const { data } = await resp.json();
    this.context.store.dispatch(subscribeUser(data.subscribeUser));
    this.setState({
      subscribedUsersList: this.state.subscribedUsersList,
    });
  }

  async unsubscribeUser(user) {
    const i = this.state.subscribedUsersList.indexOf(user);
    this.state.subscribedUsersList.splice(i, 1);
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `mutation  unsubscribe($id: String, $courseId: String){
          unsubscribeUser(
            id: $id,
            courseId: $courseId)
            { id }
        }`,
        variables: {
          id: user.id,
          courseId: this.props.course.id,
        },
      }),
    });
    const { data } = await resp.json();
    this.context.store.dispatch(unsubscribeUser(data.unsubscribeUser));

    this.setState({
      subscribedUsersList: this.state.subscribedUsersList,
    });
  }

  async addStEn() {
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `mutation create($courseId: String, $title: String, $body: String){
          createStudyEntity(
            title: $title,
            courseId: $courseId,
            body: $body)
          { id, title }
        }`,
        variables: {
          title: this.state.studyEntityName,
          courseId: this.props.course.id,
          body: this.state.studyEntityBody,
        },
      }),
    });
    const { data } = await resp.json();
    this.context.store.dispatch(addStudyEntity(data.createStudyEntity));
    this.closeStEn();
  }

  render() {
    const usersListArray = (this.state.users || []).filter(
      u => !this.state.subscribedUsersList.find(user => user.id === u.id),
    );

    const usersList = (
      <UsersList
        usersList={usersListArray}
        onClick={user => this.subscribeUser(user)}
      />
    );

    const subscribedUsersList = (
      <UsersList
        usersList={this.state.subscribedUsersList}
        onClick={user => this.unsubscribeUser(user)}
      />
    );

    return (

{this.props.title}

          <StudyEntitiesList
            studyEntities={this.state.studyEntities}
            course={this.props.course}
          />

        <Button bsStyle="primary" onClick={this.openStEn}>
          Add study entity
        </Button>
        <ModalStudyEntity
          isShowed={this.state.showModal}
          state={this.state}
          onInputChange={this.handleChange}
          onEditorChange={this.handleChangeBody}
          onSubmitClick={this.addStEn}
          onCloseClick={this.closeStEn}
        />
        <Button bsStyle="primary" onClick={this.openSubs}>
          Subscribe user
        </Button>
        <a href={`/courses/${this.props.course.id}/users`}>Users list
        <ModalSubscribe
          isShowed={this.state.showModalSubscribe}
          subscribedUsers={subscribedUsersList}
          unsubscribedUsers={usersList}
          onCloseClick={this.closeSubs}
        />

    );
  }
}

export default withStyles(s)(Course);
<|endoftext|>


<commit_before>define([
    'knockout',
    'underscore',
    'viewmodels/widget'
], function(ko, _, WidgetViewModel) {
    /**
     * A viewmodel used for domain widgets
     *
     * @constructor
     * @name DomainWidgetViewModel
     *
     * @param  {string} params - a configuration object
     */
    var DomainWidgetViewModel = function(params) {
        var self = this;

        WidgetViewModel.apply(this, [params]);

        if (this.node.config.options) {
            this.options = JSON.parse(JSON.stringify(this.node.config.options));
            this.options().forEach(function(option) {
                if (!ko.isObservable(option.text)) {
                    option.text = ko.observable(option.text);
                }
            });
            // force the node config to refresh (so it detects text observables)
            this.node.configKeys.valueHasMutated();
        }

        var flattenOptions = function(opt, allOpts) {
            if (opt['id'] !== undefined) {
                allOpts.push(opt);
            }
            if (opt.children) {
                opt.children.forEach(function(child) {
                    flattenOptions(child, allOpts);
                });
            }
            return allOpts;
        };

        this.toggleOptionSelection = function (opt) {
            var selected = !self.isOptionSelected(opt);
            self.setOptionSelection(opt, selected);
        };

        this.setOptionSelection = function (opt, selected) {
            if (self.multiple) {
                var val = self.value();
                self.value(
                    selected ?
                    _.union([opt.id], val) :
                    _.without(val ? val : [], opt.id)
                );
            } else if (selected) {
                self.value(opt.id);
            }
        };

        this.isOptionSelected = function (opt) {
            var selected = false;
            var val = self.value();
            if (val && val.indexOf) {
                selected = val.indexOf(opt.id) >= 0;
            }
            return selected;
        };

        this.flatOptions = ko.computed(function() {
            var options = self.options();
            var flatOptions = [];
            options.forEach(function(option) {
                flattenOptions(option, flatOptions);
            });
            return flatOptions;
        });

        this.multiple = false;

        this.displayValue = ko.computed(function() {
            var val = self.value();
            var opts = ko.unwrap(self.flatOptions);
            var displayVal = null;
            if (val) {
                Array.isArray(val) || (val = [val]);
                displayVal = _.without(
                    _.map(val, function(id) {
                        var opt = _.find(opts, function(opt) {
                            return opt.id === id;
                        });
                        return opt ? ko.unwrap(opt.text) : null;
                    }),
                    null
                ).join(', ');
            }
            return displayVal;
        });
    };

    return DomainWidgetViewModel;
});
<commit_msg>cleanup<commit_after>define([
    'knockout',
    'underscore',
    'viewmodels/widget'
], function(ko, _, WidgetViewModel) {
    /**
     * A viewmodel used for domain widgets
     *
     * @constructor
     * @name DomainWidgetViewModel
     *
     * @param  {string} params - a configuration object
     */
    var DomainWidgetViewModel = function(params) {
        var self = this;

        WidgetViewModel.apply(this, [params]);

        if (this.node.config.options) {
            this.options = this.node.config.options;
            this.options().forEach(function(option) {
                if (!ko.isObservable(option.text)) {
                    option.text = ko.observable(option.text);
                }
            });
            // force the node config to refresh (so it detects text observables)
            this.node.configKeys.valueHasMutated();
        }

        var flattenOptions = function(opt, allOpts) {
            if (opt['id'] !== undefined) {
                allOpts.push(opt);
            }
            if (opt.children) {
                opt.children.forEach(function(child) {
                    flattenOptions(child, allOpts);
                });
            }
            return allOpts;
        };

        this.toggleOptionSelection = function (opt) {
            var selected = !self.isOptionSelected(opt);
            self.setOptionSelection(opt, selected);
        };

        this.setOptionSelection = function (opt, selected) {
            if (self.multiple) {
                var val = self.value();
                self.value(
                    selected ?
                    _.union([opt.id], val) :
                    _.without(val ? val : [], opt.id)
                );
            } else if (selected) {
                self.value(opt.id);
            }
        };

        this.isOptionSelected = function (opt) {
            var selected = false;
            var val = self.value();
            if (val && val.indexOf) {
                selected = val.indexOf(opt.id) >= 0;
            }
            return selected;
        };

        this.flatOptions = ko.computed(function() {
            var options = self.options();
            var flatOptions = [];
            options.forEach(function(option) {
                flattenOptions(option, flatOptions);
            });
            return flatOptions;
        });

        this.multiple = false;

        this.displayValue = ko.computed(function() {
            var val = self.value();
            var opts = ko.unwrap(self.flatOptions);
            var displayVal = null;
            if (val) {
                Array.isArray(val) || (val = [val]);
                displayVal = _.without(
                    _.map(val, function(id) {
                        var opt = _.find(opts, function(opt) {
                            return opt.id === id;
                        });
                        return opt ? ko.unwrap(opt.text) : null;
                    }),
                    null
                ).join(', ');
            }
            return displayVal;
        });
    };

    return DomainWidgetViewModel;
});
<|endoftext|>


<commit_before>define(['jquery',
    'underscore',
    'backbone',
    'bootstrap',
    'arches',
    'select2',
    'knockout',
    'plugins/bootstrap-slider/bootstrap-slider.min',
    'views/forms/sections/branch-list',
    'resource-types',
    'bootstrap-datetimepicker',
    'plugins/knockout-select2'],
    function($, _, Backbone, bootstrap, arches, select2, ko, Slider, BranchList, resourceTypes) {

        return Backbone.View.extend({

            initialize: function(options) {
                var self = this;
                var date_picker = $('.datetimepicker').datetimepicker({pickTime: false});

                date_picker.on('dp.change', function(evt){
                    $('#date').trigger('change');
                });

                this.slider = new Slider('input.slider', {});
                this.slider.on('slideStop', function(evt){
                    // if ther user has the slider at it's min and max, then essentially they don't want to filter by year
                    if(self.slider.getAttribute('min') === evt.value[0] && self.slider.getAttribute('max') === evt.value[1]){
                        self.query.filter.year_min_max.removeAll();
                    }else{
                        self.query.filter.year_min_max(evt.value);
                    }
                });

                this._rawdata = ko.toJSON(JSON.parse($('#formdata').val()));
                this.viewModel = JSON.parse(this._rawdata);

                this.expanded = ko.observable(false);
                this.expanded.subscribe(function(status){
                    self.toggleFilterSection($('#time-filter'), status)
                });

                this.query = {
                    filter:  {
                        domains: this.viewModel.domains,
                        year_min_max: ko.observableArray(),
                        filters: ko.observableArray(),
                        inverted: ko.observable(false),
                        editing:{
                            filters: {}
                        },
                        defaults:{
                            filters: {
                                date: '',
                                date_types__value: '',
                                date_types__label: '',
                                date_operators__value: '',
                                date_operators__label: ''
                            }
                        }
                    },
                    changed: ko.pureComputed(function(){
                        var ret = ko.toJSON(this.query.filter.year_min_max()) +
                            ko.toJSON(this.query.filter.filters()) +
                            ko.toJSON(this.query.filter.inverted());
                        return ret;
                    }, this).extend({ rateLimit: 200 })
                };

                this.query.filter.year_min_max.subscribe(function(newValue){
                    var enabled = newValue.length === 2;
                    if(enabled){
                        self.slider.setValue(newValue);
                    }
                    this.trigger('enabled', enabled, this.query.filter.inverted());
                }, this);

                this.query.filter.filters.subscribe(function(filters){
                    var enabled = filters.length > 0;
                    this.trigger('enabled', enabled, this.query.filter.inverted());
                }, this);

                new BranchList({
                    el: $('#time-filter')[0],
                    viewModel: this.query.filter,
                    key: 'filters',
                    validateBranch: function (data) {
                        if (data.date_types__value !== '' && data.date_operators__value !== '' && data.date !== '') {
                            return true;
                        }
                        return false;
                    }
                });

                ko.applyBindings(this.query.filter, $('#time-filter')[0]);
            },

            toggleFilterSection: function(ele, expand){
                if(expand){
                    this.slideToggle(ele, 'show');
                }else{
                    this.slideToggle(ele, 'hide');
                }
            },

            slideToggle: function(ele, showOrHide){
                var self = this;
                if ($(ele).is(":visible") && showOrHide === 'hide'){
                    ele.slideToggle('slow');
                    return;
                }

                if (!($(ele).is(":visible")) && showOrHide === 'show'){
                    ele.slideToggle('slow');
                    return;
                }

                if (!showOrHide){
                    ele.slideToggle('slow');
                }
            },

            restoreState: function(filter, expanded){
                if(typeof filter !== 'undefined'){
                    if('inverted' in filter){
                        this.query.filter.inverted(filter.inverted);
                    }
                    if('filters' in filter && filter.filters.length > 0){
                        _.each(filter.filters, function(filter){
                            this.query.filter.filters.push(filter);
                        }, this);
                    }
                    if('year_min_max' in filter && filter.year_min_max.length === 2){
                        _.each(filter.year_min_max, function(year){
                            this.query.filter.year_min_max.push(year);
                        }, this);
                    }
                }

                if(typeof expanded === 'undefined'){
                    expanded = false;
                }
                this.expanded(expanded);

            },

            clear: function(){
                this.query.filter.inverted(false);
                this.query.filter.filters.removeAll();
                this.query.filter.year_min_max.removeAll();
                this.slider.setValue([this.slider.getAttribute('min'),this.slider.getAttribute('max')]);
            }

        });

});<commit_msg>fix bug in maintaining the proper status in the time filter status indicator, fixes #47<commit_after>define(['jquery',
    'underscore',
    'backbone',
    'bootstrap',
    'arches',
    'select2',
    'knockout',
    'plugins/bootstrap-slider/bootstrap-slider.min',
    'views/forms/sections/branch-list',
    'resource-types',
    'bootstrap-datetimepicker',
    'plugins/knockout-select2'],
    function($, _, Backbone, bootstrap, arches, select2, ko, Slider, BranchList, resourceTypes) {

        return Backbone.View.extend({

            initialize: function(options) {
                var self = this;
                var date_picker = $('.datetimepicker').datetimepicker({pickTime: false});

                date_picker.on('dp.change', function(evt){
                    $('#date').trigger('change');
                });

                this.slider = new Slider('input.slider', {});
                this.slider.on('slideStop', function(evt){
                    // if ther user has the slider at it's min and max, then essentially they don't want to filter by year
                    if(self.slider.getAttribute('min') === evt.value[0] && self.slider.getAttribute('max') === evt.value[1]){
                        self.query.filter.year_min_max.removeAll();
                    }else{
                        self.query.filter.year_min_max(evt.value);
                    }
                });

                this._rawdata = ko.toJSON(JSON.parse($('#formdata').val()));
                this.viewModel = JSON.parse(this._rawdata);

                this.expanded = ko.observable(false);
                this.expanded.subscribe(function(status){
                    self.toggleFilterSection($('#time-filter'), status)
                });

                this.query = {
                    filter:  {
                        domains: this.viewModel.domains,
                        year_min_max: ko.observableArray(),
                        filters: ko.observableArray(),
                        inverted: ko.observable(false),
                        editing:{
                            filters: {}
                        },
                        defaults:{
                            filters: {
                                date: '',
                                date_types__value: '',
                                date_types__label: '',
                                date_operators__value: '',
                                date_operators__label: ''
                            }
                        }
                    },
                    changed: ko.pureComputed(function(){
                        var ret = ko.toJSON(this.query.filter.year_min_max()) +
                            ko.toJSON(this.query.filter.filters()) +
                            ko.toJSON(this.query.filter.inverted());
                        return ret;
                    }, this).extend({ rateLimit: 200 })
                };

                this.query.filter.year_min_max.subscribe(function(newValue){
                    var sliderenabled = newValue.length === 2;
                    var filtersenabled = this.query.filter.filters().length > 0;
                    if(sliderenabled){
                        self.slider.setValue(newValue);
                    }
                    this.trigger('enabled', filtersenabled || sliderenabled, this.query.filter.inverted());
                }, this);

                this.query.filter.filters.subscribe(function(filters){
                    var filtersenabled = filters.length > 0;
                    var sliderenabled = this.query.filter.year_min_max().length === 2;
                    this.trigger('enabled', filtersenabled || sliderenabled, this.query.filter.inverted());
                }, this);

                new BranchList({
                    el: $('#time-filter')[0],
                    viewModel: this.query.filter,
                    key: 'filters',
                    validateBranch: function (data) {
                        if (data.date_types__value !== '' && data.date_operators__value !== '' && data.date !== '') {
                            return true;
                        }
                        return false;
                    }
                });

                ko.applyBindings(this.query.filter, $('#time-filter')[0]);
            },

            toggleFilterSection: function(ele, expand){
                if(expand){
                    this.slideToggle(ele, 'show');
                }else{
                    this.slideToggle(ele, 'hide');
                }
            },

            slideToggle: function(ele, showOrHide){
                var self = this;
                if ($(ele).is(":visible") && showOrHide === 'hide'){
                    ele.slideToggle('slow');
                    return;
                }

                if (!($(ele).is(":visible")) && showOrHide === 'show'){
                    ele.slideToggle('slow');
                    return;
                }

                if (!showOrHide){
                    ele.slideToggle('slow');
                }
            },

            restoreState: function(filter, expanded){
                if(typeof filter !== 'undefined'){
                    if('inverted' in filter){
                        this.query.filter.inverted(filter.inverted);
                    }
                    if('filters' in filter && filter.filters.length > 0){
                        _.each(filter.filters, function(filter){
                            this.query.filter.filters.push(filter);
                        }, this);
                    }
                    if('year_min_max' in filter && filter.year_min_max.length === 2){
                        _.each(filter.year_min_max, function(year){
                            this.query.filter.year_min_max.push(year);
                        }, this);
                    }
                }

                if(typeof expanded === 'undefined'){
                    expanded = false;
                }
                this.expanded(expanded);

            },

            clear: function(){
                this.query.filter.inverted(false);
                this.query.filter.filters.removeAll();
                this.query.filter.year_min_max.removeAll();
                this.slider.setValue([this.slider.getAttribute('min'),this.slider.getAttribute('max')]);
            }

        });

});<|endoftext|>


<commit_before>import {inspect} from 'util';
import typeString from '../utils/type-name-from-definition';
import typeNameFromValue from '../utils/type-name-from-value';

const error = new TypeError('Unexpected type');

function checkArgTypeInner(schema: Object, type: {kind: string}, value: any, argName: string): any {
  switch (type.kind) {
    case 'NotNull':
      if (value === null) {
        throw error;
      }
      const result = checkArgTypeInner(schema, type.type, value, argName);
      if (result === null) {
        throw error;
      }
      return result;
    case 'List':
      if (value === null) return null;
      if (!Array.isArray(value)) {
        throw error;
      }
      return value.map((v, i) => checkArgTypeInner(schema, type.type, v, argName));
    case 'NamedTypeReference':
      if (value === null) {
        return null;
      }
      const namedType = schema[type.value];
      if (!namedType) {
        throw error;
      }
      switch (namedType.kind) {
        case 'ScalarType':
          let result;
          try {
            result = namedType.parse(value);
          } catch (ex) {
            throw error;
          }
          if (result === undefined) return null;
          return result;
        default:
          throw new TypeError(`Unrecognised named type kind in arg "${argName}": ${namedType.kind}`);
      }
    default:
      throw new TypeError(`Unrecognised arg type kind in arg "${argName}": ${type.kind}`);
  }
}

export default function validateArg(schema: Object, type: {kind: string}, value: any, argName: string): any {
  try {
    return checkArgTypeInner(schema, type, value, argName);
  } catch (ex) {
    if (ex !== error) throw ex;
    const expected = typeString(type);
    const valString = inspect(value, {depth: 10});
    const actual = valString.length < 30 ? valString : 'a "' + typeNameFromValue(value) + '"';
    const err = new TypeError(
      `Expected arg "${argName}" to be of type "${expected}" but got ${actual}`
    );
    err.exposeProd = true;
    throw err;
  }
}
<commit_msg>Treat undefined as null for arg validation<commit_after>import {inspect} from 'util';
import typeString from '../utils/type-name-from-definition';
import typeNameFromValue from '../utils/type-name-from-value';

const error = new TypeError('Unexpected type');

function checkArgTypeInner(schema: Object, type: {kind: string}, value: any, argName: string): any {
  switch (type.kind) {
    case 'NotNull':
      if (value === null) {
        throw error;
      }
      const result = checkArgTypeInner(schema, type.type, value, argName);
      if (result === null) {
        throw error;
      }
      return result;
    case 'List':
      if (value == null) return null;
      if (!Array.isArray(value)) {
        throw error;
      }
      return value.map((v, i) => checkArgTypeInner(schema, type.type, v, argName));
    case 'NamedTypeReference':
      if (value == null) {
        return null;
      }
      const namedType = schema[type.value];
      if (!namedType) {
        throw error;
      }
      switch (namedType.kind) {
        case 'ScalarType':
          let result;
          try {
            result = namedType.parse(value);
          } catch (ex) {
            throw error;
          }
          if (result === undefined) return null;
          return result;
        default:
          throw new TypeError(`Unrecognised named type kind in arg "${argName}": ${namedType.kind}`);
      }
    default:
      throw new TypeError(`Unrecognised arg type kind in arg "${argName}": ${type.kind}`);
  }
}

export default function validateArg(schema: Object, type: {kind: string}, value: any, argName: string): any {
  try {
    return checkArgTypeInner(schema, type, value, argName);
  } catch (ex) {
    if (ex !== error) throw ex;
    const expected = typeString(type);
    const valString = inspect(value, {depth: 10});
    const actual = valString.length < 30 ? valString : 'a "' + typeNameFromValue(value) + '"';
    const err = new TypeError(
      `Expected arg "${argName}" to be of type "${expected}" but got ${actual}`
    );
    err.exposeProd = true;
    throw err;
  }
}
<|endoftext|>


<commit_before>const CachedInputFileSystem = require("enhanced-resolve/lib/CachedInputFileSystem");
const FunctionModulePlugin = require('webpack/lib/FunctionModulePlugin');
const JsonpTemplatePlugin = require("webpack/lib/JsonpTemplatePlugin");
const LoaderTargetPlugin = require('webpack/lib/LoaderTargetPlugin');
const NodeJsInputFileSystem = require("enhanced-resolve/lib/NodeJsInputFileSystem");
const Promise = require('bluebird');
const ResolvedNodeSourcePlugin = require("./ResolvedNodeSourcePlugin");
const WebpackCompiler = require('webpack/lib/Compiler');
const WebpackOptionsApply = require('webpack/lib/WebpackOptionsApply');
const WebpackOptionsDefaulter = require('webpack/lib/WebpackOptionsDefaulter');
const FallbackFileSystem = require('../models/FallbackFileSystem');

const path = require('path');
const getNodeSourceResolutions = require('./getNodeSourceResolutions');

async function webpackAsync(dir, inputFileSystem, outputFileSystem, options) {
  const compiler = new WebpackCompiler();

  new WebpackOptionsDefaulter().process(options);

  compiler.options = options;
  compiler.options.output.publicPath = '/my/.build/';
  compiler.options.resolve.extensions = ['', '.js'];

  // XXX The base directory of BucketFileSystem is '/'.

  compiler.options.context = '/';
  compiler.options.recordsPath = '/.build/records.json';

  compiler.options.target = function(compiler) {
    compiler.apply(
      new JsonpTemplatePlugin(options.output),
      new FunctionModulePlugin(options.output),
      new LoaderTargetPlugin("web")
    );
  };

  compiler.options = new WebpackOptionsApply().process(compiler.options, compiler);

  // XXX We use the loaders that get installed with the server software, not the
  // ones specified in the repository, because loaders are loaded via require().
  // In theory Webpack will use the loader resolver for all of the loaders.
  // However, after the loader is initially resolved with the loader resolver:
  //
  // - The resolved loader location is added to the dependency map for normal
  //   modules--the normal modules being the files that we want to apply the
  //   loader to.
  // - The dependency manager then tries to resolve the dependency map
  //   (INCLUDING THE RESOLVED LOADERS) using the normal resolver, not the
  //   loader resolver.
  // - Since our loaders are in an orthogonal filesystem (the Node local
  //   filesystem) with different paths from the normal module fileystem
  //   (BucketFileSystem or a CompositeBucketFileSystem)...the lookup fails.
  //
  // The hack to work around this for now, is to have a filesystem layer that
  // implements a minimum of methods that first checks the bucket for the file,
  // and falls back to the Node file system if that fails.
  //
  // However, why not just use CompositeFileSystem for this?
  //
  // On Heroku, `dir` is '/' always. So, can't separate by a folder.
  // On your development machine, the difference between paths will be more
  // than just a filePath segment.

  const combinedInputFileSystem = new CachedInputFileSystem(
    new FallbackFileSystem([inputFileSystem, new NodeJsInputFileSystem()]),
    60000
  );

  compiler.inputFileSystem = combinedInputFileSystem;
  ['context', 'normal', 'loader'].forEach((type) => {
    compiler.resolvers[type].fileSystem = combinedInputFileSystem;
  });

  // XXX However, because process.cwd() will probably not be '/' on a developer
  // machine where we test this...we need the loader resolver to explicitly
  // look up paths for loaders in the directory where the process

  compiler.resolvers.loader.internalResolve = compiler.resolvers.loader.resolve;
  compiler.resolvers.loader.resolve = function(_, request, callback) {
    this.internalResolve(dir, request, callback);
  };

  // XXX We apply this here, rather than in compiler.options.target like with
  // NodeSourcePlugin in normal webpack because we need the resolvers to be
  // configured to be able to fetch the relative node source resolutions.
  //
  // The resolvers are configured when we run WebpackOptionsApply.process().

  const aliases = await getNodeSourceResolutions(
    compiler.resolvers.normal,
    compiler.options.context,
    options.node
  );

  compiler.apply(new ResolvedNodeSourcePlugin(aliases, options.node));

  compiler.outputFileSystem = outputFileSystem;
  compiler.watchFileSystem = null;

  compiler.applyPlugins('environment');
  compiler.applyPlugins('after-environment');

  return await Promise.promisify(compiler.run, compiler)();
}

module.exports = webpackAsync;<commit_msg>Clarify comment.<commit_after>const CachedInputFileSystem = require("enhanced-resolve/lib/CachedInputFileSystem");
const FunctionModulePlugin = require('webpack/lib/FunctionModulePlugin');
const JsonpTemplatePlugin = require("webpack/lib/JsonpTemplatePlugin");
const LoaderTargetPlugin = require('webpack/lib/LoaderTargetPlugin');
const NodeJsInputFileSystem = require("enhanced-resolve/lib/NodeJsInputFileSystem");
const Promise = require('bluebird');
const ResolvedNodeSourcePlugin = require("./ResolvedNodeSourcePlugin");
const WebpackCompiler = require('webpack/lib/Compiler');
const WebpackOptionsApply = require('webpack/lib/WebpackOptionsApply');
const WebpackOptionsDefaulter = require('webpack/lib/WebpackOptionsDefaulter');
const FallbackFileSystem = require('../models/FallbackFileSystem');

const path = require('path');
const getNodeSourceResolutions = require('./getNodeSourceResolutions');

async function webpackAsync(dir, inputFileSystem, outputFileSystem, options) {
  const compiler = new WebpackCompiler();

  new WebpackOptionsDefaulter().process(options);

  compiler.options = options;
  compiler.options.output.publicPath = '/my/.build/';
  compiler.options.resolve.extensions = ['', '.js'];

  // XXX The base directory of BucketFileSystem is '/'.

  compiler.options.context = '/';
  compiler.options.recordsPath = '/.build/records.json';

  compiler.options.target = function(compiler) {
    compiler.apply(
      new JsonpTemplatePlugin(options.output),
      new FunctionModulePlugin(options.output),
      new LoaderTargetPlugin("web")
    );
  };

  compiler.options = new WebpackOptionsApply().process(compiler.options, compiler);

  // XXX We use the loaders that get installed with gossamer-server, not the
  // ones specified in the gossamer branch we're fetching and building, because
  // loaders are loaded via require(). (And that doesn't work with buckets.)
  //
  // In theory Webpack will use the loader resolver for all of the loaders.
  // However, after the loader is initially resolved with the loader resolver:
  //
  // - The resolved loader location is added to the dependency map for normal
  //   modules--the normal modules being the files that we want to apply the
  //   loader to.
  // - The dependency manager then tries to resolve the dependency map
  //   (INCLUDING THE RESOLVED LOADERS) using the normal resolver, not the
  //   loader resolver.
  // - Since our loaders are in an orthogonal filesystem (the Node local
  //   filesystem) with different paths from the normal module fileystem
  //   (BucketFileSystem or a CompositeBucketFileSystem)...the lookup fails.
  //
  // The hack to work around this for now, is to have a filesystem layer that
  // implements a minimum of methods that first checks the bucket for the file,
  // and falls back to the Node file system if that fails.
  //
  // However, why not just use CompositeFileSystem for this?
  //
  // On Heroku, `dir` is '/' always. So, can't separate by a folder.
  // On your development machine, the difference between paths will be more
  // than just a filePath segment.

  const combinedInputFileSystem = new CachedInputFileSystem(
    new FallbackFileSystem([inputFileSystem, new NodeJsInputFileSystem()]),
    60000
  );

  compiler.inputFileSystem = combinedInputFileSystem;
  ['context', 'normal', 'loader'].forEach((type) => {
    compiler.resolvers[type].fileSystem = combinedInputFileSystem;
  });

  // XXX However, because process.cwd() will probably not be '/' on a developer
  // machine where we test this...we need the loader resolver to explicitly
  // look up paths for loaders in the directory where the process

  compiler.resolvers.loader.internalResolve = compiler.resolvers.loader.resolve;
  compiler.resolvers.loader.resolve = function(_, request, callback) {
    this.internalResolve(dir, request, callback);
  };

  // XXX We apply this here, rather than in compiler.options.target like with
  // NodeSourcePlugin in normal webpack because we need the resolvers to be
  // configured to be able to fetch the relative node source resolutions.
  //
  // The resolvers are configured when we run WebpackOptionsApply.process().

  const aliases = await getNodeSourceResolutions(
    compiler.resolvers.normal,
    compiler.options.context,
    options.node
  );

  compiler.apply(new ResolvedNodeSourcePlugin(aliases, options.node));

  compiler.outputFileSystem = outputFileSystem;
  compiler.watchFileSystem = null;

  compiler.applyPlugins('environment');
  compiler.applyPlugins('after-environment');

  return await Promise.promisify(compiler.run, compiler)();
}

module.exports = webpackAsync;<|endoftext|>


<commit_before>/* global io */
/**
 * Playground Store
 */

import React, { Component } from 'react';
import map from 'lodash/map';
import mapValues from 'lodash/mapValues';
import find from 'lodash/find';
import debounce from 'lodash/debounce';
import 'whatwg-fetch';
import getSlug from 'speakingurl';

import getControl from '../../utils/getControl';
import randomValues from '../../utils/randomValues';
import propsToVariation from '../../utils/propsToVariation';
import variationsToProps from '../../utils/variationsToProps';
import codeToCustomMetadata from '../../utils/codeToCustomMetadata';
import customMetadataToCode from '../../utils/customMetadataToCode';
import getComponentNameFromPath from '../../../../../../utils/getComponentNameFromPath';

import Playground from '../Playground';
import PropForm from '../PropForm';
import Modal from '../Modal';
import CreateVariationButton from '../common/CreateVariationButton';
import CustomMetadataForm from '../CustomMetadataForm';

import styles from './styles.css';

const PERSISTENCE_DELAY = 1000;

class PlaygroundList extends Component {
  state = {
    variationPropsList: {},
    variationEditMode: false,
    customMetadataEditMode: false,
    selectedVariationId: undefined,
    customMetadata: undefined,
    metadataWithControls: null,
    createVariationError: '',
    loadingMetadata: true,
    loadingVariations: true,
  };

  componentWillMount() {
    this.debouncedPersistVariation = debounce(
      (variationPath, props) => { this.persistVariation(variationPath, props); },
      PERSISTENCE_DELAY
    );
    this.debouncedPersistCustomMetadata = debounce(
      (customMetadata) => { this.persistCustomMetadata(customMetadata); },
      PERSISTENCE_DELAY
    );

    this.fetchMetadata();
    this.fetchVariations();
    this.connectToSocket();
  }

  componentWillUnmount() {
    this.disconnectFromSocket();
  }

  getRandomValues = () => randomValues(this.state.metadataWithControls);

  getDataFromProps = (data) => {
    const {
      props,
      name,
    } = data;
    // Generate a human-readable JSON string from the props
    const propsString = propsToVariation(props);
    // Add the name to the data we save
    return propsString.replace(/^(\s*){/, `$1{\n  "name": "${name}",`);
  };

  fetchMetadata = () => {
    // TODO dynamic host
    fetch(`http://localhost:8000/components/${this.props.componentPath}`)
      .then((response) => response.json())
      .then((json) => {
        const customMetadata = codeToCustomMetadata(json.data);
        this.generateMetadataWithControls(customMetadata);
      }).catch((ex) => {
        // TODO proper error handling
        console.error('meta data parsing failed', ex); // eslint-disable-line no-console
      });
  };

  generateMetadataWithControls = (customMetadata) => {
    const { meta } = this.props;

    // Attach controls to propTypes meta information
    let metadataWithControls;
    if (meta.props) {
      metadataWithControls = mapValues(meta.props, (prop, propKey) => {
        const newProp = { ...prop };
        const propMeta = customMetadata && customMetadata.props && customMetadata.props[propKey];
        newProp.control = getControl(newProp, propMeta);
        return newProp;
      });
    }

    this.setState({
      metadataWithControls,
      customMetadata,
      loadingMetadata: false,
    });
  };

  connectToSocket = () => {
    this.socket = io.connect('http://localhost:8001');
    this.socket.on('componentMetadataChanged', (event) => {
      const { data } = event;
      this.generateMetadataWithControls(data);
    });
  };

  disconnectFromSocket = () => {
    if (this.socket) {
      this.socket.disconnect();
    }
  };

  fetchVariations = () => {
    // TODO dynamic host
    fetch(`http://localhost:8000/variations/${this.props.componentPath}`)
      .then((response) => response.json())
      .then((json) => {
        const variationPropsList = variationsToProps(json.data);
        this.setState({
          variationPropsList,
          loadingVariations: false,
        });

        const links = map(variationPropsList, (variation, key) => (
          {
            title: variation.name,
            id: key,
          }
        ));

        window.STYLEGUIDE_PLUGIN_CLIENT_API.updateNavigation(
          this.props.componentPath,
          'playground-plugin',
          links
        );
      }).catch((ex) => {
        // TODO proper error handling
        console.error('parsing failed', ex); // eslint-disable-line no-console
      });
  };

  createVariation = (name) => {
    const slug = getSlug(name);
    if (this.state.variationPropsList[`${slug}`] !== undefined) {
      this.setState({
        createVariationError: `A variation with the name ${name} already exists.`,
      });
      return;
    }
    this.setState({
      createVariationError: '',
    });
    const data = this.getDataFromProps({
      props: this.getRandomValues(),
      name,
    });
    // TODO dynamic host
    fetch(`http://localhost:8000/variations/${this.props.componentPath}`, {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        variation: `${slug}`,
        code: data,
      }),
    })
      .then(() => {
        // TODO only fetch in case there was a 200 response (should we switch to 201?)
        this.fetchVariations();
      }).catch((err) => {
        // TODO proper error handling
        console.error('parsing failed', err); // eslint-disable-line no-console
      });
  };

  deleteVariation = (variationPath) => {
    fetch(`http://localhost:8000/variations/${this.props.componentPath}?variation=${variationPath}`, {
      method: 'DELETE',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
    })
    .then(() => {
      this.setState({
        variationEditMode: false,
      });
      this.fetchVariations();
    })
    .catch((err) => {
      // TODO PROPER ERROR HANDLING
      console.trace(err); // eslint-disable-line no-console
    });
  };

  persistVariation = (variationPath, props) => {
    const data = this.getDataFromProps({
      props,
      name: this.state.variationPropsList[variationPath].name,
    });
    fetch(`http://localhost:8000/variations/${this.props.componentPath}`, {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        variation: variationPath,
        code: data,
      }),
    })
    .then(() => {
      this.fetchVariations();
    })
    .catch((err) => {
      // TODO PROPER ERROR HANDLING
      console.trace(err); // eslint-disable-line no-console
    });
  };

  updateCustomMetadata = (customMetadata) => {
    this.generateMetadataWithControls(customMetadata);
    // Persist changes to server every PERSISTENCE_TIMEOUT milliseconds
    this.debouncedPersistCustomMetadata(customMetadata);
  }

  persistCustomMetadata = (customMetadata) => {
    fetch(`http://localhost:8000/components/${this.props.componentPath}`, {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        code: customMetadataToCode(customMetadata),
      }),
    })
    // Unnecessary since this happens now via sockets
    // .then(() => {
    //   this.fetchVariations();
    // })
    .catch((err) => {
      // TODO PROPER ERROR HANDLING
      console.trace(err); // eslint-disable-line no-console
    });
  };

  updateVariation = (variationPath, props) => {
    // Update changes locally for snappy UI
    this.setState({
      variationPropsList: {
        ...this.state.variationPropsList,
        [variationPath]: {
          ...this.state.variationPropsList[variationPath],
          props,
        },
      },
    });

    // Persist changes to server every PERSISTENCE_TIMEOUT milliseconds
    this.debouncedPersistVariation(variationPath, props);
  };

  randomiseEverything = (path) => {
    this.persistVariation(path, this.getRandomValues());
  };

  selectVariation = (id) => {
    this.setState({
      selectedVariationId: id,
    });
  };

  startCustomMetadataEditMode = () => {
    document.body.style.overflow = 'hidden';
    this.setState({
      customMetadataEditMode: true,
    });
  };

  stopCustomMetadataEditMode = () => {
    document.body.style.overflow = '';
    this.setState({
      customMetadataEditMode: false,
    });
  };

  startVariationEditMode = (id) => {
    document.body.style.overflow = 'hidden';
    this.setState({
      variationEditMode: true,
      selectedVariationId: id,
    });
  };

  stopVariationEditMode = () => {
    document.body.style.overflow = '';
    this.setState({
      variationEditMode: false,
    });
  };

  render() {
    if (this.state.loadingMetadata && this.state.loadingVariations) {
      return
Loading …
;
    }

    const { component } = this.props;
    const selectedVariation =
      find(
        this.state.variationPropsList,
        (variationProps, key) => this.state.selectedVariationId === key
      );
    return (

          {getComponentNameFromPath(this.props.componentPath)}

        <button
          onClick={this.startCustomMetadataEditMode}
          style={{
            margin: '0 auto',
            display: 'block',
          }}
        >
          Edit Metadata
        </button>
        {/* METADATA EDIT MODE MODAL */}
        <Modal
          visible={this.state.customMetadataEditMode}
          onCloseClick={this.stopCustomMetadataEditMode}
        >
          <CustomMetadataForm
            customMetadata={this.state.customMetadata}
            parsedMetadata={this.props.meta}
            updateCustomMetadata={this.updateCustomMetadata}
          />
        </Modal>
        {/* VARIATION EDIT MODE MODAL */}
        {(this.state.selectedVariationId) && (
          <Modal
            visible={this.state.variationEditMode}
            onCloseClick={this.stopVariationEditMode}
          >

              <PropForm
                metadataWithControls={this.state.metadataWithControls}
                onVariationPropsChange={this.updateVariation}
                onRandomClick={this.randomiseEverything.bind(this, this.state.selectedVariationId)} // eslint-disable-line react/jsx-no-bind,max-len
                open={this.state.variationEditMode}
                variationPath={this.state.selectedVariationId}
                variationProps={selectedVariation.props}
              />
              <Playground
                component={component}
                fullHeight
                variationProps={selectedVariation.props}
                variationPath={this.state.selectedVariationId}
              />

          </Modal>
        )}
        {/* MAIN AREA WITH PLAYGROUNDS */}
        {map(this.state.variationPropsList, (variation, variationPath) => (
          <Playground
            key={variationPath}
            component={component}
            title={variation.name}
            variationProps={variation.props}
            variationPath={variationPath}
            onDeleteButtonClick={this.deleteVariation}
            onEditButtonClick={this.startVariationEditMode}
          />
        ))}
        <CreateVariationButton
          error={this.state.createVariationError}
          onSubmit={this.createVariation}
        />

    );
  }
}

export default PlaygroundList;
<commit_msg>move handling of metadata change into function<commit_after>/* global io */
/**
 * Playground Store
 */

import React, { Component } from 'react';
import map from 'lodash/map';
import mapValues from 'lodash/mapValues';
import find from 'lodash/find';
import debounce from 'lodash/debounce';
import 'whatwg-fetch';
import getSlug from 'speakingurl';

import getControl from '../../utils/getControl';
import randomValues from '../../utils/randomValues';
import propsToVariation from '../../utils/propsToVariation';
import variationsToProps from '../../utils/variationsToProps';
import codeToCustomMetadata from '../../utils/codeToCustomMetadata';
import customMetadataToCode from '../../utils/customMetadataToCode';
import getComponentNameFromPath from '../../../../../../utils/getComponentNameFromPath';

import Playground from '../Playground';
import PropForm from '../PropForm';
import Modal from '../Modal';
import CreateVariationButton from '../common/CreateVariationButton';
import CustomMetadataForm from '../CustomMetadataForm';

import styles from './styles.css';

const PERSISTENCE_DELAY = 1000;

class PlaygroundList extends Component {
  state = {
    variationPropsList: {},
    variationEditMode: false,
    customMetadataEditMode: false,
    selectedVariationId: undefined,
    customMetadata: undefined,
    metadataWithControls: null,
    createVariationError: '',
    loadingMetadata: true,
    loadingVariations: true,
  };

  componentWillMount() {
    this.debouncedPersistVariation = debounce(
      (variationPath, props) => { this.persistVariation(variationPath, props); },
      PERSISTENCE_DELAY
    );
    this.debouncedPersistCustomMetadata = debounce(
      (customMetadata) => { this.persistCustomMetadata(customMetadata); },
      PERSISTENCE_DELAY
    );

    this.fetchMetadata();
    this.fetchVariations();
    this.connectToSocket();
  }

  componentWillUnmount() {
    this.disconnectFromSocket();
  }

  getRandomValues = () => randomValues(this.state.metadataWithControls);

  getDataFromProps = (data) => {
    const {
      props,
      name,
    } = data;
    // Generate a human-readable JSON string from the props
    const propsString = propsToVariation(props);
    // Add the name to the data we save
    return propsString.replace(/^(\s*){/, `$1{\n  "name": "${name}",`);
  };

  fetchMetadata = () => {
    // TODO dynamic host
    fetch(`http://localhost:8000/components/${this.props.componentPath}`)
      .then((response) => response.json())
      .then((json) => {
        const customMetadata = codeToCustomMetadata(json.data);
        this.generateMetadataWithControls(customMetadata);
      }).catch((ex) => {
        // TODO proper error handling
        console.error('meta data parsing failed', ex); // eslint-disable-line no-console
      });
  };

  generateMetadataWithControls = (customMetadata) => {
    const { meta } = this.props;

    // Attach controls to propTypes meta information
    let metadataWithControls;
    if (meta.props) {
      metadataWithControls = mapValues(meta.props, (prop, propKey) => {
        const newProp = { ...prop };
        const propMeta = customMetadata && customMetadata.props && customMetadata.props[propKey];
        newProp.control = getControl(newProp, propMeta);
        return newProp;
      });
    }

    this.setState({
      metadataWithControls,
      customMetadata,
      loadingMetadata: false,
    });
  };

  connectToSocket = () => {
    this.socket = io.connect('http://localhost:8001');
    this.socket.on('componentMetadataChanged', this.onComponentMetadataChanged);
  };

  disconnectFromSocket = () => {
    if (this.socket) {
      this.socket.disconnect();
    }
  };

  onComponentMetadataChanged = (event) => {
    const { data } = event;
    this.generateMetadataWithControls(data);
  };

  fetchVariations = () => {
    // TODO dynamic host
    fetch(`http://localhost:8000/variations/${this.props.componentPath}`)
      .then((response) => response.json())
      .then((json) => {
        const variationPropsList = variationsToProps(json.data);
        this.setState({
          variationPropsList,
          loadingVariations: false,
        });

        const links = map(variationPropsList, (variation, key) => (
          {
            title: variation.name,
            id: key,
          }
        ));

        window.STYLEGUIDE_PLUGIN_CLIENT_API.updateNavigation(
          this.props.componentPath,
          'playground-plugin',
          links
        );
      }).catch((ex) => {
        // TODO proper error handling
        console.error('parsing failed', ex); // eslint-disable-line no-console
      });
  };

  createVariation = (name) => {
    const slug = getSlug(name);
    if (this.state.variationPropsList[`${slug}`] !== undefined) {
      this.setState({
        createVariationError: `A variation with the name ${name} already exists.`,
      });
      return;
    }
    this.setState({
      createVariationError: '',
    });
    const data = this.getDataFromProps({
      props: this.getRandomValues(),
      name,
    });
    // TODO dynamic host
    fetch(`http://localhost:8000/variations/${this.props.componentPath}`, {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        variation: `${slug}`,
        code: data,
      }),
    })
      .then(() => {
        // TODO only fetch in case there was a 200 response (should we switch to 201?)
        this.fetchVariations();
      }).catch((err) => {
        // TODO proper error handling
        console.error('parsing failed', err); // eslint-disable-line no-console
      });
  };

  deleteVariation = (variationPath) => {
    fetch(`http://localhost:8000/variations/${this.props.componentPath}?variation=${variationPath}`, {
      method: 'DELETE',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
    })
    .then(() => {
      this.setState({
        variationEditMode: false,
      });
      this.fetchVariations();
    })
    .catch((err) => {
      // TODO PROPER ERROR HANDLING
      console.trace(err); // eslint-disable-line no-console
    });
  };

  persistVariation = (variationPath, props) => {
    const data = this.getDataFromProps({
      props,
      name: this.state.variationPropsList[variationPath].name,
    });
    fetch(`http://localhost:8000/variations/${this.props.componentPath}`, {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        variation: variationPath,
        code: data,
      }),
    })
    .then(() => {
      this.fetchVariations();
    })
    .catch((err) => {
      // TODO PROPER ERROR HANDLING
      console.trace(err); // eslint-disable-line no-console
    });
  };

  updateCustomMetadata = (customMetadata) => {
    this.generateMetadataWithControls(customMetadata);
    // Persist changes to server every PERSISTENCE_TIMEOUT milliseconds
    this.debouncedPersistCustomMetadata(customMetadata);
  }

  persistCustomMetadata = (customMetadata) => {
    fetch(`http://localhost:8000/components/${this.props.componentPath}`, {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        code: customMetadataToCode(customMetadata),
      }),
    })
    // Unnecessary since this happens now via sockets
    // .then(() => {
    //   this.fetchVariations();
    // })
    .catch((err) => {
      // TODO PROPER ERROR HANDLING
      console.trace(err); // eslint-disable-line no-console
    });
  };

  updateVariation = (variationPath, props) => {
    // Update changes locally for snappy UI
    this.setState({
      variationPropsList: {
        ...this.state.variationPropsList,
        [variationPath]: {
          ...this.state.variationPropsList[variationPath],
          props,
        },
      },
    });

    // Persist changes to server every PERSISTENCE_TIMEOUT milliseconds
    this.debouncedPersistVariation(variationPath, props);
  };

  randomiseEverything = (path) => {
    this.persistVariation(path, this.getRandomValues());
  };

  selectVariation = (id) => {
    this.setState({
      selectedVariationId: id,
    });
  };

  startCustomMetadataEditMode = () => {
    document.body.style.overflow = 'hidden';
    this.setState({
      customMetadataEditMode: true,
    });
  };

  stopCustomMetadataEditMode = () => {
    document.body.style.overflow = '';
    this.setState({
      customMetadataEditMode: false,
    });
  };

  startVariationEditMode = (id) => {
    document.body.style.overflow = 'hidden';
    this.setState({
      variationEditMode: true,
      selectedVariationId: id,
    });
  };

  stopVariationEditMode = () => {
    document.body.style.overflow = '';
    this.setState({
      variationEditMode: false,
    });
  };

  render() {
    if (this.state.loadingMetadata && this.state.loadingVariations) {
      return
Loading …
;
    }

    const { component } = this.props;
    const selectedVariation =
      find(
        this.state.variationPropsList,
        (variationProps, key) => this.state.selectedVariationId === key
      );
    return (

          {getComponentNameFromPath(this.props.componentPath)}

        <button
          onClick={this.startCustomMetadataEditMode}
          style={{
            margin: '0 auto',
            display: 'block',
          }}
        >
          Edit Metadata
        </button>
        {/* METADATA EDIT MODE MODAL */}
        <Modal
          visible={this.state.customMetadataEditMode}
          onCloseClick={this.stopCustomMetadataEditMode}
        >
          <CustomMetadataForm
            customMetadata={this.state.customMetadata}
            parsedMetadata={this.props.meta}
            updateCustomMetadata={this.updateCustomMetadata}
          />
        </Modal>
        {/* VARIATION EDIT MODE MODAL */}
        {(this.state.selectedVariationId) && (
          <Modal
            visible={this.state.variationEditMode}
            onCloseClick={this.stopVariationEditMode}
          >

              <PropForm
                metadataWithControls={this.state.metadataWithControls}
                onVariationPropsChange={this.updateVariation}
                onRandomClick={this.randomiseEverything.bind(this, this.state.selectedVariationId)} // eslint-disable-line react/jsx-no-bind,max-len
                open={this.state.variationEditMode}
                variationPath={this.state.selectedVariationId}
                variationProps={selectedVariation.props}
              />
              <Playground
                component={component}
                fullHeight
                variationProps={selectedVariation.props}
                variationPath={this.state.selectedVariationId}
              />

          </Modal>
        )}
        {/* MAIN AREA WITH PLAYGROUNDS */}
        {map(this.state.variationPropsList, (variation, variationPath) => (
          <Playground
            key={variationPath}
            component={component}
            title={variation.name}
            variationProps={variation.props}
            variationPath={variationPath}
            onDeleteButtonClick={this.deleteVariation}
            onEditButtonClick={this.startVariationEditMode}
          />
        ))}
        <CreateVariationButton
          error={this.state.createVariationError}
          onSubmit={this.createVariation}
        />

    );
  }
}

export default PlaygroundList;
<|endoftext|>


<commit_before>import { useMoralis } from 'react-moralis';
import { navigate } from 'gatsby-link';

export function GuestbookAuth() {
  const { authenticate, logout, Moralis } = useMoralis();

  return {
    login: async () => {
      Moralis.Web3.getSigningData = () =>
        'Sign the web3 guestbook on iammatthias.com';
      try {
        await authenticate({
          provider: 'walletconnect',
          onComplete: () => {
            navigate('/guestbook');
          },
        });
      } catch (e) {
        console.error(e.message, e);
      }
    },
  };
}
<commit_msg>Add logout function in `onComplete`<commit_after>import { useMoralis } from 'react-moralis';
import { navigate } from 'gatsby-link';

export function GuestbookAuth() {
  const { authenticate, logout, Moralis } = useMoralis();

  return {
    login: async () => {
      Moralis.Web3.getSigningData = () =>
        'Sign the web3 guestbook on iammatthias.com';
      try {
        await authenticate({
          provider: 'walletconnect',
          onSuccess: () => {
            navigate('/guestbook');
            logout();
          },
        });
      } catch (e) {
        console.error(e.message, e);
      }
    },
  };
}
<|endoftext|>


<commit_before>
$.extend({
  ie:  jQuery.browser.msie,
  ie6: jQuery.browser.msie    && parseInt(jQuery.browser.version, 10) == 6,
  ie7: jQuery.browser.msie    && parseInt(jQuery.browser.version, 10) == 7,
  ie8: jQuery.browser.msie    && parseInt(jQuery.browser.version, 10) == 8,
  ff2: jQuery.browser.mozilla && parseFloat(jQuery.browser.version) < 1.9
});
<commit_msg>Removed white lines from assets/jzip/jquery/extensions/browser_detect.js<commit_after>$.extend({
  ie:  jQuery.browser.msie,
  ie6: jQuery.browser.msie    && parseInt(jQuery.browser.version, 10) == 6,
  ie7: jQuery.browser.msie    && parseInt(jQuery.browser.version, 10) == 7,
  ie8: jQuery.browser.msie    && parseInt(jQuery.browser.version, 10) == 8,
  ff2: jQuery.browser.mozilla && parseFloat(jQuery.browser.version) < 1.9
});<|endoftext|>