<commit_before>import React from 'react';

import DiffPanel from './DiffPanel';
import CommitMessage from './CommitMessage';

import Promise from 'promise';
import Git from 'nodegit';

const gitFunctions = {

  getRepo: (path) => {
    const pathToRepo = require('path').resolve(path);

    return Git.Repository.open(pathToRepo);
  }
};

const constStyles = {
  fontFamily: `apple-system,
          BlinkMacSystemFont,"Segoe UI",
          Roboto,Helvetica,Arial,sans-serif,
          "Apple Color Emoji","Segoe UI Emoji",
          "Segoe UI Symbol"`,
  darkRed: '#b60a0a',
  grey: '#ededed',
  blue: '#9CE8FA',
  darkBlue: '#0C6990'
};

class StageSelective extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commitMsg: '',
    }
  }

  createCommit = (filesArr) => {

    if(filesArr.length === 0) {
      console.log('Please stage lines which are modified');
      return;
    }

    // console.log(filesArr);

    let repo;
    gitFunctions.getRepo(this.props.repo.path)
    .then( (repo) => {
      repo = repo;
      const isStaged = false;

      let promises = [];
      filesArr.forEach( (file, index) => {
        promises.push(repo.stageLines(file.path,file.lines,isStaged));
      });
      return Promise.all(promises);
    })
    .catch( (err) => {
      console.log('err:',err);
    })
    .then( (num) => {
      console.log('done!');
      return repo.refreshIndex();
    });
  }

  collectCheckedLines = (commitMsg) => {

    const LINESTATUS = {
      UNMODIFIED: 32,
      ADDED: 43,
      DELETED: 45,
    };
    const checked = this.diffPanel.state.checked;
    const diffsArr = this.diffPanel.state.diffsArr;

    let filesArr = [];
    diffsArr.forEach( (diffFile, fileIndex) => {

      let linesArr = [];
      diffFile.diffs.forEach( (diff, diffIndex) => {
        diff.lines.forEach( (line, lineIndex) => {

          // only accept checked and modified lines
          if(checked[fileIndex][diffIndex][lineIndex] &&
          line.origin() !== LINESTATUS.UNMODIFIED)
            linesArr.push(line);
        });
      });

      if(linesArr.length !== 0) {
        filesArr.push({lines: linesArr, path: diffFile.path.old});
      }
    });

    this.createCommit(filesArr);
  }

  render = () => {

    const styles = {
      main: {
        display: 'flex',
        flexDirection: 'column',
        border: '4px solid'+constStyles.blue,
        borderLeft: '2px solid'+constStyles.blue,
      },
      commitmsg: {
        paddingLeft: '5%',
        paddingBottom: 15,
        width: '50%',
      },
      cover: {
        borderBottom: '4px solid'+constStyles.blue,
      }
    };

    return (

            <CommitMessage buttonMsg='Commit selected lines!' commitCB={this.collectCheckedLines} />

        <DiffPanel {...this.props} showSelect={true} ref={(ref) => this.diffPanel = ref} />

    );
  }
}

export default StageSelective;<commit_msg>View: Changed overflow property so that only diff panel scrolls<commit_after>import React from 'react';

import DiffPanel from './DiffPanel';
import CommitMessage from './CommitMessage';

import Promise from 'promise';
import Git from 'nodegit';

const gitFunctions = {

  getRepo: (path) => {
    const pathToRepo = require('path').resolve(path);

    return Git.Repository.open(pathToRepo);
  }
};

const constStyles = {
  fontFamily: `apple-system,
          BlinkMacSystemFont,"Segoe UI",
          Roboto,Helvetica,Arial,sans-serif,
          "Apple Color Emoji","Segoe UI Emoji",
          "Segoe UI Symbol"`,
  darkRed: '#b60a0a',
  grey: '#ededed',
  blue: '#9CE8FA',
  darkBlue: '#0C6990'
};

class StageSelective extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commitMsg: '',
    }
  }

  createCommit = (filesArr) => {

    if(filesArr.length === 0) {
      console.log('Please stage lines which are modified');
      return;
    }

    // console.log(filesArr);

    let repo;
    gitFunctions.getRepo(this.props.repo.path)
    .then( (repo) => {
      repo = repo;
      const isStaged = false;

      let promises = [];
      filesArr.forEach( (file, index) => {
        promises.push(repo.stageLines(file.path,file.lines,isStaged));
      });
      return Promise.all(promises);
    })
    .catch( (err) => {
      console.log('err:',err);
    })
    .then( (num) => {
      console.log('done!');
      return repo.refreshIndex();
    });
  }

  collectCheckedLines = (commitMsg) => {

    const LINESTATUS = {
      UNMODIFIED: 32,
      ADDED: 43,
      DELETED: 45,
    };
    const checked = this.diffPanel.state.checked;
    const diffsArr = this.diffPanel.state.diffsArr;

    let filesArr = [];
    diffsArr.forEach( (diffFile, fileIndex) => {

      let linesArr = [];
      diffFile.diffs.forEach( (diff, diffIndex) => {
        diff.lines.forEach( (line, lineIndex) => {

          // only accept checked and modified lines
          if(checked[fileIndex][diffIndex][lineIndex] &&
          line.origin() !== LINESTATUS.UNMODIFIED)
            linesArr.push(line);
        });
      });

      if(linesArr.length !== 0) {
        filesArr.push({lines: linesArr, path: diffFile.path.old});
      }
    });

    this.createCommit(filesArr);
  }

  render = () => {

    const styles = {
      main: {
        overflow: 'hidden',
        display: 'flex',
        flexDirection: 'column',
        border: '4px solid'+constStyles.blue,
        borderLeft: '2px solid'+constStyles.blue,
      },
      commitmsg: {
        paddingLeft: '5%',
        paddingBottom: 15,
        width: '50%',
      },
      cover: {
        borderBottom: '4px solid'+constStyles.blue,
      },
      diff: {
        overflow: 'auto'
      }
    };

    return (

            <CommitMessage buttonMsg='Commit selected lines!' commitCB={this.collectCheckedLines} />

          <DiffPanel {...this.props} showSelect={true} ref={(ref) => this.diffPanel = ref} />

    );
  }
}

export default StageSelective;<|endoftext|>


<commit_before>import { React, PropTypes, styled, css, observer, cn } from 'vendor';
import { StickyTable, Row, Cell } from 'react-sticky-table';
import TutorLink from '../../components/link';
import { Button } from 'react-bootstrap';
import S from '../../helpers/string';
import { Icon, ArbitraryHtmlAndMath } from 'shared';
import HomeworkQuestions, { ExerciseNumber } from '../../components/homework-questions';
import InfoIcon from '../../components/icons/info';
import { colors } from 'theme';
import Loading from 'shared/components/loading-animation';
import { isEmpty, compact } from 'lodash';

// https://projects.invisionapp.com/d/main#/console/18937568/403651098/preview

const ALPHABET = 'abcdefghijklmnopqrstuvwxyz';

const Wrapper = styled.div`
  margin-top: 4rem;
`;

const Footer = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 1.6rem;
`;

const StyledIcon = styled(Icon)`
  font-size: 2.7rem;
  flex-shrink: 0;
  &&:hover {
    box-shadow: none;
  }
`;

const QuestionHeader = observer(({ ux, styleVariant, label, info }) => (
  <>
    <ExerciseNumber variant={styleVariant} data-question-id={info.question.id}>
      {info.hasFreeResponse && (

      );
    });

    if (isEmpty(compact(responses))) { return null; }

    return (
      <ResponseWrapper key={`answer-${answer.id}`}>
        <ResponseHeader>

            {ALPHABET[i]}

          <ArbitraryHtmlAndMath
            html={answer.content_html}
          />
        </ResponseHeader>

          {responses}

      </ResponseWrapper>
    );
  })
));

const WRQFreeResponse = observer(({ info }) => {
  const responses = info.responses.map((response, i) => {
    const student = response.student;
    return response.free_response && (
      <ResponseWrapper key={i} wrq={true}>

      </ResponseWrapper>
    );
  });

  if (isEmpty(compact(responses))) { return null; }

  return (
    <div key={`wrq-responses-${info.question.id}`}>
      {responses}

  );
});

const QuestionFreeResponse = observer(({ ux, info }) => {
  if (!ux.isShowingFreeResponseForQuestion(info.question)) { return null; }
  return (

      {info.question.isMultipleChoice ? <MCQFreeResponse ux={ux} question={info.question} />
        : <WRQFreeResponse ux={ux} info={info} />}

  );
});

const StyledStickyTable = styled(StickyTable)`
  .sticky-table-table {
    border: 1px solid ${colors.neutral.pale};
  }

  .sticky-table-cell {
    &:not(:last-child) {
      border-right: 1px solid ${colors.neutral.pale};
    }
    &:not(:first-child) {
      text-align: center;
    }
  }

  .sticky-table-cell, .sticky-table-row {
    vertical-align: middle;
    padding: 0 1.6rem;
    height: 4.1rem;
    border-color: ${colors.neutral.pale};
  }
`;

const Header = styled(Cell)`
  background: ${colors.assignments.submissions.background};
  color: ${colors.neutral.grayblue};
  ${props => props.center && 'text-align: center;'}
`;

const Legend = styled.div`
  margin: 0.8rem 0;
  color: ${colors.neutral.thin};
`;

const Toolbar = styled.div`
  display: flex;
  align-items: center;
  margin: 0 auto 2rem;
  max-width: 60rem;
  p {
    margin: 0 1.6rem 0 0;
  }
`;

const GradeButton = styled(TutorLink)`
  &&& {
    padding: 1.5rem 2.1rem 1.5rem;
    line-height: 1.9rem;
    ${props => props.displayingFlag && 'padding-left: 1.1rem;'}
  }
`;

const GradingBlock = observer(({ ux }) => {
  if (!ux.canDisplayGradingButton) { return null; }

  return (
    <Toolbar>

This assignment is now open for grading.

      <GradeButton
        to="gradeAssignment"
        className="btn btn-primary btn-new-flag btn-standard"
        displayingFlag={ux.gradeableQuestionCount > 0}
        params={{
          courseId: ux.course.id,
          id: ux.planId,
          periodId: ux.selectedPeriod.id,
        }}
      >
        {ux.gradeableQuestionCount > 0 &&
          {ux.gradeableQuestionCount} NEW}
        Grade answers
      </GradeButton>
    </Toolbar>
  );
});

const AvailablePoints = ({ value }) => {
  if (!value) {
    return (
      <InfoIcon
        color="#f36a31"
        tooltip="Students received different numbers of Tutor-selected questions.  This can happen when questions aren’t
        available, a student works an assignment late, or a student hasn’t started the assignment."
      />
    );
  }
  return (
    ({S.numberWithOneDecimalPlace(value)})
  );
};
AvailablePoints.propTypes = {
  value: PropTypes.oneOfType([
    PropTypes.number,
    PropTypes.string,
    PropTypes.bool,
  ]),
};

const StyledButton = styled(Button)`
  && { text-decoration: underline; }
`;

const StyledCell = styled(Cell)`
  ${props => props.isTrouble && css`
    background: ${colors.states.trouble};
  `}
