<commit_before>import React, {PropTypes} from 'react'
import {withRouter} from 'react-router'
import {connect} from 'react-redux'

import {NavBar, NavBlock, NavHeader, NavListItem} from 'src/side_nav/components/NavItems'

const {
  bool,
  shape,
  string,
} = PropTypes

const SideNav = React.createClass({
  propTypes: {
    params: shape({
      sourceID: string.isRequired,
    }).isRequired,
    location: shape({
      pathname: string.isRequired,
    }).isRequired,
    me: shape({
      email: string,
    }),
    isHidden: bool.isRequired,
  },

  render() {
    const {me, params: {sourceID}, location: {pathname: location}, isHidden} = this.props

    const sourcePrefix = `/sources/${sourceID}`
    const dataExplorerLink = `${sourcePrefix}/chronograf/data-explorer`
    const showLogout = !!(me && me.name)

    return isHidden ?
      null : (
      <NavBar location={location}>

        <NavBlock icon="cubo-node" link={`${sourcePrefix}/hosts`}>
          <NavHeader link={`${sourcePrefix}/hosts`} title="Host List" />
        </NavBlock>
        <NavBlock icon="graphline" link={dataExplorerLink}>
          <NavHeader link={dataExplorerLink} title="Data Explorer" />
        </NavBlock>
        <NavBlock icon="dash-h" link={`${sourcePrefix}/dashboards`}>
          <NavHeader link={`${sourcePrefix}/dashboards`} title={'Dashboards'} />
        </NavBlock>
        <NavBlock matcher="alerts" icon="alert-triangle" link={`${sourcePrefix}/alerts`}>
          <NavHeader link={`${sourcePrefix}/alerts`} title="Alerting" />
          <NavListItem link={`${sourcePrefix}/alerts`}>Alert History</NavListItem>
          <NavListItem link={`${sourcePrefix}/alert-rules`}>Kapacitor Rules</NavListItem>
        </NavBlock>
        <NavBlock icon="crown2" link={`${sourcePrefix}/admin`}>
          <NavHeader link={`${sourcePrefix}/admin`} title="Admin" />
        </NavBlock>
        <NavBlock icon="cog-thick" link={`${sourcePrefix}/manage-sources`}>
          <NavHeader link={`${sourcePrefix}/manage-sources`} title="Configuration" />
          <NavListItem link={`${sourcePrefix}/manage-sources`}>InfluxDB</NavListItem>
          <NavListItem link={`${sourcePrefix}/kapacitor-config`}>Kapacitor</NavListItem>
        </NavBlock>
        {
          showLogout ? (
          <NavBlock icon="user-outline" className="sidebar__square-last">
            Logout
          </NavBlock>
          ) :
          null
        }
      </NavBar>
    )
  },
})

const mapStateToProps = ({auth: {me}, app: {ephemeral: {inPresentationMode}}}) => ({
  me,
  isHidden: inPresentationMode,
})

export default connect(mapStateToProps)(withRouter(SideNav))
<commit_msg>remove navigation to kapacitor config app<commit_after>import React, {PropTypes} from 'react'
import {withRouter} from 'react-router'
import {connect} from 'react-redux'

import {NavBar, NavBlock, NavHeader, NavListItem} from 'src/side_nav/components/NavItems'

const {
  bool,
  shape,
  string,
} = PropTypes

const SideNav = React.createClass({
  propTypes: {
    params: shape({
      sourceID: string.isRequired,
    }).isRequired,
    location: shape({
      pathname: string.isRequired,
    }).isRequired,
    me: shape({
      email: string,
    }),
    isHidden: bool.isRequired,
  },

  render() {
    const {me, params: {sourceID}, location: {pathname: location}, isHidden} = this.props

    const sourcePrefix = `/sources/${sourceID}`
    const dataExplorerLink = `${sourcePrefix}/chronograf/data-explorer`
    const showLogout = !!(me && me.name)

    return isHidden ?
      null : (
      <NavBar location={location}>

        <NavBlock icon="cubo-node" link={`${sourcePrefix}/hosts`}>
          <NavHeader link={`${sourcePrefix}/hosts`} title="Host List" />
        </NavBlock>
        <NavBlock icon="graphline" link={dataExplorerLink}>
          <NavHeader link={dataExplorerLink} title="Data Explorer" />
        </NavBlock>
        <NavBlock icon="dash-h" link={`${sourcePrefix}/dashboards`}>
          <NavHeader link={`${sourcePrefix}/dashboards`} title={'Dashboards'} />
        </NavBlock>
        <NavBlock matcher="alerts" icon="alert-triangle" link={`${sourcePrefix}/alerts`}>
          <NavHeader link={`${sourcePrefix}/alerts`} title="Alerting" />
          <NavListItem link={`${sourcePrefix}/alerts`}>Alert History</NavListItem>
          <NavListItem link={`${sourcePrefix}/alert-rules`}>Kapacitor Rules</NavListItem>
        </NavBlock>
        <NavBlock icon="crown2" link={`${sourcePrefix}/admin`}>
          <NavHeader link={`${sourcePrefix}/admin`} title="Admin" />
        </NavBlock>
        <NavBlock icon="cog-thick" link={`${sourcePrefix}/manage-sources`}>
          <NavHeader link={`${sourcePrefix}/manage-sources`} title="Configuration" />
        </NavBlock>
        {
          showLogout ? (
          <NavBlock icon="user-outline" className="sidebar__square-last">
            Logout
          </NavBlock>
          ) :
          null
        }
      </NavBar>
    )
  },
})

const mapStateToProps = ({auth: {me}, app: {ephemeral: {inPresentationMode}}}) => ({
  me,
  isHidden: inPresentationMode,
})

export default connect(mapStateToProps)(withRouter(SideNav))
<|endoftext|>


<commit_before>'use strict';

/* jasmine specs for controllers go here */

describe('controllers', function() {

    beforeEach(function() {
        module('ownblock');
        module('ownblock.services');
        module('ownblock.controllers');
    });

    beforeEach(module('stateMock'));

    it('should maybe show a list of notices', inject(
        function($rootScope,
            $controller, _$httpBackend_) {
            var scope = $rootScope.$new(),
                httpBackend = _$httpBackend_;

            httpBackend.when('GET', '/api/notices/notices').
            respond(
                [{
                    id: 1,
                    title: 'test this sucka',
                    author: {
                        full_name: 'Tester'
                    }
                }]
            );
            $controller('notices.ListCtrl', {
                $scope: scope
            });

            httpBackend.flush();
            expect(scope.paginator.total).toBe(1);
        }));

});
<commit_msg>More js tests<commit_after>'use strict';

/* jasmine specs for controllers go here */

describe('controllers', function() {

    beforeEach(function() {
        module('ownblock');
        module('ownblock.services');
        module('ownblock.controllers');
    });

    beforeEach(module('stateMock'));

    it('should add a new notice', inject(
        function($rootScope, $controller, $state, _$httpBackend_) {
            var scope = $rootScope.$new(),
                httpBackend = _$httpBackend_,
                state = $state;

            httpBackend.when('POST', '/api/notices/notices').respond('OK');

            $controller('notices.NewCtrl', {
                $scope: scope
            });

            scope.save();
            state.expectTransitionTo('notices.list');

        }
    ));

    it('should show a single notice', inject(
        function($rootScope, $controller, _$httpBackend_) {

            var scope = $rootScope.$new(),
                httpBackend = _$httpBackend_,
                state = {
                    params: {
                        id: 1
                    }
                };

            httpBackend.when('GET', '/api/notices/notices/1').
            respond({
                id: 1,
                title: 'test',
                author: {
                    full_name: 'tester'
                }
            });
            $controller('notices.DetailCtrl', {
                $scope: scope,
                $state: state
            });
            httpBackend.flush();
            expect(scope.notice.title).toBe('test');
        }));

    it('should show a list of notices', inject(
        function($rootScope,
            $controller, _$httpBackend_) {
            var scope = $rootScope.$new(),
                httpBackend = _$httpBackend_;

            httpBackend.when('GET', '/api/notices/notices').
            respond(
                [{
                    id: 1,
                    title: 'test this sucka',
                    author: {
                        full_name: 'Tester'
                    }
                }]
            );
            $controller('notices.ListCtrl', {
                $scope: scope
            });

            httpBackend.flush();
            expect(scope.paginator.total).toBe(1);
        }));

});
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import PropTypes from "prop-types";
import ReactAudioPlayer from 'react-audio-player';
import axios from "axios";

class AvailableDatalist extends React.Component {
  render() {
    console.log("props during render songs")
    console.log(this.props)
    var ret = []
    if(this.props.songs[0] != 0){
      console.log("wenn songs inhalt hat")
      ret = this.props.songs.map(c => {

c.songName[0]

c.album

c.author

c.date

      })
    }else{
      console.log("wenn songs inhalt hat")
      ret[0] = "test"
    }

    return(
{ret}
)
  }
}

AvailableDatalist.propTypes = {
  songs: PropTypes.array.isRequired
};

class SongBoard extends React.Component {
state = {
  songs: [0:{name:"none", album:"none", author:"none"}]
};

componentDidMount() {
  axios
  .get("http://192.168.1.107:8000/album/")
  .then(response => {
    const songs = response.data.map(c => {

      return{
        songName: c.songs.map(d => {return(d.name)}),
        album: c.name,
        author: c.author,
        date: c.release_date
      };
    });

    const newState = Object.assign({}, this.state, {
          songs: songs
    });
    this.setState(newState);
    console.log("state after api request")
    console.log(this.state)

  })
  .catch(error => console.log(error));

}

  render() {

    return(

            <button className="song">
              Song
            </button>
            <button className="album">
              Album
            </button>

          <AvailableDatalist songs={this.state.songs}/> {/*songs={this.state.contacts}*/}

    )
  }
}

class Player extends React.Component {
  render() {
    return(
      <ReactAudioPlayer
        src="my_audio_file.ogg"
        autoPlay
        controls
      />
    )
  }
}

class Site extends React.Component {
  render() {
    return (

          <Player />

          <SongBoard />

    )
  }
}

ReactDOM.render(
  <Site />,
  document.getElementById('root')
);
<commit_msg>songs<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import PropTypes from "prop-types";
import ReactAudioPlayer from 'react-audio-player';
import axios from "axios";

class AvailableDatalist extends React.Component {
  render() {
    console.log("props during render songs")
    console.log(this.props)
    var ret = []
    if(this.props.songs[0] != 0){
      ret = this.props.songs.map(c => {

c.songName[0]

c.album

c.author

c.date

      })
    }else{
      ret[0] = "test"
    }
    console.log("ret nach bearbeitung")
    console.log(ret)
    return(
{ret}
)
  }
}

AvailableDatalist.propTypes = {
  songs: PropTypes.array.isRequired
};

class SongBoard extends React.Component {
state = {
  songs: [0:{name:"none", album:"none", author:"none"}]
};

componentDidMount() {
  axios
  .get("http://192.168.1.107:8000/album/")
  .then(response => {
    const songs = response.data.map(c => {

      return{
        songName: c.songs.map(d => {return(d.name)}),
        album: c.name,
        author: c.author,
        date: c.release_date
      };
    });

    const newState = Object.assign({}, this.state, {
          songs: songs
    });
    this.setState(newState);
    console.log("state after api request")
    console.log(this.state)

  })
  .catch(error => console.log(error));

}

