<commit_before>/*==================================================================

  [Page Specific Script]

	=> /sitefiles

  [Table of Contents]

	1. Tab Click Listeners
	2. Ajax Load Status Tab
	3. Ajax Load Software Tab

===================================================================*/

/*------------------------------------------------------------------
 * 1. Tab Click Listeners
 * ---------------------------------------------------------------*/
$(document).ready(function() {

	// Ajax load status tab
	$('#tab-status a').click(function (e) {
		currentPanel = $(this).attr('href')
		if ($(currentPanel).has('.ajax-loader').length != 0 ) {
			loadTabStatus()
		}
	})

	// Ajax load software tab
	$('#tab-software a').click(function (e) {
		currentPanel = $(this).attr('href')
		if ($(currentPanel).has('.ajax-loader').length != 0 ) {
			loadTabSoftware()
		}
	})
})

/*------------------------------------------------------------------
 * 2. Ajax Load Status Tab
 * ---------------------------------------------------------------*/
function loadTabStatus() {
	var jqxhr = $.getJSON( '../dashboard/checks.json', function(data) {
		// loop through each category
		$.each( data, function( category, checks ) {
			failCount = 0

			// generate
 items for each check in the current category
			$.each( data[category], function( index, check ) {
				if (check.pass == true ) {
					icon = ''
					$('#status-' + category + ' ul').append( '
' + icon + check.message + '
')
				} else {
					icon = ''
					$('#status-' + category + ' ul').append( '
' + icon + check.message + '
')
					failCount++
				}
			});

			// set panel header to danger for failed category
			if (failCount != 0) {
				$('#status-' + category).removeClass('panel-primary')
				$('#status-' + category).addClass('danger')
			}
		});
	})
	.done(function() {
		$('#panel-status .ajax-loader').html('').remove()
		$('#panel-status .widget').removeClass('hidden')
	})
	.fail(function() {
		alert( 'So sorry, something went wrong fetching checks' )
	})
}

/*------------------------------------------------------------------
 * 3. Ajax Load Software Tab
 * ---------------------------------------------------------------*/
function loadTabSoftware() {
	var jqxhr = $.getJSON( '../dashboard/software.json', function(data) {
		console.dir(data)

		// fill OS panel
		$('.os-description').append('' + data['operating_system']['DISTRIB_DESCRIPTION'] + '')
		$('.os-codename').append(data['operating_system']['DISTRIB_CODENAME'])
		$('.os-architecture').append(data['operating_system']['architecture'])

		// fill Software panel
		$.each(data['packages'], function( index, column ) {
			var target = $('.panel-body.packages > .row')
			var col = $('
').appendTo(target)
			var list = $('
').appendTo('#packages-column-' + index)

			// one LI per package
			$.each(column, function(index, package) {
				li = '
'
				if (package.version) {
					li += '' + package.name + ' ' + package.version + ''
				} else {
					li += '' + package.name + ' '
				}
				li += '
'
				list.append(li)
			})
		})

		// fill PHP Modules panel
		$.each(data['php_modules'], function( index, column ) {
			var target = $('.panel-body.php-modules > .row')
			var col = $('
').appendTo(target)
			var list = $('
').appendTo('#php-modules-column-' + index)

			// one LI per package
			$.each(column, function(index, phpmodule) {
				li = '
'
				if (phpmodule['link']) {
					li += '' + phpmodule.name + ''
				} else {
					li += phpmodule.name
				}
				li += '
'
				list.append(li)
			})
		})

		// fill nginx core-modules column
		$.each(data['nginx_modules']['core'], function( index, module ) {
			var list = $('#nginx-core-modules > ul')
			list.append('
' + module.short_name + '')
		})

		// fill nginx 3rd-party-modules column
		$.each(data['nginx_modules']['3rdparty'], function( index, module ) {
			var list = $('#nginx-3rdparty-modules > ul')
			list.append('
' + module.short_name + '')
		})

	})
	.done(function() {
		$('#panel-software .ajax-loader').html('').remove()
		$('#panel-software .widget').removeClass('hidden')
	})
	.fail(function() {
		alert( 'So sorry, something went wrong fetching software' )
	})
}
<commit_msg>Adds CLI log ajax loader<commit_after>/*==================================================================

  [Page Specific Script]

	=> /sitefiles

  [Table of Contents]

	1. Tab Click Listeners
	2. Ajax Load Status Tab
	3. Ajax Load Software Tab
	4. Ajax Load CLI Log Tab

===================================================================*/

/*------------------------------------------------------------------
 * 1. Tab Click Listeners
 * ---------------------------------------------------------------*/
$(document).ready(function() {

	// Ajax load status tab
	$('#tab-status a').click(function (e) {
		currentPanel = $(this).attr('href')
		if ($(currentPanel).has('.ajax-loader').length != 0 ) {
			loadTabStatus()
		}
	})

	// Ajax load software tab
	$('#tab-software a').click(function (e) {
		currentPanel = $(this).attr('href')
		if ($(currentPanel).has('.ajax-loader').length != 0 ) {
			loadTabSoftware()
		}
	})

	// Ajax load CLI log tab
	$('#tab-clilog a').click(function (e) {
		currentPanel = $(this).attr('href')
		if ($(currentPanel).has('.ajax-loader').length != 0 ) {
			loadTabCliLog()
		}
	})
})

/*------------------------------------------------------------------
 * 2. Ajax Load Status Tab
 * ---------------------------------------------------------------*/
function loadTabStatus() {
	var jqxhr = $.getJSON( '../dashboard/checks.json', function(data) {
		// loop through each category
		$.each( data, function( category, checks ) {
			failCount = 0

			// generate
 items for each check in the current category
			$.each( data[category], function( index, check ) {
				if (check.pass == true ) {
					icon = ''
					$('#status-' + category + ' ul').append( '
' + icon + check.message + '
')
				} else {
					icon = ''
					$('#status-' + category + ' ul').append( '
' + icon + check.message + '
')
					failCount++
				}
			});

			// set panel header to danger for failed category
			if (failCount != 0) {
				$('#status-' + category).removeClass('panel-primary')
				$('#status-' + category).addClass('danger')
			}
		});
	})
	.done(function() {
		$('#panel-status .ajax-loader').html('').remove()
		$('#panel-status .widget').removeClass('hidden')
	})
	.fail(function() {
		alert( 'So sorry, something went wrong fetching checks' )
	})
}

/*------------------------------------------------------------------
 * 3. Ajax Load Software Tab
 * ---------------------------------------------------------------*/
function loadTabSoftware() {
	var jqxhr = $.getJSON( '../dashboard/software.json', function(data) {
		console.dir(data)

		// fill OS panel
		$('.os-description').append('' + data['operating_system']['DISTRIB_DESCRIPTION'] + '')
		$('.os-codename').append(data['operating_system']['DISTRIB_CODENAME'])
		$('.os-architecture').append(data['operating_system']['architecture'])

		// fill Software panel
		$.each(data['packages'], function( index, column ) {
			var target = $('.panel-body.packages > .row')
			var col = $('
').appendTo(target)
			var list = $('
').appendTo('#packages-column-' + index)

			// one LI per package
			$.each(column, function(index, package) {
				li = '
'
				if (package.version) {
					li += '' + package.name + ' ' + package.version + ''
				} else {
					li += '' + package.name + ' '
				}
				li += '
'
				list.append(li)
			})
		})

		// fill PHP Modules panel
		$.each(data['php_modules'], function( index, column ) {
			var target = $('.panel-body.php-modules > .row')
			var col = $('
').appendTo(target)
			var list = $('
').appendTo('#php-modules-column-' + index)

			// one LI per package
			$.each(column, function(index, phpmodule) {
				li = '
'
				if (phpmodule['link']) {
					li += '' + phpmodule.name + ''
				} else {
					li += phpmodule.name
				}
				li += '
'
				list.append(li)
			})
		})

		// fill nginx core-modules column
		$.each(data['nginx_modules']['core'], function( index, module ) {
			var list = $('#nginx-core-modules > ul')
			list.append('
' + module.short_name + '')
		})

		// fill nginx 3rd-party-modules column
		$.each(data['nginx_modules']['3rdparty'], function( index, module ) {
			var list = $('#nginx-3rdparty-modules > ul')
			list.append('
' + module.short_name + '')
		})

	})
	.done(function() {
		$('#panel-software .ajax-loader').html('').remove()
		$('#panel-software .widget').removeClass('hidden')
	})
	.fail(function() {
		alert( 'So sorry, something went wrong fetching software' )
	})
}

/*------------------------------------------------------------------
 * 4. Ajax Load CLI Log Tab
 * ---------------------------------------------------------------*/
function loadTabCliLog() {
	var jqxhr = $.getJSON( '../dashboard/clilog.json', function(data) {
		console.dir(data)

		var tbody = $('.panel-body.clilog > table > tbody')
		$.each( data.log, function( key, entry ) {
		 	tbody.append('
' + entry.date + '	' + entry.time + '	' + entry.level + '	' + entry.message + '
' + "\n")
		});
	})
	.done(function() {
		$('#panel-clilog .ajax-loader').html('').remove()
		$('#panel-clilog .widget').removeClass('hidden')
	})
	.fail(function() {
		alert( 'So sorry, something went wrong fetching CLI log' )
	})
}
<|endoftext|>


<commit_before>import * as React from "react";

import { Button, ClipboardButton } from "./buttons.js";
import EditorState from "./EditorState.js";
import { DebugPanel, InputPanel, OutputPanel } from "./panels.js";
import PrettierFormat from "./PrettierFormat.js";
import { shallowEqual } from "./helpers.js";
import * as urlHash from "./urlHash.js";
import formatMarkdown from "./markdown.js";
import * as util from "./util.js";
import getCodeSample from "./codeSamples.js";

import { Sidebar, SidebarCategory } from "./sidebar/components.js";
import SidebarOptions from "./sidebar/SidebarOptions.js";
import Option from "./sidebar/options.js";
import { Checkbox } from "./sidebar/inputs.js";

const CATEGORIES_ORDER = [
  "Global",
  "Common",
  "JavaScript",
  "Markdown",
  "HTML",
  "Special",
];
const ENABLED_OPTIONS = [
  "parser",
  "printWidth",
  "tabWidth",
  "useTabs",
  "semi",
  "singleQuote",
  "bracketSpacing",
  "jsxSingleQuote",
  "quoteProps",
  "arrowParens",
  "trailingComma",
  "proseWrap",
  "htmlWhitespaceSensitivity",
  "bracketSameLine",
  "insertPragma",
  "requirePragma",
  "vueIndentScriptAndStyle",
  "embeddedLanguageFormatting",
];
const ISSUES_URL = "https://github.com/prettier/prettier/issues/new?body=";
const MAX_LENGTH = 8000 - ISSUES_URL.length; // it seems that GitHub limit is 8195
const COPY_MESSAGE =
  "\n";

class Playground extends React.Component {
  constructor(props) {
    super();

    const original = urlHash.read();

    const defaultOptions = util.getDefaults(
      props.availableOptions,
      ENABLED_OPTIONS
    );

    const options = Object.assign(defaultOptions, original.options);

    // backwards support for old parser `babylon`
    if (options.parser === "babylon") {
      options.parser = "babel";
    }

    const content = original.content || getCodeSample(options.parser);
    const selection = {};

    this.state = { content, options, selection };

    this.handleOptionValueChange = this.handleOptionValueChange.bind(this);

    this.setContent = (content) => this.setState({ content });
    this.clearContent = this.setContent.bind(this, "");
    this.resetOptions = () => this.setState({ options: defaultOptions });
    this.setSelection = (selection) => this.setState({ selection });
    this.setSelectionAsRange = () => {
      const { selection, content, options } = this.state;
      const { head, anchor } = selection;
      const range = [head, anchor].map(
        ({ ch, line }) =>
          content.split("\n").slice(0, line).join("\n").length +
          ch +
          (line ? 1 : 0)
      );
      const [rangeStart, rangeEnd] = range.sort((a, b) => a - b);
      const updatedOptions = { ...options, rangeStart, rangeEnd };
      if (rangeStart === rangeEnd) {
        delete updatedOptions.rangeStart;
        delete updatedOptions.rangeEnd;
      }
      this.setState({ options: updatedOptions });
    };

    this.enabledOptions = orderOptions(props.availableOptions, ENABLED_OPTIONS);
    this.rangeStartOption = props.availableOptions.find(
      (opt) => opt.name === "rangeStart"
    );
    this.rangeEndOption = props.availableOptions.find(
      (opt) => opt.name === "rangeEnd"
    );
  }

  componentDidUpdate(_, prevState) {
    const { content, options } = this.state;
    if (
      !shallowEqual(prevState.options, this.state.options) ||
      prevState.content !== content
    ) {
      urlHash.replace({ content, options });
    }
  }

  handleOptionValueChange(option, value) {
    this.setState((state) => {
      const options = { ...state.options };

      if (option.type === "int" && Number.isNaN(value)) {
        delete options[option.name];
      } else {
        options[option.name] = value;
      }

      const content =
        state.content === "" ||
        state.content === getCodeSample(state.options.parser)
          ? getCodeSample(options.parser)
          : state.content;

      return { options, content };
    });
  }

  getMarkdown({ formatted, reformatted, full, doc }) {
    const { content, options } = this.state;
    const { availableOptions, version } = this.props;
    const orderedOptions = orderOptions(availableOptions, [
      ...ENABLED_OPTIONS,
      "rangeStart",
      "rangeEnd",
    ]);
    const cliOptions = util.buildCliArgs(orderedOptions, options);

    return formatMarkdown({
      input: content,
      output: formatted,
      output2: reformatted,
      doc,
      version,
      url: window.location.href,
      options,
      cliOptions,
      full,
    });
  }

  render() {
    const { worker, version } = this.props;
    const { content, options } = this.state;

    // TODO: remove this when v2.3.0 is released
    const [major, minor] = version.split(".", 2).map(Number);
    const showShowComments =
      Number.isNaN(major) || (major === 2 && minor >= 3) || major > 2;

    return (
      <EditorState>
        {(editorState) => (
          <PrettierFormat
            worker={worker}
            code={content}
            options={options}
            debugAst={editorState.showAst}
            debugDoc={editorState.showDoc}
            debugComments={showShowComments && editorState.showComments}
            reformat={editorState.showSecondFormat}
          >
            {({ formatted, debug }) => {
              const fullReport = this.getMarkdown({
                formatted,
                reformatted: debug.reformatted,
                full: true,
              });
              const showFullReport =
                encodeURIComponent(fullReport).length < MAX_LENGTH;
              return (
                <React.Fragment>

                    <Sidebar visible={editorState.showSidebar}>
                      <SidebarOptions
                        categories={CATEGORIES_ORDER}
                        availableOptions={this.enabledOptions}
                        optionValues={options}
                        onOptionValueChange={this.handleOptionValueChange}
                      />
                      <SidebarCategory title="Range">

                          The selected range will be highlighted in yellow in
                          the input editor

                        <Option
                          option={this.rangeStartOption}
                          value={
                            typeof options.rangeStart === "number"
                              ? options.rangeStart
                              : ""
                          }
                          onChange={this.handleOptionValueChange}
                        />
                        <Option
                          option={this.rangeEndOption}
                          value={
                            typeof options.rangeEnd === "number"
                              ? options.rangeEnd
                              : ""
                          }
                          overrideMax={content.length}
                          onChange={this.handleOptionValueChange}
                        />

                        <Button onClick={this.setSelectionAsRange}>
                          Set selected text as range
                        </Button>
                      </SidebarCategory>
                      <SidebarCategory title="Debug">
                        <Checkbox
                          label="show input"
                          checked={editorState.showInput}
                          onChange={editorState.toggleInput}
                        />
                        <Checkbox
                          label="show AST"
                          checked={editorState.showAst}
                          onChange={editorState.toggleAst}
                        />
                        <Checkbox
                          label="show doc"
                          checked={editorState.showDoc}
                          onChange={editorState.toggleDoc}
                        />
                        {showShowComments && (
                          <Checkbox
                            label="show comments"
                            checked={editorState.showComments}
                            onChange={editorState.toggleComments}
                          />
                        )}
                        <Checkbox
                          label="show output"
                          checked={editorState.showOutput}
                          onChange={editorState.toggleOutput}
                        />
                        <Checkbox
                          label="show second format"
                          checked={editorState.showSecondFormat}
                          onChange={editorState.toggleSecondFormat}
                        />
                        {editorState.showDoc && debug.doc && (
                          <ClipboardButton
                            copy={() => this.getMarkdown({ doc: debug.doc })}
                          >
                            Copy doc
                          </ClipboardButton>
                        )}
                      </SidebarCategory>

                        <Button onClick={this.resetOptions}>
                          Reset to defaults
                        </Button>

                    </Sidebar>

                      {editorState.showInput ? (
                        <InputPanel
                          mode={util.getCodemirrorMode(options.parser)}
                          ruler={options.printWidth}
                          value={content}
                          codeSample={getCodeSample(options.parser)}
                          overlayStart={options.rangeStart}
                          overlayEnd={options.rangeEnd}
                          onChange={this.setContent}
                          onSelectionChange={this.setSelection}
                        />
                      ) : null}
                      {editorState.showAst ? (
                        <DebugPanel
                          value={debug.ast || ""}
                          autoFold={util.getAstAutoFold(options.parser)}
                        />
                      ) : null}
                      {editorState.showDoc ? (
                        <DebugPanel value={debug.doc || ""} />
                      ) : null}
                      {showShowComments && editorState.showComments ? (
                        <DebugPanel
                          value={debug.comments || ""}
                          autoFold={util.getAstAutoFold(options.parser)}
                        />
                      ) : null}
                      {editorState.showOutput ? (
                        <OutputPanel
                          mode={util.getCodemirrorMode(options.parser)}
                          value={formatted}
                          ruler={options.printWidth}
                        />
                      ) : null}
                      {editorState.showSecondFormat ? (
                        <OutputPanel
                          mode={util.getCodemirrorMode(options.parser)}
                          value={getSecondFormat(formatted, debug.reformatted)}
                          ruler={options.printWidth}
                        />
                      ) : null}

                      <Button onClick={editorState.toggleSidebar}>
                        {editorState.showSidebar ? "Hide" : "Show"} options
                      </Button>
                      <Button onClick={this.clearContent}>Clear</Button>
                      <ClipboardButton
                        copy={JSON.stringify(
                          // Remove `parser` since people usually paste this
                          // into their .prettierrc and specifying a top-level
                          // parser there is an anti-pattern. Note:
                          // `JSON.stringify` omits keys whose values are
                          // `undefined`.
                          { ...options, parser: undefined },
                          null,
                          2
                        )}
                      >
                        Copy config JSON
                      </ClipboardButton>

                      <ClipboardButton copy={window.location.href}>
                        Copy link
                      </ClipboardButton>
                      <ClipboardButton
                        copy={() =>
                          this.getMarkdown({
                            formatted,
                            reformatted: debug.reformatted,
                          })
                        }
                      >
                        Copy markdown
                      </ClipboardButton>

                        <ClipboardButton
                          copy={() => (showFullReport ? "" : fullReport)}
                        >
                          Report issue
                        </ClipboardButton>

                </React.Fragment>
              );
            }}
          </PrettierFormat>
        )}
      </EditorState>
    );
  }
}

function orderOptions(availableOptions, order) {
  const optionsByName = {};
  for (const option of availableOptions) {
    optionsByName[option.name] = option;
  }

  return order.map((name) => optionsByName[name]);
}

function getReportLink(reportBody) {
  return `${ISSUES_URL}${encodeURIComponent(reportBody)}`;
}

function getSecondFormat(formatted, reformatted) {
  return formatted === ""
    ? ""
    : formatted === reformatted
    ? "✓ Second format is unchanged."
    : reformatted;
}

export default Playground;
<commit_msg>Fix Playground (#11433)<commit_after>import * as React from "react";

import { Button, ClipboardButton } from "./buttons.js";
import EditorState from "./EditorState.js";
import { DebugPanel, InputPanel, OutputPanel } from "./panels.js";
import PrettierFormat from "./PrettierFormat.js";
import { shallowEqual } from "./helpers.js";
import * as urlHash from "./urlHash.js";
import formatMarkdown from "./markdown.js";
import * as util from "./util.js";
import getCodeSample from "./codeSamples.js";

import { Sidebar, SidebarCategory } from "./sidebar/components.js";
import SidebarOptions from "./sidebar/SidebarOptions.js";
import Option from "./sidebar/options.js";
import { Checkbox } from "./sidebar/inputs.js";

const CATEGORIES_ORDER = [
  "Global",
  "Common",
  "JavaScript",
  "Markdown",
  "HTML",
  "Special",
];
const ISSUES_URL = "https://github.com/prettier/prettier/issues/new?body=";
const MAX_LENGTH = 8000 - ISSUES_URL.length; // it seems that GitHub limit is 8195
const COPY_MESSAGE =
  "\n";

const isProduction = location.host === "prettier.io";
const isPreview = location.host.includes("netlify.app");
const ENABLED_OPTIONS = [
  "parser",
  "printWidth",
  "tabWidth",
  "useTabs",
  "semi",
  "singleQuote",
  "bracketSpacing",
  "jsxSingleQuote",
  "quoteProps",
  "arrowParens",
  "trailingComma",
  "proseWrap",
  "htmlWhitespaceSensitivity",
  "insertPragma",
  "requirePragma",
  "vueIndentScriptAndStyle",
  "embeddedLanguageFormatting",
];
// "jsxBracketSameLine" will be deprecated in 2.4
if (isProduction) {
  ENABLED_OPTIONS.push("jsxBracketSameLine");
}
// "bracketSameLine" will be landed in 2.4
if (isPreview) {
  ENABLED_OPTIONS.push("bracketSameLine");
}

class Playground extends React.Component {
  constructor(props) {
    super();

    const original = urlHash.read();

    const defaultOptions = util.getDefaults(
      props.availableOptions,
      ENABLED_OPTIONS
    );

    const options = Object.assign(defaultOptions, original.options);

    // backwards support for old parser `babylon`
    if (options.parser === "babylon") {
      options.parser = "babel";
    }

    const content = original.content || getCodeSample(options.parser);
    const selection = {};

    this.state = { content, options, selection };

    this.handleOptionValueChange = this.handleOptionValueChange.bind(this);

    this.setContent = (content) => this.setState({ content });
    this.clearContent = this.setContent.bind(this, "");
    this.resetOptions = () => this.setState({ options: defaultOptions });
    this.setSelection = (selection) => this.setState({ selection });
    this.setSelectionAsRange = () => {
      const { selection, content, options } = this.state;
      const { head, anchor } = selection;
      const range = [head, anchor].map(
        ({ ch, line }) =>
          content.split("\n").slice(0, line).join("\n").length +
          ch +
          (line ? 1 : 0)
      );
      const [rangeStart, rangeEnd] = range.sort((a, b) => a - b);
      const updatedOptions = { ...options, rangeStart, rangeEnd };
      if (rangeStart === rangeEnd) {
        delete updatedOptions.rangeStart;
        delete updatedOptions.rangeEnd;
      }
      this.setState({ options: updatedOptions });
    };

    this.enabledOptions = orderOptions(props.availableOptions, ENABLED_OPTIONS);
    this.rangeStartOption = props.availableOptions.find(
      (opt) => opt.name === "rangeStart"
    );
    this.rangeEndOption = props.availableOptions.find(
      (opt) => opt.name === "rangeEnd"
    );
  }

  componentDidUpdate(_, prevState) {
    const { content, options } = this.state;
    if (
      !shallowEqual(prevState.options, this.state.options) ||
      prevState.content !== content
    ) {
      urlHash.replace({ content, options });
    }
  }

  handleOptionValueChange(option, value) {
    this.setState((state) => {
      const options = { ...state.options };

      if (option.type === "int" && Number.isNaN(value)) {
        delete options[option.name];
      } else {
        options[option.name] = value;
      }

      const content =
        state.content === "" ||
        state.content === getCodeSample(state.options.parser)
          ? getCodeSample(options.parser)
          : state.content;

      return { options, content };
    });
  }

  getMarkdown({ formatted, reformatted, full, doc }) {
    const { content, options } = this.state;
    const { availableOptions, version } = this.props;
    const orderedOptions = orderOptions(availableOptions, [
      ...ENABLED_OPTIONS,
      "rangeStart",
      "rangeEnd",
    ]);
    const cliOptions = util.buildCliArgs(orderedOptions, options);

    return formatMarkdown({
      input: content,
      output: formatted,
      output2: reformatted,
      doc,
      version,
      url: window.location.href,
      options,
      cliOptions,
      full,
    });
  }

  render() {
    const { worker, version } = this.props;
    const { content, options } = this.state;

    // TODO: remove this when v2.3.0 is released
    const [major, minor] = version.split(".", 2).map(Number);
    const showShowComments =
      Number.isNaN(major) || (major === 2 && minor >= 3) || major > 2;

    return (
      <EditorState>
        {(editorState) => (
          <PrettierFormat
            worker={worker}
            code={content}
            options={options}
            debugAst={editorState.showAst}
            debugDoc={editorState.showDoc}
            debugComments={showShowComments && editorState.showComments}
            reformat={editorState.showSecondFormat}
          >
            {({ formatted, debug }) => {
              const fullReport = this.getMarkdown({
                formatted,
                reformatted: debug.reformatted,
                full: true,
              });
              const showFullReport =
                encodeURIComponent(fullReport).length < MAX_LENGTH;
              return (
                <React.Fragment>

                    <Sidebar visible={editorState.showSidebar}>
                      <SidebarOptions
                        categories={CATEGORIES_ORDER}
                        availableOptions={this.enabledOptions}
                        optionValues={options}
                        onOptionValueChange={this.handleOptionValueChange}
                      />
                      <SidebarCategory title="Range">

                          The selected range will be highlighted in yellow in
                          the input editor

                        <Option
                          option={this.rangeStartOption}
                          value={
                            typeof options.rangeStart === "number"
                              ? options.rangeStart
                              : ""
                          }
                          onChange={this.handleOptionValueChange}
                        />
                        <Option
                          option={this.rangeEndOption}
                          value={
                            typeof options.rangeEnd === "number"
                              ? options.rangeEnd
                              : ""
                          }
                          overrideMax={content.length}
                          onChange={this.handleOptionValueChange}
                        />

                        <Button onClick={this.setSelectionAsRange}>
                          Set selected text as range
                        </Button>
                      </SidebarCategory>
                      <SidebarCategory title="Debug">
                        <Checkbox
                          label="show input"
                          checked={editorState.showInput}
                          onChange={editorState.toggleInput}
                        />
                        <Checkbox
                          label="show AST"
                          checked={editorState.showAst}
                          onChange={editorState.toggleAst}
                        />
                        <Checkbox
                          label="show doc"
                          checked={editorState.showDoc}
                          onChange={editorState.toggleDoc}
                        />
                        {showShowComments && (
                          <Checkbox
                            label="show comments"
                            checked={editorState.showComments}
                            onChange={editorState.toggleComments}
                          />
                        )}
                        <Checkbox
                          label="show output"
                          checked={editorState.showOutput}
                          onChange={editorState.toggleOutput}
                        />
                        <Checkbox
                          label="show second format"
                          checked={editorState.showSecondFormat}
                          onChange={editorState.toggleSecondFormat}
                        />
                        {editorState.showDoc && debug.doc && (
                          <ClipboardButton
                            copy={() => this.getMarkdown({ doc: debug.doc })}
                          >
                            Copy doc
                          </ClipboardButton>
                        )}
                      </SidebarCategory>

                        <Button onClick={this.resetOptions}>
                          Reset to defaults
                        </Button>

                    </Sidebar>

                      {editorState.showInput ? (
                        <InputPanel
                          mode={util.getCodemirrorMode(options.parser)}
                          ruler={options.printWidth}
                          value={content}
                          codeSample={getCodeSample(options.parser)}
                          overlayStart={options.rangeStart}
                          overlayEnd={options.rangeEnd}
                          onChange={this.setContent}
                          onSelectionChange={this.setSelection}
                        />
                      ) : null}
                      {editorState.showAst ? (
                        <DebugPanel
                          value={debug.ast || ""}
                          autoFold={util.getAstAutoFold(options.parser)}
                        />
                      ) : null}
                      {editorState.showDoc ? (
                        <DebugPanel value={debug.doc || ""} />
                      ) : null}
                      {showShowComments && editorState.showComments ? (
                        <DebugPanel
                          value={debug.comments || ""}
                          autoFold={util.getAstAutoFold(options.parser)}
                        />
                      ) : null}
                      {editorState.showOutput ? (
                        <OutputPanel
                          mode={util.getCodemirrorMode(options.parser)}
                          value={formatted}
                          ruler={options.printWidth}
                        />
                      ) : null}
                      {editorState.showSecondFormat ? (
                        <OutputPanel
                          mode={util.getCodemirrorMode(options.parser)}
                          value={getSecondFormat(formatted, debug.reformatted)}
                          ruler={options.printWidth}
                        />
                      ) : null}

                      <Button onClick={editorState.toggleSidebar}>
                        {editorState.showSidebar ? "Hide" : "Show"} options
                      </Button>
                      <Button onClick={this.clearContent}>Clear</Button>
                      <ClipboardButton
                        copy={JSON.stringify(
                          // Remove `parser` since people usually paste this
                          // into their .prettierrc and specifying a top-level
                          // parser there is an anti-pattern. Note:
                          // `JSON.stringify` omits keys whose values are
                          // `undefined`.
                          { ...options, parser: undefined },
                          null,
                          2
                        )}
                      >
                        Copy config JSON
                      </ClipboardButton>

                      <ClipboardButton copy={window.location.href}>
                        Copy link
                      </ClipboardButton>
                      <ClipboardButton
                        copy={() =>
                          this.getMarkdown({
                            formatted,
                            reformatted: debug.reformatted,
                          })
                        }
                      >
                        Copy markdown
                      </ClipboardButton>

                        <ClipboardButton
                          copy={() => (showFullReport ? "" : fullReport)}
                        >
                          Report issue
                        </ClipboardButton>

                </React.Fragment>
              );
            }}
          </PrettierFormat>
        )}
      </EditorState>
    );
  }
}

function orderOptions(availableOptions, order) {
  const optionsByName = {};
  for (const option of availableOptions) {
    optionsByName[option.name] = option;
  }

  return order.map((name) => optionsByName[name]);
}

function getReportLink(reportBody) {
  return `${ISSUES_URL}${encodeURIComponent(reportBody)}`;
}

function getSecondFormat(formatted, reformatted) {
  return formatted === ""
    ? ""
    : formatted === reformatted
    ? "✓ Second format is unchanged."
    : reformatted;
}

export default Playground;
<|endoftext|>


<commit_before>'use strict';

const { MovieInfo } = require('../../models/types.js');
const leech = require('../leech-promise.js');
const util = require('../util.js');
const dict = require('../category-dictionary.js');

const NAME = 'fc2';
module.exports.name = function () {
    return NAME;
}

const TEMPLATE = {
    "search": "",
    "id": "http://adult.contents.fc2.com/article/{qtext}/",
}

const DOMAIN = 'adult.contents.fc2.com';
module.exports.domain = function () {
    return DOMAIN;
}

const BASE_URL = 'http://' + DOMAIN;

function crawl (opt) {
    let url = "";
    if (typeof url == "string") {
        url = opt;
    }

    let qtext = opt.qtext || "";
    if (qtext) {
        url = TEMPLATE["id"].replace("{qtext}", qtext);
    }

    if (url == "") {
        throw new Error("Invalid Arguments");
    }

    return leech.get(url)
    .then($ => {
        let info = new MovieInfo({ url: url, country: 'Japan', origlang: 'Japanese' });

        info.origtitle = $('.items_article_headerInfo > h3').text().trim();

        let dReleaseDate = $('.items_article_Releasedate').text().split(":")[1].trim();
        info.releasedate = util.replaceAll(dReleaseDate, '/', '-');
        info.year = dReleaseDate.slice(0, 4);

        info.posters.push({
            url: "https:" + $('.items_article_MainitemThumb img').attr('src')
        });

        info.thumb.push({
            url: "https:" + $('.items_article_MainitemThumb img').attr('src')
        });

        $('a[data-image-slideshow="sample-images"]').each((i, el) => {
            let ele = $(el);
            info.screenshots.push({
                url: ele.attr('href')
            })
        });

        let dDirector = $('.items_article_headerInfo ul li:nth-child(3) a');
        let makerURL = dDirector.attr("href");

        info.director = {
            url: dDirector.attr("href"),
            text: dDirector.text()
        }

        info.label = {
            url: makerURL,
            text: makerURL.split('/').slice(-2, -1)[0]
        };

        info.maker = dDirector.text();

        // info.description = $('section.explain p.text').html().trim();

        info.genres.push({
            url: '',
            text: 'Uncensored'
        });

        return info;
    });
}

module.exports.crawl = crawl;
<commit_msg>fix crawler<commit_after>'use strict';

const { MovieInfo } = require('../../models/types.js');
const leech = require('../leech-promise.js');
const util = require('../util.js');
const dict = require('../category-dictionary.js');

const NAME = 'fc2';
module.exports.name = function () {
    return NAME;
}

const TEMPLATE = {
    "search": "",
    "id": "http://adult.contents.fc2.com/article/{qtext}/",
}

const DOMAIN = 'adult.contents.fc2.com';
module.exports.domain = function () {
    return DOMAIN;
}

const BASE_URL = 'http://' + DOMAIN;

function crawl (opt) {
    let url = "";
    if (typeof url == "string") {
        url = opt;
    }

    let qtext = opt.qtext || "";
    if (qtext) {
        url = TEMPLATE["id"].replace("{qtext}", qtext);
    }

    if (url == "") {
        throw new Error("Invalid Arguments");
    }

    return leech.get(url)
    .then($ => {
        let info = new MovieInfo({ url: url, country: 'Japan', origlang: 'Japanese' });

        info.origtitle = $('.items_article_headerInfo > h3').text().trim();

        let dReleaseDate = $('.items_article_Releasedate').text().split(":")[1].trim();
        info.releasedate = util.replaceAll(dReleaseDate, '/', '-');
        info.year = dReleaseDate.slice(0, 4);

        info.posters.push({
            url: "https:" + $('.items_article_MainitemThumb img').attr('src')
        });

        info.thumb.push({
            url: "https:" + $('.items_article_MainitemThumb img').attr('src')
        });

        $('a[data-image-slideshow="sample-images"]').each((i, el) => {
            let ele = $(el);
            info.screenshots.push({
                url: ele.attr('href')
            })
        });

        let dDirector = $('.items_article_headerInfo ul li:nth-child(3) a');

        if (dDirector.length == 0) {
            dDirector = $('.items_article_headerInfo ul li:nth-child(2) a');
        }

        let makerURL = dDirector.attr("href");

        info.director = {
            url: dDirector.attr("href"),
            text: dDirector.text()
        }

        info.label = {
            url: makerURL,
            text: makerURL.split('/').slice(-2, -1)[0]
        };

        info.maker = dDirector.text();

        // info.description = $('section.explain p.text').html().trim();

        info.genres.push({
            url: '',
            text: 'Uncensored'
        });

        return info;
    });
}

module.exports.crawl = crawl;
<|endoftext|>


<commit_before>'use strict';

let path = process.cwd();
let ctrlPath = path + '/server/ctrl';

const ImageController = require(ctrlPath + '/image-ctrl.server.js');
const UserController = require(ctrlPath + '/user-ctrl.server.js');
const debug = require('debug')('book:routes');

let _log = function(msg) {
    console.log('[LOG@SERVER]: ' + msg);
};

/* Function for debug logging requests.*/
let reqDebug = function(req) {
	_log('\t\tHeaders: ' + JSON.stringify(req.headers));
	_log('\t\tBody: ' + JSON.stringify(req.body));
	_log('\t\tParams: ' + JSON.stringify(req.params));
	_log('\t\tUrl:' + JSON.stringify(req.url));
	_log('\t\tText:' + JSON.stringify(req.text));
	_log('\t\tContent:' + JSON.stringify(req.content));
	_log('\t\tQuery:' + JSON.stringify(req.query));
};

const _u = function(username) {
    return '|' + username + '|';
};

// Msg objects sent back to the client
let notAuthorized = {msg: 'Operation not authorized. Log in first.'};
let errorInternal = {msg: 'Server internal error.'};
let errorForbidden = {msg: 'Requested action forbidden.'};

/* Contains all routes for this application. */
module.exports = function(app, passport) {

    /* Renders a pug template.*/
    let renderPug = function(req, res, pugFile) {
        let isAuth = req.isAuthenticated();
        debug('renderPug auth: ' + isAuth + ' file: ' + pugFile);
        res.render(path + '/pug/' + pugFile, {isAuth: isAuth});
    };

    /* loggedIn func from clementine.js. */
	let isLoggedInOrRedirect = function(req, res, next) {
		if (req.isAuthenticated()) {
			return next();
		}
        else {
            debug('Redirecting non-auth user to /login');
			return res.redirect('/login');
		}
	};

    let isLoggedInAjax = function(req, res, next) {
		if (req.isAuthenticated()) {
			return next();
		}
        else {
            debug('Non-authorized ajax call received');
            return res.status(403).json(notAuthorized);
        }
    };

    /* Returns the username from the request. Logs an error if username is not
     * present. */
    let getUserName = function(req, route) {
        if (req.user) {
            if (req.user.username) {
                return req.user.username;
            }
            else {
                logError(route, 'getUserName: No req.user.username exists.',
                    req);
            }
        }
        else {
            logError(route, 'getUserName: No req.user exists.', req);
        }
        return null;
    };

    let logErrorReq = function(req) {
        console.error('Error REQ headers: ');
        reqDebug(req);
    };

    /* Logs an error with route and request information included.*/
    let logError = function(route, err, req) {
        let date = new Date();
        console.error(date + ' [ERROR@SERVER] route ' + route + ' | ' + err);
        if (req) {
            logErrorReq(req);
        }
    };

    let debugJSON = function(msg, obj) {
        debug(msg + ' ' + JSON.stringify(obj));
    };

    // CONTROLLERS
    let userController = new UserController(path);
    let imageController = new ImageController(path);

    //----------------------------------------------------------------------
    // ROUTES
    //----------------------------------------------------------------------

	app.route('/')
		.get((req, res) => {
            renderPug(req, res, 'index.pug');
		});

	app.route('/about')
		.get((req, res) => {
            renderPug(req, res, 'about.pug');
		});

	app.route('/grid')
		.get((req, res) => {
            renderPug(req, res, 'grid.pug');
		});

	app.route('/all-images')
		.get((req, res) => {
            renderPug(req, res, 'images.pug');
		});

	app.route('/walls')
		.get((req, res) => {
            renderPug(req, res, 'walls.pug');
		});

	app.route('/signup')
		.get((req, res) => {
            renderPug(req, res, 'signup.pug');
		});

	app.route('/login')
		.get((req, res) => {
            renderPug(req, res, 'login.pug');
		});

	app.route('/loginFailed')
		.get((req, res) => {
            res.render(path + '/pug/login.pug',
                {isAuth: false, loginFailed: true});
        });

    // If a user logs out, return to main page
	app.route('/logout')
		.get((req, res) => {
			req.logout();
			res.redirect('/');
		});

	app.route('/profile')
		.get(isLoggedInOrRedirect, (req, res) => {
            renderPug(req, res, 'profile.pug');
		});

    // Handle registration of user
    app.route('/forms/signup')
        .post((req, res) => {
            debug('Got a signup form GET request..');
            userController.addLocalUser(req, res);
        });

    //----------------------------------------------------
    // /users/ Routes for accessing/manipulating user data
    //----------------------------------------------------

    // Called by client to check their authentication status
	app.route('/users/amiauth')
		.get((req, res) => {
            let data = {isAuth: false};
            if (req.isAuthenticated()) {
                data.isAuth = true;
                data.username = req.user.username;
                userController.getUserID(data.username, (err, userID) => {
                    if (err) {
                        logError('/users/amiauth', err, req);
                        res.status(500).json({error: 'Failed to authenticate'});
                    }
                    else {
                        data.userID = userID;
                        res.status(200).json(data);
                    }
                });
            }
            else {
                res.status(200).json(data);
            }
		});

    // Returns names of all users
    app.route('/users/list')
        .get((req, res) => {
            userController.getUserList(req, (err, resp) => {
                if (err) {
                    logError('/users/list', err, req);
                    res.status(500).json({error: 'No user list found.'});
                }
                else {
                    res.status(200).json(resp);
                }

            });
        });

    app.route('/users/:name')
        .get(isLoggedInAjax, (req, res) => {
            let username = req.params.name;
            if (username === req.user.username) {
                userController.getUserByName(username, (err, data) => {
                    if (err) {
                        logError('/users/' + username, err, req);
                        res.status(500).json(errorInternal);
                    }
                    else {
                        delete data.local.password;
                        res.json(data);
                    }
                });
            }
            else {
                // Forbidden
                logError('/users/' + username,
                    'Forbidden action attempted.', req);
                res.status(403).json(errorForbidden);
            }
        });

    app.route('/users/update')
        .post(isLoggedInAjax, (req, res) => {
            let username = getUserName(req, '/user/update');
            let userInfo = req.body;
            debugJSON('/users/update ' + _u(username) + ' info: ', userInfo);
            userController.updateUserInfo(username, userInfo, (err, data) => {
                if (err) {
                    logError('/users/update', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    res.json(data);
                }
            });
        });

    app.route('/users')
        .get(isLoggedInAjax, (req, res) => {
            let username = req.user.username;
            userController.getUserByName(username, (err, data) => {
                if (err) {
                    logError('/users/' + username, err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    delete data.local.password;
                    res.json(data);
                }
            });
        });

    //--------------------------------------
    // Images
    //--------------------------------------

    app.route('/images')

        .get( (req, res) => {
            imageController.getAllImages( (err, data) => {
                if (err) {
                    logError('/images', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debugJSON('GET /images result (200): ', data);
                    res.status(200).json(data);
                }
            });
        })

        /* Used for updating existing images. */
        .put(isLoggedInAjax, (req, res) => {
            debugJSON('PUT /images req.body: ', req.body);
            let username = req.user.username;
            imageController.updateImage(username, req.body, (err, result) => {
                if (err) {
                    logError('/images', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debugJSON('PUT /images result (200): ', result);
                    res.status(200).json({msg: 'OK'});
                }

            });
        })

        .post(isLoggedInAjax, (req, res) => {
            debug('/images POST');
            debugJSON('/images POST req.body: ', req.body);
            let username = req.user.username;
            imageController.addImage(username, req.body, (err, result) => {
                if (err) {
                    logError('/images POST', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debugJSON('/images POST result (200): ', result);
                    res.status(200).json({msg: 'OK'});
                }
            });

        })

        .delete(isLoggedInAjax, (req, res) => {
            debug('/images DELETE');
            debugJSON('/images DELETE req.body: ', req.body);
            let username = req.user.username;
            imageController.removeImage(username, req.body, (err, result) => {
                if (err) {
                    logError('/images DELETE', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debugJSON('/images DELETE result (200): ', result);
                    res.status(200).json({msg: 'OK'});
                }
            });

        });

    //--------------------------------------
    // User registration and authentication
    //--------------------------------------

	app.get('/auth/twitter',
		passport.authenticate('twitter'));

	app.get('/auth/twitter/callback',
		passport.authenticate('twitter', { failureRedirect: '/login' }),
		(req, res) => {
			// Successful authentication, redirect home.
			res.redirect('/profile');
		});

    // Logs user in via form (after successful authentication)
	app.route('/auth/userlogin')
        .post(passport.authenticate('local',
            { failureRedirect: '/loginFailed' }), (req, res) => {
			res.redirect('/');
		});

};
<commit_msg>Corrected args to getUSerList.<commit_after>'use strict';

let path = process.cwd();
let ctrlPath = path + '/server/ctrl';

const ImageController = require(ctrlPath + '/image-ctrl.server.js');
const UserController = require(ctrlPath + '/user-ctrl.server.js');
const debug = require('debug')('book:routes');

let _log = function(msg) {
    console.log('[LOG@SERVER]: ' + msg);
};

/* Function for debug logging requests.*/
let reqDebug = function(req) {
	_log('\t\tHeaders: ' + JSON.stringify(req.headers));
	_log('\t\tBody: ' + JSON.stringify(req.body));
	_log('\t\tParams: ' + JSON.stringify(req.params));
	_log('\t\tUrl:' + JSON.stringify(req.url));
	_log('\t\tText:' + JSON.stringify(req.text));
	_log('\t\tContent:' + JSON.stringify(req.content));
	_log('\t\tQuery:' + JSON.stringify(req.query));
};

const _u = function(username) {
    return '|' + username + '|';
};

// Msg objects sent back to the client
let notAuthorized = {msg: 'Operation not authorized. Log in first.'};
let errorInternal = {msg: 'Server internal error.'};
let errorForbidden = {msg: 'Requested action forbidden.'};

/* Contains all routes for this application. */
module.exports = function(app, passport) {

    /* Renders a pug template.*/
    let renderPug = function(req, res, pugFile) {
        let isAuth = req.isAuthenticated();
        debug('renderPug auth: ' + isAuth + ' file: ' + pugFile);
        res.render(path + '/pug/' + pugFile, {isAuth: isAuth});
    };

    /* loggedIn func from clementine.js. */
	let isLoggedInOrRedirect = function(req, res, next) {
		if (req.isAuthenticated()) {
			return next();
		}
        else {
            debug('Redirecting non-auth user to /login');
			return res.redirect('/login');
		}
	};

    let isLoggedInAjax = function(req, res, next) {
		if (req.isAuthenticated()) {
			return next();
		}
        else {
            debug('Non-authorized ajax call received');
            return res.status(403).json(notAuthorized);
        }
    };

    /* Returns the username from the request. Logs an error if username is not
     * present. */
    let getUserName = function(req, route) {
        if (req.user) {
            if (req.user.username) {
                return req.user.username;
            }
            else {
                logError(route, 'getUserName: No req.user.username exists.',
                    req);
            }
        }
        else {
            logError(route, 'getUserName: No req.user exists.', req);
        }
        return null;
    };

    let logErrorReq = function(req) {
        console.error('Error REQ headers: ');
        reqDebug(req);
    };

    /* Logs an error with route and request information included.*/
    let logError = function(route, err, req) {
        let date = new Date();
        console.error(date + ' [ERROR@SERVER] route ' + route + ' | ' + err);
        if (req) {
            logErrorReq(req);
        }
    };

    let debugJSON = function(msg, obj) {
        debug(msg + ' ' + JSON.stringify(obj));
    };

    // CONTROLLERS
    let userController = new UserController(path);
    let imageController = new ImageController(path);

    //----------------------------------------------------------------------
    // ROUTES
    //----------------------------------------------------------------------

	app.route('/')
		.get((req, res) => {
            renderPug(req, res, 'index.pug');
		});

	app.route('/about')
		.get((req, res) => {
            renderPug(req, res, 'about.pug');
		});

	app.route('/grid')
		.get((req, res) => {
            renderPug(req, res, 'grid.pug');
		});

	app.route('/all-images')
		.get((req, res) => {
            renderPug(req, res, 'images.pug');
		});

	app.route('/walls')
		.get((req, res) => {
            renderPug(req, res, 'walls.pug');
		});

	app.route('/signup')
		.get((req, res) => {
            renderPug(req, res, 'signup.pug');
		});

	app.route('/login')
		.get((req, res) => {
            renderPug(req, res, 'login.pug');
		});

	app.route('/loginFailed')
		.get((req, res) => {
            res.render(path + '/pug/login.pug',
                {isAuth: false, loginFailed: true});
        });

    // If a user logs out, return to main page
	app.route('/logout')
		.get((req, res) => {
			req.logout();
			res.redirect('/');
		});

	app.route('/profile')
		.get(isLoggedInOrRedirect, (req, res) => {
            renderPug(req, res, 'profile.pug');
		});

    // Handle registration of user
    app.route('/forms/signup')
        .post((req, res) => {
            debug('Got a signup form GET request..');
            userController.addLocalUser(req, res);
        });

    //----------------------------------------------------
    // /users/ Routes for accessing/manipulating user data
    //----------------------------------------------------

    // Called by client to check their authentication status
	app.route('/users/amiauth')
		.get((req, res) => {
            let data = {isAuth: false};
            if (req.isAuthenticated()) {
                data.isAuth = true;
                data.username = req.user.username;
                userController.getUserID(data.username, (err, userID) => {
                    if (err) {
                        logError('/users/amiauth', err, req);
                        res.status(500).json({error: 'Failed to authenticate'});
                    }
                    else {
                        data.userID = userID;
                        res.status(200).json(data);
                    }
                });
            }
            else {
                res.status(200).json(data);
            }
		});

    // Returns names of all users
    app.route('/users/list')
        .get((req, res) => {
            userController.getUserList((err, resp) => {
                if (err) {
                    logError('/users/list', err, req);
                    res.status(500).json({error: 'No user list found.'});
                }
                else {
                    res.status(200).json(resp);
                }

            });
        });

    app.route('/users/:name')
        .get(isLoggedInAjax, (req, res) => {
            let username = req.params.name;
            if (username === req.user.username) {
                userController.getUserByName(username, (err, data) => {
                    if (err) {
                        logError('/users/' + username, err, req);
                        res.status(500).json(errorInternal);
                    }
                    else {
                        delete data.local.password;
                        res.json(data);
                    }
                });
            }
            else {
                // Forbidden
                logError('/users/' + username,
                    'Forbidden action attempted.', req);
                res.status(403).json(errorForbidden);
            }
        });

    app.route('/users/update')
        .post(isLoggedInAjax, (req, res) => {
            let username = getUserName(req, '/user/update');
            let userInfo = req.body;
            debugJSON('/users/update ' + _u(username) + ' info: ', userInfo);
            userController.updateUserInfo(username, userInfo, (err, data) => {
                if (err) {
                    logError('/users/update', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    res.json(data);
                }
            });
        });

    app.route('/users')
        .get(isLoggedInAjax, (req, res) => {
            let username = req.user.username;
            userController.getUserByName(username, (err, data) => {
                if (err) {
                    logError('/users/' + username, err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    delete data.local.password;
                    res.json(data);
                }
            });
        });

    //--------------------------------------
    // Images
    //--------------------------------------

    app.route('/images')

        .get( (req, res) => {
            imageController.getAllImages( (err, data) => {
                if (err) {
                    logError('/images', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debugJSON('GET /images result (200): ', data);
                    res.status(200).json(data);
                }
            });
        })

        /* Used for updating existing images. */
        .put(isLoggedInAjax, (req, res) => {
            debugJSON('PUT /images req.body: ', req.body);
            let username = req.user.username;
            imageController.updateImage(username, req.body, (err, result) => {
                if (err) {
                    logError('/images', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debugJSON('PUT /images result (200): ', result);
                    res.status(200).json({msg: 'OK'});
                }

            });
        })

        .post(isLoggedInAjax, (req, res) => {
            debug('/images POST');
            debugJSON('/images POST req.body: ', req.body);
            let username = req.user.username;
            imageController.addImage(username, req.body, (err, result) => {
                if (err) {
                    logError('/images POST', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debugJSON('/images POST result (200): ', result);
                    res.status(200).json({msg: 'OK'});
                }
            });

        })

        .delete(isLoggedInAjax, (req, res) => {
            debug('/images DELETE');
            debugJSON('/images DELETE req.body: ', req.body);
            let username = req.user.username;
            imageController.removeImage(username, req.body, (err, result) => {
                if (err) {
                    logError('/images DELETE', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debugJSON('/images DELETE result (200): ', result);
                    res.status(200).json({msg: 'OK'});
                }
            });

        });

    //--------------------------------------
    // User registration and authentication
    //--------------------------------------

	app.get('/auth/twitter',
		passport.authenticate('twitter'));

	app.get('/auth/twitter/callback',
		passport.authenticate('twitter', { failureRedirect: '/login' }),
		(req, res) => {
			// Successful authentication, redirect home.
			res.redirect('/profile');
		});

    // Logs user in via form (after successful authentication)
	app.route('/auth/userlogin')
        .post(passport.authenticate('local',
            { failureRedirect: '/loginFailed' }), (req, res) => {
			res.redirect('/');
		});

};
<|endoftext|>


<commit_before>const Joi = require('joi')

exports.create = Joi.object({
  location: Joi.object({
    latitude: Joi.number().required(),
    longitude: Joi.number().required()
  }),
  place: {
    id: Joi.string(),
    name: Joi.string()
  },
  visitor: {
    message: Joi.string().required(),
    name: Joi.string().allow('', null)
  }
}).options({ stripUnknown: true })

exports.getAllQuery = Joi.object({
  visitors: Joi.boolean()
}).options({ stripUnknown: true })

exports.response = Joi.array().items(Joi.object({
  location: Joi.object({
    latitude: Joi.number().required(),
    longitude: Joi.number().required()
  }).rename('lat', 'latitude')
    .rename('lng', 'longitude'),
  name: Joi.string().required(),
  placeId: Joi.string().required()
}).rename('place_id', 'placeId')
  .options({ stripUnknown: true }))

exports.searchQuery = Joi.object({
  location: Joi.string().required(),
  keyword: Joi.string()
})

<commit_msg>Add callback schema for Foursquare authentication<commit_after>const Joi = require('joi')

exports.create = Joi.object({
  location: Joi.object({
    latitude: Joi.number().required(),
    longitude: Joi.number().required()
  }),
  place: {
    id: Joi.string(),
    name: Joi.string()
  },
  visitor: {
    message: Joi.string().required(),
    name: Joi.string().allow('', null)
  }
}).options({ stripUnknown: true })

exports.getAllQuery = Joi.object({
  visitors: Joi.boolean()
}).options({ stripUnknown: true })

exports.callbackQuery = Joi.object({
  code: Joi.string()
}).options({ stripUnknown: true })

exports.response = Joi.array().items(Joi.object({
  location: Joi.object({
    latitude: Joi.number().required(),
    longitude: Joi.number().required()
  }).rename('lat', 'latitude')
    .rename('lng', 'longitude'),
  name: Joi.string().required(),
  placeId: Joi.string().required()
}).rename('place_id', 'placeId')
  .options({ stripUnknown: true }))

exports.searchQuery = Joi.object({
  location: Joi.string().required(),
  keyword: Joi.string()
})

<|endoftext|>


<commit_before>var express = require('express');
var sequelize = require('./db/database.js');
var app = express();

app.set('view engine', 'html');
app.use('/', express.static('./public'));

var bodyParser = require('body-parser');
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());

module.exports = app;

//require sequelize models
var models = require('./db/orm-model.js');
var models = models();
var User = models.User;
var Activity = models.Activity;

//Insert or update user information in database
app.post('/data/user', function(req, res) {
  'use strict';
  User.upsert({
    userId: req.body.user_id,
    email: req.body.email,
    picture: req.body.picture,
    name: req.body.name,
    nickname:req.body.nickname});
  res.sendStatus(200);
});

app.get('/data/user', function(req, res){
  'use strict';
  res.sendStatus(200);
});

app.post('/data/activities', function(req, res){
  'use strict';
    Activity.build({
      title: req.body.title,
      description: req.body.description,
      location: req.body.location,
      keywords: req.body.keywords,
      ownerIdUserId: req.body.user_id,
      active: true
    })
    .save();
  res.redirect('/');
});

app.get('/data/activities', function(req, res){
  'use strict';

  //query for all activities for which the user is NOT an owner
  sequelize.query("select id, description, title, keywords, location, " +
    "(select picture from Users user where userId = activity.ownerIdUserId) " +
     "as avatar, (select name from Users user where userId = " +
      "activity.ownerIdUserId) as owner from Activities activity " +
    "where ownerIdUserId != '" + req.query.userID + "'",
    { type: sequelize.QueryTypes.SELECT}).then(function(results){
      res.send(results);
  });

});//app.get

app.post('/data/join', function(req, res){
  'use strict';
  User.find({where: {userId: req.body.user_id}})
    .then(function(user){
      Activity.find({where: {id: req.body.activity_id}})
      .then(function(activity){
        user.addActivity(activity);
      });
    });
  res.redirect('/');
});

app.post('/data/leave', function(req, res){
  'use strict';
  User.find({where: {userId: req.body.user_id}})
    .then(function(user){
      Activity.find({where: {id: req.body.activity_id}})
      .then(function(activity){
        user.removeActivity(activity);
      });
    });
  res.redirect('/');
});
//tell the difference between owner vs. just belonging to activity;
//also show activity if owner in side-bar

app.get('/data/userActivities', function(req, res){
  'use strict';
  Activity.findAll({
    where: {
      ownerIdUserId : req.query.userID,
      active: true
    }
  }).then(function(ownedActivities){

    res.send(ownedActivities);
  });
});//app.get

app.get('/data/participatingActivities', function(req, res){
  'use strict';
  User.find({
    where: {
      userId: req.query.userID
    }
  }).then(function(user){
    user.getActivities({
      where : {
        active : true
      }
    })
    .then(function(activities){
      res.send(activities);
    });
  });
});//app.get

app.get('/data/closedActivities', function(req, res){
   'use strict';
  Activity.findAll({
    where: {
      ownerIdUserId : req.query.userID,
      active : false
    }
  }).then(function(ownedActivities){
    res.send(ownedActivities);
  });
});//app.get

app.post('/data/toggle', function(req, res){
  'use strict';
  Activity.find({
    where: {
      id: req.body.activity_id
    }
  })
  .then(function(activity){
    activity.updateAttributes({active: !activity.get('active')});
  });
  res.redirect('/');
});
<commit_msg>Added active filter to query.<commit_after>var express = require('express');
var sequelize = require('./db/database.js');
var app = express();

app.set('view engine', 'html');
app.use('/', express.static('./public'));

var bodyParser = require('body-parser');
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());

module.exports = app;

//require sequelize models
var models = require('./db/orm-model.js');
var models = models();
var User = models.User;
var Activity = models.Activity;

//Insert or update user information in database
app.post('/data/user', function(req, res) {
  'use strict';
  User.upsert({
    userId: req.body.user_id,
    email: req.body.email,
    picture: req.body.picture,
    name: req.body.name,
    nickname:req.body.nickname});
  res.sendStatus(200);
});

app.get('/data/user', function(req, res){
  'use strict';
  res.sendStatus(200);
});

app.post('/data/activities', function(req, res){
  'use strict';
    Activity.build({
      title: req.body.title,
      description: req.body.description,
      location: req.body.location,
      keywords: req.body.keywords,
      ownerIdUserId: req.body.user_id,
      active: true
    })
    .save();
  res.redirect('/');
});

app.get('/data/activities', function(req, res){
  'use strict';

  //query for all activities for which the user is NOT an owner
  sequelize.query("select id, description, title, keywords, location, " +
    "(select picture from Olympus.Users user where userId = activity.ownerIdUserId) " +
     "as avatar, (select name from Olympus.Users user where userId = " +
      "activity.ownerIdUserId) as owner from Olympus.Activities activity " +
    "where ownerIdUserId != '" + req.query.userID + "' and active = true",
    { type: sequelize.QueryTypes.SELECT}).then(function(results){
      res.send(results);
  });

});//app.get

app.post('/data/join', function(req, res){
  'use strict';
  User.find({where: {userId: req.body.user_id}})
    .then(function(user){
      Activity.find({where: {id: req.body.activity_id}})
      .then(function(activity){
        user.addActivity(activity);
      });
    });
  res.redirect('/');
});

app.post('/data/leave', function(req, res){
  'use strict';
  User.find({where: {userId: req.body.user_id}})
    .then(function(user){
      Activity.find({where: {id: req.body.activity_id}})
      .then(function(activity){
        user.removeActivity(activity);
      });
    });
  res.redirect('/');
});
//tell the difference between owner vs. just belonging to activity;
//also show activity if owner in side-bar

app.get('/data/userActivities', function(req, res){
  'use strict';
  Activity.findAll({
    where: {
      ownerIdUserId : req.query.userID,
      active: true
    }
  }).then(function(ownedActivities){

    res.send(ownedActivities);
  });
});//app.get

app.get('/data/participatingActivities', function(req, res){
  'use strict';
  User.find({
    where: {
      userId: req.query.userID
    }
  }).then(function(user){
    user.getActivities({
      where : {
        active : true
      }
    })
    .then(function(activities){
      res.send(activities);
    });
  });
});//app.get

app.get('/data/closedActivities', function(req, res){
   'use strict';
  Activity.findAll({
    where: {
      ownerIdUserId : req.query.userID,
      active : false
    }
  }).then(function(ownedActivities){
    res.send(ownedActivities);
  });
});//app.get

app.post('/data/toggle', function(req, res){
  'use strict';
  Activity.find({
    where: {
      id: req.body.activity_id
    }
  })
  .then(function(activity){
    activity.updateAttributes({active: !activity.get('active')});
  });
  res.redirect('/');
});
<|endoftext|>


<commit_before>/**
 * muvia db service. offers a facade to communicate with the backend DB.
 */
"use strict";

var config = require('../config.js');
var mongodb = require('mongodb').MongoClient;

mongodb.connect(config.dburl, function(err, db) {
  if(!err) {
	console.log('mudb.js: connected to DB!');
  }
});

<commit_msg>defining a db object for the mudb service<commit_after>/**
 * muvia db service. offers a facade to communicate with the backend DB.
 */
"use strict";

var config = require('../config.js');
var mongodbclient = require('mongodb').MongoClient;
var mongodb = null;

mongodbclient.connect(config.dburl, function(err, db) {
  if(!err) {
	console.log('mudb.js: connected to DB!');
	mongodb = db;
  }else{
  	console.log("mudb.js: error connecting to db:", err);
  }
});

<|endoftext|>


<commit_before>import path from 'path'
import express from 'express'

import base, { SiteConf } from 'base'

const commonStatics = () => [
  { route: '/dist', dir: path.join(__dirname, '../../dist') },
  { route: '/registerSwV1.js', dir: path.join(__dirname, '../serviceWorker/register.js') },
  { route: '/serviceWorker.js', dir: path.join(__dirname, '../serviceWorker/serviceWorker.js') },
  { route: '/manifest.json', dir: path.join(__dirname, '../manifest.json') },
  { route: '/offline.html', dir: path.join(__dirname, '../templates/offline.html') },
]

const devStatics = () => [
  { route: '/', dir: path.join(__dirname, '../../src/app') },
  { route: '/dlls', dir: path.join(__dirname, '../../dist/') },
  { route: '/content', dir: path.resolve(SiteConf.ContentPath), cache: { maxage: 31557600 } }
]

const prodStatics = () => [
  { route: '/', dir: path.join(__dirname, '../../dist') },
  { route: '/tag/assets/', dir: path.join(__dirname, '../../dist/assets') },
]

const envStatics = (base.env === 'development') ?
  commonStatics().concat(devStatics()) : commonStatics().concat(prodStatics())

export default function applyStaticsPaths(app) {
  envStatics.map(function(staticPath) {
    app.use(staticPath.route, express.static(staticPath.dir, staticPath.cache))
    base.console.success(`Applied static path ${staticPath.route}`)
  })
}
<commit_msg>Set no-cache in sw<commit_after>import path from 'path'
import express from 'express'

import base, { SiteConf } from 'base'

const commonStatics = () => [
  { route: '/dist', dir: path.join(__dirname, '../../dist') },
  { route: '/registerSwV1.js', dir: path.join(__dirname, '../serviceWorker/register.js'), cache: { maxage: 'no-cache' } },
  { route: '/serviceWorker.js', dir: path.join(__dirname, '../serviceWorker/serviceWorker.js'), cache: { maxage: 'no-cache' } },
  { route: '/manifest.json', dir: path.join(__dirname, '../manifest.json'), cache: { maxage: 'no-cache' } },
  { route: '/offline.html', dir: path.join(__dirname, '../templates/offline.html') },
]

const devStatics = () => [
  { route: '/', dir: path.join(__dirname, '../../src/app') },
  { route: '/dlls', dir: path.join(__dirname, '../../dist/') },
  { route: '/content', dir: path.resolve(SiteConf.ContentPath), cache: { maxage: 31557600 } }
]

const prodStatics = () => [
  { route: '/', dir: path.join(__dirname, '../../dist') },
  { route: '/tag/assets/', dir: path.join(__dirname, '../../dist/assets') },
]

const envStatics = (base.env === 'development') ?
  commonStatics().concat(devStatics()) : commonStatics().concat(prodStatics())

export default function applyStaticsPaths(app) {
  envStatics.map(function(staticPath) {
    app.use(staticPath.route, express.static(staticPath.dir, staticPath.cache))
    base.console.success(`Applied static path ${staticPath.route}`)
  })
}
<|endoftext|>


<commit_before>/* globals setInterval, clearInterval, setTimeout */
import { getPositions } from './devices';
import { BLACK, RESET_DESK_LIGHT_STRIP_TIMEOUT } from 'constants';

const random = (cap) => Math.floor(Math.random() * (cap - 1)) + 1;

export const cylonEye = {
  start(strip, stripLength) {
    const FPS = 160;
    const UP = 'UP';
    const DOWN = 'DOWN';
    const positions = getPositions(stripLength);

    let red = 100;
    let blue = 0;
    let blueDirection = UP;
    let redDirection = DOWN;
    let direction = UP;
    let valueToLight = 0;

    this.interval = setInterval(() => {
      strip.color(BLACK);

      if (blue >= 255) {
        blueDirection = DOWN;
      } else if (blue <= 0) {
        blueDirection = UP;
      }

      if (blueDirection === UP) {
        blue++;
      } else {
        blue--;
      }

      if (red >= 100) {
        redDirection = DOWN;
      } else if (red <= 0) {
        redDirection = UP;
      }

      if (redDirection === UP) {
        red++;
      } else {
        red--;
      }

      if (valueToLight >= stripLength - 1) {
        direction = DOWN;
      }

      if (valueToLight <= 0) {
        direction = UP;
      }

      if (direction === UP) {
        valueToLight++;
      } else {
        valueToLight--;
      }

      const color = `rgb(${red}, ${0}, ${blue})`;

      strip.pixel(positions[valueToLight]).color(color);
      strip.show();
    }, 1000 / FPS);
  },

  stop(strip) {
    strip.color(BLACK);
    clearInterval(this.interval);
  }
};

export const rain = {
  start(strip, stripLength) {
    const UP = 'UP';
    const DOWN = 'DOWN';
    const rgbBiases = [ 'RED', 'BLUE' ];
    const generateColor = (r, g, b) => `rgb(${r}, ${0}, ${b})`;
    const generateRGBBias = () => rgbBiases[random(rgbBiases.length + 1) - 1];
    const createDrop = () => ({
      color: generateColor(0, 0, 0),
      rgbBias: generateRGBBias(),
      intensity: random(255),
      position: random(stripLength),
      direction: UP
    });
    const FPS = 90;
    const positions = getPositions(stripLength);

    const drops = [];

    for (let i of Array(10).keys()) { // eslint-disable-line no-unused-vars, prefer-const
      drops.push(createDrop(stripLength));
    }

    this.interval = setInterval(() => {
      strip.show();

      drops.forEach((drop, index) => {
        strip.pixel(positions[drop.position]).color(drop.color);

        if (drop.direction === UP) {
          drop.intensity = drop.intensity + 6;
        } else if (drop.direction === DOWN) {
          drop.intensity = drop.intensity - 6;
        }

        if (drop.intensity >= 255) {
          drop.direction = DOWN;
        } else if (drop.intensity <= 0) {
          drop.direction = UP;
          drop.position = random(stripLength);
          drop.rgbBias = generateRGBBias();
        }

        const tunedDown = Math.max(drop.intensity - 50, 0);
        if (drop.rgbBiases === RED) {
          drop.color = generateColor(drop.intensity, tunedDown, tunedDown);
        } else if (drop.rgbBias === GREEN) {
          drop.color = generateColor(tunedDown, drop.intensity, tunedDown);
        } else if (drop.rgbBias === BLUE) {
          drop.color = generateColor(tunedDown, tunedDown, drop.intensity);
        }
      });

    }, 100 / FPS);
  },

  stop(strip) {
    strip.color(BLACK);
    clearInterval(this.interval);
  }
};

export const flashColor = (strip, color, callback) => {
  strip.color(color);
  strip.show();

  setTimeout(() => {
    strip.color(BLACK);
    strip.show();

    callback();
  }, RESET_DESK_LIGHT_STRIP_TIMEOUT);
};

export const buzz = (piezo) => piezo.play({
  song: [
    ['C4', 1],
    [null, 1],
    ['D4', 1],
    [null, 1],
    ['C4', 1]
  ],
  tempo: 1000
});

export const doot = (piezo) => piezo.play({
  song: [
    ['C4', 1],
    [null, 1],
    ['D4', 1],
    [null, 1],
    ['C4', 1]
  ],
  tempo: 1000
});
<commit_msg>Fix rain effect<commit_after>/* globals setInterval, clearInterval, setTimeout */
import { getPositions } from './devices';
import { BLACK, RESET_DESK_LIGHT_STRIP_TIMEOUT } from 'constants';

const random = (cap) => Math.floor(Math.random() * (cap - 1)) + 1;

export const cylonEye = {
  start(strip, stripLength) {
    const FPS = 160;
    const UP = 'UP';
    const DOWN = 'DOWN';
    const positions = getPositions(stripLength);

    let red = 100;
    let blue = 0;
    let blueDirection = UP;
    let redDirection = DOWN;
    let direction = UP;
    let valueToLight = 0;

    this.interval = setInterval(() => {
      strip.color(BLACK);

      if (blue >= 255) {
        blueDirection = DOWN;
      } else if (blue <= 0) {
        blueDirection = UP;
      }

      if (blueDirection === UP) {
        blue++;
      } else {
        blue--;
      }

      if (red >= 100) {
        redDirection = DOWN;
      } else if (red <= 0) {
        redDirection = UP;
      }

      if (redDirection === UP) {
        red++;
      } else {
        red--;
      }

      if (valueToLight >= stripLength - 1) {
        direction = DOWN;
      }

      if (valueToLight <= 0) {
        direction = UP;
      }

      if (direction === UP) {
        valueToLight++;
      } else {
        valueToLight--;
      }

      const color = `rgb(${red}, ${0}, ${blue})`;

      strip.pixel(positions[valueToLight]).color(color);
      strip.show();
    }, 1000 / FPS);
  },

  stop(strip) {
    strip.color(BLACK);
    clearInterval(this.interval);
  }
};

export const rain = {
  start(strip, stripLength) {
    const UP = 'UP';
    const DOWN = 'DOWN';
    const rgbBiases = [ 'RED', 'BLUE' ];
    const generateColor = (r, g, b) => `rgb(${r}, ${0}, ${b})`;
    const generateRGBBias = () => rgbBiases[random(rgbBiases.length + 1) - 1];
    const createDrop = () => ({
      color: generateColor(0, 0, 0),
      rgbBias: generateRGBBias(),
      intensity: random(255),
      position: random(stripLength),
      direction: UP
    });
    const FPS = 90;
    const positions = getPositions(stripLength);

    const drops = [];

    for (let i of Array(10).keys()) { // eslint-disable-line no-unused-vars, prefer-const
      drops.push(createDrop(stripLength));
    }

    this.interval = setInterval(() => {
      strip.show();

      drops.forEach((drop, index) => {
        strip.pixel(positions[drop.position]).color(drop.color);

        if (drop.direction === UP) {
          drop.intensity = drop.intensity + 6;
        } else if (drop.direction === DOWN) {
          drop.intensity = drop.intensity - 6;
        }

        if (drop.intensity >= 255) {
          drop.direction = DOWN;
        } else if (drop.intensity <= 0) {
          drop.direction = UP;
          drop.position = random(stripLength);
          drop.rgbBias = generateRGBBias();
        }

        const tunedDown = Math.max(drop.intensity - 50, 0);
        if (drop.rgbBiases === 'RED') {
          drop.color = generateColor(drop.intensity, tunedDown, tunedDown);
        } else if (drop.rgbBias === 'GREEN') {
          drop.color = generateColor(tunedDown, drop.intensity, tunedDown);
        } else if (drop.rgbBias === 'BLUE') {
          drop.color = generateColor(tunedDown, tunedDown, drop.intensity);
        }
      });

    }, 100 / FPS);
  },

  stop(strip) {
    strip.color(BLACK);
    clearInterval(this.interval);
  }
};

export const flashColor = (strip, color, callback) => {
  strip.color(color);
  strip.show();

  setTimeout(() => {
    strip.color(BLACK);
    strip.show();

    callback();
  }, RESET_DESK_LIGHT_STRIP_TIMEOUT);
};

export const buzz = (piezo) => piezo.play({
  song: [
    ['C4', 1],
    [null, 1],
    ['D4', 1],
    [null, 1],
    ['C4', 1]
  ],
  tempo: 1000
});

export const doot = (piezo) => piezo.play({
  song: [
    ['C4', 1],
    [null, 1],
    ['D4', 1],
    [null, 1],
    ['C4', 1]
  ],
  tempo: 1000
});
<|endoftext|>