`;

const Overview = observer(({ ux, ux: { scores } }) => (
  <Wrapper data-test-id="overview">
    <GradingBlock ux={ux}/>
     : h.title}
          )}
      </Row>
      <Row>
        Question Type
        {scores.question_headings.map((h, i) => <Cell key={i}>{h.type}</Cell>)}
      </Row>
      <Row>

          Available Points <AvailablePoints value={(scores.hasEqualTutorQuestions && scores.availablePoints) || false} />

        {scores.question_headings.map((h, i) => <Cell key={i}>{S.numberWithOneDecimalPlace(h.points)}</Cell>)}
      </Row>
      <Row>
        Correct Responses
        {scores.question_headings.map((h, i) => (

        ))}
      </Row>
    </StyledStickyTable>
    <Legend>
      MCQ: Multiple Choice Question (auto-graded);
      WRQ: Written Response Question (manually-graded);
      Tutor: OpenStax Tutor Beta selection (MCQs and auto-graded)
    </Legend>

    {ux.isExercisesReady ? (
      <HomeworkQuestions
        questionsInfo={scores.questionsInfo}
        questionType="teacher-review"
        headerContentRenderer={(props) => <QuestionHeader ux={ux} {...props} />}
        questionInfoRenderer={(props) => <QuestionFreeResponse ux={ux} {...props} />}
        footerContentRenderer={(props) => <QuestionFooter ux={ux} {...props} />}
        styleVariant="submission"
      />) : <Loading message="Loading Questions…"/>}

  </Wrapper>
));

Overview.title = 'Submission Overview';
Overview.propTypes = {
  ux: PropTypes.object.isRequired,
};

export default Overview;
<commit_msg>don't render question footer for multiple choice<commit_after>import { React, PropTypes, styled, css, observer, cn } from 'vendor';
import { StickyTable, Row, Cell } from 'react-sticky-table';
import TutorLink from '../../components/link';
import { Button } from 'react-bootstrap';
import S from '../../helpers/string';
import { Icon, ArbitraryHtmlAndMath } from 'shared';
import HomeworkQuestions, { ExerciseNumber } from '../../components/homework-questions';
import InfoIcon from '../../components/icons/info';
import { colors } from 'theme';
import Loading from 'shared/components/loading-animation';
import { isEmpty, compact } from 'lodash';

// https://projects.invisionapp.com/d/main#/console/18937568/403651098/preview

const ALPHABET = 'abcdefghijklmnopqrstuvwxyz';

const Wrapper = styled.div`
  margin-top: 4rem;
`;

const Footer = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 1.6rem;
`;

const StyledIcon = styled(Icon)`
  font-size: 2.7rem;
  flex-shrink: 0;
  &&:hover {
    box-shadow: none;
  }
`;

const QuestionHeader = observer(({ ux, styleVariant, label, info }) => (
  <>
    <ExerciseNumber variant={styleVariant} data-question-id={info.question.id}>
      {info.hasFreeResponse && (

      );
    });

    if (isEmpty(compact(responses))) { return null; }

    return (
      <ResponseWrapper key={`answer-${answer.id}`}>
        <ResponseHeader>

            {ALPHABET[i]}

          <ArbitraryHtmlAndMath
            html={answer.content_html}
          />
        </ResponseHeader>

          {responses}

      </ResponseWrapper>
    );
  })
));

const WRQFreeResponse = observer(({ info }) => {
  const responses = info.responses.map((response, i) => {
    const student = response.student;
    return response.free_response && (
      <ResponseWrapper key={i} wrq={true}>

      </ResponseWrapper>
    );
  });

  if (isEmpty(compact(responses))) { return null; }

  return (
    <div key={`wrq-responses-${info.question.id}`}>
      {responses}

  );
});

const QuestionFreeResponse = observer(({ ux, info }) => {
  if (!ux.isShowingFreeResponseForQuestion(info.question)) { return null; }
  return (

      {info.question.isMultipleChoice ? <MCQFreeResponse ux={ux} question={info.question} />
        : <WRQFreeResponse ux={ux} info={info} />}

  );
});

const StyledStickyTable = styled(StickyTable)`
  .sticky-table-table {
    border: 1px solid ${colors.neutral.pale};
  }

  .sticky-table-cell {
    &:not(:last-child) {
      border-right: 1px solid ${colors.neutral.pale};
    }
    &:not(:first-child) {
      text-align: center;
    }
  }

  .sticky-table-cell, .sticky-table-row {
    vertical-align: middle;
    padding: 0 1.6rem;
    height: 4.1rem;
    border-color: ${colors.neutral.pale};
  }
`;

const Header = styled(Cell)`
  background: ${colors.assignments.submissions.background};
  color: ${colors.neutral.grayblue};
  ${props => props.center && 'text-align: center;'}
`;

const Legend = styled.div`
  margin: 0.8rem 0;
  color: ${colors.neutral.thin};
`;

const Toolbar = styled.div`
  display: flex;
  align-items: center;
  margin: 0 auto 2rem;
  max-width: 60rem;
  p {
    margin: 0 1.6rem 0 0;
  }
`;

const GradeButton = styled(TutorLink)`
  &&& {
    padding: 1.5rem 2.1rem 1.5rem;
    line-height: 1.9rem;
    ${props => props.displayingFlag && 'padding-left: 1.1rem;'}
  }
`;

const GradingBlock = observer(({ ux }) => {
  if (!ux.canDisplayGradingButton) { return null; }

  return (
    <Toolbar>

This assignment is now open for grading.

      <GradeButton
        to="gradeAssignment"
        className="btn btn-primary btn-new-flag btn-standard"
        displayingFlag={ux.gradeableQuestionCount > 0}
        params={{
          courseId: ux.course.id,
          id: ux.planId,
          periodId: ux.selectedPeriod.id,
        }}
      >
        {ux.gradeableQuestionCount > 0 &&
          {ux.gradeableQuestionCount} NEW}
        Grade answers
      </GradeButton>
    </Toolbar>
  );
});

const AvailablePoints = ({ value }) => {
  if (!value) {
    return (
      <InfoIcon
        color="#f36a31"
        tooltip="Students received different numbers of Tutor-selected questions.  This can happen when questions aren’t
        available, a student works an assignment late, or a student hasn’t started the assignment."
      />
    );
  }
  return (
    ({S.numberWithOneDecimalPlace(value)})
  );
};
AvailablePoints.propTypes = {
  value: PropTypes.oneOfType([
    PropTypes.number,
    PropTypes.string,
    PropTypes.bool,
  ]),
};

const StyledButton = styled(Button)`
  && { text-decoration: underline; }
`;

const StyledCell = styled(Cell)`
  ${props => props.isTrouble && css`
    background: ${colors.states.trouble};
  `}
`;

const Overview = observer(({ ux, ux: { scores } }) => (
  <Wrapper data-test-id="overview">
    <GradingBlock ux={ux}/>
     : h.title}
          )}
      </Row>
      <Row>
        Question Type
        {scores.question_headings.map((h, i) => <Cell key={i}>{h.type}</Cell>)}
      </Row>
      <Row>

          Available Points <AvailablePoints value={(scores.hasEqualTutorQuestions && scores.availablePoints) || false} />

        {scores.question_headings.map((h, i) => <Cell key={i}>{S.numberWithOneDecimalPlace(h.points)}</Cell>)}
      </Row>
      <Row>
        Correct Responses
        {scores.question_headings.map((h, i) => (

        ))}
      </Row>
    </StyledStickyTable>
    <Legend>
      MCQ: Multiple Choice Question (auto-graded);
      WRQ: Written Response Question (manually-graded);
      Tutor: OpenStax Tutor Beta selection (MCQs and auto-graded)
    </Legend>

    {ux.isExercisesReady ? (
      <HomeworkQuestions
        questionsInfo={scores.questionsInfo}
        questionType="teacher-review"
        headerContentRenderer={(props) => <QuestionHeader ux={ux} {...props} />}
        questionInfoRenderer={(props) => <QuestionFreeResponse ux={ux} {...props} />}
        footerContentRenderer={(props) => <QuestionFooter ux={ux} {...props} />}
        styleVariant="submission"
      />) : <Loading message="Loading Questions…"/>}

  </Wrapper>
));

Overview.title = 'Submission Overview';
Overview.propTypes = {
  ux: PropTypes.object.isRequired,
};

export default Overview;
<|endoftext|>


<commit_before>var path = require('path'),
    url = require('url'),
    async = require('async'),
    exec = require('child_process').exec,
    icomoonPath = require.resolve('icomoon-phantomjs'),
    vm = require('vm'),
    Tempfile = require('temporary/lib/file'),
    request = require('request'),
    Zip = require('node-zip');

function IcoMoonPhantomJsEngine(options) {
  // Create a place to store files
  this.files = [];
}
IcoMoonPhantomJsEngine.prototype = {
  // Method to add new SVGs
  addSvg: function (file, cb) {
    // Save the path for later
    this.files.push(file);
    cb();
  },
  // Method to export resulting fonts/map
  'export': function (callback) {
    // Set up shared variables
    var files = this.files,
        tmp,
        zipFiles,
        namespace,
        retObj = {};

    // In series
    async.waterfall([
      // Write paths to file
      function writeTmpFile (cb) {
        tmp = new Tempfile();
        tmp.writeFile(JSON.stringify(files), 'utf8', cb);
      },
      // Invoke icomoon-phantomjs
      function execIcoMoon (cb) {
        var tmpPath = tmp.path;
        // TODO: Move onto programatic API once its coded
        exec('phantomjs ' + icomoonPath + ' ' + tmpPath, cb);
      },
      // Handle any stderr errors
      function handleIcoMoon (stdout, stderr, cb) {
        // If there is an stderr
        if (stderr) {
          // Strip out lines that are complaints about fonts
          // https://github.com/twolfson/grunt-fontsmith/issues/10
          var errLines = stderr.split(/\n/g);
          var validErrLines = errLines.filter(function (line) {
            return line.match(/(WARNING: Method userSpaceScaleFactor|CoreText performance note:)/) === null;
          });

          // If there still is an error, callback with it
          if (validErrLines.length) {
            var err = new Error(validErrLines.join('\n'));
            return cb(err);
          }
        }

        // Otherwise, continue with stdout
        cb(null, stdout);
      },
      // Download our zip
      function downloadIcoMoonZip (zipUrl, cb) {
        request({'url': zipUrl, 'encoding': 'binary'}, cb);
      },
      // Parse out the zip
      function extractZip (res, body, cb) {
        // Prepare the zip files for easier interfacing
        var zip = new Zip(body),
            urlPath = res.request.path;

        // Save the namespace and zipFiles for further iterations
        namespace = path.basename(urlPath, '.zip');
        zipFiles = zip.files;

        // Continue to the next section
        cb();
      },
      // Pluck out fonts
      function pluckFonts (cb) {
        retObj.fonts = {
          svg: zipFiles[namespace + '/fonts/icomoon.svg'].data,
          ttf: zipFiles[namespace + '/fonts/icomoon.ttf'].data,
          woff: zipFiles[namespace + '/fonts/icomoon.woff'].data,
          eot: zipFiles[namespace + '/fonts/icomoon.eot'].data,
          'dev-svg': zipFiles[namespace + '/fonts/icomoon.dev.svg'].data
        };
        cb();
      },
      // Extract mapping for SVGs
      function pluckMapping (cb) {
        // Grab the substring of IE JS that specifies a filename mapping
        var ieJs = zipFiles[namespace + '/lte-ie7.js'].data,
            iconsVarSubstr = ieJs.match(/var\s*icons[^\}]+}/)[0];
            iconWindow = {};
        vm.runInNewContext(iconsVarSubstr, iconWindow);

        // Pluck out namespaced keys and get off of HTML entities
        var iconNamespaceObj = iconWindow.icons,
            iconNamespaceKeys = Object.getOwnPropertyNames(iconNamespaceObj),
            iconObj = {};
        iconNamespaceKeys.forEach(function (nsKey) {
          var key = nsKey.replace('icon-', ''),
              strVal = iconNamespaceObj[nsKey].replace('&#x', '').replace(';'),
              val = parseInt(strVal, 16);
          iconObj[key] = val;
        });

        // Save the normalized iconKey
        retObj.map = iconObj;

        // Continue
        cb();
      },
      // Callback with the formalized object
      function callbackWithResults (cb) {
        cb(null, retObj);
      }
    ], callback);
  }
};