  render() {

    return(

            <button className="song">
              Song
            </button>
            <button className="album">
              Album
            </button>

          <AvailableDatalist songs={this.state.songs}/> {/*songs={this.state.contacts}*/}

    )
  }
}

class Player extends React.Component {
  render() {
    return(
      <ReactAudioPlayer
        src="my_audio_file.ogg"
        autoPlay
        controls
      />
    )
  }
}

class Site extends React.Component {
  render() {
    return (

          <Player />

          <SongBoard />

    )
  }
}

ReactDOM.render(
  <Site />,
  document.getElementById('root')
);
<|endoftext|>


<commit_before>#!/usr/bin/env node
require("source-map-support/register");

const semver = require("semver"); // to validate Node version

const TruffleError = require("@truffle/error");
const TaskError = require("./lib/errors/taskerror");
const analytics = require("./lib/services/analytics");
const version = require("./lib/version");
const versionInfo = version.info();
const XRegExp = require("xregexp");

// pre-flight check: Node version compatibility
const minimumNodeVersion = "10.23.0";
if (!semver.satisfies(process.version, ">=" + minimumNodeVersion)) {
  console.log(
    "Error: Node version not supported. You are currently using version " +
      process.version.slice(1) +
      " of Node. Truffle requires Node v" +
      minimumNodeVersion +
      " or higher."
  );

  analytics.send({
    exception: "wrong node version",
    version: versionInfo.bundle || "(unbundled) " + versionInfo.core
  });

  process.exit(1);
}

const Command = require("./lib/command");

// enable Truffle to run both from the bundles out of packages/dist
// and using the raw JS directly - we inject BUNDLE_VERSION when building
const command =
  typeof BUNDLE_VERSION !== "undefined"
    ? new Command(require("./commands.bundled.js"))
    : new Command(require("./lib/commands"));

// This should be removed when issue is resolved upstream:
// https://github.com/ethereum/web3.js/issues/1648
const listeners = process.listeners("warning");
listeners.forEach(listener => process.removeListener("warning", listener));

let options = {logger: console};

const inputArguments = process.argv.slice(2);
const userWantsGeneralHelp =
  inputArguments.length === 1 && ["help", "--help"].includes(inputArguments[0]);

if (userWantsGeneralHelp) {
  command.displayGeneralHelp();
  process.exit(0);
}

command
  .run(inputArguments, options)
  .then((returnStatus) => {
    process.exit(returnStatus);
  })
  .catch(error => {
    if (error instanceof TaskError) {
      analytics.send({
        exception: "TaskError - display general help message",
        version: versionInfo.bundle
          ? versionInfo.bundle
          : "(unbundled) " + versionInfo.core
      });
      command.displayGeneralHelp();
    } else if (error instanceof TruffleError) {
      analytics.send({
        exception: "TruffleError - missing configuration file",
        version: versionInfo.bundle
          ? versionInfo.bundle
          : "(unbundled) " + versionInfo.core
      });
      console.log(error.message);
      version.logTruffleAndNode(options.logger);
    } else if (typeof error === "number") {
      analytics.send({
        exception: "Numbered Error - " + error,
        version: versionInfo.bundle
          ? versionInfo.bundle
          : "(unbundled) " + versionInfo.core
      });
      // If a number is returned, exit with that number.
      process.exit(error);
    } else {
      let errorData = error.stack || error.message || error.toString();
      //remove identifying information if error stack is passed to analytics
      if (errorData === error.stack) {
        const directory = __dirname;
        //making sure users' identifying information does not get sent to
        //analytics by cutting off everything before truffle. Will not properly catch the user's info
        //here if the user has truffle in their name.
        let identifyingInfo = String.raw`${directory.split("truffle")[0]}`;
        let removedInfo = new XRegExp(XRegExp.escape(identifyingInfo), "g");
        errorData = errorData.replace(removedInfo, "");
      }
      analytics.send({
        exception: "Other Error - " + errorData,
        version: versionInfo.bundle
          ? versionInfo.bundle
          : "(unbundled) " + versionInfo.core
      });
      // Bubble up all other unexpected errors.
      console.log(error.stack || error.message || error.toString());
      version.logTruffleAndNode(options.logger);
    };
    process.exit(1);
  });
<commit_msg>Use gte semver method instead of satisfies<commit_after>#!/usr/bin/env node
require("source-map-support/register");

const semver = require("semver"); // to validate Node version

const TruffleError = require("@truffle/error");
const TaskError = require("./lib/errors/taskerror");
const analytics = require("./lib/services/analytics");
const version = require("./lib/version");
const versionInfo = version.info();
const XRegExp = require("xregexp");

// pre-flight check: Node version compatibility
const minimumNodeVersion = "10.9.0";
if (!semver.gte(process.version, minimumNodeVersion)) {
  console.log(
    "Error: Node version not supported. You are currently using version " +
      process.version.slice(1) +
      " of Node. Truffle requires Node v" +
      minimumNodeVersion +
      " or higher."
  );

  analytics.send({
    exception: "wrong node version",
    version: versionInfo.bundle || "(unbundled) " + versionInfo.core
  });

  process.exit(1);
}

const Command = require("./lib/command");

// enable Truffle to run both from the bundles out of packages/dist
// and using the raw JS directly - we inject BUNDLE_VERSION when building
const command =
  typeof BUNDLE_VERSION !== "undefined"
    ? new Command(require("./commands.bundled.js"))
    : new Command(require("./lib/commands"));

// This should be removed when issue is resolved upstream:
// https://github.com/ethereum/web3.js/issues/1648
const listeners = process.listeners("warning");
listeners.forEach(listener => process.removeListener("warning", listener));

let options = {logger: console};

const inputArguments = process.argv.slice(2);
const userWantsGeneralHelp =
  inputArguments.length === 1 && ["help", "--help"].includes(inputArguments[0]);

if (userWantsGeneralHelp) {
  command.displayGeneralHelp();
  process.exit(0);
}

command
  .run(inputArguments, options)
  .then((returnStatus) => {
    process.exit(returnStatus);
  })
  .catch(error => {
    if (error instanceof TaskError) {
      analytics.send({
        exception: "TaskError - display general help message",
        version: versionInfo.bundle
          ? versionInfo.bundle
          : "(unbundled) " + versionInfo.core
      });
      command.displayGeneralHelp();
    } else if (error instanceof TruffleError) {
      analytics.send({
        exception: "TruffleError - missing configuration file",
        version: versionInfo.bundle
          ? versionInfo.bundle
          : "(unbundled) " + versionInfo.core
      });
      console.log(error.message);
      version.logTruffleAndNode(options.logger);
    } else if (typeof error === "number") {
      analytics.send({
        exception: "Numbered Error - " + error,
        version: versionInfo.bundle
          ? versionInfo.bundle
          : "(unbundled) " + versionInfo.core
      });
      // If a number is returned, exit with that number.
      process.exit(error);
    } else {
      let errorData = error.stack || error.message || error.toString();
      //remove identifying information if error stack is passed to analytics
      if (errorData === error.stack) {
        const directory = __dirname;
        //making sure users' identifying information does not get sent to
        //analytics by cutting off everything before truffle. Will not properly catch the user's info
        //here if the user has truffle in their name.
        let identifyingInfo = String.raw`${directory.split("truffle")[0]}`;
        let removedInfo = new XRegExp(XRegExp.escape(identifyingInfo), "g");
        errorData = errorData.replace(removedInfo, "");
      }
      analytics.send({
        exception: "Other Error - " + errorData,
        version: versionInfo.bundle
          ? versionInfo.bundle
          : "(unbundled) " + versionInfo.core
      });
      // Bubble up all other unexpected errors.
      console.log(error.stack || error.message || error.toString());
      version.logTruffleAndNode(options.logger);
    };
    process.exit(1);
  });
<|endoftext|>


<commit_before>import {keysIn} from './keysIn';
import {reduce} from '../list/reduce';

export const shallowClone =
  x => reduce(
    (acc, key) => (acc[key] = x[key], acc),
    {},
    keysIn(x)
  )
<commit_msg>refactor(shallowClone): simplified using Object.assign<commit_after>export const shallowClone =
  x => Object.assign({}, x);
<|endoftext|>


<commit_before>/**
 * Created by Oleg Rusak on 08.01.2017.
 */

'use strict';

const createDebug = require('debug')
const debug = createDebug("monad:sequence")
const debugDetailValue = createDebug("monad:sequence:value")
const util = require('util')

const srvDI = require('./monad-di-service');
const srvGeneral = require('./monad-general-service');

class AsyncSequenceService {

    static executeAsyncSequence (listOperation, settings, scope) {
        const promiseValueInit = Promise.resolve({});
        const strictMode = settings.codeExecuteMode;
        const handlerError = settings.handlerError;

        //  deep copy init scope data. for resolve collision with parallels change data object in scope.
        const _initScopeInit = scope ? srvGeneral.objectDeepCopy(scope) : {}
        const scopeInit = srvDI._initScope(_initScopeInit)

        const chainOperation = listOperation.reduce(function calculateSequence (value, operation, index) {
            const nameOperation = operation.inspect() || "Operation noname";

            const valueExecute = value
            //  todo: operation name, index
                .then(function (data) {
                    debugDetailValue(`          ${nameOperation} [${index}] start. Execute: %O`, data);
                    debugDetailValue(`          ${nameOperation} [${index}] start. Scope value: %O`, scopeInit);

                    return data
                })
                .then(AsyncSequenceService.executeOperation(operation, settings, scopeInit, index))
                .then(srvDI._updateScope(scopeInit, strictMode, operation.name, index))
                //  todo: operation name, index
                .then(function (data) {
                    debugDetailValue(`          ${nameOperation} [${index}] end. Result: %O`, data);
                    debugDetailValue(`          ${nameOperation} [${index}] end. Scope value: %O`, scopeInit);

                    return data
                })

            return valueExecute

        }, promiseValueInit);

        const chainOperationHandlerErrorInit = AsyncSequenceService.applyHandlerErrorCatch(chainOperation,
            handlerError, settings, scopeInit);

        return chainOperationHandlerErrorInit;
    }

    static executeOperation (operation, settings, scope, index) {
        //  action primitive type
        if (srvGeneral.isFunction(operation)) {
            //  action function
            return function executeOperationFunction (data) {

                return operation(data, scope, srvDI.initParameterAction.bind(null, data, scope))
            }
        }

        //  todo: problem circular require module monad for check instanseof operation
        //  operation instanceof require('./monad') - Error: Right-hand side of 'instanceof' is not callable
        if (Object.getPrototypeOf(operation).constructor.name === "MonadSequence") {

            return function executeOperationMonad () {
                const subMonadSequence = operation;
                const settingInheritParentMonad = {
                    codeExecuteMode: settings.codeExecuteMode,
                    debug: settings.debug
                }

                subMonadSequence.execute(settingInheritParentMonad, scope)

                return subMonadSequence.value()
            }
        }

        throw new Error(`Expect operation [${operation}(${typeof operation})] must be operation function or monad.sequence.`);
    }