// Async function to create a new engine
function createPalette(options, cb) {
  var palette = new IcoMoonPhantomJsEngine(options);
  cb(null, palette);
}

// Expose create and our engine
module.exports = {
  create: createPalette,
  IcoMoonPhantomJsEngine: IcoMoonPhantomJsEngine
};<commit_msg>Stripping out empty lines<commit_after>var path = require('path'),
    url = require('url'),
    async = require('async'),
    exec = require('child_process').exec,
    icomoonPath = require.resolve('icomoon-phantomjs'),
    vm = require('vm'),
    Tempfile = require('temporary/lib/file'),
    request = require('request'),
    Zip = require('node-zip');

function IcoMoonPhantomJsEngine(options) {
  // Create a place to store files
  this.files = [];
}
IcoMoonPhantomJsEngine.prototype = {
  // Method to add new SVGs
  addSvg: function (file, cb) {
    // Save the path for later
    this.files.push(file);
    cb();
  },
  // Method to export resulting fonts/map
  'export': function (callback) {
    // Set up shared variables
    var files = this.files,
        tmp,
        zipFiles,
        namespace,
        retObj = {};

    // In series
    async.waterfall([
      // Write paths to file
      function writeTmpFile (cb) {
        tmp = new Tempfile();
        tmp.writeFile(JSON.stringify(files), 'utf8', cb);
      },
      // Invoke icomoon-phantomjs
      function execIcoMoon (cb) {
        var tmpPath = tmp.path;
        // TODO: Move onto programatic API once its coded
        exec('phantomjs ' + icomoonPath + ' ' + tmpPath, cb);
      },
      // Handle any stderr errors
      function handleIcoMoon (stdout, stderr, cb) {
        // If there is an stderr
        if (stderr) {
          // Strip out lines that are complaints about fonts
          // https://github.com/twolfson/grunt-fontsmith/issues/10
          var errLines = stderr.split(/\n/g);
          var validErrLines = errLines.filter(function (line) {
            if (line.match(/(WARNING: Method userSpaceScaleFactor|CoreText performance note:)/)) {
              return false;
            }

            // Filter out falsy (empty) lines
            return line;
          });

          // If there still is an error, callback with it
          if (validErrLines.length) {
            var err = new Error(validErrLines.join('\n'));
            return cb(err);
          }
        }

        // Otherwise, continue with stdout
        cb(null, stdout);
      },
      // Download our zip
      function downloadIcoMoonZip (zipUrl, cb) {
        request({'url': zipUrl, 'encoding': 'binary'}, cb);
      },
      // Parse out the zip
      function extractZip (res, body, cb) {
        // Prepare the zip files for easier interfacing
        var zip = new Zip(body),
            urlPath = res.request.path;

        // Save the namespace and zipFiles for further iterations
        namespace = path.basename(urlPath, '.zip');
        zipFiles = zip.files;

        // Continue to the next section
        cb();
      },
      // Pluck out fonts
      function pluckFonts (cb) {
        retObj.fonts = {
          svg: zipFiles[namespace + '/fonts/icomoon.svg'].data,
          ttf: zipFiles[namespace + '/fonts/icomoon.ttf'].data,
          woff: zipFiles[namespace + '/fonts/icomoon.woff'].data,
          eot: zipFiles[namespace + '/fonts/icomoon.eot'].data,
          'dev-svg': zipFiles[namespace + '/fonts/icomoon.dev.svg'].data
        };
        cb();
      },
      // Extract mapping for SVGs
      function pluckMapping (cb) {
        // Grab the substring of IE JS that specifies a filename mapping
        var ieJs = zipFiles[namespace + '/lte-ie7.js'].data,
            iconsVarSubstr = ieJs.match(/var\s*icons[^\}]+}/)[0];
            iconWindow = {};
        vm.runInNewContext(iconsVarSubstr, iconWindow);

        // Pluck out namespaced keys and get off of HTML entities
        var iconNamespaceObj = iconWindow.icons,
            iconNamespaceKeys = Object.getOwnPropertyNames(iconNamespaceObj),
            iconObj = {};
        iconNamespaceKeys.forEach(function (nsKey) {
          var key = nsKey.replace('icon-', ''),
              strVal = iconNamespaceObj[nsKey].replace('&#x', '').replace(';'),
              val = parseInt(strVal, 16);
          iconObj[key] = val;
        });

        // Save the normalized iconKey
        retObj.map = iconObj;

        // Continue
        cb();
      },
      // Callback with the formalized object
      function callbackWithResults (cb) {
        cb(null, retObj);
      }
    ], callback);
  }
};

// Async function to create a new engine
function createPalette(options, cb) {
  var palette = new IcoMoonPhantomJsEngine(options);
  cb(null, palette);
}

// Expose create and our engine
module.exports = {
  create: createPalette,
  IcoMoonPhantomJsEngine: IcoMoonPhantomJsEngine
};<|endoftext|>


<commit_before>import fs from 'fs';
import path from 'path';
import util from './Util';
import Promise from 'bluebird';

var VirtualBox = {
  command: function () {
    if (util.isWindows()) {
      if (process.env.VBOX_MSI_INSTALL_PATH) {
        return path.join(process.env.VBOX_MSI_INSTALL_PATH, 'VBoxManage.exe');
      } else {
        return path.join(process.env.VBOX_INSTALL_PATH, 'VBoxManage.exe');
      }
    } else {
      return '/Applications/VirtualBox.app/Contents/MacOS/VBoxManage';
    }
  },
  installed: function () {
    if (util.isWindows()) {
      return (process.env.VBOX_MSI_INSTALL_PATH && fs.existsSync(path.join(process.env.VBOX_MSI_INSTALL_PATH, 'VBoxManage.exe'))) ||
             (process.env.VBOX_INSTALL_PATH && fs.existsSync(path.join(process.env.VBOX_INSTALL_PATH, 'VBoxManage.exe')));
    } else {
      return fs.existsSync('/Applications/VirtualBox.app') && fs.existsSync('/Applications/VirtualBox.app/Contents/MacOS/VBoxManage');
    }
  },
  active: function () {
    return fs.existsSync('/dev/vboxnetctl');
  },
  version: function () {
    return new Promise((resolve, reject) => {
      util.exec([this.command(), '-v']).then(stdout => {
        var match = stdout.match(/(\d+\.\d+\.\d+).*/);
        if (!match || match.length < 2) {
          reject('VBoxManage -v output format not recognized.');
        }
        resolve(match[1]);
      }).catch(reject);
    });
  },
  poweroffall: function () {
    return util.exec(this.command() + ' list runningvms | sed -E \'s/.*\\{(.*)\\}/\\1/\' | xargs -L1 -I {} ' + this.command() + ' controlvm {} poweroff');
  },
  mountSharedDir: function (vmName, pathName, hostPath) {
    return util.exec([this.command(), 'sharedfolder', 'add', vmName, '--name', pathName, '--hostpath', hostPath, '--automount']);
  },
  killall: function () {
    if (util.isWindows()) {
      return this.poweroffall().then(() => {
        return util.exec(['powershell.exe', '\"get-process VBox* | stop-process\"']);
      }).catch(() => {});
    } else {
      return this.poweroffall().then(() => {
        return util.exec(['pkill', 'VirtualBox']);
      }).then(() => {
        return util.exec(['pkill', 'VBox']);
      }).catch(() => {

      });
    }
  },
  vmExists: function (name) {
    return util.exec([this.command(), 'showvminfo', name]).then(() => {
      return true;
    }).catch((err) => {
      return false;
    });
  }
};

module.exports = VirtualBox;
<commit_msg>Better error & retry tracking in Kitematic<commit_after>import fs from 'fs';
import path from 'path';
import util from './Util';
import Promise from 'bluebird';

var VirtualBox = {
  command: function () {
    if (util.isWindows()) {
      if (process.env.VBOX_MSI_INSTALL_PATH) {
        return path.join(process.env.VBOX_MSI_INSTALL_PATH, 'VBoxManage.exe');
      } else {
        return path.join(process.env.VBOX_INSTALL_PATH, 'VBoxManage.exe');
      }
    } else {
      return '/Applications/VirtualBox.app/Contents/MacOS/VBoxManage';
    }
  },
  installed: function () {
    if (util.isWindows()) {
      return (process.env.VBOX_MSI_INSTALL_PATH && fs.existsSync(path.join(process.env.VBOX_MSI_INSTALL_PATH, 'VBoxManage.exe'))) ||
             (process.env.VBOX_INSTALL_PATH && fs.existsSync(path.join(process.env.VBOX_INSTALL_PATH, 'VBoxManage.exe')));
    } else {
      return fs.existsSync('/Applications/VirtualBox.app') && fs.existsSync('/Applications/VirtualBox.app/Contents/MacOS/VBoxManage');
    }
  },
  active: function () {
    return fs.existsSync('/dev/vboxnetctl');
  },
  version: function () {
    return new Promise((resolve, reject) => {
      util.exec([this.command(), '-v']).then(stdout => {
        var match = stdout.match(/(\d+\.\d+\.\d+).*/);
        if (!match || match.length < 2) {
          reject('VBoxManage -v output format not recognized.');
        }
        resolve(match[1]);
      }).catch(() => {
        resolve(null);
      });
    });
  },
  poweroffall: function () {
    return util.exec(this.command() + ' list runningvms | sed -E \'s/.*\\{(.*)\\}/\\1/\' | xargs -L1 -I {} ' + this.command() + ' controlvm {} poweroff');
  },
  mountSharedDir: function (vmName, pathName, hostPath) {
    return util.exec([this.command(), 'sharedfolder', 'add', vmName, '--name', pathName, '--hostpath', hostPath, '--automount']);
  },
  killall: function () {
    if (util.isWindows()) {
      return this.poweroffall().then(() => {
        return util.exec(['powershell.exe', '\"get-process VBox* | stop-process\"']);
      }).catch(() => {});
    } else {
      return this.poweroffall().then(() => {
        return util.exec(['pkill', 'VirtualBox']);
      }).then(() => {
        return util.exec(['pkill', 'VBox']);
      }).catch(() => {

      });
    }
  },
  vmExists: function (name) {
    return util.exec([this.command(), 'showvminfo', name]).then(() => {
      return true;
    }).catch((err) => {
      return false;
    });
  }
};