    static applyHandlerErrorCatch (chain, handlerError, settings, scope) {
        const chainInit = chain.catch(function asyncErrorHandler (error) {
            debug("     Error execute operation");
            debugDetailValue("          Error execute operation. Error: %O. Scope: %O", error, scope);

            if (srvGeneral.isFunction(handlerError)) {
                return handlerError(error, settings, scope);
            }
        })

        return chainInit;
    }
}

module.exports = AsyncSequenceService;
<commit_msg>fix error operation function without inspection<commit_after>/**
 * Created by Oleg Rusak on 08.01.2017.
 */

'use strict';

const createDebug = require('debug')
const debug = createDebug("monad:sequence")
const debugDetailValue = createDebug("monad:sequence:value")
const util = require('util')

const srvDI = require('./monad-di-service');
const srvGeneral = require('./monad-general-service');

class AsyncSequenceService {

    static executeAsyncSequence (listOperation, settings, scope) {
        const promiseValueInit = Promise.resolve({});
        const strictMode = settings.codeExecuteMode;
        const handlerError = settings.handlerError;

        //  deep copy init scope data. for resolve collision with parallels change data object in scope.
        const _initScopeInit = scope ? srvGeneral.objectDeepCopy(scope) : {}
        const scopeInit = srvDI._initScope(_initScopeInit)

        const chainOperation = listOperation.reduce(function calculateSequence (value, operation, index) {
            const nameOperation = operation.inspect ? operation.inspect() : operation.name;

            const valueExecute = value
            //  todo: operation name, index
                .then(function (data) {
                    debugDetailValue(`          ${nameOperation} [${index}] start. Execute: %O`, data);
                    debugDetailValue(`          ${nameOperation} [${index}] start. Scope value: %O`, scopeInit);

                    return data
                })
                .then(AsyncSequenceService.executeOperation(operation, settings, scopeInit, index))
                .then(srvDI._updateScope(scopeInit, strictMode, operation.name, index))
                //  todo: operation name, index
                .then(function (data) {
                    debugDetailValue(`          ${nameOperation} [${index}] end. Result: %O`, data);
                    debugDetailValue(`          ${nameOperation} [${index}] end. Scope value: %O`, scopeInit);

                    return data
                })

            return valueExecute

        }, promiseValueInit);

        const chainOperationHandlerErrorInit = AsyncSequenceService.applyHandlerErrorCatch(chainOperation,
            handlerError, settings, scopeInit);

        return chainOperationHandlerErrorInit;
    }

    static executeOperation (operation, settings, scope, index) {
        //  action primitive type
        if (srvGeneral.isFunction(operation)) {
            //  action function
            return function executeOperationFunction (data) {

                return operation(data, scope, srvDI.initParameterAction.bind(null, data, scope))
            }
        }

        //  todo: problem circular require module monad for check instanseof operation
        //  operation instanceof require('./monad') - Error: Right-hand side of 'instanceof' is not callable
        if (Object.getPrototypeOf(operation).constructor.name === "MonadSequence") {

            return function executeOperationMonad () {
                const subMonadSequence = operation;
                const settingInheritParentMonad = {
                    codeExecuteMode: settings.codeExecuteMode,
                    debug: settings.debug
                }

                subMonadSequence.execute(settingInheritParentMonad, scope)

                return subMonadSequence.value()
            }
        }

        throw new Error(`Expect operation [${operation}(${typeof operation})] must be operation function or monad.sequence.`);
    }

    static applyHandlerErrorCatch (chain, handlerError, settings, scope) {
        const chainInit = chain.catch(function asyncErrorHandler (error) {
            debug("     Error execute operation");
            debugDetailValue("          Error execute operation. Error: %O. Scope: %O", error, scope);

            if (srvGeneral.isFunction(handlerError)) {
                return handlerError(error, settings, scope);
            }
        })

        return chainInit;
    }
}

module.exports = AsyncSequenceService;
<|endoftext|>


<commit_before>goog.provide('ol.control.FullScreen');

goog.require('goog.asserts');
goog.require('ol.events');
goog.require('ol.events.EventType');
goog.require('ol');
goog.require('ol.control.Control');
goog.require('ol.dom');
goog.require('ol.css');

/**
 * @classdesc
 * Provides a button that when clicked fills up the full screen with the map.
 * The full screen source element is by default the element containing the map viewport unless
 * overriden by providing the `source` option. In which case, the dom
 * element introduced using this parameter will be displayed in full screen.
 *
 * When in full screen mode, a close button is shown to exit full screen mode.
 * The [Fullscreen API](http://www.w3.org/TR/fullscreen/) is used to
 * toggle the map in full screen mode.
 *
 *
 * @constructor
 * @extends {ol.control.Control}
 * @param {olx.control.FullScreenOptions=} opt_options Options.
 * @api stable
 */
ol.control.FullScreen = function(opt_options) {

  var options = opt_options ? opt_options : {};

  /**
   * @private
   * @type {string}
   */
  this.cssClassName_ = options.className !== undefined ? options.className :
      'ol-full-screen';

  var label = options.label !== undefined ? options.label : '\u2922';

  /**
   * @private
   * @type {Node}
   */
  this.labelNode_ = typeof label === 'string' ?
      document.createTextNode(label) : label;

  var labelActive = options.labelActive !== undefined ? options.labelActive : '\u00d7';

  /**
   * @private
   * @type {Node}
   */
  this.labelActiveNode_ = typeof labelActive === 'string' ?
      document.createTextNode(labelActive) : labelActive;

  var tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
  var button = document.createElement('button');
  button.className = this.cssClassName_ + '-' + ol.control.FullScreen.isFullScreen();
  button.setAttribute('type', 'button');
  button.title = tipLabel;
  button.appendChild(this.labelNode_);

  ol.events.listen(button, ol.events.EventType.CLICK,
      this.handleClick_, this);

  var cssClasses = this.cssClassName_ + ' ' + ol.css.CLASS_UNSELECTABLE +
      ' ' + ol.css.CLASS_CONTROL + ' ' +
      (!ol.control.FullScreen.isFullScreenSupported() ? ol.css.CLASS_UNSUPPORTED : '');
  var element = document.createElement('div');
  element.className = cssClasses;
  element.appendChild(button);

  ol.control.Control.call(this, {
    element: element,
    target: options.target
  });

  /**
   * @private
   * @type {boolean}
   */
  this.keys_ = options.keys !== undefined ? options.keys : false;

  /**
   * @private
   * @type {Element|string|undefined}
   */
  this.source_ = options.source;

  /**
   * @private
   * @type {string|undefined}
   */
  this.changeType_ = undefined;

};
ol.inherits(ol.control.FullScreen, ol.control.Control);

/**
 * @param {Event} event The event to handle
 * @private
 */
ol.control.FullScreen.prototype.handleClick_ = function(event) {
  event.preventDefault();
  this.handleFullScreen_();
};

/**
 * @private
 */
ol.control.FullScreen.prototype.handleFullScreen_ = function() {
  if (!ol.control.FullScreen.isFullScreenSupported()) {
    return;
  }
  var map = this.getMap();
  if (!map) {
    return;
  }
  if (ol.control.FullScreen.isFullScreen()) {
    ol.control.FullScreen.exitFullScreen();
  } else {
    var element;
    if (this.source_) {
      element = typeof this.source_ === 'string' ?
        document.getElementById(this.source_) :
        this.source_;
    } else {
      element = map.getTargetElement();
    }
    goog.asserts.assert(element, 'element should be defined');
    if (this.keys_) {
      ol.control.FullScreen.requestFullScreenWithKeys(element);

    } else {
      ol.control.FullScreen.requestFullScreen(element);
    }
  }
};

/**
 * @private
 */
ol.control.FullScreen.prototype.handleFullScreenChange_ = function() {
  var button = this.element.firstElementChild;
  var map = this.getMap();
  if (ol.control.FullScreen.isFullScreen()) {
    button.className = this.cssClassName_ + '-true';
    ol.dom.replaceNode(this.labelActiveNode_, this.labelNode_);
  } else {
    button.className = this.cssClassName_ + '-false';
    ol.dom.replaceNode(this.labelNode_, this.labelActiveNode_);
  }
  if (map) {
    map.updateSize();
  }
};

/**
 * @inheritDoc
 * @api stable
 */
ol.control.FullScreen.prototype.setMap = function(map) {
  ol.control.Control.prototype.setMap.call(this, map);
  if (map) {
    if (!this.changeType_) {
      this.changeType_ = (function() {
        var body = document.body;
        if (body.webkitRequestFullscreen) {
          return 'webkitfullscreenchange';
        } else if (body.mozRequestFullScreen) {
          return 'mozfullscreenchange';
        } else if (body.msRequestFullscreen) {
          return 'MSFullscreenChange';
        } else if (body.requestFullscreen) {
          return 'fullscreenchange';
        }
        return undefined;
      })();
    }
    this.listenerKeys.push(
        ol.events.listen(ol.global.document, this.changeType_,
          this.handleFullScreenChange_, this)
    );
  }
};

/**
 * @return {boolean} Fullscreen is supported by the current platform.
 */
ol.control.FullScreen.isFullScreenSupported = function() {
  var body = document.body;
  return !!(
    body.webkitRequestFullscreen ||
    (body.mozRequestFullScreen && document.mozFullScreenEnabled) ||
    (body.msRequestFullscreen && document.msFullscreenEnabled) ||
    (body.requestFullscreen && document.fullscreenEnabled)
  );
};

/**
 * @return {boolean} Element is currently in fullscreen.
 */
ol.control.FullScreen.isFullScreen = function() {
  return !!(
    document.webkitIsFullScreen || document.mozFullScreen ||
    document.msFullscreenElement || document.fullscreenElement
  );
};

/**
 * Request to fullscreen an element.
 * @param {Node} element Element to request fullscreen
 */
ol.control.FullScreen.requestFullScreen = function(element) {
  if (element.requestFullscreen) {
    element.requestFullscreen();
  } else if (element.msRequestFullscreen) {
    element.msRequestFullscreen();
  } else if (element.mozRequestFullScreen) {
    element.mozRequestFullScreen();
  } else if (element.webkitRequestFullscreen) {
    element.webkitRequestFullscreen();
  }
};

/**
 * Request to fullscreen an element with keyboard input.
 * @param {Node} element Element to request fullscreen
 */
ol.control.FullScreen.requestFullScreenWithKeys = function(element) {
  if (element.mozRequestFullScreenWithKeys) {
    element.mozRequestFullScreenWithKeys();
  } else if (element.webkitRequestFullscreen) {
    element.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
  } else {
    ol.control.FullScreen.requestFullScreen(element);
  }
};

/**
 * Exit fullscreen.
 */
ol.control.FullScreen.exitFullScreen = function() {
  if (document.exitFullscreen) {
    document.exitFullscreen();
  } else if (document.msExitFullscreen) {
    document.msExitFullscreen();
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen();
  } else if (document.webkitExitFullscreen) {
    document.webkitExitFullscreen();
  }
};
<commit_msg>Create a dedicated function to changeType.<commit_after>goog.provide('ol.control.FullScreen');

goog.require('goog.asserts');
goog.require('ol.events');
goog.require('ol.events.EventType');
goog.require('ol');
goog.require('ol.control.Control');
goog.require('ol.dom');
goog.require('ol.css');

/**
 * @classdesc
 * Provides a button that when clicked fills up the full screen with the map.
 * The full screen source element is by default the element containing the map viewport unless
 * overriden by providing the `source` option. In which case, the dom
 * element introduced using this parameter will be displayed in full screen.
 *
 * When in full screen mode, a close button is shown to exit full screen mode.
 * The [Fullscreen API](http://www.w3.org/TR/fullscreen/) is used to
 * toggle the map in full screen mode.
 *
 *
 * @constructor
 * @extends {ol.control.Control}
 * @param {olx.control.FullScreenOptions=} opt_options Options.
 * @api stable
 */
ol.control.FullScreen = function(opt_options) {

  var options = opt_options ? opt_options : {};

  /**
   * @private
   * @type {string}
   */
  this.cssClassName_ = options.className !== undefined ? options.className :
      'ol-full-screen';

  var label = options.label !== undefined ? options.label : '\u2922';

  /**
   * @private
   * @type {Node}
   */
  this.labelNode_ = typeof label === 'string' ?
      document.createTextNode(label) : label;

  var labelActive = options.labelActive !== undefined ? options.labelActive : '\u00d7';

  /**
   * @private
   * @type {Node}
   */
  this.labelActiveNode_ = typeof labelActive === 'string' ?
      document.createTextNode(labelActive) : labelActive;

  var tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
  var button = document.createElement('button');
  button.className = this.cssClassName_ + '-' + ol.control.FullScreen.isFullScreen();
  button.setAttribute('type', 'button');
  button.title = tipLabel;
  button.appendChild(this.labelNode_);

  ol.events.listen(button, ol.events.EventType.CLICK,
      this.handleClick_, this);

  var cssClasses = this.cssClassName_ + ' ' + ol.css.CLASS_UNSELECTABLE +
      ' ' + ol.css.CLASS_CONTROL + ' ' +
      (!ol.control.FullScreen.isFullScreenSupported() ? ol.css.CLASS_UNSUPPORTED : '');
  var element = document.createElement('div');
  element.className = cssClasses;
  element.appendChild(button);

  ol.control.Control.call(this, {
    element: element,
    target: options.target
  });

  /**
   * @private
   * @type {boolean}
   */
  this.keys_ = options.keys !== undefined ? options.keys : false;

  /**
   * @private
   * @type {Element|string|undefined}
   */
  this.source_ = options.source;

};
ol.inherits(ol.control.FullScreen, ol.control.Control);

/**
 * @param {Event} event The event to handle
 * @private
 */
ol.control.FullScreen.prototype.handleClick_ = function(event) {
  event.preventDefault();
  this.handleFullScreen_();
};

/**
 * @private
 */
ol.control.FullScreen.prototype.handleFullScreen_ = function() {
  if (!ol.control.FullScreen.isFullScreenSupported()) {
    return;
  }
  var map = this.getMap();
  if (!map) {
    return;
  }
  if (ol.control.FullScreen.isFullScreen()) {
    ol.control.FullScreen.exitFullScreen();
  } else {
    var element;
    if (this.source_) {
      element = typeof this.source_ === 'string' ?
        document.getElementById(this.source_) :
        this.source_;
    } else {
      element = map.getTargetElement();
    }
    goog.asserts.assert(element, 'element should be defined');
    if (this.keys_) {
      ol.control.FullScreen.requestFullScreenWithKeys(element);

    } else {
      ol.control.FullScreen.requestFullScreen(element);
    }
  }
};

/**
 * @private
 */
ol.control.FullScreen.prototype.handleFullScreenChange_ = function() {
  var button = this.element.firstElementChild;
  var map = this.getMap();
  if (ol.control.FullScreen.isFullScreen()) {
    button.className = this.cssClassName_ + '-true';
    ol.dom.replaceNode(this.labelActiveNode_, this.labelNode_);
  } else {
    button.className = this.cssClassName_ + '-false';
    ol.dom.replaceNode(this.labelNode_, this.labelActiveNode_);
  }
  if (map) {
    map.updateSize();
  }
};

/**
 * @inheritDoc
 * @api stable
 */
ol.control.FullScreen.prototype.setMap = function(map) {
  ol.control.Control.prototype.setMap.call(this, map);
  if (map) {
    this.listenerKeys.push(ol.events.listen(ol.global.document,
        ol.control.FullScreen.getChangeType_(),
        this.handleFullScreenChange_, this)
    );
  }
};

/**
 * @return {boolean} Fullscreen is supported by the current platform.
 */
ol.control.FullScreen.isFullScreenSupported = function() {
  var body = document.body;
  return !!(
    body.webkitRequestFullscreen ||
    (body.mozRequestFullScreen && document.mozFullScreenEnabled) ||
    (body.msRequestFullscreen && document.msFullscreenEnabled) ||
    (body.requestFullscreen && document.fullscreenEnabled)
  );
};

/**
 * @return {boolean} Element is currently in fullscreen.
 */
ol.control.FullScreen.isFullScreen = function() {
  return !!(
    document.webkitIsFullScreen || document.mozFullScreen ||
    document.msFullscreenElement || document.fullscreenElement
  );
};

/**
 * Request to fullscreen an element.
 * @param {Node} element Element to request fullscreen
 */
ol.control.FullScreen.requestFullScreen = function(element) {
  if (element.requestFullscreen) {
    element.requestFullscreen();
  } else if (element.msRequestFullscreen) {
    element.msRequestFullscreen();
  } else if (element.mozRequestFullScreen) {
    element.mozRequestFullScreen();
  } else if (element.webkitRequestFullscreen) {
    element.webkitRequestFullscreen();
  }
};

/**
 * Request to fullscreen an element with keyboard input.
 * @param {Node} element Element to request fullscreen
 */
ol.control.FullScreen.requestFullScreenWithKeys = function(element) {
  if (element.mozRequestFullScreenWithKeys) {
    element.mozRequestFullScreenWithKeys();
  } else if (element.webkitRequestFullscreen) {
    element.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
  } else {
    ol.control.FullScreen.requestFullScreen(element);
  }
};

/**
 * Exit fullscreen.
 */
ol.control.FullScreen.exitFullScreen = function() {
  if (document.exitFullscreen) {
    document.exitFullscreen();
  } else if (document.msExitFullscreen) {
    document.msExitFullscreen();
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen();
  } else if (document.webkitExitFullscreen) {
    document.webkitExitFullscreen();
  }
};

/**
 * @return {string} Change type.
 * @private
 */
ol.control.FullScreen.getChangeType_ = (function() {
  var changeType;
  return function() {
    if (!changeType) {
      var body = document.body;
      if (body.webkitRequestFullscreen) {
        changeType = 'webkitfullscreenchange';
      } else if (body.mozRequestFullScreen) {
        changeType = 'mozfullscreenchange';
      } else if (body.msRequestFullscreen) {
        changeType = 'MSFullscreenChange';
      } else if (body.requestFullscreen) {
        changeType = 'fullscreenchange';
      }
    }
    return changeType;
  };
})();
<|endoftext|>


<commit_before>import React, { Component, Fragment } from 'react'
import ErrorPage from 'components/admin/ErrorPage'
import LoadingBar from 'components/LoadingBar'
import Login from 'components/auth/Login'
import Helmet from 'react-helmet'
import Nav from 'components/apply/ApplyNav'
import Fuse from 'fuse.js'
import Chart from 'components/admin/operations/CheckInChart'
import { timeSince, formatDate } from 'helpers'
import {
  Text,
  Card,
  Container,
  Link,
  Icon,
  Flex,
  Box,
  Field,
  Heading
} from '@hackclub/design-system'
import api from 'api'

const FlexCardLink = Card.withComponent('a').extend`
  display: flex;
  align-items: center;

  div {
    flex: 1 1 auto;
  }
`

class ClubCard extends Component {
  state = {
    status: 'loading'
  }

  componentDidMount() {
    api
      .get(`v1/new_clubs/${this.props.id}/dumb_check_ins`)
      .then(checkIns => {
        this.setState({ status: 'success', checkIns })
      })
      .catch(err => {
        this.setState({ status: 'error' })
      })
  }

  mostRecentCheckin() {
    const { checkIns } = this.state
    if (checkIns.length > 0) {
      let mostRecentUpdate = new Date(checkIns[0].created_at)
      checkIns.forEach(checkIn => {
        mostRecentUpdate = new Date(
          Math.max(new Date(checkIn.created_at), mostRecentUpdate)
        )
      })
      const daysSinceCheckIn =
        (new Date() - mostRecentUpdate) / (24 * 60 * 60 * 1000)
      let textColor = 'gray.4'
      if (daysSinceCheckIn < 7) {
        textColor = 'gray.8'
      } else if (daysSinceCheckIn < 14) {
        textColor = 'accent'
      } else if (daysSinceCheckIn < 21) {
        textColor = 'warning'
      } else {
        textColor = 'error'
      }
      const checkInData = checkIns.slice(0, 6).map(checkIn => ({
        y: checkIn.attendance || 0,
        x: formatDate('mmm dd', checkIn.meeting_date)
      }))
      return (
        <Fragment>
          <Text color={textColor} f={1}>
            Last checked-in {timeSince(mostRecentUpdate)} ago
          </Text>
          <Flex mt={3}>
            {checkIns.length > 1 && <Chart data={checkInData} />}
          </Flex>
        </Fragment>
      )
    } else {
      return (
        <Text f={1} color="muted">
          Never checked in
        </Text>
      )
    }
  }

  renderSwitch() {
    const { status, checkIns } = this.state
    switch (status) {
      case 'success':
        return this.mostRecentCheckin()
      case 'loading':
        return <LoadingBar />
      default:
        return '⚠ Something broke ⚠'
    }
  }

  render() {
    if (!this.props.visible) return null
    return (
      <FlexCardLink
        boxShadowSize="sm"
        p={[2, 3]}
        m={3}
        f={3}
        href={`/admin/operations/club?id=${this.props.id}`}
      >
        <Box align="left" mr={3}>
          <Text bold color="black">
            {this.props.high_school_name}
          </Text>
          <Text color="slate" f={1}>
            {this.props.new_leaders.map((leader, index) => (
              <Fragment key={leader.id}>
                <Text.span>{leader.name}</Text.span>
                {this.props.new_leaders.length - 1 > index && ', '}
              </Fragment>
            ))}
          </Text>
          {this.renderSwitch()}
        </Box>
        <Icon name="chevron_right" color="info" />
      </FlexCardLink>
    )
  }
}

export default class extends Component {
  state = {
    status: 'loading',
    searchQuery: '',
    queryUpdatedAt: null
  }

  componentDidMount() {
    api
      .currentUser()
      .then(user => {
        api.get(`v1/new_clubs/owned`).then(clubs => {
          this.setState({ user, clubs, status: 'success' })
        })
      })
      .catch(err => {
        switch (err.status) {
          case 401:
          case 403:
            this.setState({ status: 'needsToAuth' })
            break
          default:
            this.setState({ status: 'error' })
            break
        }
      })
  }

  handleChange(e) {
    this.setState({ searchQuery: e.target.value, queryUpdatedAt: Date.now() })
  }