module.exports = VirtualBox;
<|endoftext|>


<commit_before>import React from 'react'

import SPaginationInfo from './pagination-info'
import SPagination from './pagination'
import SMaterialsList from './materials-list'

export default class SearchResultGroup extends React.Component {
  constructor (props) {
    super(props)
    this.state = Object.assign({ loading: false }, this.props)
    this.onPaginationSelect = this.onPaginationSelect.bind(this)
    this.updateState = this.updateState.bind(this)
  }

  onPaginationSelect (page) {
    if (page !== this.state.group.pagination.current_page) {
      jQuery(`#${this.pageParam}`).val(page)
      let query = jQuery('#material_search_form').serialize()

      window.updateSearchUrl(query)

      // strip out all material_types[] params
      query = query.replace(/(^|&)material_types(\[|%5B)(\]|%5D)=[^&]*/g, '')

      // add back the one for this group"s material type
      query += `&material_types[]=${this.materialType}`

      jQuery.ajax({
        dataType: 'json',
        url: Portal.API_V1.SEARCH,
        data: query,
        success: response => this.updateState(response)
      })

      this.setState({ loading: true })
    }
  }

  updateState (groupData) {
    this.setState({ group: groupData.results[0] })
  }

  renderLoading () {
    return (

Finding materials...

    )
  }

  renderResults () {
    const { group } = this.state
    return (

          <SPaginationInfo info={group.pagination} />

        <SPagination info={group.pagination} onSelect={this.onPaginationSelect} />
        <SMaterialsList materials={group.materials} />

        <SPagination info={group.pagination} onSelect={this.onPaginationSelect} />

    )
  }