  render() {
    const { status, clubs, searchQuery } = this.state
    switch (status) {
      case 'loading':
        return <LoadingBar fill />
      case 'success':
        const fuse = new Fuse(clubs, {
          threshold: 0.4,
          keys: ['high_school_name', 'new_leaders.name', 'new_leaders.email']
        })
        const visibleClubIds = fuse.search(searchQuery).map(club => club.id)
        return (
          <Fragment>
            <Helmet title="🛠 Dumb Operations Dashboard – Hack Club" />
            <Nav />
            <Container maxWidth={32}>
              {clubs.length > 8 && (
                <Field
                  placeholder="Search by high school or leaders"
                  value={searchQuery}
                  onChange={e => this.handleChange(e)}
                  mt={5}
                />
              )}
              <Box mx={-3}>
                {clubs.map(club => (
                  <ClubCard
                    {...club}
                    key={club.id}
                    visible={
                      searchQuery === '' ||
                      visibleClubIds.indexOf(club.id) !== -1
                    }
                  />
                ))}
              </Box>
            </Container>
          </Fragment>
        )
      case 'needsToAuth':
        return <Login userType="owner" />
      case 'error':
      default:
        return <ErrorPage />
    }
  }
}
<commit_msg>Remove redundant word<commit_after>import React, { Component, Fragment } from 'react'
import ErrorPage from 'components/admin/ErrorPage'
import LoadingBar from 'components/LoadingBar'
import Login from 'components/auth/Login'
import Helmet from 'react-helmet'
import Nav from 'components/apply/ApplyNav'
import Fuse from 'fuse.js'
import Chart from 'components/admin/operations/CheckInChart'
import { timeSince, formatDate } from 'helpers'
import {
  Text,
  Card,
  Container,
  Link,
  Icon,
  Flex,
  Box,
  Field,
  Heading
} from '@hackclub/design-system'
import api from 'api'

const FlexCardLink = Card.withComponent('a').extend`
  display: flex;
  align-items: center;

  div {
    flex: 1 1 auto;
  }
`

class ClubCard extends Component {
  state = {
    status: 'loading'
  }

  componentDidMount() {
    api
      .get(`v1/new_clubs/${this.props.id}/dumb_check_ins`)
      .then(checkIns => {
        this.setState({ status: 'success', checkIns })
      })
      .catch(err => {
        this.setState({ status: 'error' })
      })
  }

  mostRecentCheckin() {
    const { checkIns } = this.state
    if (checkIns.length > 0) {
      let mostRecentUpdate = new Date(checkIns[0].created_at)
      checkIns.forEach(checkIn => {
        mostRecentUpdate = new Date(
          Math.max(new Date(checkIn.created_at), mostRecentUpdate)
        )
      })
      const daysSinceCheckIn =
        (new Date() - mostRecentUpdate) / (24 * 60 * 60 * 1000)
      let textColor = 'gray.4'
      if (daysSinceCheckIn < 7) {
        textColor = 'gray.8'
      } else if (daysSinceCheckIn < 14) {
        textColor = 'accent'
      } else if (daysSinceCheckIn < 21) {
        textColor = 'warning'
      } else {
        textColor = 'error'
      }
      const checkInData = checkIns.slice(0, 6).map(checkIn => ({
        y: checkIn.attendance || 0,
        x: formatDate('mmm dd', checkIn.meeting_date)
      }))
      return (
        <Fragment>
          <Text color={textColor} f={1}>
            Last checked-in {timeSince(mostRecentUpdate)}
          </Text>
          <Flex mt={3}>
            {checkIns.length > 1 && <Chart data={checkInData} />}
          </Flex>
        </Fragment>
      )
    } else {
      return (
        <Text f={1} color="muted">
          Never checked in
        </Text>
      )
    }
  }

  renderSwitch() {
    const { status, checkIns } = this.state
    switch (status) {
      case 'success':
        return this.mostRecentCheckin()
      case 'loading':
        return <LoadingBar />
      default:
        return '⚠ Something broke ⚠'
    }
  }

  render() {
    if (!this.props.visible) return null
    return (
      <FlexCardLink
        boxShadowSize="sm"
        p={[2, 3]}
        m={3}
        f={3}
        href={`/admin/operations/club?id=${this.props.id}`}
      >
        <Box align="left" mr={3}>
          <Text bold color="black">
            {this.props.high_school_name}
          </Text>
          <Text color="slate" f={1}>
            {this.props.new_leaders.map((leader, index) => (
              <Fragment key={leader.id}>
                <Text.span>{leader.name}</Text.span>
                {this.props.new_leaders.length - 1 > index && ', '}
              </Fragment>
            ))}
          </Text>
          {this.renderSwitch()}
        </Box>
        <Icon name="chevron_right" color="info" />
      </FlexCardLink>
    )
  }
}

export default class extends Component {
  state = {
    status: 'loading',
    searchQuery: '',
    queryUpdatedAt: null
  }

  componentDidMount() {
    api
      .currentUser()
      .then(user => {
        api.get(`v1/new_clubs/owned`).then(clubs => {
          this.setState({ user, clubs, status: 'success' })
        })
      })
      .catch(err => {
        switch (err.status) {
          case 401:
          case 403:
            this.setState({ status: 'needsToAuth' })
            break
          default:
            this.setState({ status: 'error' })
            break
        }
      })
  }

  handleChange(e) {
    this.setState({ searchQuery: e.target.value, queryUpdatedAt: Date.now() })
  }

  render() {
    const { status, clubs, searchQuery } = this.state
    switch (status) {
      case 'loading':
        return <LoadingBar fill />
      case 'success':
        const fuse = new Fuse(clubs, {
          threshold: 0.4,
          keys: ['high_school_name', 'new_leaders.name', 'new_leaders.email']
        })
        const visibleClubIds = fuse.search(searchQuery).map(club => club.id)
        return (
          <Fragment>
            <Helmet title="🛠 Dumb Operations Dashboard – Hack Club" />
            <Nav />
            <Container maxWidth={32}>
              {clubs.length > 8 && (
                <Field
                  placeholder="Search by high school or leaders"
                  value={searchQuery}
                  onChange={e => this.handleChange(e)}
                  mt={5}
                />
              )}
              <Box mx={-3}>
                {clubs.map(club => (
                  <ClubCard
                    {...club}
                    key={club.id}
                    visible={
                      searchQuery === '' ||
                      visibleClubIds.indexOf(club.id) !== -1
                    }
                  />
                ))}
              </Box>
            </Container>
          </Fragment>
        )
      case 'needsToAuth':
        return <Login userType="owner" />
      case 'error':
      default:
        return <ErrorPage />
    }
  }
}
<|endoftext|>


<commit_before>/**
* Styleswitch stylesheet switcher built on jQuery
* Under an Attribution, Share Alike License
* By Kelvin Luck ( http://www.kelvinluck.com/ )
**/