  render () {
    const { group } = this.state
    switch (group.type) {
      case 'investigations':
        this.materialType = 'Investigation'
        this.pageParam = 'investigation_page'
        break
      case 'activities':
        this.materialType = 'Activity'
        this.pageParam = 'activity_page'
        break
      case 'interactives':
        this.materialType = 'Interactive'
        this.pageParam = 'interactive_page'
        break
      case 'collections':
        this.materialType = 'Collection'
        this.pageParam = 'collection_page'
        break
      default:
        throw new Error('unknown group type')
    }

    return (
      <div id={`${group.type}_bookmark`} className={`materials_container ${group.type}`}>

{group.header}

        {this.state.loading ? this.renderLoading() : this.renderResults()}

    )
  }
}
<commit_msg>Reset loading to false on search results load [#173780068]<commit_after>import React from 'react'

import SPaginationInfo from './pagination-info'
import SPagination from './pagination'
import SMaterialsList from './materials-list'

export default class SearchResultGroup extends React.Component {
  constructor (props) {
    super(props)
    this.state = Object.assign({ loading: false }, this.props)
    this.onPaginationSelect = this.onPaginationSelect.bind(this)
    this.updateState = this.updateState.bind(this)
  }

  onPaginationSelect (page) {
    if (page !== this.state.group.pagination.current_page) {
      jQuery(`#${this.pageParam}`).val(page)
      let query = jQuery('#material_search_form').serialize()

      window.updateSearchUrl(query)

      // strip out all material_types[] params
      query = query.replace(/(^|&)material_types(\[|%5B)(\]|%5D)=[^&]*/g, '')

      // add back the one for this group"s material type
      query += `&material_types[]=${this.materialType}`

      jQuery.ajax({
        dataType: 'json',
        url: Portal.API_V1.SEARCH,
        data: query,
        success: response => this.updateState(response)
      })

      this.setState({ loading: true })
    }
  }

  updateState (groupData) {
    this.setState({ loading: false, group: groupData.results[0] })
  }

  renderLoading () {
    return (

Finding materials...

    )
  }

  renderResults () {
    const { group } = this.state
    return (

          <SPaginationInfo info={group.pagination} />

        <SPagination info={group.pagination} onSelect={this.onPaginationSelect} />
        <SMaterialsList materials={group.materials} />

        <SPagination info={group.pagination} onSelect={this.onPaginationSelect} />

    )
  }

  render () {
    const { group } = this.state
    switch (group.type) {
      case 'investigations':
        this.materialType = 'Investigation'
        this.pageParam = 'investigation_page'
        break
      case 'activities':
        this.materialType = 'Activity'
        this.pageParam = 'activity_page'
        break
      case 'interactives':
        this.materialType = 'Interactive'
        this.pageParam = 'interactive_page'
        break
      case 'collections':
        this.materialType = 'Collection'
        this.pageParam = 'collection_page'
        break
      default:
        throw new Error('unknown group type')
    }

    return (
      <div id={`${group.type}_bookmark`} className={`materials_container ${group.type}`}>

{group.header}

        {this.state.loading ? this.renderLoading() : this.renderResults()}

    )
  }
}
<|endoftext|>


<commit_before>/*!
 * Express Session RethinkDB
 * MIT Licensed
 */

var r = require('rethinkdbdash');

module.exports = function (session) {
  var Store = session.Store;

  function RethinkStore(options) {
    options = options || {};
    options.clientOptions = options.clientOptions || {};
    Store.call(this, options);

    r.connect(options.clientOptions);

    this.emit('connect');
    this.browserSessionsMaxAge = options.browserSessionsMaxAge || 86400000; // 1 day
    this.table = options.table || 'session';
    setInterval( function() {
      var now = (new Date()).getTime();
      try {
        r.table(this.table).filter(r.row('expires').lt(now)).delete().run();
      }
      catch (error) {
        console.error( error );
      }
    }.bind( this ), options.maxAge || 60000 );
  }

  RethinkStore.prototype = new Store();

  // Get Session
  RethinkStore.prototype.get = function (sid, fn) {
    r.table(this.table).get(sid).run().then(function (data) {
      return data ? JSON.parse(data.session) : null;
    }).error( function (err) {
      fn(err);
    });
  }

  // Set Session
  RethinkStore.prototype.set = function (sid, sess, fn) {
    var sessionToStore = {
      id: sid,
      expires: (new Date()).getTime() + (sess.cookie.originalMaxAge || this.browserSessionsMaxAge),
      session: JSON.stringify(sess)
    };
    r.table(this.table).insert(sessionToStore, { conflict: 'update' }).run().then(function (data) {
      fn();
    }).error( function (err) {
      fn(err);
    });
  };

  // Destroy Session
  RethinkStore.prototype.destroy = function (sid, fn) {
    r.table(this.table).get(sid).delete().run().then(function (data) {
      fn();
    }, function (err) {
      fn(err);
    });
  };

  return RethinkStore;
}
<commit_msg>Converted over to use the rethinkdbdash driver<commit_after>/*!
 * Express Session RethinkDB
 * MIT Licensed
 */

var rethinkdb = require('rethinkdbdash');

module.exports = function (session) {
  var Store = session.Store;

  function RethinkStore(options) {
    options = options || {};
    options.clientOptions = options.clientOptions || {};
    Store.call(this, options);

    r = new rethinkdb(options.clientOptions);

    this.emit('connect');
    this.browserSessionsMaxAge = options.browserSessionsMaxAge || 86400000; // 1 day
    this.table = options.table || 'session';
    setInterval( function() {
      var now = (new Date()).getTime();
      try {
        r.table(this.table).filter(r.row('expires').lt(now)).delete().run();
      }
      catch (error) {
        console.error( error );
      }
    }.bind( this ), options.maxAge || 60000 );
  }

  RethinkStore.prototype = new Store();

  // Get Session
  RethinkStore.prototype.get = function (sid, fn) {
    r.table(this.table).get(sid).run().then(function (data) {
      fn( null, data ? JSON.parse(data.session) : null );
    }).error( function (err) {
      fn(err);
    });
  }

  // Set Session
  RethinkStore.prototype.set = function (sid, sess, fn) {
    var sessionToStore = {
      id: sid,
      expires: (new Date()).getTime() + (sess.cookie.originalMaxAge || this.browserSessionsMaxAge),
      session: JSON.stringify(sess)
    };
    r.table(this.table).insert(sessionToStore, { conflict: 'update' }).run().then(function (data) {
      fn();
    }).error( function (err) {
      fn(err);
    });
  };

  // Destroy Session
  RethinkStore.prototype.destroy = function (sid, fn) {
    r.table(this.table).get(sid).delete().run().then(function (data) {
      fn();
    }).error( function (err) {
      fn(err);
    });
  };

  return RethinkStore;
}
<|endoftext|>


<commit_before>import flattenObject from './flatten-object';

/**
 * Cleans XML parsed JSON from MAL.
 *
 * @example
 * cleanApiData({ anime: { entry: [ { key: ['value'] } ] } })
 * [ { key: 'value' } ]
 *
 * cleanApiData({ manga: { entry: [ { key: ['value'] } ] } })
 * [ { key: 'value' } ]
 *
 * cleanApiData({ user: { key: ['value'] } })
 * { key: 'value' }
 *
 * @param  {object} data - MyAnimeList's API parsed XML
 * @return {object} - Good looking object
 */
export default function cleanApiData(data) {
	if (data === null) {
		return data;
	}

	let newData = data.anime || data.manga || data.user || data;

	if (Array.isArray(newData.entry)) {
		newData.entry.map(flattenObject);
		newData = newData.entry;
	} else if (typeof newData === 'object') {
		newData = flattenObject(newData);
	}

	return newData;
}
<commit_msg>Clean search API responses<commit_after>import flattenObject from './flatten-object';

/**
 * Cleans XML parsed JSON from MAL.
 *
 * @example
 * cleanApiData({ anime: { entry: [ { key: ['value'] } ] } })
 * [ { key: 'value' } ]
 *
 * cleanApiData({ manga: { entry: [ { key: ['value'] } ] } })
 * [ { key: 'value' } ]
 *
 * cleanApiData({ user: { key: ['value'] } })
 * { key: 'value' }
 *
 * @param  {object} data - MyAnimeList's API parsed XML
 * @return {object} - Good looking object
 */
export default function cleanApiData(data) {
	if (data === null) {
		return data;
	}

	let newData = data.anime || data.manga || data.user || data;

	if (Array.isArray(newData.entry)) {
		newData = newData.entry.map(flattenObject);
	} else if (typeof newData === 'object') {
		newData = flattenObject(newData);
	}

	return newData;
}
<|endoftext|>


<commit_before>/* jshint node: true */
/* global require, module */

var EmberAddon = require('ember-cli/lib/broccoli/ember-addon');

var app = new EmberAddon();

// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.

module.exports = app.toTree();
<commit_msg>brocfile deprecation<commit_after><|endoftext|>


<commit_before>import { h, ref, computed, watch, toRaw, getCurrentInstance } from 'vue'

import QDialog from '../dialog/QDialog.js'
import QBtn from '../btn/QBtn.js'

import QCard from '../card/QCard.js'
import QCardSection from '../card/QCardSection.js'
import QCardActions from '../card/QCardActions.js'
import QSeparator from '../separator/QSeparator.js'

import QInput from '../input/QInput.js'
import QOptionGroup from '../option-group/QOptionGroup.js'

import QSpinner from '../spinner/QSpinner.js'

import { createComponent } from '../../utils/private/create.js'
import useDark, { useDarkProps } from '../../composables/private/use-dark.js'

import { isKeyCode } from '../../utils/private/key-composition.js'
import { isObject } from '../../utils/private/is.js'

export default createComponent({
  name: 'DialogPlugin',

  props: {
    ...useDarkProps,

    title: String,
    message: String,
    prompt: Object,
    options: Object,
    progress: [ Boolean, Object ],

    html: Boolean,

    ok: {
      type: [ String, Object, Boolean ],
      default: true
    },
    cancel: [ String, Object, Boolean ],
    focus: {
      type: String,
      default: 'ok',
      validator: v => [ 'ok', 'cancel', 'none' ].includes(v)
    },

    stackButtons: Boolean,
    color: String,

    cardClass: [ String, Array, Object ],
    cardStyle: [ String, Array, Object ]
  },

  emits: [ 'ok', 'hide' ],

  setup (props, { emit }) {
    const { proxy } = getCurrentInstance()
    const { $q } = proxy

    const isDark = useDark(props, $q)

    const dialogRef = ref(null)

    const model = ref(
      props.prompt !== void 0
        ? props.prompt.model
        : (props.options !== void 0 ? props.options.model : void 0)
    )

    const classes = computed(() =>
      'q-dialog-plugin'
      + (isDark.value === true ? ' q-dialog-plugin--dark q-dark' : '')
      + (props.progress !== false ? ' q-dialog-plugin--progress' : '')
    )

    const vmColor = computed(() =>
      props.color || (isDark.value === true ? 'amber' : 'primary')
    )

    const spinner = computed(() => (
      props.progress === false
        ? null
        : (
            isObject(props.progress) === true
              ? {
                  component: props.progress.spinner || QSpinner,
                  props: { color: props.progress.color || vmColor.value }
                }
              : {
                  component: QSpinner,
                  props: { color: vmColor.value }
                }
          )
    ))

    const hasForm = computed(() =>
      props.prompt !== void 0 || props.options !== void 0
    )

    const formProps = computed(() => {
      if (hasForm.value !== true) {
        return {}
      }

      const { model, isValid, items, ...formProps } = props.prompt !== void 0
        ? props.prompt
        : props.options

      return formProps
    })

    const okLabel = computed(() => (
      isObject(props.ok) === true
        ? $q.lang.label.ok
        : (
            props.ok === true
              ? $q.lang.label.ok
              : props.ok
          )
    ))

    const cancelLabel = computed(() => (
      isObject(props.cancel) === true
        ? $q.lang.label.cancel
        : (
            props.cancel === true
              ? $q.lang.label.cancel
              : props.cancel
          )
    ))

    const okDisabled = computed(() => {
      if (props.prompt !== void 0) {
        return props.prompt.isValid !== void 0
          && props.prompt.isValid(model.value) !== true
      }
      if (props.options !== void 0) {
        return props.options.isValid !== void 0
          && props.options.isValid(model.value) !== true
      }
      return false
    })

    const okProps = computed(() => ({
      color: vmColor.value,
      label: okLabel.value,
      ripple: false,
      disable: okDisabled.value,
      ...(isObject(props.ok) === true ? props.ok : { flat: true }),
      'data-autofocus': (props.focus === 'ok' && hasForm.value !== true) || void 0,
      onClick: onOk
    }))

    const cancelProps = computed(() => ({
      color: vmColor.value,
      label: cancelLabel.value,
      ripple: false,
      ...(isObject(props.cancel) === true ? props.cancel : { flat: true }),
      'data-autofocus': (props.focus === 'cancel' && hasForm.value !== true) || void 0,
      onClick: onCancel
    }))

    watch(() => props.prompt && props.prompt.model, onUpdateModel)
    watch(() => props.options && props.options.model, onUpdateModel)

    function show () {
      dialogRef.value.show()
    }

    function hide () {
      dialogRef.value.hide()
    }

    function onOk () {
      emit('ok', toRaw(model.value))
      hide()
    }

    function onCancel () {
      hide()
    }

    function onDialogHide () {
      emit('hide')
    }

    function onUpdateModel (val) {
      model.value = val
    }

    function onInputKeyup (evt) {
      // if ENTER key
      if (
        okDisabled.value !== true
        && props.prompt.type !== 'textarea'
        && isKeyCode(evt, 13) === true
      ) {
        onOk()
      }
    }

    function getSection (classes, text) {
      return props.html === true
        ? h(QCardSection, {
          class: classes,
          innerHTML: text
        })
        : h(QCardSection, { class: classes }, () => text)
    }

    function getPrompt () {
      return [
        h(QInput, {
          modelValue: model.value,
          ...formProps.value,
          color: vmColor.value,
          dense: true,
          autofocus: true,
          dark: isDark.value,
          'onUpdate:modelValue': onUpdateModel,
          onKeyup: onInputKeyup
        })
      ]
    }

    function getOptions () {
      return [
        h(QOptionGroup, {
          modelValue: model.value,
          ...formProps.value,
          color: vmColor.value,
          options: props.options.items,
          dark: isDark.value,
          'onUpdate:modelValue': onUpdateModel
        })
      ]
    }

    function getButtons () {
      const child = []

      props.cancel && child.push(
        h(QBtn, cancelProps.value)
      )

      props.ok && child.push(
        h(QBtn, okProps.value)
      )

      return h(QCardActions, {
        class: props.stackButtons === true ? 'items-end' : '',
        vertical: props.stackButtons,
        align: 'right'
      }, () => child)
    }

    function getCardContent () {
      const child = []

      props.title && child.push(
        getSection('q-dialog__title', props.title)
      )

      props.progress !== false && child.push(
        h(
          QCardSection,
          { class: 'q-dialog__progress' },
          () => h(spinner.value.component, spinner.value.props)
        )
      )

      props.message && child.push(
        getSection('q-dialog__message', props.message)
      )

      if (props.prompt !== void 0) {
        child.push(
          h(
            QCardSection,
            { class: 'scroll q-dialog-plugin__form' },
            getPrompt
          )
        )
      }
      else if (props.options !== void 0) {
        child.push(
          h(QSeparator, { dark: isDark.value }),
          h(
            QCardSection,
            { class: 'scroll q-dialog-plugin__form' },
            getOptions
          ),
          h(QSeparator, { dark: isDark.value })
        )
      }

      if (props.ok || props.cancel) {
        child.push(getButtons())
      }

      return child
    }

    function getContent () {
      return [
        h(QCard, {
          class: [
            classes.value,
            props.cardClass
          ],
          style: props.cardStyle,
          dark: isDark.value
        }, getCardContent)
      ]
    }

    // expose public methods
    Object.assign(proxy, { show, hide })

    return () => h(QDialog, {
      ref: dialogRef,
      onHide: onDialogHide
    }, getContent)
  }
})
<commit_msg>fix(DialogPlugin): switch positions of OK and Cancel for accessibility/focus #12871<commit_after>import { h, ref, computed, watch, toRaw, getCurrentInstance } from 'vue'

import QDialog from '../dialog/QDialog.js'
import QBtn from '../btn/QBtn.js'

import QCard from '../card/QCard.js'
import QCardSection from '../card/QCardSection.js'
import QCardActions from '../card/QCardActions.js'
import QSeparator from '../separator/QSeparator.js'

import QInput from '../input/QInput.js'
import QOptionGroup from '../option-group/QOptionGroup.js'

import QSpinner from '../spinner/QSpinner.js'

import { createComponent } from '../../utils/private/create.js'
import useDark, { useDarkProps } from '../../composables/private/use-dark.js'

import { isKeyCode } from '../../utils/private/key-composition.js'
import { isObject } from '../../utils/private/is.js'

export default createComponent({
  name: 'DialogPlugin',

  props: {
    ...useDarkProps,

    title: String,
    message: String,
    prompt: Object,
    options: Object,
    progress: [ Boolean, Object ],

    html: Boolean,

    ok: {
      type: [ String, Object, Boolean ],
      default: true
    },
    cancel: [ String, Object, Boolean ],
    focus: {
      type: String,
      default: 'ok',
      validator: v => [ 'ok', 'cancel', 'none' ].includes(v)
    },

    stackButtons: Boolean,
    color: String,

    cardClass: [ String, Array, Object ],
    cardStyle: [ String, Array, Object ]
  },

  emits: [ 'ok', 'hide' ],

  setup (props, { emit }) {
    const { proxy } = getCurrentInstance()
    const { $q } = proxy

    const isDark = useDark(props, $q)

    const dialogRef = ref(null)

    const model = ref(
      props.prompt !== void 0
        ? props.prompt.model
        : (props.options !== void 0 ? props.options.model : void 0)
    )

    const classes = computed(() =>
      'q-dialog-plugin'
      + (isDark.value === true ? ' q-dialog-plugin--dark q-dark' : '')
      + (props.progress !== false ? ' q-dialog-plugin--progress' : '')
    )

    const vmColor = computed(() =>
      props.color || (isDark.value === true ? 'amber' : 'primary')
    )

    const spinner = computed(() => (
      props.progress === false
        ? null
        : (
            isObject(props.progress) === true
              ? {
                  component: props.progress.spinner || QSpinner,
                  props: { color: props.progress.color || vmColor.value }
                }
              : {
                  component: QSpinner,
                  props: { color: vmColor.value }
                }
          )
    ))

    const hasForm = computed(() =>
      props.prompt !== void 0 || props.options !== void 0
    )

    const formProps = computed(() => {
      if (hasForm.value !== true) {
        return {}
      }

      const { model, isValid, items, ...formProps } = props.prompt !== void 0
        ? props.prompt
        : props.options

      return formProps
    })

    const okLabel = computed(() => (
      isObject(props.ok) === true
        ? $q.lang.label.ok
        : (
            props.ok === true
              ? $q.lang.label.ok
              : props.ok
          )
    ))

    const cancelLabel = computed(() => (
      isObject(props.cancel) === true
        ? $q.lang.label.cancel
        : (
            props.cancel === true
              ? $q.lang.label.cancel
              : props.cancel
          )
    ))

    const okDisabled = computed(() => {
      if (props.prompt !== void 0) {
        return props.prompt.isValid !== void 0
          && props.prompt.isValid(model.value) !== true
      }
      if (props.options !== void 0) {
        return props.options.isValid !== void 0
          && props.options.isValid(model.value) !== true
      }
      return false
    })

    const okProps = computed(() => ({
      color: vmColor.value,
      label: okLabel.value,
      ripple: false,
      disable: okDisabled.value,
      ...(isObject(props.ok) === true ? props.ok : { flat: true }),
      'data-autofocus': (props.focus === 'ok' && hasForm.value !== true) || void 0,
      onClick: onOk
    }))

    const cancelProps = computed(() => ({
      color: vmColor.value,
      label: cancelLabel.value,
      ripple: false,
      ...(isObject(props.cancel) === true ? props.cancel : { flat: true }),
      'data-autofocus': (props.focus === 'cancel' && hasForm.value !== true) || void 0,
      onClick: onCancel
    }))

    watch(() => props.prompt && props.prompt.model, onUpdateModel)
    watch(() => props.options && props.options.model, onUpdateModel)

    function show () {
      dialogRef.value.show()
    }

    function hide () {
      dialogRef.value.hide()
    }

    function onOk () {
      emit('ok', toRaw(model.value))
      hide()
    }

    function onCancel () {
      hide()
    }

    function onDialogHide () {
      emit('hide')
    }

    function onUpdateModel (val) {
      model.value = val
    }

    function onInputKeyup (evt) {
      // if ENTER key
      if (
        okDisabled.value !== true
        && props.prompt.type !== 'textarea'
        && isKeyCode(evt, 13) === true
      ) {
        onOk()
      }
    }

    function getSection (classes, text) {
      return props.html === true
        ? h(QCardSection, {
          class: classes,
          innerHTML: text
        })
        : h(QCardSection, { class: classes }, () => text)
    }

    function getPrompt () {
      return [
        h(QInput, {
          modelValue: model.value,
          ...formProps.value,
          color: vmColor.value,
          dense: true,
          autofocus: true,
          dark: isDark.value,
          'onUpdate:modelValue': onUpdateModel,
          onKeyup: onInputKeyup
        })
      ]
    }

    function getOptions () {
      return [
        h(QOptionGroup, {
          modelValue: model.value,
          ...formProps.value,
          color: vmColor.value,
          options: props.options.items,
          dark: isDark.value,
          'onUpdate:modelValue': onUpdateModel
        })
      ]
    }

    function getButtons () {
      const child = []

      props.ok && child.push(
        h(QBtn, okProps.value)
      )

      props.cancel && child.push(
        h(QBtn, cancelProps.value)
      )

      return h(QCardActions, {
        class: props.stackButtons === true ? 'items-end' : '',
        vertical: props.stackButtons,
        align: 'right'
      }, () => child)
    }

    function getCardContent () {
      const child = []

      props.title && child.push(
        getSection('q-dialog__title', props.title)
      )

      props.progress !== false && child.push(
        h(
          QCardSection,
          { class: 'q-dialog__progress' },
          () => h(spinner.value.component, spinner.value.props)
        )
      )

      props.message && child.push(
        getSection('q-dialog__message', props.message)
      )

      if (props.prompt !== void 0) {
        child.push(
          h(
            QCardSection,
            { class: 'scroll q-dialog-plugin__form' },
            getPrompt
          )
        )
      }
      else if (props.options !== void 0) {
        child.push(
          h(QSeparator, { dark: isDark.value }),
          h(
            QCardSection,
            { class: 'scroll q-dialog-plugin__form' },
            getOptions
          ),
          h(QSeparator, { dark: isDark.value })
        )
      }

      if (props.ok || props.cancel) {
        child.push(getButtons())
      }

      return child
    }

    function getContent () {
      return [
        h(QCard, {
          class: [
            classes.value,
            props.cardClass
          ],
          style: props.cardStyle,
          dark: isDark.value
        }, getCardContent)
      ]
    }

    // expose public methods
    Object.assign(proxy, { show, hide })

    return () => h(QDialog, {
      ref: dialogRef,
      onHide: onDialogHide
    }, getContent)
  }
})
<|endoftext|>


<commit_before>/**
 * Created by Jacky.Gao on 2017-10-20.
 */
import Property from './Property.js';
export default class SelectProperty extends Property{
    constructor(report){
        super();
        this.col.append(this.buildBindParameter());
        this.positionLabelGroup=this.buildPositionLabelGroup();
        this.col.append(this.positionLabelGroup);
        this.col.append(this.buildLabelGroup());
        this.optionFormGroup=$("
");
        this.col.append(this.optionFormGroup);
    }
    refreshValue(editor){
        super.refreshValue(editor);
        this.optionFormGroup.empty();
        const group=$(`<div class="form-group"><label>数据来源</label></div>`);
        const datasourceSelect=$(`<select class="form-control">
            <option value="dataset">数据集</option>
            <option value="simple">固定值</option>
        </select>`);
        group.append(datasourceSelect);
        this.optionFormGroup.append(group);
        this.simpleOptionGroup=$(`<div class="form-group"></div>`);
        this.optionFormGroup.append(this.simpleOptionGroup);
        this.datasetGroup=$(`<div class="form-group"></div>`);
        this.optionFormGroup.append(this.datasetGroup);
        const _this=this;
        datasourceSelect.change(function(){
            if($(this).val()==='dataset'){
                editor.useDataset=true;
                _this.datasetGroup.show();
                _this.simpleOptionGroup.hide();
            }else{
                editor.useDataset=false;
                _this.datasetGroup.hide();
                _this.simpleOptionGroup.show();
            }
        });
        const datasetGroup=$(`<div class="form-group"><label>数据集</label></div>`);
        this.datasetGroup.append(datasetGroup);
        const datasetSelect=$(`<select class="form-control"></select>`);
        datasetGroup.append(datasetSelect);
        let dsName=null;
        for(let datasetName of formBuilder.datasetMap.keys()){
            datasetSelect.append(`<option>${datasetName}</option>`);
            dsName=datasetName;
        }
        if(editor.dataset){
            dsName=editor.dataset;
        }else{
            editor.dataset=dsName;
        }
        datasetSelect.val(dsName);
        let fields=formBuilder.datasetMap.get(dsName);
        if(!fields)fields=[];
        const labelGroup=$(`<div class="form-group"><label>显示值字段名</label></div>`);
        this.datasetGroup.append(labelGroup);
        const labelSelect=$(`<select class="form-control"></select>`);
        labelGroup.append(labelSelect);
        const valueGroup=$(`<div class="form-group"><label>实际值字段名</label></div>`);
        this.datasetGroup.append(valueGroup);
        const valueSelect=$(`<select class="form-control"></select>`);
        labelSelect.change(function(){
            editor.labelField=$(this).val();
        });
        valueSelect.change(function(){
            editor.valueField=$(this).val();
        });
        let targetField=null;
        for(let field of fields){
            labelSelect.append(`<option>${field.name}</option>`);
            valueSelect.append(`<option>${field.name}</option>`);
            targetField=field.name;
        }
        if(editor.labelField){
            targetField=editor.labelField;
        }else{
            editor.labelField=targetField;
        }
        labelSelect.val(targetField);
        if(editor.valueField){
            targetField=editor.valueField;
        }else{
            editor.valueField=targetField;
        }
        valueSelect.val(targetField);
        valueGroup.append(valueSelect);
        if(editor.useDataset){
            datasourceSelect.val('dataset');
            this.datasetGroup.show();
            this.simpleOptionGroup.hide();
        }else{
            this.datasetGroup.hide();
            this.simpleOptionGroup.show();
            datasourceSelect.val('simple');
        }
        this.simpleOptionGroup.append($("固定值选项(若显示值与实际值不同，则用“,”分隔，如“是,true”等)"));
        var self=this;
        $.each(editor.options,function(index,option){
            self.addOptionEditor(option);
        });
    }
    addOptionEditor(option){
        var inputGroup=$("
");
        var input=$("<input class='form-control' type='text'>");

        if(option.label===option.value){
            input.val(option.label);
        }else{
            input.val(option.label+","+option.value);
        }

        input.change(function(){
            var value=$(this).val();
            var json={value:value,label:value};
            var array=value.split(",");
            if(array.length==2){
                json.label=array[0];
                json.value=array[1];
            }
            option.setValue(json);
        });
        inputGroup.append(input);
        var addon=$("");
        inputGroup.append(addon);
        var self=this;
        var del=$("

");
        del.click(function(){
            if(self.current.options.length===1){
                bootbox.alert("至少要保留一个列表选项!");
                return;
            }
            self.current.removeOption(option);
            inputGroup.remove();
        });
        addon.append(del);
        var add=$("
");
        add.click(function(){
            var newOption=self.current.addOption();
            self.addOptionEditor(newOption);
        });
        addon.append(add);
        this.simpleOptionGroup.append(inputGroup);
    }
}<commit_msg>修复查询表单设计器数据列表配置时数据源切换属性不变化的BUG<commit_after>/**
 * Created by Jacky.Gao on 2017-10-20.
 */
import Property from './Property.js';
export default class SelectProperty extends Property{
    constructor(report){
        super();
        this.col.append(this.buildBindParameter());
        this.positionLabelGroup=this.buildPositionLabelGroup();
        this.col.append(this.positionLabelGroup);
        this.col.append(this.buildLabelGroup());
        this.optionFormGroup=$("
");
        this.col.append(this.optionFormGroup);
    }
    refreshValue(editor){
        super.refreshValue(editor);
        this.optionFormGroup.empty();
        const group=$(`<div class="form-group"><label>数据来源</label></div>`);
        const datasourceSelect=$(`<select class="form-control">
            <option value="dataset">数据集</option>
            <option value="simple">固定值</option>
        </select>`);
        group.append(datasourceSelect);
        this.optionFormGroup.append(group);
        this.simpleOptionGroup=$(`<div class="form-group"></div>`);
        this.optionFormGroup.append(this.simpleOptionGroup);
        this.datasetGroup=$(`<div class="form-group"></div>`);
        this.optionFormGroup.append(this.datasetGroup);
        const _this=this;
        datasourceSelect.change(function(){
            if($(this).val()==='dataset'){
                editor.useDataset=true;
                _this.datasetGroup.show();
                _this.simpleOptionGroup.hide();
            }else{
                editor.useDataset=false;
                _this.datasetGroup.hide();
                _this.simpleOptionGroup.show();
            }
        });
        const datasetGroup=$(`<div class="form-group"><label>数据集</label></div>`);
        this.datasetGroup.append(datasetGroup);
        const datasetSelect=$(`<select class="form-control"></select>`);
        datasetGroup.append(datasetSelect);
        let dsName=null;
        for(let datasetName of formBuilder.datasetMap.keys()){
            datasetSelect.append(`<option>${datasetName}</option>`);
            dsName=datasetName;
        }
        if(editor.dataset){
            dsName=editor.dataset;
        }else{
            editor.dataset=dsName;
        }
        datasetSelect.val(dsName);
        let fields=formBuilder.datasetMap.get(dsName);
        if(!fields)fields=[];
        const labelGroup=$(`<div class="form-group"><label>显示值字段名</label></div>`);
        this.datasetGroup.append(labelGroup);
        const labelSelect=$(`<select class="form-control"></select>`);
        labelGroup.append(labelSelect);
        const valueGroup=$(`<div class="form-group"><label>实际值字段名</label></div>`);
        this.datasetGroup.append(valueGroup);
        const valueSelect=$(`<select class="form-control"></select>`);
        labelSelect.change(function(){
            editor.labelField=$(this).val();
        });
        valueSelect.change(function(){
            editor.valueField=$(this).val();
        });
        let targetField=null;
        for(let field of fields){
            labelSelect.append(`<option>${field.name}</option>`);
            valueSelect.append(`<option>${field.name}</option>`);
            targetField=field.name;
        }
        datasetSelect.change(function () {
            const dsName=$(this).val();
            if(!dsName){
                return;
            }
            editor.dataset=dsName;
            labelSelect.empty();
            valueSelect.empty();
            fields=formBuilder.datasetMap.get(dsName);
            if(!fields)fields=[];
            for(let field of fields){
                labelSelect.append(`<option>${field.name}</option>`);
                valueSelect.append(`<option>${field.name}</option>`);
                targetField=field.name;
            }
            editor.labelField=targetField;
            editor.valueField=targetField;
            labelSelect.val(targetField);
            valueSelect.val(targetField);
        });
        if(editor.labelField){
            targetField=editor.labelField;
        }else{
            editor.labelField=targetField;
        }
        labelSelect.val(targetField);
        if(editor.valueField){
            targetField=editor.valueField;
        }else{
            editor.valueField=targetField;
        }
        valueSelect.val(targetField);
        valueGroup.append(valueSelect);
        if(editor.useDataset){
            datasourceSelect.val('dataset');
            this.datasetGroup.show();
            this.simpleOptionGroup.hide();
        }else{
            this.datasetGroup.hide();
            this.simpleOptionGroup.show();
            datasourceSelect.val('simple');
        }
        this.simpleOptionGroup.append($("固定值选项(若显示值与实际值不同，则用“,”分隔，如“是,true”等)"));
        var self=this;
        $.each(editor.options,function(index,option){
            self.addOptionEditor(option);
        });
    }
    addOptionEditor(option){
        var inputGroup=$("
");
        var input=$("<input class='form-control' type='text'>");

        if(option.label===option.value){
            input.val(option.label);
        }else{
            input.val(option.label+","+option.value);
        }

        input.change(function(){
            var value=$(this).val();
            var json={value:value,label:value};
            var array=value.split(",");
            if(array.length==2){
                json.label=array[0];
                json.value=array[1];
            }
            option.setValue(json);
        });
        inputGroup.append(input);
        var addon=$("");
        inputGroup.append(addon);
        var self=this;
        var del=$("

");
        del.click(function(){
            if(self.current.options.length===1){
                bootbox.alert("至少要保留一个列表选项!");
                return;
            }
            self.current.removeOption(option);
            inputGroup.remove();
        });
        addon.append(del);
        var add=$("
");
        add.click(function(){
            var newOption=self.current.addOption();
            self.addOptionEditor(newOption);
        });
        addon.append(add);
        this.simpleOptionGroup.append(inputGroup);
    }
}<|endoftext|>


<commit_before>window.emit = function emit() {

  if(window.callPhantom) {
    //we need comverts arguments object into a array to be stringified in phantomjs
    arguments = Array.prototype.slice.call(arguments, 0);
    payload = JSON.stringify(arguments);

    window.callPhantom(payload);
  }
};

window.waitForDOM = function(selector, callback) {
    var checker, observer, checkDOM;
    if(typeof selector === 'function') {
        checkDOM = selector;
    } else if(window.$ === undefined) {
        // You can use this without jQuery, but then you're limited to IDs or
        // passing a function
        if(selector[0] === '#') {
            checkDOM = function() {
                return document.getElementById(selector.substr(1)) !== null;
            }
        } else {
            throw new TypeError("When jQuery isn't installed, you're limited to selectors in the #id form. Or pass your own function!")
        }
    } else {
        checkDOM = function() {
            return checkDOM() !== 0;
        }
    }

    if(checkDOM()) {
        callback();
    } else if(window.MutationObserver !== undefined) {
        observer = new MutationObserver(function() {
            if(checkDOM()) {
                callback();
                observer.disconnect();
            }
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true,
            attributes: true,
            characterData: false
        });
    } else {
        checker = function() {
            if(checkDOM()) {
                return callback();
            } else {
                return Meteor.setTimeout(checker, 50);
            }
        };
        checker();
    }
};
<commit_msg>fix embarrassing search/replace bug in waitForDOM; would crash with jQuery<commit_after>window.emit = function emit() {

  if(window.callPhantom) {
    //we need comverts arguments object into a array to be stringified in phantomjs
    arguments = Array.prototype.slice.call(arguments, 0);
    payload = JSON.stringify(arguments);

    window.callPhantom(payload);
  }
};

window.waitForDOM = function(selector, callback) {
    var checker, observer, checkDOM;
    if(typeof selector === 'function') {
        checkDOM = selector;
    } else if(window.$ === undefined) {
        // You can use this without jQuery, but then you're limited to IDs or
        // passing a function
        if(selector[0] === '#') {
            checkDOM = function() {
                return document.getElementById(selector.substr(1)) !== null;
            }
        } else {
            throw new TypeError("When jQuery isn't installed, you're limited to selectors in the #id form. Or pass your own function!")
        }
    } else {
        checkDOM = function() {
            return $(selector).length !== 0;
        }
    }

    if(checkDOM()) {
        callback();
    } else if(window.MutationObserver !== undefined) {
        observer = new MutationObserver(function() {
            if(checkDOM()) {
                callback();
                observer.disconnect();
            }
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true,
            attributes: true,
            characterData: false
        });
    } else {
        checker = function() {
            if(checkDOM()) {
                return callback();
            } else {
                return Meteor.setTimeout(checker, 50);
            }
        };
        checker();
    }
};
<|endoftext|>


<commit_before>// Start Streamly Radio

// * This function loads the video for the Streamly Radio function

function loadAutoplayData(iteration) {
  autoplayVideos = [];
  autoplayVideoIteration = -1;

  highlight(iteration, "radio", false);
  baseAutoplayVideoId = videos[iteration][2];
  var dataFrame = document.createElement("iframe");
  dataFrame.setAttribute("id", "radioDataFrame");
  dataFrame.setAttribute("src", "");
  document.getElementById("dataFramesContainer").appendChild(dataFrame);
  radioDataPlayer = new YT.Player('radioDataFrame', {
    events: {
      'onReady': onRadioDataPlayerReady,
      'onStateChange': onRadioDataPlayerStateChange
    }
  });
  dataFrame.setAttribute("src", "https://www.youtube.com/embed/" + baseAutoplayVideoId + "?enablejsapi=1");
}

// * This function cues the playlist for use in the next function

function onRadioDataPlayerReady() {
  var autoplayUrl = "RD" + baseAutoplayVideoId;
  radioDataPlayer.cuePlaylist({list:autoplayUrl});
}

// * This function compiles an array of videos for Streamly Radio
// * Making sure they aren't in the current playlist already

function onRadioDataPlayerStateChange(event) {
  if (event.data === 5) {
    var autoplayVideosSpare = [];
    autoplayVideos = radioDataPlayer.getPlaylist();

    for (var i = 0; i <= 25; i++) {
      var notInPlaylist = true;
      var autoplayVideo = autoplayVideos[i];
      for (var x = 1; x < videos.length; x++) {
        if (videos[x][2] === autoplayVideo) {
          notInPlaylist = false;
        }
      }
      if (notInPlaylist) {
        autoplayVideosSpare.push(autoplayVideo);
      }
    }
    autoplayVideos = autoplayVideosSpare;

    radioDataPlayer.destroy();
    if (autoplayVideos.length > 1) {
      addAutoplayVideo();
    }
  }
}

// * This function loads the latest Streamly Radio video into the playlist

function addAutoplayVideo() {
  if (playlistAutoplay && videos.length > 0) {
    if (!autoplayVideos.length > 0) {
      loadAutoplayData(videoIteration);
    }
    else if (videoIteration === videoCounter) {
      if (autoplayVideoIteration < autoplayVideos.length - 1) {
        autoplayVideoIteration++;
        console.log("Getting new video: " + autoplayVideos[autoplayVideoIteration] + " data");
        getVideoData(autoplayVideos[autoplayVideoIteration]);
      }
      else {
        loadAutoplayData(videoIteration);
      }
    }
  }
}

// End Streamly Radio
<commit_msg>Update radio.js<commit_after>/**
  Copyright 2018 LNFWebsite
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
**/

// Start Streamly Radio

// * This function loads the video for the Streamly Radio function

function loadAutoplayData(iteration) {
  autoplayVideos = [];
  autoplayVideoIteration = -1;

  highlight(iteration, "radio", false);
  baseAutoplayVideoId = videos[iteration][2];
  var dataFrame = document.createElement("iframe");
  dataFrame.setAttribute("id", "radioDataFrame");
  dataFrame.setAttribute("src", "");
  document.getElementById("dataFramesContainer").appendChild(dataFrame);
  radioDataPlayer = new YT.Player('radioDataFrame', {
    events: {
      'onReady': onRadioDataPlayerReady,
      'onStateChange': onRadioDataPlayerStateChange
    }
  });
  dataFrame.setAttribute("src", "https://www.youtube.com/embed/" + baseAutoplayVideoId + "?enablejsapi=1");
}

// * This function cues the playlist for use in the next function

function onRadioDataPlayerReady() {
  var autoplayUrl = "RD" + baseAutoplayVideoId;
  radioDataPlayer.cuePlaylist({list:autoplayUrl});
}

// * This function compiles an array of videos for Streamly Radio
// * Making sure they aren't in the current playlist already

function onRadioDataPlayerStateChange(event) {
  if (event.data === 5) {
    var autoplayVideosSpare = [];
    autoplayVideos = radioDataPlayer.getPlaylist();

    for (var i = 0; i <= 25; i++) {
      var notInPlaylist = true;
      var autoplayVideo = autoplayVideos[i];
      for (var x = 1; x < videos.length; x++) {
        if (videos[x][2] === autoplayVideo) {
          notInPlaylist = false;
        }
      }
      if (notInPlaylist) {
        autoplayVideosSpare.push(autoplayVideo);
      }
    }
    autoplayVideos = autoplayVideosSpare;

    radioDataPlayer.destroy();
    if (autoplayVideos.length > 1) {
      addAutoplayVideo();
    }
  }
}

// * This function loads the latest Streamly Radio video into the playlist

function addAutoplayVideo() {
  if (playlistAutoplay && videos.length > 0) {
    if (!autoplayVideos.length > 0) {
      loadAutoplayData(videoIteration);
    }
    else if (videoIteration === videoCounter) {
      if (autoplayVideoIteration < autoplayVideos.length - 1) {
        autoplayVideoIteration++;
        console.log("Getting new video: " + autoplayVideos[autoplayVideoIteration] + " data");
        getVideoData(autoplayVideos[autoplayVideoIteration]);
      }
      else {
        loadAutoplayData(videoIteration);
      }
    }
  }
}

// End Streamly Radio
<|endoftext|>


<commit_before>/**
 * Clarify.
 *
 * Copyright (C) 2012 Roger Dudler <roger.dudler@gmail.com>
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */
(function($) {
    Tc.Module.ScreenBrowser = Tc.Module.extend({

        on: function(callback) {
            var project = this.$ctx.data('project'),
                $ctx = this.$ctx,
                that = this;
            var $colors = $('.colors .color', $ctx);

            $('.fileupload').fileupload({
                dataType: 'json',
                url: '/api/screen/upload/' + project,
                dropZone: $('.create'),
                progress: function (e, data) {
                    var progress = parseInt(data.loaded / data.total * 100, 10);
                    $('.create').find('.meta').text(progress + '%');
                },
                done: function (e, data) {
                    window.location.reload();
                }
            });

            $('.fileupload-replace').fileupload({
                dataType: 'json',
                url: '/api/screen/replace/',
                progress: function (e, data) {
                    var progress = parseInt(data.loaded / data.total * 100, 10);
                    $('.create').find('.meta').text(progress + '%');
                },
                done: function (e, data) {
                    window.location.reload();
                }
            });

            // replace action
            $('.btn-replace').on('click', function(e) {
                $('.fileupload-replace').fileupload('option', 'url', '/api/screen/replace/' + $(this).data('screen'));
                $('.fileupload-replace').click();
                e.stopPropagation();
                return false;
            });

            $('.create').on('click', function(e) {
                that.screen = null;
                $('.fileupload').click();
                e.stopPropagation();
                return false;
            });

            $('.title > a').on('click', function(e) {
                var screen = $(this).data('screen');
                var title = $(this).data('title');
                var data = { 'screen': screen, 'name': title };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('rename-screen', data, function() {
                    var $input = $(this).closest('.modal').find('.fld-name');
                    $.ajax({
                        url: "/api/screen/setting/" + screen + "/title/" + encodeURIComponent($input.val()),
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            location.reload();
                        }
                    });
                });
                return false;
            });

            $('.btn-account-settings').on('click', function(e) {
                var data = { 'name': $(this).data('name') };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('account-settings', data, function() {
                    var $input = $(this).closest('.modal').find('.fld-name');
                    $.ajax({
                        url: "/api/user/setting/name/" + encodeURIComponent($input.val()),
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            location.reload();
                        }
                    });
                }, function() {
                    alert('Not possible yet.');
                    /*
                    $.ajax({
                        url: "/api/user/account/delete",
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            location.reload();
                        }
                    });
                     */
                });
                return false;
            });

            $('.delete').on('click', function(e) {
                var screen = $(this).data('screen');
                var data = { 'screen': screen };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('delete-screen', data, function() {
                    $.ajax({
                        url: "/api/screen/delete/" + screen,
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            location.reload();
                        }
                    });
                });
                return false;
            });

            $('.screen').hover(
                function(e) {
                    $('.delete', $(this)).show();
                },
                function(e) {
                    $('.delete', $(this)).hide();
                }
            );

            $('.btn-project-settings').on('click', function() {
                var project = $(this).data('project');
                var name = $(this).data('name');
                var screen_background_color = $(this).data('screen-background-color');
                var data = {
                    'project': project,
                    'name': name,
                    'screen_background_color': screen_background_color ? screen_background_color : '#FFFFFF'
                };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('project-settings', data, function() {
                    var $input = $(this).closest('.modal').find('.fld-name');
                    $.ajax({
                        url: "/api/project/setting/" + project + "/name/" + encodeURIComponent($input.val()),
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            location.reload();
                        }
                    });
                }, function() {
                    modal.open('delete-project', data, function() {
                        $.ajax({
                            url: "/api/project/delete/" + project,
                            dataType: 'json',
                            type: 'POST',
                            success: function(data){
                                location.href='/';
                            }
                        });
                    });
                });
                return false;
            });

            $('.btn-export-css').on('click', function(e) {
                var colors = '';
                $colors.each(function(){
                     colors += $(this).data('less')+"\r\n";
                });
                var data = { 'code': colors };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('export-color-library-less', data, function() {});
                return false;
            });

            $('.btn-export-sass').on('click', function(e) {
                var colors = '';
                $colors.each(function(){
                     colors += $(this).data('sass')+"\r\n";
                });
                var data = { 'code': colors };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('export-color-library-sass', data, function() {});
                return false;
            });

            $('.btn-create-project', $ctx).on('click', function() {
                $(this).fadeOut('fast');
                $('.add-project').slideToggle('fast', function() {
                    $('.project-name').focus();
                });
            });

            $('.color', this.$ctx).tooltip();

            // fade in images
            $('.image > img').fadeIn();

            callback();
        }
    });
})(Tc.$);<commit_msg>removed fade effect.<commit_after>/**
 * Clarify.
 *
 * Copyright (C) 2012 Roger Dudler <roger.dudler@gmail.com>
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */
(function($) {
    Tc.Module.ScreenBrowser = Tc.Module.extend({

        on: function(callback) {
            var project = this.$ctx.data('project'),
                $ctx = this.$ctx,
                that = this;
            var $colors = $('.colors .color', $ctx);

            $('.fileupload').fileupload({
                dataType: 'json',
                url: '/api/screen/upload/' + project,
                dropZone: $('.create'),
                progress: function (e, data) {
                    var progress = parseInt(data.loaded / data.total * 100, 10);
                    $('.create').find('.meta').text(progress + '%');
                },
                done: function (e, data) {
                    window.location.reload();
                }
            });

            $('.fileupload-replace').fileupload({
                dataType: 'json',
                url: '/api/screen/replace/',
                progress: function (e, data) {
                    var progress = parseInt(data.loaded / data.total * 100, 10);
                    $('.create').find('.meta').text(progress + '%');
                },
                done: function (e, data) {
                    window.location.reload();
                }
            });

            // replace action
            $('.btn-replace').on('click', function(e) {
                $('.fileupload-replace').fileupload('option', 'url', '/api/screen/replace/' + $(this).data('screen'));
                $('.fileupload-replace').click();
                e.stopPropagation();
                return false;
            });

            $('.create').on('click', function(e) {
                that.screen = null;
                $('.fileupload').click();
                e.stopPropagation();
                return false;
            });

            $('.title > a').on('click', function(e) {
                var screen = $(this).data('screen');
                var title = $(this).data('title');
                var data = { 'screen': screen, 'name': title };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('rename-screen', data, function() {
                    var $input = $(this).closest('.modal').find('.fld-name');
                    $.ajax({
                        url: "/api/screen/setting/" + screen + "/title/" + encodeURIComponent($input.val()),
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            location.reload();
                        }
                    });
                });
                return false;
            });

            $('.btn-account-settings').on('click', function(e) {
                var data = { 'name': $(this).data('name') };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('account-settings', data, function() {
                    var $input = $(this).closest('.modal').find('.fld-name');
                    $.ajax({
                        url: "/api/user/setting/name/" + encodeURIComponent($input.val()),
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            location.reload();
                        }
                    });
                }, function() {
                    alert('Not possible yet.');
                    /*
                    $.ajax({
                        url: "/api/user/account/delete",
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            location.reload();
                        }
                    });
                     */
                });
                return false;
            });

            $('.delete').on('click', function(e) {
                var screen = $(this).data('screen');
                var data = { 'screen': screen };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('delete-screen', data, function() {
                    $.ajax({
                        url: "/api/screen/delete/" + screen,
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            location.reload();
                        }
                    });
                });
                return false;
            });

            $('.screen').hover(
                function(e) {
                    $('.delete', $(this)).show();
                },
                function(e) {
                    $('.delete', $(this)).hide();
                }
            );

            $('.btn-project-settings').on('click', function() {
                var project = $(this).data('project');
                var name = $(this).data('name');
                var screen_background_color = $(this).data('screen-background-color');
                var data = {
                    'project': project,
                    'name': name,
                    'screen_background_color': screen_background_color ? screen_background_color : '#FFFFFF'
                };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('project-settings', data, function() {
                    var $input = $(this).closest('.modal').find('.fld-name');
                    $.ajax({
                        url: "/api/project/setting/" + project + "/name/" + encodeURIComponent($input.val()),
                        dataType: 'json',
                        type: 'POST',
                        success: function(data){
                            location.reload();
                        }
                    });
                }, function() {
                    modal.open('delete-project', data, function() {
                        $.ajax({
                            url: "/api/project/delete/" + project,
                            dataType: 'json',
                            type: 'POST',
                            success: function(data){
                                location.href='/';
                            }
                        });
                    });
                });
                return false;
            });

            $('.btn-export-css').on('click', function(e) {
                var colors = '';
                $colors.each(function(){
                     colors += $(this).data('less')+"\r\n";
                });
                var data = { 'code': colors };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('export-color-library-less', data, function() {});
                return false;
            });

            $('.btn-export-sass').on('click', function(e) {
                var colors = '';
                $colors.each(function(){
                     colors += $(this).data('sass')+"\r\n";
                });
                var data = { 'code': colors };
                var modal = that.sandbox.getModuleById($('.modModal').data('id'));
                modal.open('export-color-library-sass', data, function() {});
                return false;
            });

            $('.btn-create-project', $ctx).on('click', function() {
                $(this).fadeOut('fast');
                $('.add-project').slideToggle('fast', function() {
                    $('.project-name').focus();
                });
            });

            $('.color', this.$ctx).tooltip();

            callback();
        }
    });
})(Tc.$);<|endoftext|>


<commit_before>import uniq from 'lodash/uniq'
import { mainLog } from '@zap/utils/log'
import { getSupportedProviders } from './providers'
import requestTicker from './requestTicker'
/**
 * requestTickerWithFallback - Returns ticker for the specified `coin` and `currency` using `provider`
 * falls back to `fallback` if operation was unsuccessful.
 *
 * @param {string} provider Provider of interest
 * @param {('BTC'|'LTC')} coin Crypto currency of interest
 * @param {string} currency Fiat currency of interest
 * @returns {Promise} Promise that resolves to {[currency]:rate} Object. Or empty object if something went wrong
 */
async function requestTickerWithFallback(provider, coin, currency) {
  const fallbackProviders = Object.keys(getSupportedProviders(coin, currency))
  const allProviders = uniq([provider].concat(fallbackProviders))

  // Try each provider sequentially until we get a result.
  let result = {}
  for (const currentProvider of allProviders) {
    try {
      // Attempt to fetch the ticker data.
      result = await requestTicker(currentProvider, coin, currency)
      // If we got the result we were looking for abort early.
      if (result[currency]) {
        break
      }
      throw new Error('No data')
    } catch (e) {
      mainLog.warn('Unable to fetch %s/%s ticker from %s: %o', coin, currency, currentProvider, e)
    }
  }

  return result
}

export default requestTickerWithFallback
<commit_msg>chore(lint): disable no-await-in-loop rule in requestTickerWithFallback<commit_after>import uniq from 'lodash/uniq'
import { mainLog } from '@zap/utils/log'
import { getSupportedProviders } from './providers'
import requestTicker from './requestTicker'
/**
 * requestTickerWithFallback - Returns ticker for the specified `coin` and `currency` using `provider`
 * falls back to `fallback` if operation was unsuccessful.
 *
 * @param {string} provider Provider of interest
 * @param {('BTC'|'LTC')} coin Crypto currency of interest
 * @param {string} currency Fiat currency of interest
 * @returns {Promise} Promise that resolves to {[currency]:rate} Object. Or empty object if something went wrong
 */
async function requestTickerWithFallback(provider, coin, currency) {
  const fallbackProviders = Object.keys(getSupportedProviders(coin, currency))
  const allProviders = uniq([provider].concat(fallbackProviders))

  // Try each provider sequentially until we get a result.
  let result = {}
  for (const currentProvider of allProviders) {
    try {
      // Attempt to fetch the ticker data.
      // eslint-disable-next-line no-await-in-loop
      result = await requestTicker(currentProvider, coin, currency)
      // If we got the result we were looking for abort early.
      if (result[currency]) {
        break
      }
      throw new Error('No data')
    } catch (e) {
      mainLog.warn('Unable to fetch %s/%s ticker from %s: %o', coin, currency, currentProvider, e)
    }
  }

  return result
}

export default requestTickerWithFallback
<|endoftext|>