(function($)
{
	$(document).ready(function() {
		$('.styleswitch').click(function()
		{
			switchStylestyle(this.getAttribute("rel"));
			return false;
		});
		var c = readCookie('style');
		if (c) switchStylestyle(c);
	});

	function switchStylestyle(styleName)
	{
		$('link[@rel*=style][title]').each(function(i)
		{
			this.disabled = true;
			if (this.getAttribute('title') == styleName) this.disabled = false;
		});
		createCookie('style', styleName, 365);
	}
})(jQuery);
// cookie functions http://www.quirksmode.org/js/cookies.html
function createCookie(name,value,days)
{
	if (days)
	{
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}
function readCookie(name)
{
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++)
	{
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}
function eraseCookie(name)
{
	createCookie(name,"",-1);
}
// /cookie functions<commit_msg>Delete switcher.js<commit_after><|endoftext|>


<commit_before>import gitRawCommits from 'git-raw-commits'
import gitLatestTag from 'git-latest-semver-tag'
import commitsParser from 'conventional-commits-parser'
import commitsFilter from 'conventional-commits-filter'
import concat from 'concat-stream'
import { forEach, separator, log, clear } from '../../util'

function incrementName (code) {
  switch (code) {
    case 1: return 'patch'
    case 2: return 'minor'
    case 3: return 'major'
    default: return ''
  }
}

export const checkRelease = function (packages) {
  const status = {}

  packages.forEach(function (packageName) {
    status[packageName] = {
      increment: 0, // 0 = nothing, 1 = patch, 2 = minor, 3 = major
      commits: []
    }
  })

  return latestTag()
    .catch(err => console.log(err))
    .then(rawCommits)
    .catch(() => {
      showReportHeaderNegative()
      console.log(separator())
    })
    .then((commits) => getStatus(packages, commits))
    .then((status) => {
      const packageNames = Object.keys(status)

      let headerShown = false
      forEach(packageNames, function (packageName) {
        if (status[packageName].increment > 0) {
          if (!headerShown) {
            showReportHeaderPositive()
            headerShown = true
          }

          log('`' + packageName + '` needs a new ' +
            incrementName(status[packageName].increment).toUpperCase() +
            ' version released because:')

          forEach(status[packageName].commits, function (commit) {
            log('  - ' + commit.header)
            if (isCommitBreakingChange(commit)) {
              log('    BREAKING CHANGE')
            }
          })
        }
      })

      console.log(separator())
      return status
    })
}

export function isCommitBreakingChange (commit) {
  return (typeof commit.footer === 'string' &&
    commit.footer.indexOf('BREAKING CHANGE') !== -1)
}

export function getStatus (packages, commits) {
  const status = {}

  forEach(packages, function (packageName) {
    status[packageName] = {
      increment: 0, // 0 = nothing, 1 = patch, 2 = minor, 3 = major
      commits: []
    }
  })

  for (let i = commits.length - 1; i >= 0; --i) {
    const commit = commits[i]

    if (packages.indexOf(commit.scope) === -1) continue

    const packageName = commit.scope
    let toPush = null
    if (commit.type === 'fix' || commit.type === 'perf') {
      status[packageName].increment = Math.max(status[packageName].increment, 1)
      toPush = commit
    }
    if (commit.type === 'feat') {
      status[packageName].increment = Math.max(status[packageName].increment, 2)
      toPush = commit
    }
    if (isCommitBreakingChange(commit)) {
      status[packageName].increment = Math.max(status[packageName].increment, 3)
      toPush = commit
    }
    if (toPush) {
      status[packageName].commits.push(commit)
    }
    if (commit.type === 'release') {
      status[packageName].increment = 0
      status[packageName].commits = []
    }
  }

  return status
}

export function latestTag () {
  return new Promise((resolve, reject) => {
    gitLatestTag((err, tag) => {
      if (err) reject(err)
      else resolve(tag)
    })
  })
}

export function rawCommits (tag) {
  return new Promise((resolve, reject) => {
    gitRawCommits({ format: '%B%n-hash-%n%H', from: tag })
      .pipe(commitsParser())
      .pipe(concat(function (data) {
        console.log(data)
        const commits = commitsFilter(data)
        if (!commits || !commits.length) {
          reject(null)
        } else {
          resolve(commits)
        }
      }))
  })
}

function showReportHeaderPositive () {
  clear()
  console.log(separator())
  log('RELEASES TO DO\n\n' +
      '    We checked all packages and recent commits, and discovered that\n' +
      '    according to semver.org you should release new versions for the\n' +
      '    following packages.\n')
}

function showReportHeaderNegative () {
  clear()
  console.log(separator())
  log('Nothing to release.\n\n' +
      '    We checked all packages and recent commits, and discovered that\n' +
      '    you do not need to release any new version, according to semver.org.')
}
<commit_msg>fix(northbrook): remove unneeded console.log<commit_after>import gitRawCommits from 'git-raw-commits'
import gitLatestTag from 'git-latest-semver-tag'
import commitsParser from 'conventional-commits-parser'
import commitsFilter from 'conventional-commits-filter'
import concat from 'concat-stream'
import { forEach, separator, log, clear } from '../../util'

function incrementName (code) {
  switch (code) {
    case 1: return 'patch'
    case 2: return 'minor'
    case 3: return 'major'
    default: return ''
  }
}

export const checkRelease = function (packages) {
  const status = {}

  packages.forEach(function (packageName) {
    status[packageName] = {
      increment: 0, // 0 = nothing, 1 = patch, 2 = minor, 3 = major
      commits: []
    }
  })

  return latestTag()
    .catch(err => console.log(err))
    .then(rawCommits)
    .catch(() => {
      showReportHeaderNegative()
      console.log(separator())
    })
    .then((commits) => getStatus(packages, commits))
    .then((status) => {
      const packageNames = Object.keys(status)

      let headerShown = false
      forEach(packageNames, function (packageName) {
        if (status[packageName].increment > 0) {
          if (!headerShown) {
            showReportHeaderPositive()
            headerShown = true
          }

          log('`' + packageName + '` needs a new ' +
            incrementName(status[packageName].increment).toUpperCase() +
            ' version released because:')

          forEach(status[packageName].commits, function (commit) {
            log('  - ' + commit.header)
            if (isCommitBreakingChange(commit)) {
              log('    BREAKING CHANGE')
            }
          })
        }
      })

      console.log(separator())
      return status
    })
}

export function isCommitBreakingChange (commit) {
  return (typeof commit.footer === 'string' &&
    commit.footer.indexOf('BREAKING CHANGE') !== -1)
}

export function getStatus (packages, commits) {
  const status = {}

  forEach(packages, function (packageName) {
    status[packageName] = {
      increment: 0, // 0 = nothing, 1 = patch, 2 = minor, 3 = major
      commits: []
    }
  })

  for (let i = commits.length - 1; i >= 0; --i) {
    const commit = commits[i]

    if (packages.indexOf(commit.scope) === -1) continue

    const packageName = commit.scope
    let toPush = null
    if (commit.type === 'fix' || commit.type === 'perf') {
      status[packageName].increment = Math.max(status[packageName].increment, 1)
      toPush = commit
    }
    if (commit.type === 'feat') {
      status[packageName].increment = Math.max(status[packageName].increment, 2)
      toPush = commit
    }
    if (isCommitBreakingChange(commit)) {
      status[packageName].increment = Math.max(status[packageName].increment, 3)
      toPush = commit
    }
    if (toPush) {
      status[packageName].commits.push(commit)
    }
    if (commit.type === 'release') {
      status[packageName].increment = 0
      status[packageName].commits = []
    }
  }

  return status
}

export function latestTag () {
  return new Promise((resolve, reject) => {
    gitLatestTag((err, tag) => {
      if (err) reject(err)
      else resolve(tag)
    })
  })
}

export function rawCommits (tag) {
  return new Promise((resolve, reject) => {
    gitRawCommits({ format: '%B%n-hash-%n%H', from: tag })
      .pipe(commitsParser())
      .pipe(concat(function (data) {
        const commits = commitsFilter(data)
        if (!commits || !commits.length) {
          reject(null)
        } else {
          resolve(commits)
        }
      }))
  })
}

function showReportHeaderPositive () {
  clear()
  console.log(separator())
  log('RELEASES TO DO\n\n' +
      '    We checked all packages and recent commits, and discovered that\n' +
      '    according to semver.org you should release new versions for the\n' +
      '    following packages.\n')
}

function showReportHeaderNegative () {
  clear()
  console.log(separator())
  log('Nothing to release.\n\n' +
      '    We checked all packages and recent commits, and discovered that\n' +
      '    you do not need to release any new version, according to semver.org.')
}
<|endoftext|>


<commit_before>/***
|''Name''|TiddlySpaceInclusion|
|''Version''|0.5.0|
|''Description''|provides user interfaces for managing TiddlySpace inclusions|
|''Status''|@@beta@@|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/raw/master/src/plugins/TiddlySpaceInclusion.js|
|''Requires''|TiddlySpaceConfig TiddlySpaceUserControls chrjs|
!HTMLForm
<form action="#">
	<fieldset>
		<legend />

Space Name:

<input type="text" name="space" />

Space Selection:

				<select>
					<option></option>
				</select>

		<input type="submit" />
	</fieldset>
</form>
!Code
***/
//{{{
(function($) {

var host = config.extensions.tiddlyweb.host;
var currentSpace = config.extensions.tiddlyspace.currentSpace.name;

var macro = config.macros.TiddlySpaceInclusion = {
	formTemplate: store.getTiddlerText(tiddler.title + "##HTMLForm"),
	locale: {
		addPassiveLabel: "Include space",
		addActiveLabel: "Include into space",
		passiveDesc: "Include a space into the current space",
		activeDesc: "Include another space in the current space",
		addSuccess: "included %0 in %1",
		delPrompt: "Are you sure you want to exclude %0 from the current space?",
		delTooltip: "click to exclude from the space",
		delError: "error excluding %0: %1",
		listError: "error retrieving spaces included in space %0: %1",
		forbiddenError: "unauthorized to modify space %0",
		noSpaceError: "space %0 does not exist",
		conflictError: "space %0 is already included in %1",
		noInclusions: "no spaces are included",
		recursiveInclusions: "Spaces included by the removed space are highlighted and should be removed manually.",
		reloadPrompt: "The page must be reloaded for inclusion to take effect. Reload now?"
	},

	handler: function(place, macroName, params, wikifier, paramString, tiddler) {
		// passive mode means subscribing given space to current space
		// active mode means subscribing current space to given space
		this.name = macroName;
		var mode = params[0] || "list";
		var form = $(this.formTemplate).
			find(".annotation").hide().end();
		if(mode == "passive") {
			if(!readOnly) {
				form.submit(function(ev) { return macro.onSubmit(this, mode); }).
					find("._active").remove().end().
					find("legend").text(this.locale.addPassiveLabel).end().
					find(".description").text(this.locale.passiveDesc).end().
					find("[type=submit]").val(this.locale.addPassiveLabel).end().
					appendTo(place);
			}
		} else if(mode == "active") {
			form.submit(function(ev) { return macro.onSubmit(this, mode); }).
				find("._passive").remove().end().
				find("legend").text(this.locale.addActiveLabel).end().
				find(".description").text(this.locale.activeDesc).end().
				find("[type=submit]").val(this.locale.addActiveLabel).end().
				appendTo(place);
			this.populateSpaces(form);
		} else {
			var container = $("
").addClass(this.name).appendTo(place);
			$('
').hide().appendTo(container);
			this.listInclusions(container);
		}
	},
	listInclusions: function(container) {
		var recipe = new tiddlyweb.Recipe(currentSpace + "_public", host);
		recipe.get(function(recipe, status, xhr) {
			var inclusions = $.map(recipe.recipe, function(item, i) { // TODO: refactor to canonicalize; move to TiddlySpaceConfig!?
				var arr = item[0].split("_public");
				return (arr[0] != currentSpace && arr[1] === "") ? arr[0] : null;
			});
			var items = $.map(inclusions, function(item, i) { // TODO: DRY (cf. displayMembers)
				var link = $('').text(item); // TODO: link to space
				var btn = $('').
					text("x"). // TODO: i18n (use icon!?)
					attr("title", macro.locale.delTooltip).
					data("space", item).click(macro.onDelClick);
				if(readOnly) {
					btn.hide();
				}
				return $("
").append(link).append(btn)[0];
			});
			if(items.length) {
				$("
").append(items).appendTo(container);
			} else {
				$('
').
					text(macro.locale.noInclusions).appendTo(container);
			}
		}, function(xhr, error, exc) {
			displayMessage(macro.locale.listError.format([currentSpace, error]));
		});
	},
	populateSpaces: function(form) { // TODO: rename?
		$.ajax({ // TODO: add to model/space.js?
			url: host + "/spaces?mine=1",
			type: "GET",
			success: function(data, status, xhr) {
				var spaces = $.map(data, function(item, i) {
					return $("<option />", { value: item.name }).text(item.name)[0];
				});
				$("select", form).append(spaces);
			} // TODO: error handling?
		});
	},
	onSubmit: function(el, mode) {
		var form = $(el).closest("form");
		var selector = mode == "passive" ? "[name=space]" : "select";
		var space = form.find(selector).val();
		var provider = mode == "passive" ? space : currentSpace;
		var subscriber = mode == "passive" ? currentSpace : space;
		var loc = macro.locale;
		var callback = function(data, status, xhr) {
			displayMessage(loc.addSuccess.format([provider, subscriber]));
			if(confirm(loc.reloadPrompt)) {
				window.location.reload();
			}
		};
		var errback = function(xhr, error, exc) {
			if(xhr.status == 409) {
				var included = "already subscribed";
				xhr = { // XXX: hacky
					status: xhr.responseText.indexOf(included) != -1 ? "409a" : "409b"
				};
			}
			var ctx = {
				msg: {
					403: loc.forbiddenError.format([subscriber]),
					404: loc.noSpaceError.format([subscriber]), // XXX: only relevant for passive mode
					"409a": loc.conflictError.format([provider, subscriber]),
					"409b": loc.noSpaceError.format([provider])
				},
				form: form,
				selector: selector
			};
			config.macros.TiddlySpaceLogin.displayError(xhr, error, exc, ctx);
		};
		this.inclusion(provider, subscriber, callback, errback, false);
		return false;
	},
	onDelClick: function(ev) { // XXX: too long, needs refactoring
		var btn = $(this);
		var provider = btn.data("space");

		var msg = macro.locale.delPrompt.format([provider]);
		var callback = function(data, status, xhr) {
			btn.closest("li").slideUp(function(ev) { $(this).remove(); });
		};
		var errback = function(xhr, error, exc) { // XXX: doesn't actually happen
			displayMessage(macro.locale.delError.format([username, error]));
		};
		if(confirm(msg)) {
			var recipe = new tiddlyweb.Recipe(provider + "_public", host);
			recipe.get(function(recipe, status, xhr) {
				var inclusions = $.map(recipe.recipe, function(item, i) { // XXX: duplicated from above
					var arr = item[0].split("_public");
					return (arr[0] != provider && arr[1] === "") ? arr[0] : null;
				});
				var recursiveMatch = false;
				btn.closest("ul").find("li").each(function(i, node) {
					var space = $(".deleteButton", node).data("space"); // XXX: relying on button is hacky
					if($.inArray(space, inclusions) != -1) {
						recursiveMatch = true;
						$(node).addClass("annotation"); // TODO: proper highlighting
					}
				});
				if(recursiveMatch) {
					btn.closest("." + macro.name).find("> .annotation").
						text(macro.locale.recursiveInclusions).slideDown();
				}
			});
			macro.inclusion(provider, currentSpace, callback, errback, true);
		}
		return false;
	},
	inclusion: function(provider, subscriber, callback, errback, remove) {
		var data = {};
		var key = remove ? "unsubscriptions" : "subscriptions";
		data[key] = [provider];
		$.ajax({ // TODO: add to model/space.js?
			url: host + "/spaces/" + subscriber,
			type: "POST",
			contentType: "application/json",
			data: $.toJSON(data),
			success: callback,
			error: errback
		});
	}
};

})(jQuery);
//}}}
<commit_msg>added space links to entries in list of inclusions<commit_after>/***
|''Name''|TiddlySpaceInclusion|
|''Version''|0.5.1|
|''Description''|provides user interfaces for managing TiddlySpace inclusions|
|''Status''|@@beta@@|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/raw/master/src/plugins/TiddlySpaceInclusion.js|
|''Requires''|TiddlySpaceConfig TiddlySpaceUserControls chrjs|
!HTMLForm
<form action="#">
	<fieldset>
		<legend />

Space Name:

<input type="text" name="space" />

Space Selection:

				<select>
					<option></option>
				</select>

		<input type="submit" />
	</fieldset>
</form>
!Code
***/
//{{{
(function($) {

var tweb = config.extensions.tiddlyweb;
var currentSpace = config.extensions.tiddlyspace.currentSpace.name;

var macro = config.macros.TiddlySpaceInclusion = {
	formTemplate: store.getTiddlerText(tiddler.title + "##HTMLForm"),
	locale: {
		addPassiveLabel: "Include space",
		addActiveLabel: "Include into space",
		passiveDesc: "Include a space into the current space",
		activeDesc: "Include another space in the current space",
		addSuccess: "included %0 in %1",
		delPrompt: "Are you sure you want to exclude %0 from the current space?",
		delTooltip: "click to exclude from the space",
		delError: "error excluding %0: %1",
		listError: "error retrieving spaces included in space %0: %1",
		forbiddenError: "unauthorized to modify space %0",
		noSpaceError: "space %0 does not exist",
		conflictError: "space %0 is already included in %1",
		noInclusions: "no spaces are included",
		recursiveInclusions: "Spaces included by the removed space are highlighted and should be removed manually.",
		reloadPrompt: "The page must be reloaded for inclusion to take effect. Reload now?"
	},

	handler: function(place, macroName, params, wikifier, paramString, tiddler) {
		// passive mode means subscribing given space to current space
		// active mode means subscribing current space to given space
		this.name = macroName;
		var mode = params[0] || "list";
		var form = $(this.formTemplate).
			find(".annotation").hide().end();
		if(mode == "passive") {
			if(!readOnly) {
				form.submit(function(ev) { return macro.onSubmit(this, mode); }).
					find("._active").remove().end().
					find("legend").text(this.locale.addPassiveLabel).end().
					find(".description").text(this.locale.passiveDesc).end().
					find("[type=submit]").val(this.locale.addPassiveLabel).end().
					appendTo(place);
			}
		} else if(mode == "active") {
			form.submit(function(ev) { return macro.onSubmit(this, mode); }).
				find("._passive").remove().end().
				find("legend").text(this.locale.addActiveLabel).end().
				find(".description").text(this.locale.activeDesc).end().
				find("[type=submit]").val(this.locale.addActiveLabel).end().
				appendTo(place);
			this.populateSpaces(form);
		} else {
			var container = $("
").addClass(this.name).appendTo(place);
			$('
').hide().appendTo(container);
			this.listInclusions(container);
		}
	},
	listInclusions: function(container) {
		var recipe = new tiddlyweb.Recipe(currentSpace + "_public", tweb.host);
		recipe.get(function(recipe, status, xhr) {
			var inclusions = $.map(recipe.recipe, function(item, i) { // TODO: refactor to canonicalize; move to TiddlySpaceConfig!?
				var arr = item[0].split("_public");
				return (arr[0] != currentSpace && arr[1] === "") ? arr[0] : null;
			});
			var items = $.map(inclusions, function(item, i) { // TODO: DRY (cf. displayMembers)
				var link = $("").text(item);
				tweb.getStatus(function(status) {
					var uri = config.extensions.tiddlyspace.getHost(
						status.server_host, item);
					link.attr("href", uri);
				});
				var btn = $('').
					text("x"). // TODO: i18n (use icon!?)
					attr("title", macro.locale.delTooltip).
					data("space", item).click(macro.onDelClick);
				if(readOnly) {
					btn.hide();
				}
				return $("
").append(link).append(btn)[0];
			});
			if(items.length) {
				$("
").append(items).appendTo(container);
			} else {
				$('
').
					text(macro.locale.noInclusions).appendTo(container);
			}
		}, function(xhr, error, exc) {
			displayMessage(macro.locale.listError.format([currentSpace, error]));
		});
	},
	populateSpaces: function(form) { // TODO: rename?
		$.ajax({ // TODO: add to model/space.js?
			url: tweb.host + "/spaces?mine=1",
			type: "GET",
			success: function(data, status, xhr) {
				var spaces = $.map(data, function(item, i) {
					return $("<option />", { value: item.name }).text(item.name)[0];
				});
				$("select", form).append(spaces);
			} // TODO: error handling?
		});
	},
	onSubmit: function(el, mode) {
		var form = $(el).closest("form");
		var selector = mode == "passive" ? "[name=space]" : "select";
		var space = form.find(selector).val();
		var provider = mode == "passive" ? space : currentSpace;
		var subscriber = mode == "passive" ? currentSpace : space;
		var loc = macro.locale;
		var callback = function(data, status, xhr) {
			displayMessage(loc.addSuccess.format([provider, subscriber]));
			if(confirm(loc.reloadPrompt)) {
				window.location.reload();
			}
		};
		var errback = function(xhr, error, exc) {
			if(xhr.status == 409) {
				var included = "already subscribed";
				xhr = { // XXX: hacky
					status: xhr.responseText.indexOf(included) != -1 ? "409a" : "409b"
				};
			}
			var ctx = {
				msg: {
					403: loc.forbiddenError.format([subscriber]),
					404: loc.noSpaceError.format([subscriber]), // XXX: only relevant for passive mode
					"409a": loc.conflictError.format([provider, subscriber]),
					"409b": loc.noSpaceError.format([provider])
				},
				form: form,
				selector: selector
			};
			config.macros.TiddlySpaceLogin.displayError(xhr, error, exc, ctx);
		};
		this.inclusion(provider, subscriber, callback, errback, false);
		return false;
	},
	onDelClick: function(ev) { // XXX: too long, needs refactoring
		var btn = $(this);
		var provider = btn.data("space");

		var msg = macro.locale.delPrompt.format([provider]);
		var callback = function(data, status, xhr) {
			btn.closest("li").slideUp(function(ev) { $(this).remove(); });
		};
		var errback = function(xhr, error, exc) { // XXX: doesn't actually happen
			displayMessage(macro.locale.delError.format([username, error]));
		};
		if(confirm(msg)) {
			var recipe = new tiddlyweb.Recipe(provider + "_public", tweb.host);
			recipe.get(function(recipe, status, xhr) {
				var inclusions = $.map(recipe.recipe, function(item, i) { // XXX: duplicated from above
					var arr = item[0].split("_public");
					return (arr[0] != provider && arr[1] === "") ? arr[0] : null;
				});
				var recursiveMatch = false;
				btn.closest("ul").find("li").each(function(i, node) {
					var space = $(".deleteButton", node).data("space"); // XXX: relying on button is hacky
					if($.inArray(space, inclusions) != -1) {
						recursiveMatch = true;
						$(node).addClass("annotation"); // TODO: proper highlighting
					}
				});
				if(recursiveMatch) {
					btn.closest("." + macro.name).find("> .annotation").
						text(macro.locale.recursiveInclusions).slideDown();
				}
			});
			macro.inclusion(provider, currentSpace, callback, errback, true);
		}
		return false;
	},
	inclusion: function(provider, subscriber, callback, errback, remove) {
		var data = {};
		var key = remove ? "unsubscriptions" : "subscriptions";
		data[key] = [provider];
		$.ajax({ // TODO: add to model/space.js?
			url: tweb.host + "/spaces/" + subscriber,
			type: "POST",
			contentType: "application/json",
			data: $.toJSON(data),
			success: callback,
			error: errback
		});
	}
};

})(jQuery);
//}}}
<|endoftext|>


<commit_before>/***
|''Name''|TiddlySpacePublisher|
|''Version''||
|''Description''|Provides a batch publishing tool for managing lots of tiddlers in TiddlySpace|
|''Requires''|TiddlySpacePublishCommand TiddlySpaceTiddlerIconsPlugin|
|''Author''|Jon Robson|
|''Version''|0.2.0|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/blob/master/src/plugins/TiddlySpacePublisher.js|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
!Usage
{{{
<<TiddlySpacePublisher>>
creates an interface with which you can manage unpublished versions of tiddlers.
}}}
!Parameters
filter: allows you to run the publisher on a filtered set of tiddlers.
eg. filter:[tag[systemConfig]]

!TODO
batch publishing for the other way round (public to private)

!Code
***/
//{{{
(function($) {

var currentSpace = config.extensions.tiddlyspace.currentSpace.name;
var originMacro = config.macros.tiddlerOrigin;

var macro = config.macros.TiddlySpacePublisher = {
	locale: {
		title: "Publisher",
		updatedPrivateTiddler: "newer than published version (click {{viewPublicTiddler{%0}}} to view)",
		makePublicLabel: "Make public",
		noTiddlersText: "No tiddlers to publish",
		makePublicPrompt: "Make all the selected tiddlers public.",
		description: "Publish tiddlers to public version of this space",
		pleaseWait: "please wait while we load the publisher... "
	},

	listViewTemplate: {
		columns: [
			{ name: "Selected", field: "Selected", rowName: "title", type: "Selector" },
			{ name: "Tiddler", field: "tiddler", title: "Tiddler", type: "Tiddler" },
			{ name: "Status", field: "status", title: "Status", type: "WikiText" }
		],
		rowClasses: [
			{ className: "updated", field: "updated" },
			{ className: "notPublished", field: "notPublished" }
		]
	},

	publishedTiddlers: {}, // maps tiddler titles to a currently public tiddler where public tiddlers exist
	getPublicTiddlers: function(listWrapper, paramString, spaceName, tiddler) { // fills in publishedTiddlers variable above
		var adaptor = tiddler.getAdaptor();
		var context = {
			workspace: "recipes/%0_public".format([spaceName])
		};
		var callback = function(context, userParams) {
			if(context.status) {
				var tiddlers = context.tiddlers;
				for(var i = 0; i < tiddlers.length; i++) {
					var tid = tiddlers[i];
					macro.publishedTiddlers[tid.title] = tid;
				}
				macro.refresh(listWrapper, paramString);
			}
		};
		adaptor.getTiddlerList(context, null, callback);
	},
	makePublic: function(e, listWrapper, paramString) { // this is what is called when you click the publish button
		var wizard = new Wizard(e.target);
			var listView = wizard.getValue("listView");
			var rowNames = ListView.getSelectedRows(listView);
			var callback = function(status) {
				macro.refresh(listWrapper, paramString);
			};
			var cmd = config.commands.publishTiddler;
			var publicWorkspace;
			for(var i = 0; i < rowNames.length; i++) {
				var title = rowNames[i];
				var tiddler = store.getTiddler(title);
				if(!publicWorkspace) {
					publicWorkspace = cmd.toggleWorkspace(tiddler, "public");
				}
				macro.publishedTiddlers[title] = tiddler;
				var newTiddler = {
					title: tiddler.title,
					fields: { "server.workspace": publicWorkspace }
				};
				config.commands.publishTiddler.moveTiddler(tiddler, newTiddler, true, callback);
			}
	},
	handler: function(place, macroName, params, wikifier, paramString, tiddler) {
		var wizard = new Wizard();
		var locale = macro.locale;
		wizard.createWizard(place, locale.title);
		wizard.addStep(macro.locale.description, '<input type="hidden" name="markList" />');
		var markList = wizard.getElement("markList");
		var listWrapper = document.createElement("div");
		markList.parentNode.insertBefore(listWrapper, markList);
		listWrapper.setAttribute("refresh", "macro");
		listWrapper.setAttribute("macroName", "SpaceManager");
		listWrapper.setAttribute("params", paramString);

		$(listWrapper).text(macro.locale.pleaseWait);
		this.getPublicTiddlers(listWrapper, paramString, currentSpace, tiddler);
	},
	refresh: function(listWrapper, paramString) {
		var wizard = new Wizard(listWrapper);
		var locale = macro.locale;
		var selectedRows = [];
		ListView.forEachSelector(listWrapper, function(e, rowName) {
			if(e.checked) {
				selectedRows.push(e.getAttribute("rowName"));
			}
		});
		removeChildren(listWrapper);
		var params = paramString.parseParams("anon");
		var publishCandidates = [];
		var unpublishedTiddlers;
		var filter = params[0].filter;
		if(filter) {
			unpublishedTiddlers = store.filterTiddlers(filter[0]);
		} else {
			unpublishedTiddlers = store.getTiddlers();
		}
		var publishedTiddlers = macro.publishedTiddlers;
		var privateBag = currentSpace + "_private";
		for(var t = 0; t < unpublishedTiddlers.length; t++) {
			var include = false;
			var tiddler = unpublishedTiddlers[t];
			var bag = tiddler.fields["server.bag"];
			if(!tiddler.tags.contains("excludePublisher")) {
				if(bag == privateBag) {
					var candidate = {
						title: tiddler.title,
						tiddler: tiddler
					};
					var publishedTiddler = publishedTiddlers[tiddler.title];
					if(!publishedTiddler) {
						candidate.status = "unpublished";
						include = true;
						candidate.notPublished = true;
					} else if(!originMacro.areIdentical(tiddler, publishedTiddler)) {
						candidate.status = locale.updatedPrivateTiddler.format([tiddler.title]);
						candidate.publicTiddler = publishedTiddler;
						candidate.updated = true;
						include = true;
					}
					if(include) {
						publishCandidates.push(candidate);
					}
				}
			}
		}

		if(publishCandidates.length === 0) {
			createTiddlyElement(listWrapper, "em", null, null, locale.noTiddlersText);
		} else {
			var listView = ListView.create(listWrapper, publishCandidates, macro.listViewTemplate);
			wizard.setValue("listView", listView);

			var btnHandler = function(ev) {
				macro.makePublic(ev, listWrapper, paramString);
			};
			wizard.setButtons([
				{ caption: locale.makePublicLabel, tooltip: locale.makePublicPrompt, onClick: btnHandler }
			]);
		}

		var publicLinks = $(".viewPublicTiddler");
		$.each(publicLinks, function(index, el) {
			el = $(el);
			var title = el.text();
			el.empty();
			var handler = function(ev) {
				ev.preventDefault();
				var tiddler = store.getTiddler(title);
				config.extensions.tiddlyspace.spawnPublicTiddler(tiddler, el);
			};
			$('').text(title).click(handler).appendTo(el);
		});
	}
};

var unpublishedTabText = 'Unpublished "Manage unpublished tiddlers" TabUnpublished';
config.shadowTiddlers.TabMore = config.shadowTiddlers.TabMore.replace(
	"TabMoreShadowed", "TabMoreShadowed %0".format([unpublishedTabText]));

})(jQuery);
//}}}
<commit_msg>Updated Publisher to send bag as argument rather than workspace<commit_after>/***
|''Name''|TiddlySpacePublisher|
|''Version''||
|''Description''|Provides a batch publishing tool for managing lots of tiddlers in TiddlySpace|
|''Requires''|TiddlySpacePublishCommand TiddlySpaceTiddlerIconsPlugin|
|''Author''|Jon Robson|
|''Version''|0.3.0|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/blob/master/src/plugins/TiddlySpacePublisher.js|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
!Usage
{{{
<<TiddlySpacePublisher>>
creates an interface with which you can manage unpublished versions of tiddlers.
}}}
!Parameters
filter: allows you to run the publisher on a filtered set of tiddlers.
eg. filter:[tag[systemConfig]]

!TODO
batch publishing for the other way round (public to private)

!Code
***/
//{{{
(function($) {

var currentSpace = config.extensions.tiddlyspace.currentSpace.name;
var originMacro = config.macros.tiddlerOrigin;

var macro = config.macros.TiddlySpacePublisher = {
	locale: {
		title: "Publisher",
		updatedPrivateTiddler: "newer than published version (click {{viewPublicTiddler{%0}}} to view)",
		makePublicLabel: "Make public",
		noTiddlersText: "No tiddlers to publish",
		makePublicPrompt: "Make all the selected tiddlers public.",
		description: "Publish tiddlers to public version of this space",
		pleaseWait: "please wait while we load the publisher... "
	},

	listViewTemplate: {
		columns: [
			{ name: "Selected", field: "Selected", rowName: "title", type: "Selector" },
			{ name: "Tiddler", field: "tiddler", title: "Tiddler", type: "Tiddler" },
			{ name: "Status", field: "status", title: "Status", type: "WikiText" }
		],
		rowClasses: [
			{ className: "updated", field: "updated" },
			{ className: "notPublished", field: "notPublished" }
		]
	},

	publishedTiddlers: {}, // maps tiddler titles to a currently public tiddler where public tiddlers exist
	getPublicTiddlers: function(listWrapper, paramString, spaceName, tiddler) { // fills in publishedTiddlers variable above
		var adaptor = tiddler.getAdaptor();
		var context = {
			workspace: "recipes/%0_public".format([spaceName])
		};
		var callback = function(context, userParams) {
			if(context.status) {
				var tiddlers = context.tiddlers;
				for(var i = 0; i < tiddlers.length; i++) {
					var tid = tiddlers[i];
					macro.publishedTiddlers[tid.title] = tid;
				}
				macro.refresh(listWrapper, paramString);
			}
		};
		adaptor.getTiddlerList(context, null, callback);
	},
	makePublic: function(e, listWrapper, paramString) { // this is what is called when you click the publish button
		var wizard = new Wizard(e.target);
			var listView = wizard.getValue("listView");
			var rowNames = ListView.getSelectedRows(listView);
			var callback = function(status) {
				macro.refresh(listWrapper, paramString);
			};
			var cmd = config.commands.publishTiddler;
			var publicWorkspace;
			for(var i = 0; i < rowNames.length; i++) {
				var title = rowNames[i];
				var tiddler = store.getTiddler(title);
				if(!publicBag) {
					publicBag = cmd.toggleBag(tiddler, "public");
				}
				macro.publishedTiddlers[title] = tiddler;
				var newTiddler = {
					title: tiddler.title,
					fields: { "server.bag": publicBag }
				};
				config.commands.publishTiddler.moveTiddler(tiddler, newTiddler, true, callback);
			}
	},
	handler: function(place, macroName, params, wikifier, paramString, tiddler) {
		var wizard = new Wizard();
		var locale = macro.locale;
		wizard.createWizard(place, locale.title);
		wizard.addStep(macro.locale.description, '<input type="hidden" name="markList" />');
		var markList = wizard.getElement("markList");
		var listWrapper = document.createElement("div");
		markList.parentNode.insertBefore(listWrapper, markList);
		listWrapper.setAttribute("refresh", "macro");
		listWrapper.setAttribute("macroName", "SpaceManager");
		listWrapper.setAttribute("params", paramString);

		$(listWrapper).text(macro.locale.pleaseWait);
		this.getPublicTiddlers(listWrapper, paramString, currentSpace, tiddler);
	},
	refresh: function(listWrapper, paramString) {
		var wizard = new Wizard(listWrapper);
		var locale = macro.locale;
		var selectedRows = [];
		ListView.forEachSelector(listWrapper, function(e, rowName) {
			if(e.checked) {
				selectedRows.push(e.getAttribute("rowName"));
			}
		});
		removeChildren(listWrapper);
		var params = paramString.parseParams("anon");
		var publishCandidates = [];
		var unpublishedTiddlers;
		var filter = params[0].filter;
		if(filter) {
			unpublishedTiddlers = store.filterTiddlers(filter[0]);
		} else {
			unpublishedTiddlers = store.getTiddlers();
		}
		var publishedTiddlers = macro.publishedTiddlers;
		var privateBag = currentSpace + "_private";
		for(var t = 0; t < unpublishedTiddlers.length; t++) {
			var include = false;
			var tiddler = unpublishedTiddlers[t];
			var bag = tiddler.fields["server.bag"];
			if(!tiddler.tags.contains("excludePublisher")) {
				if(bag == privateBag) {
					var candidate = {
						title: tiddler.title,
						tiddler: tiddler
					};
					var publishedTiddler = publishedTiddlers[tiddler.title];
					if(!publishedTiddler) {
						candidate.status = "unpublished";
						include = true;
						candidate.notPublished = true;
					} else if(!originMacro.areIdentical(tiddler, publishedTiddler)) {
						candidate.status = locale.updatedPrivateTiddler.format([tiddler.title]);
						candidate.publicTiddler = publishedTiddler;
						candidate.updated = true;
						include = true;
					}
					if(include) {
						publishCandidates.push(candidate);
					}
				}
			}
		}

		if(publishCandidates.length === 0) {
			createTiddlyElement(listWrapper, "em", null, null, locale.noTiddlersText);
		} else {
			var listView = ListView.create(listWrapper, publishCandidates, macro.listViewTemplate);
			wizard.setValue("listView", listView);

			var btnHandler = function(ev) {
				macro.makePublic(ev, listWrapper, paramString);
			};
			wizard.setButtons([
				{ caption: locale.makePublicLabel, tooltip: locale.makePublicPrompt, onClick: btnHandler }
			]);
		}

		var publicLinks = $(".viewPublicTiddler");
		$.each(publicLinks, function(index, el) {
			el = $(el);
			var title = el.text();
			el.empty();
			var handler = function(ev) {
				ev.preventDefault();
				var tiddler = store.getTiddler(title);
				config.extensions.tiddlyspace.spawnPublicTiddler(tiddler, el);
			};
			$('').text(title).click(handler).appendTo(el);
		});
	}
};

var unpublishedTabText = 'Unpublished "Manage unpublished tiddlers" TabUnpublished';
config.shadowTiddlers.TabMore = config.shadowTiddlers.TabMore.replace(
	"TabMoreShadowed", "TabMoreShadowed %0".format([unpublishedTabText]));

})(jQuery);
//}}}
<|endoftext|>