<commit_before>(function ($) {
  Drupal.behaviors.owsinfield = {
    attach: function (context, settings) {
      // Add code here.
      $("label").inFieldLabels();
    }
  }
})(jQuery);<commit_msg>tweaking the infield label js so it doesn't affect other forms.<commit_after>(function ($) {
  Drupal.behaviors.owsinfield = {
    attach: function (context, settings) {
      // Add code here.
      $("div.newsletter-wrapper label").inFieldLabels();
    }
  }
})(jQuery);
<|endoftext|>


<commit_before>/*jslint browser: true, undef: true *//*global Ext*/
Ext.define('SlateAdmin.Application', {
    extend: 'Ext.app.Application',
    requires: [
        'SlateAdmin.API',

        // Jarvus enhancements
//        'Jarvus.ext.override.grid.column.ActionEvents', // TODO: replace with jarvus-ext-actionevents package
//        'Jarvus.ext.override.grid.column.ActionGlyphs', // TODO: replace with jarvus-ext-glyphs package
//        'Jarvus.ext.override.panel.ToggleEvent',
        'Jarvus.ext.override.tree.Records',
        'Jarvus.ext.override.data.RequireLoadedStores',

        // Jarvus bug fixes
//        'Jarvus.ext.patch.panel.ExpandBeforeRender',
//        'Jarvus.ext.patch.grid.ResetTipAttributes',
//        'Jarvus.ext.patch.data.BufferedStoreStrictId',
//        'Jarvus.ext.patch.data.TreeStoreIndexOf',
//        'Jarvus.ext.patch.grid.DisableGroupingFeature', // not used

        // framework features
        'Ext.state.LocalStorageProvider'
    ],

    // application config
    name: 'SlateAdmin',
    suspendLayoutUntilInitialRoute: true,

    controllers: [
        'Viewport',
        'Login',

        'People',
//        'people.Invite',
        'people.Profile',
        'people.Courses',
        'people.Contacts',

        'Courses',
        'courses.Profile',
        'courses.Participants',

        'Settings',
        'settings.Groups',

        'Terms',
        'Locations'

        //<debug>
        ,'DeveloperTools'
        //</debug>
    ],

    // application template methods
    init: function() {
        var pageParams = Ext.Object.fromQueryString(location.search);

        Ext.state.Manager.setProvider(Ext.create('Ext.state.LocalStorageProvider', {
            prefix: 'slateadmin-'
        }));

        if (pageParams.apiHost) {
            SlateAdmin.API.setHostname(pageParams.apiHost);
        }
    },

    // application methods
    getModuleByRootPath: function(rootPath) {
        var matchedController;

        this.controllers.each(function(controller) {
            if (controller.rootPath == rootPath) {
                matchedController = controller;
                return false;
            }
        });

        return matchedController;
    },

    onRouteNotFound: function(token) {
        if (!token) {
            Ext.util.History.add('people');
        } else {
            console.warn('Route not found: %o', token);
        }
    }
});<commit_msg>removing ResetTipAttributes patch -  The discussion thread reference in comment for this patch must be for support only forums users, but the fiddle referenced in comment indicates this issue was fixed sometime between 4.2.0.663 and 4.2.1.883.  The issue does not seem to happen in current Ext 5.1.1.451<commit_after>/*jslint browser: true, undef: true *//*global Ext*/
Ext.define('SlateAdmin.Application', {
    extend: 'Ext.app.Application',
    requires: [
        'SlateAdmin.API',

        // Jarvus enhancements
//        'Jarvus.ext.override.grid.column.ActionEvents', // TODO: replace with jarvus-ext-actionevents package
//        'Jarvus.ext.override.grid.column.ActionGlyphs', // TODO: replace with jarvus-ext-glyphs package
//        'Jarvus.ext.override.panel.ToggleEvent',
        'Jarvus.ext.override.tree.Records',
        'Jarvus.ext.override.data.RequireLoadedStores',

        // Jarvus bug fixes
//        'Jarvus.ext.patch.panel.ExpandBeforeRender',
//        'Jarvus.ext.patch.data.BufferedStoreStrictId',
//        'Jarvus.ext.patch.data.TreeStoreIndexOf',
//        'Jarvus.ext.patch.grid.DisableGroupingFeature', // not used

        // framework features
        'Ext.state.LocalStorageProvider'
    ],

    // application config
    name: 'SlateAdmin',
    suspendLayoutUntilInitialRoute: true,

    controllers: [
        'Viewport',
        'Login',

        'People',
//        'people.Invite',
        'people.Profile',
        'people.Courses',
        'people.Contacts',

        'Courses',
        'courses.Profile',
        'courses.Participants',

        'Settings',
        'settings.Groups',

        'Terms',
        'Locations'

        //<debug>
        ,'DeveloperTools'
        //</debug>
    ],

    // application template methods
    init: function() {
        var pageParams = Ext.Object.fromQueryString(location.search);

        Ext.state.Manager.setProvider(Ext.create('Ext.state.LocalStorageProvider', {
            prefix: 'slateadmin-'
        }));

        if (pageParams.apiHost) {
            SlateAdmin.API.setHostname(pageParams.apiHost);
        }
    },

    // application methods
    getModuleByRootPath: function(rootPath) {
        var matchedController;

        this.controllers.each(function(controller) {
            if (controller.rootPath == rootPath) {
                matchedController = controller;
                return false;
            }
        });

        return matchedController;
    },

    onRouteNotFound: function(token) {
        if (!token) {
            Ext.util.History.add('people');
        } else {
            console.warn('Route not found: %o', token);
        }
    }
});
<|endoftext|>


<commit_before>import deepmerge from 'deepmerge';
import isPlainObject from 'is-plain-object';
import fs from 'fs'

const hideSpoilers = {
  backgroundColor: 'black',
  color: 'black',
  '& a, & a:hover, & a:focus': {
    color: 'black'
  },
  '& code': {
    backgroundColor: 'black',
  }
}

const spoilerStyles = (theme) => ({
  '& p.spoiler': {
    margin: 0,
  },
  '& .spoiler': {
    padding: 8,
    pointerEvents: 'auto',
    minHeight: theme.typography.commentStyle.fontSize,
    '& .public-DraftStyleDefault-block': {
      margin: 0,
    },
    '&:not(:hover)': { // using ':not(:hover)' means we don't need to manually reset elements with special colors or backgrounds, instead they just automatically stay the same if we're not hovering
      ...hideSpoilers,
    }
  },
  // Note: ".spoiler" is the old class Oli originally used. ".spoilers" is a new class
  // that is applied in make_editable_callbacks.js to groups of adjaecent spoiler paragraphs.
  // (see the make_editable_callbacks.js file for details)
  '& div.spoilers': {
    margin: '1em 0',
    overflow: 'auto',
    '&:not(:hover)': {
      ...hideSpoilers,
    },
    '&:hover': {
      background: 'rgba(0,0,0,.12)' // This leaves a light grey background over the revealed-spoiler to make it more obvious where it started.
    }
  },
  '& p.spoiler-v2': {
    margin: 0,
    padding: '0.5em 8px'
  },
  '& .spoilers:not(:hover)::selection, & .spoilers:not(:hover) ::selection': {
    backgroundColor: 'transparent'
  },
  '& .spoilers > p:hover ~ p': {
    ...hideSpoilers
  }
})

const tableStyles = {
  borderCollapse: "collapse",
  borderSpacing: 0,
  border: "1px double #b3b3b3",
  margin: "auto"
}

const tableCellStyles = {
  minWidth: "2em",
  padding: ".4em",
  border: "1px double #d9d9d9",
}

const tableHeadingStyles = {
  background: "#fafafa",
  fontWeight: 700
}

const baseBodyStyles = theme => ({
  ...theme.typography.body1,
  ...theme.typography.postStyle,
  wordBreak: "break-word",
  '& pre': {
    ...theme.typography.codeblock
  },
  '& code': {
    ...theme.typography.code
  },
  '& blockquote': {
    ...theme.typography.blockquote,
    ...theme.typography.body1,
    ...theme.typography.postStyle
  },
  '& li': {
    ...theme.typography.body1,
    ...theme.typography.li,
    ...theme.typography.postStyle
  },
  '& h1': {
    ...theme.typography.display2,
    ...theme.typography.headerStyle,
  },
  // If a post starts with a header, it should still be flush with the top of
  // the container
  '& h1:first-child': {
    marginTop: 0,
    // Otherwise the line height lowers it noticeably
    marginBlockStart: '-3px',
  },
  '& h2': {
    ...theme.typography.display1,
    ...theme.typography.headerStyle,
  },
  '& h2:first-child': {
    marginTop: 0,
    marginBlockStart: '-2px',
  },
  '& h3': {
    ...theme.typography.display0,
    ...theme.typography.headerStyle,
  },
  '& h3:first-child': {
    marginTop: 0,
    marginBlockStart: 0,
  },
  '& h4': {
    ...theme.typography.body1,
    ...theme.typography.postStyle,
    fontWeight:600,
  },
  '& img': {
    maxWidth: "100%"
  },
  '& sup': {
    verticalAlign: 'baseline',
    top: '-0.6em',
    fontSize: '65%',
    position: 'relative'
  },
  '& a, & a:hover, & a:active': {
    color: theme.palette.primary.main
  },
  '& table': {
    ...tableStyles
  },
  '& td, & th': {
    ...tableCellStyles
  },
  '& th': {
    ...tableHeadingStyles
  },
  '& figure': {
    margin: '1em auto',
    textAlign: "center"
  },
  '& figcaption': {
    ...theme.typography.caption,
    ...theme.typography.postStyle
  }
})

export const postBodyStyles = (theme) => {
  const result = {
    ...baseBodyStyles(theme),
    ...spoilerStyles(theme),
    // Used for R:A-Z imports as well as markdown-it-footnotes
    '& .footnotes': {
      marginTop: 40,
      fontSize: '0.9em',
      paddingTop: 40,
      borderTop: 'solid 1px rgba(0,0,0,0.2)',
      '& sup': {
        marginRight: 10,
      },
      '& ol': {
        marginBlockStart: '1em',
        paddingInlineStart: 0,
        marginInlineStart: '1em'
      },
      '& li': {
        fontSize: '0.9em' // Overwriting default size setting for list items
      },
    },
    // Hiding the footnote-separator that markdown-it adds by default
    '& .footnotes-sep': {
      display: 'none'
    },
  }
  if (fs.writeFileSync) fs.writeFileSync('/Users/jpaddison/Desktop/headerstyles-2.json', JSON.stringify(result))
  return result
}

export const commentBodyStyles = theme => {
  const commentBodyStyles = {
    marginTop: ".5em",
    marginBottom: ".25em",
    wordBreak: "break-word",
    ...theme.typography.body2,
    ...theme.typography.commentStyle,

    ...spoilerStyles(theme),
    '& blockquote': {
      ...theme.typography.commentBlockquote,
      ...theme.typography.body2,
      ...theme.typography.commentStyle
    },
    '& li': {
      ...theme.typography.body2,
      ...theme.typography.commentStyle
    },
    '& h1, & h2, & h3': {
      ...theme.typography.commentHeader,
      ...theme.typography.commentStyle
    },
    // spoiler styles
    // HACK FIXME: Playing with pointer events is a horrible idea in general, and probably also in this context
    // but it's the only way I was able to make this weird stuff work.
    pointerEvents: 'none',
    '& *': {
      pointerEvents: 'auto'
    },
    '& > *:hover ~ .spoiler': {
      color: 'black'
    },
    '& > *:hover ~ .spoiler:before': {
      content: '"spoiler (hover/select to reveal)"',
      color: 'white',
    },
  }
  return deepmerge(postBodyStyles(theme), commentBodyStyles, {isMergeableObject:isPlainObject})
}

// Currently emails have only the basics
export const emailBodyStyles = baseBodyStyles

export const postHighlightStyles = theme => {
  const postHighlightStyles = {
    ...theme.typography.body2,
    ...theme.typography.postStyle,
    '& blockquote': {
      ...theme.typography.body2,
      ...theme.typography.postStyle,
      '& > p': {
        margin:0
      },
    },
    '& ul': {
      paddingInlineStart: 30
    },
    '& li': {
      ...theme.typography.body2,
      ...theme.typography.postStyle,
    },
    '& h1, & h2, & h3': {
      ...theme.typography.commentHeader,
    },
  }
  return deepmerge(postBodyStyles(theme), postHighlightStyles, {isMergeableObject:isPlainObject})
}

export const pBodyStyle = {
  marginTop: "1em",
  marginBottom: "1em",
  '&:first-of-type': {
    marginTop: 0,
  },
  '&:last-of-type': {
    marginBottom: 0,
  }
}

export const ckEditorStyles = theme => {
  return {
    '& .ck': {
      '& code .public-DraftStyleDefault-block': {
        marginTop: 0,
        marginBottom: 0,
      },
      '& blockquote .public-DraftStyleDefault-block': {
        marginTop: 0,
        marginBottom: 0,
      },
      '--ck-spacing-standard': `${theme.spacing.unit}px`,
      '&.ck-content': {
        marginLeft: -theme.spacing.unit,
        '--ck-focus-outer-shadow-geometry': "none",
        '--ck-focus-ring': "solid 1px rgba(0,0,0,0)",
        '--ck-focus-outer-shadow': "none",
        '--ck-inner-shadow': "none",
        '& p': {
          marginTop: "1em",
          marginBottom: "1em",
          '&:first-of-type': {
            marginTop: 0,
          }
        },
        '& .table table': {
          ...tableStyles
        },
        '& .table table td, & .table table th': {
          ...tableCellStyles
        },
        '& .table table th': {
          ...tableHeadingStyles
        },
        '.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected, .ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected': {
          outline: "none"
        },
        '& .image>figcaption': {
          ...theme.typography.caption,
          backgroundColor: "unset",
        },
      },
      '&.ck-sidebar, &.ck-presence-list': { //\u25B6
        '& li': {
          // By default ckEditor elements get the styles from postBodyStyles li elements
          marginBottom: 'unset',
          fontFamily: 'unset',
          fontSize: 'unset',
          fontWeight: 'unset',
          lineHeight: 'unset'
        },
        '& .ck-comment:after': {
          display:"none"
        },
        '& .ck-annotation__info-name, & .ck-annotation__info-time, & .ck-comment__input, & .ck-thread__comment-count, & .ck-annotation__main p, & .ck-annotation__info-name, & .ck-annotation__info-time, & .ck-presence-list__counter, &.ck-presence-list': {
          ...commentBodyStyles(theme),
          marginTop: 0,
          alignItems: "flex-start",
          marginBottom: 12
        },
        '&.ck-presence-list': {
          marginBottom: 32,
          '--ck-user-avatar-size': '20px',
          '& .ck-user': {
            marginTop: 0
          }
        },
        '& .ck-thread__comment-count': {
          paddingLeft: theme.spacing.unit*2,
          color: theme.palette.grey[600],
          margin: 0,
          paddingBottom: ".5em",
          '&:before': {
            content: '"\\25B6"'
          }
        },
        '& .ck-comment__input': {
          paddingLeft: theme.spacing.unit*2
        },
        '& .ck-annotation__main, & .ck-comment__input, & .ck-thread__input': {
          width : "100%"
        },
        '& .ck-comment__wrapper': {
          borderTop: 'solid 1px rgba(0,0,0,.15)',
        },
        '& .ck-annotation__info-name, & .ck-annotation__info-time': {
          color: theme.palette.grey[600],
          fontSize: "1rem"
        },
        '& .ck-annotation__user, & .ck-thread__user': {
          display: "none"
        },
        '--ck-color-comment-count': theme.palette.primary.main,
      }
    }
  }
}

export const editorStyles = (theme, styleFunction) => ({
    '& .public-DraftStyleDefault-block': {
      marginTop: '1em',
      marginBottom: '1em',
    },
    '& code .public-DraftStyleDefault-block': {
      marginTop: 0,
      marginBottom: 0,
    },
    '& blockquote .public-DraftStyleDefault-block': {
      marginTop: 0,
      marginBottom: 0,
    },
    // Using '*' selectors is a bit dangerous, as is using '!important'
    // This is necessary to catch spoiler-selectors on 'code' elemenents, as implemented in draft-js,
    // which involved nested spans with manually set style attributes, which can't be overwritten except via 'important'
    //
    // This selector isn't necessary on rendered posts/comments, just the draft-js editor.
    // To minimize potential damage from */important it's only applied here.
    '& .spoiler:not(:hover) *': {
      backgroundColor: "black !important"
    },
    ...styleFunction(theme),
    ...ckEditorStyles(theme)
})
<commit_msg>remove styles saving<commit_after>import deepmerge from 'deepmerge';
import isPlainObject from 'is-plain-object';

const hideSpoilers = {
  backgroundColor: 'black',
  color: 'black',
  '& a, & a:hover, & a:focus': {
    color: 'black'
  },
  '& code': {
    backgroundColor: 'black',
  }
}

const spoilerStyles = (theme) => ({
  '& p.spoiler': {
    margin: 0,
  },
  '& .spoiler': {
    padding: 8,
    pointerEvents: 'auto',
    minHeight: theme.typography.commentStyle.fontSize,
    '& .public-DraftStyleDefault-block': {
      margin: 0,
    },
    '&:not(:hover)': { // using ':not(:hover)' means we don't need to manually reset elements with special colors or backgrounds, instead they just automatically stay the same if we're not hovering
      ...hideSpoilers,
    }
  },
  // Note: ".spoiler" is the old class Oli originally used. ".spoilers" is a new class
  // that is applied in make_editable_callbacks.js to groups of adjaecent spoiler paragraphs.
  // (see the make_editable_callbacks.js file for details)
  '& div.spoilers': {
    margin: '1em 0',
    overflow: 'auto',
    '&:not(:hover)': {
      ...hideSpoilers,
    },
    '&:hover': {
      background: 'rgba(0,0,0,.12)' // This leaves a light grey background over the revealed-spoiler to make it more obvious where it started.
    }
  },
  '& p.spoiler-v2': {
    margin: 0,
    padding: '0.5em 8px'
  },
  '& .spoilers:not(:hover)::selection, & .spoilers:not(:hover) ::selection': {
    backgroundColor: 'transparent'
  },
  '& .spoilers > p:hover ~ p': {
    ...hideSpoilers
  }
})

const tableStyles = {
  borderCollapse: "collapse",
  borderSpacing: 0,
  border: "1px double #b3b3b3",
  margin: "auto"
}

const tableCellStyles = {
  minWidth: "2em",
  padding: ".4em",
  border: "1px double #d9d9d9",
}

const tableHeadingStyles = {
  background: "#fafafa",
  fontWeight: 700
}

const baseBodyStyles = theme => ({
  ...theme.typography.body1,
  ...theme.typography.postStyle,
  wordBreak: "break-word",
  '& pre': {
    ...theme.typography.codeblock
  },
  '& code': {
    ...theme.typography.code
  },
  '& blockquote': {
    ...theme.typography.blockquote,
    ...theme.typography.body1,
    ...theme.typography.postStyle
  },
  '& li': {
    ...theme.typography.body1,
    ...theme.typography.li,
    ...theme.typography.postStyle
  },
  '& h1': {
    ...theme.typography.display2,
    ...theme.typography.headerStyle,
  },
  // If a post starts with a header, it should still be flush with the top of
  // the container
  '& h1:first-child': {
    marginTop: 0,
    // Otherwise the line height lowers it noticeably
    marginBlockStart: '-3px',
  },
  '& h2': {
    ...theme.typography.display1,
    ...theme.typography.headerStyle,
  },
  '& h2:first-child': {
    marginTop: 0,
    marginBlockStart: '-2px',
  },
  '& h3': {
    ...theme.typography.display0,
    ...theme.typography.headerStyle,
  },
  '& h3:first-child': {
    marginTop: 0,
    marginBlockStart: 0,
  },
  '& h4': {
    ...theme.typography.body1,
    ...theme.typography.postStyle,
    fontWeight:600,
  },
  '& img': {
    maxWidth: "100%"
  },
  '& sup': {
    verticalAlign: 'baseline',
    top: '-0.6em',
    fontSize: '65%',
    position: 'relative'
  },
  '& a, & a:hover, & a:active': {
    color: theme.palette.primary.main
  },
  '& table': {
    ...tableStyles
  },
  '& td, & th': {
    ...tableCellStyles
  },
  '& th': {
    ...tableHeadingStyles
  },
  '& figure': {
    margin: '1em auto',
    textAlign: "center"
  },
  '& figcaption': {
    ...theme.typography.caption,
    ...theme.typography.postStyle
  }
})

export const postBodyStyles = (theme) => {
  return {
    ...baseBodyStyles(theme),
    ...spoilerStyles(theme),
    // Used for R:A-Z imports as well as markdown-it-footnotes
    '& .footnotes': {
      marginTop: 40,
      fontSize: '0.9em',
      paddingTop: 40,
      borderTop: 'solid 1px rgba(0,0,0,0.2)',
      '& sup': {
        marginRight: 10,
      },
      '& ol': {
        marginBlockStart: '1em',
        paddingInlineStart: 0,
        marginInlineStart: '1em'
      },
      '& li': {
        fontSize: '0.9em' // Overwriting default size setting for list items
      },
    },
    // Hiding the footnote-separator that markdown-it adds by default
    '& .footnotes-sep': {
      display: 'none'
    },
  }
}

export const commentBodyStyles = theme => {
  const commentBodyStyles = {
    marginTop: ".5em",
    marginBottom: ".25em",
    wordBreak: "break-word",
    ...theme.typography.body2,
    ...theme.typography.commentStyle,

    ...spoilerStyles(theme),
    '& blockquote': {
      ...theme.typography.commentBlockquote,
      ...theme.typography.body2,
      ...theme.typography.commentStyle
    },
    '& li': {
      ...theme.typography.body2,
      ...theme.typography.commentStyle
    },
    '& h1, & h2, & h3': {
      ...theme.typography.commentHeader,
      ...theme.typography.commentStyle
    },
    // spoiler styles
    // HACK FIXME: Playing with pointer events is a horrible idea in general, and probably also in this context
    // but it's the only way I was able to make this weird stuff work.
    pointerEvents: 'none',
    '& *': {
      pointerEvents: 'auto'
    },
    '& > *:hover ~ .spoiler': {
      color: 'black'
    },
    '& > *:hover ~ .spoiler:before': {
      content: '"spoiler (hover/select to reveal)"',
      color: 'white',
    },
  }
  return deepmerge(postBodyStyles(theme), commentBodyStyles, {isMergeableObject:isPlainObject})
}

// Currently emails have only the basics
export const emailBodyStyles = baseBodyStyles

export const postHighlightStyles = theme => {
  const postHighlightStyles = {
    ...theme.typography.body2,
    ...theme.typography.postStyle,
    '& blockquote': {
      ...theme.typography.body2,
      ...theme.typography.postStyle,
      '& > p': {
        margin:0
      },
    },
    '& ul': {
      paddingInlineStart: 30
    },
    '& li': {
      ...theme.typography.body2,
      ...theme.typography.postStyle,
    },
    '& h1, & h2, & h3': {
      ...theme.typography.commentHeader,
    },
  }
  return deepmerge(postBodyStyles(theme), postHighlightStyles, {isMergeableObject:isPlainObject})
}

export const pBodyStyle = {
  marginTop: "1em",
  marginBottom: "1em",
  '&:first-of-type': {
    marginTop: 0,
  },
  '&:last-of-type': {
    marginBottom: 0,
  }
}

export const ckEditorStyles = theme => {
  return {
    '& .ck': {
      '& code .public-DraftStyleDefault-block': {
        marginTop: 0,
        marginBottom: 0,
      },
      '& blockquote .public-DraftStyleDefault-block': {
        marginTop: 0,
        marginBottom: 0,
      },
      '--ck-spacing-standard': `${theme.spacing.unit}px`,
      '&.ck-content': {
        marginLeft: -theme.spacing.unit,
        '--ck-focus-outer-shadow-geometry': "none",
        '--ck-focus-ring': "solid 1px rgba(0,0,0,0)",
        '--ck-focus-outer-shadow': "none",
        '--ck-inner-shadow': "none",
        '& p': {
          marginTop: "1em",
          marginBottom: "1em",
          '&:first-of-type': {
            marginTop: 0,
          }
        },
        '& .table table': {
          ...tableStyles
        },
        '& .table table td, & .table table th': {
          ...tableCellStyles
        },
        '& .table table th': {
          ...tableHeadingStyles
        },
        '.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected, .ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected': {
          outline: "none"
        },
        '& .image>figcaption': {
          ...theme.typography.caption,
          backgroundColor: "unset",
        },
      },
      '&.ck-sidebar, &.ck-presence-list': { //\u25B6
        '& li': {
          // By default ckEditor elements get the styles from postBodyStyles li elements
          marginBottom: 'unset',
          fontFamily: 'unset',
          fontSize: 'unset',
          fontWeight: 'unset',
          lineHeight: 'unset'
        },
        '& .ck-comment:after': {
          display:"none"
        },
        '& .ck-annotation__info-name, & .ck-annotation__info-time, & .ck-comment__input, & .ck-thread__comment-count, & .ck-annotation__main p, & .ck-annotation__info-name, & .ck-annotation__info-time, & .ck-presence-list__counter, &.ck-presence-list': {
          ...commentBodyStyles(theme),
          marginTop: 0,
          alignItems: "flex-start",
          marginBottom: 12
        },
        '&.ck-presence-list': {
          marginBottom: 32,
          '--ck-user-avatar-size': '20px',
          '& .ck-user': {
            marginTop: 0
          }
        },
        '& .ck-thread__comment-count': {
          paddingLeft: theme.spacing.unit*2,
          color: theme.palette.grey[600],
          margin: 0,
          paddingBottom: ".5em",
          '&:before': {
            content: '"\\25B6"'
          }
        },
        '& .ck-comment__input': {
          paddingLeft: theme.spacing.unit*2
        },
        '& .ck-annotation__main, & .ck-comment__input, & .ck-thread__input': {
          width : "100%"
        },
        '& .ck-comment__wrapper': {
          borderTop: 'solid 1px rgba(0,0,0,.15)',
        },
        '& .ck-annotation__info-name, & .ck-annotation__info-time': {
          color: theme.palette.grey[600],
          fontSize: "1rem"
        },
        '& .ck-annotation__user, & .ck-thread__user': {
          display: "none"
        },
        '--ck-color-comment-count': theme.palette.primary.main,
      }
    }
  }
}

export const editorStyles = (theme, styleFunction) => ({
    '& .public-DraftStyleDefault-block': {
      marginTop: '1em',
      marginBottom: '1em',
    },
    '& code .public-DraftStyleDefault-block': {
      marginTop: 0,
      marginBottom: 0,
    },
    '& blockquote .public-DraftStyleDefault-block': {
      marginTop: 0,
      marginBottom: 0,
    },
    // Using '*' selectors is a bit dangerous, as is using '!important'
    // This is necessary to catch spoiler-selectors on 'code' elemenents, as implemented in draft-js,
    // which involved nested spans with manually set style attributes, which can't be overwritten except via 'important'
    //
    // This selector isn't necessary on rendered posts/comments, just the draft-js editor.
    // To minimize potential damage from */important it's only applied here.
    '& .spoiler:not(:hover) *': {
      backgroundColor: "black !important"
    },
    ...styleFunction(theme),
    ...ckEditorStyles(theme)
})
<|endoftext|>


<commit_before>
Tinytest.add("minifiers - url rewriting when merging", function (test) {
  var stylesheet = function(backgroundPath) {
    return "body { color: green; background: top center url(" + backgroundPath + ") black, bottom center url(" + backgroundPath + "); }"
  };

  var filename = 'dir/subdir/style.css';
  var parseOptions = { source: filename, position: true };

  var t = function(relativeUrl, absoluteUrl, desc) {
    var ast1 = CssTools.parseCss(stylesheet(relativeUrl), parseOptions);
    var ast2 = CssTools.parseCss(stylesheet(absoluteUrl), parseOptions);
    CssTools.rewriteCssUrls(ast1);

    test.equal(CssTools.stringifyCss(ast1), CssTools.stringifyCss(ast2), desc);
  };

  t('../image.png', 'dir/image.png', 'parent directory');
  t('./../image.png', 'dir/image.png', 'parent directory');
  t('../subdir2/image.png', 'dir/subdir2/image.png', 'cousin directory');
  t('../../image.png', 'image.png', 'grand parent directory');
  t('./image.png', 'dir/subdir/image.png', 'current directory');
  t('./child/image.png', 'dir/subdir/child/image.png', 'child directory');
  t('child/image.png', 'dir/subdir/child/image.png', 'child directory');
  t('/image.png', '/image.png', 'absolute url');
  t('"/image.png"', '"/image.png"', 'double quoted url');
  t("'/image.png'", "'/image.png'", 'single quoted url');
  t('"./../image.png"', '"dir/image.png"', 'quoted parent directory');
  t('http://i.imgur.com/fBcdJIh.gif', 'http://i.imgur.com/fBcdJIh.gif', 'complete URL');
  t('"http://i.imgur.com/fBcdJIh.gif"', '"http://i.imgur.com/fBcdJIh.gif"', 'complete quoted URL');
  t('data:image/png;base64,iVBORw0K=', 'data:image/png;base64,iVBORw0K=', 'data URI');
  t('http://', 'http://', 'malformed URL');
});
<commit_msg>Tests for CSS url rewrites fixed to the new implementation<commit_after>
Tinytest.add("minifiers - url rewriting when merging", function (test) {
  var stylesheet = function(backgroundPath) {
    return "body { color: green; background: top center url(" + backgroundPath + ") black, bottom center url(" + backgroundPath + "); }"
  };

  var parseOptions = { source: null, position: true };

  var t = function(relativeUrl, absoluteUrl, desc) {
    var ast1 = CssTools.parseCss(stylesheet(relativeUrl), parseOptions);
    var ast2 = CssTools.parseCss(stylesheet(absoluteUrl), parseOptions);
    CssTools.rewriteCssUrls(ast1);

    test.equal(CssTools.stringifyCss(ast1), CssTools.stringifyCss(ast2), desc);
  };

  parseOptions.source = 'packages/nameOfPackage/style.css';
  t('../image.png', 'packages/image.png', 'parent directory');
  t('./../image.png', 'packages/image.png', 'parent directory');
  t('../nameOfPackage2/image.png', 'packages/nameOfPackage2/image.png', 'cousin directory');
  t('../../image.png', 'image.png', 'grand parent directory');
  t('./image.png', 'packages/nameOfPackage/image.png', 'current directory');
  t('./child/image.png', 'packages/nameOfPackage/child/image.png', 'child directory');
  t('child/image.png', 'packages/nameOfPackage/child/image.png', 'child directory');
  t('/image.png', '/image.png', 'absolute url');
  t('"/image.png"', '"/image.png"', 'double quoted url');
  t("'/image.png'", "'/image.png'", 'single quoted url');
  t('"./../image.png"', '"packages/image.png"', 'quoted parent directory');
  t('http://i.imgur.com/fBcdJIh.gif', 'http://i.imgur.com/fBcdJIh.gif', 'complete URL');
  t('"http://i.imgur.com/fBcdJIh.gif"', '"http://i.imgur.com/fBcdJIh.gif"', 'complete quoted URL');
  t('data:image/png;base64,iVBORw0K=', 'data:image/png;base64,iVBORw0K=', 'data URI');
  t('http://', 'http://', 'malformed URL');

  parseOptions.source = 'application/client/dir/other-style.css';
  t('./image.png', '/image.png', 'base path is root');
  t('./child/image.png', '/child/image.png', 'child directory from root');
  t('child/image.png', '/child/image.png', 'child directory from root');
  t('/image.png', '/image.png', 'absolute url');
  t('"/image.png"', '"/image.png"', 'double quoted url');
  t("'/image.png'", "'/image.png'", 'single quoted url');
  t('http://i.imgur.com/fBcdJIh.gif', 'http://i.imgur.com/fBcdJIh.gif', 'complete URL');
  t('"http://i.imgur.com/fBcdJIh.gif"', '"http://i.imgur.com/fBcdJIh.gif"', 'complete quoted URL');
  t('data:image/png;base64,iVBORw0K=', 'data:image/png;base64,iVBORw0K=', 'data URI');
  t('http://', 'http://', 'malformed URL');
});
<|endoftext|>


<commit_before>(function() {
    'use strict';

    angular.module('app.people')
        .factory('peopleService', peopleService);

    peopleService.$inject = ['$http', '$q', '$log', 'apiEndPoint'];

    function peopleService($http, $q, $log, apiEndPoint) {

        var roleTitles = {
            staff: 'Staff Member',
            mentor: 'Mentor',
            student: 'Student'
        };

        //////// Service API ////////

        return {
            getAllPeople: getAllPeople,
            getPersonById: getPersonById,
            roleTitles: roleTitles
        };

        //////// Implementation ////////

        function getAllPeople() {
            return $http({
                    url: apiEndPoint + '/persons',
                    method: 'GET',
                    cache: true
                })
                .then(function(resp) {
                    return resp.data;
                    })
                .catch(function(e) {
                    return handleFailure(e, 'getAllPeople');
                });
        }

        function getPersonById(id) {
            return $http({
                    url: apiEndPoint + '/persons/' + id,
                    method: 'GET',
                    cache: true
                })
                .then(function(resp) {
                    return resp.data;
                })
                .catch(function(e) {
                    return handleFailure(e, 'getPersonById');
                });
        }

        function handleFailure(e, funcName) {
            var newMessage = 'XHR Failed for ' + funcName;
            if (e.data && e.data.description) {
                newMessage = newMessage + '\n' + e.data.description;
            }
            e.data.description = newMessage;
            $log.error(newMessage);
            return $q.reject(e);
        }
    }

})();<commit_msg>reformatted code<commit_after>(function () {
    'use strict';

    angular.module('app.people')
        .factory('peopleService', peopleService);

    peopleService.$inject = ['$http', '$q', '$log', 'apiEndPoint'];

    function peopleService($http, $q, $log, apiEndPoint) {

        var roleTitles = {
            staff: 'Staff Member',
            mentor: 'Mentor',
            student: 'Student'
        };

        //////// Service API ////////

        return {
            getAllPeople: getAllPeople,
            getPersonById: getPersonById,
            roleTitles: roleTitles
        };

        //////// Implementation ////////

        function getAllPeople() {
            return $http({
                url: apiEndPoint + '/persons',
                method: 'GET',
                cache: true
            }).then(function (resp) {
                return resp.data;
            }).catch(function (e) {
                return handleFailure(e, 'getAllPeople');
            });
        }

        function getPersonById(id) {
            return $http({
                url: apiEndPoint + '/persons/' + id,
                method: 'GET',
                cache: true
            }).then(function (resp) {
                return resp.data;
            }).catch(function (e) {
                return handleFailure(e, 'getPersonById');
            });
        }

        function handleFailure(e, funcName) {
            var newMessage = 'XHR Failed for ' + funcName;
            if (e.data && e.data.description) {
                newMessage = newMessage + '\n' + e.data.description;
            }
            e.data.description = newMessage;
            $log.error(newMessage);
            return $q.reject(e);
        }
    }

})();<|endoftext|>


<commit_before>const PAGE_SIZE = 1000;
const PAGES_TO_LOAD = 3;

function parseRow(row, hasFlag) {
  const profileLink = row.children[1 + hasFlag].firstChild;
  const profile = {
    id: getQueryVariable('id', profileLink.getAttribute('href')),
    rank: +row.children[0].innerHTML,
    name: profileLink.innerHTML,
    rating: +row.children[2 + hasFlag].innerHTML,
    solved: +row.children[3 + hasFlag].innerHTML,
    lastAC: row.children[4 + hasFlag].innerHTML,
  };
  if (hasFlag) {
    profile.flag = row.children[1].innerHTML;
  }
  return profile;
}

function parseProfilePage(dom) {
  const row = dom.querySelector('.ranklist tr.current');
  const profile = parseRow(row, false);
  profile.flag = dom.querySelector('.author_flag').innerHTML;
  return profile;
}

function removeNondataRows(ranklist) {
  Array.from(ranklist.querySelectorAll('.navigation')).forEach(item => item.remove());
  const header = ranklist.querySelector('tr');
  header.remove();
  return header;
}

function parseRanklistPage(dom) {
  const ranklist = dom.querySelector('.ranklist tbody');
  removeNondataRows(ranklist);
  const profiles = [];
  Array.from(ranklist.querySelectorAll('tr')).forEach(row => {
    profiles.push(parseRow(row, true));
  });
  return profiles;
}

function renderRow(profile) {
  const tr = document.createElement('tr');
  tr.classList.add('content');
  if (profile.me) {
    tr.classList.add('current');
  }

  const rank = document.createElement('td');
  rank.innerHTML = profile.rank || '';
  tr.appendChild(rank);

  const flag = document.createElement('td');
  flag.innerHTML = profile.flag || '';
  tr.appendChild(flag);

  const name = document.createElement('td');
  name.classList.add('name');
  if (profile.name) {
    const a = document.createElement('a');
    a.href = `author.aspx?id=${profile.id}`;
    a.innerHTML = profile.name;
    name.appendChild(a);
  } else {
    name.innerHTML = ' ';
  }
  tr.appendChild(name);

  const rating = document.createElement('td');
  rating.innerHTML = profile.rating || '';
  tr.appendChild(rating);

  const solved = document.createElement('td');
  solved.innerHTML = profile.solved || '';
  tr.appendChild(solved);

  const lastAC = document.createElement('td');
  lastAC.innerHTML = profile.lastAC || '';
  tr.appendChild(lastAC);

  return tr;
}

function renderRows(profiles) {
  const profileArr = Object.keys(profiles).map(id => profiles[id]);
  profileArr.sort((a, b) => {
    const rankA = a.rank || Number.POSITIVE_INFINITY;
    const rankB = b.rank || Number.POSITIVE_INFINITY;
    return rankA - rankB;
  });
  return profileArr.map(renderRow);
}

function renderRanklist(header, profiles) {
  const ranklist = document.createElement('tbody');
  ranklist.appendChild(header);
  renderRows(profiles).forEach(row => ranklist.appendChild(row));
  return ranklist;
}

function cacheRanks(profiles) {
  const ranks = {};
  Object.keys(profiles).map(id => {
    ranks[id] = profiles[id].rank;
  });
  chrome.runtime.sendMessage({ setCachedRanks: true, cachedRanks: ranks });
}

const startTime = new Date().getTime();

init({ friends: true, cachedRanks: true }, ({ friends, cachedRanks }) => {
  const profiles = {};
  let loadingProfiles = 0;
  Object.keys(friends).map(friendId => {
    profiles[friendId] = {
      id: friendId,
      needsLoading: true,
    };
    ++loadingProfiles;
  });

  function loadProfile(profile) {
    if (!friends.hasOwnProperty(profile.id)) {
      return;
    }
    if (profiles[profile.id].needsLoading) {
      --loadingProfiles;
      if (loadingProfiles === 0) {
        cacheRanks(profiles);
      }
    }
    profiles[profile.id] = profile;
  }

  let ranklist = document.querySelector('.ranklist tbody');
  let header;

  function replaceRanklist() {
    const newRanklist = renderRanklist(header, profiles);
    ranklist.parentNode.replaceChild(newRanklist, ranklist);
    ranklist = newRanklist;
    console.log((new Date().getTime() - startTime) / 1000, 's elapsed');
  }

  document.title = getMessage('friends_ranklist');
  const pageBody = ranklist.parentElement.parentElement;
  pageBody.querySelector('.title').innerText = getMessage('friends_ranklist');
  pageBody.querySelector('div').remove(); // Volume navigation

  header = removeNondataRows(ranklist);
  parseRanklistPage(document).forEach(loadProfile);
  replaceRanklist();

  const pagesToLoad = {};
  Object.keys(friends).forEach(friendId => {
    if (!profiles[friendId].needsLoading) {
      return;
    }
    // TODO: what if a friend goes 3000 -> 3001?
    const page = Math.floor((cachedRanks[friendId] - 1) / PAGE_SIZE) + 1;
    if (page <= PAGES_TO_LOAD) {
      pagesToLoad[page] = true;
    } else {
      ajax({
        method: 'GET',
        url: `/author.aspx?id=${friendId}`,
      }, response => {
        const parser = new DOMParser();
        const dom = parser.parseFromString(response, 'text/html');
        loadProfile(parseProfilePage(dom));
        replaceRanklist();
      });
    }
  });

  console.log('pagesToLoad', pagesToLoad);
  Object.keys(pagesToLoad).forEach(page => {
    const start = PAGE_SIZE * (page - 1) + 1;
    ajax({
      method: 'GET',
      url: `/ranklist.aspx?from=${start}&count=${PAGE_SIZE}`,
    }, response => {
      const parser = new DOMParser();
      const dom = parser.parseFromString(response, 'text/html');
      parseRanklistPage(dom).forEach(loadProfile);
      replaceRanklist();
    });
  });

  ajax({
    method: 'GET',
    url: `/textstatus.aspx?author=me&count=1`,
  }, response => {
    // TODO: handle errors
    console.log('me', response);
    const myId = response.split('\n')[1].split('\t')[2];
    console.log('me', myId);
    profiles[myId].me = true;
    replaceRanklist();
  });
});
<commit_msg>Refactor friends and profiles<commit_after>const PAGE_SIZE = 1000;
const PAGES_TO_LOAD = 3;

function parseRow(row, hasFlag) {
  const profileLink = row.children[1 + hasFlag].firstChild;
  const profile = {
    id: getQueryVariable('id', profileLink.getAttribute('href')),
    rank: +row.children[0].innerHTML,
    name: profileLink.innerHTML,
    rating: +row.children[2 + hasFlag].innerHTML,
    solved: +row.children[3 + hasFlag].innerHTML,
    lastAC: row.children[4 + hasFlag].innerHTML,
  };
  if (hasFlag) {
    profile.flag = row.children[1].innerHTML;
  }
  return profile;
}

function parseProfilePage(dom) {
  const row = dom.querySelector('.ranklist tr.current');
  const profile = parseRow(row, false);
  profile.flag = dom.querySelector('.author_flag').innerHTML;
  return profile;
}

function removeNondataRows(ranklist) {
  Array.from(ranklist.querySelectorAll('.navigation')).forEach(item => item.remove());
  const header = ranklist.querySelector('tr');
  header.remove();
  return header;
}

function parseRanklistPage(dom) {
  const ranklist = dom.querySelector('.ranklist tbody');
  removeNondataRows(ranklist);
  const profiles = [];
  Array.from(ranklist.querySelectorAll('tr')).forEach(row => {
    profiles.push(parseRow(row, true));
  });
  return profiles;
}

function renderRow(profile) {
  const tr = document.createElement('tr');
  tr.classList.add('content');
  if (profile.me) {
    tr.classList.add('current');
  }

  const rank = document.createElement('td');
  rank.innerHTML = profile.rank || '';
  tr.appendChild(rank);

  const flag = document.createElement('td');
  flag.innerHTML = profile.flag || '';
  tr.appendChild(flag);

  const name = document.createElement('td');
  name.classList.add('name');
  if (profile.name) {
    const a = document.createElement('a');
    a.href = `author.aspx?id=${profile.id}`;
    a.innerHTML = profile.name;
    name.appendChild(a);
  } else {
    name.innerHTML = ' ';
  }
  tr.appendChild(name);

  const rating = document.createElement('td');
  rating.innerHTML = profile.rating || '';
  tr.appendChild(rating);

  const solved = document.createElement('td');
  solved.innerHTML = profile.solved || '';
  tr.appendChild(solved);

  const lastAC = document.createElement('td');
  lastAC.innerHTML = profile.lastAC || '';
  tr.appendChild(lastAC);

  return tr;
}

function renderRows(profiles) {
  const profileArr = Object.keys(profiles).map(id => profiles[id]);
  profileArr.sort((a, b) => {
    const rankA = a.rank || Number.POSITIVE_INFINITY;
    const rankB = b.rank || Number.POSITIVE_INFINITY;
    return rankA - rankB;
  });
  return profileArr.map(renderRow);
}

function renderRanklist(header, profiles) {
  const ranklist = document.createElement('tbody');
  ranklist.appendChild(header);
  renderRows(profiles).forEach(row => ranklist.appendChild(row));
  return ranklist;
}

function cacheRanks(profiles) {
  const ranks = {};
  Object.keys(profiles).map(id => {
    ranks[id] = profiles[id].rank;
  });
  chrome.runtime.sendMessage({ setCachedRanks: true, cachedRanks: ranks });
}

const startTime = new Date().getTime();

init({ friends: true, cachedRanks: true }, ({ friends, cachedRanks }) => {
  let loadingFriends = 0;
  Object.keys(friends).map(friendId => {
    friends[friendId] = {
      id: friendId,
      needsLoading: true,
    };
    ++loadingFriends;
  });

  function loadProfile(profile) {
    if (!friends.hasOwnProperty(profile.id)) {
      return;
    }
    if (friends[profile.id].needsLoading) {
      --loadingFriends;
      if (loadingFriends === 0) {
        cacheRanks(friends);
      }
    }
    friends[profile.id] = profile;
  }

  let ranklist = document.querySelector('.ranklist tbody');
  let header;

  function replaceRanklist() {
    const newRanklist = renderRanklist(header, friends);
    ranklist.parentNode.replaceChild(newRanklist, ranklist);
    ranklist = newRanklist;
    console.log((new Date().getTime() - startTime) / 1000, 's elapsed');
  }

  document.title = getMessage('friends_ranklist');
  const pageBody = ranklist.parentElement.parentElement;
  pageBody.querySelector('.title').innerText = getMessage('friends_ranklist');
  pageBody.querySelector('div').remove(); // Volume navigation

  header = removeNondataRows(ranklist);
  parseRanklistPage(document).forEach(loadProfile);
  replaceRanklist();

  const pagesToLoad = {};
  Object.keys(friends).forEach(friendId => {
    if (!friends[friendId].needsLoading) {
      return;
    }
    // TODO: what if a friend goes 3000 -> 3001?
    const page = Math.floor((cachedRanks[friendId] - 1) / PAGE_SIZE) + 1;
    if (page <= PAGES_TO_LOAD) {
      pagesToLoad[page] = true;
    } else {
      ajax({
        method: 'GET',
        url: `/author.aspx?id=${friendId}`,
      }, response => {
        const parser = new DOMParser();
        const dom = parser.parseFromString(response, 'text/html');
        loadProfile(parseProfilePage(dom));
        replaceRanklist();
      });
    }
  });

  console.log('pagesToLoad', pagesToLoad);
  Object.keys(pagesToLoad).forEach(page => {
    const start = PAGE_SIZE * (page - 1) + 1;
    ajax({
      method: 'GET',
      url: `/ranklist.aspx?from=${start}&count=${PAGE_SIZE}`,
    }, response => {
      const parser = new DOMParser();
      const dom = parser.parseFromString(response, 'text/html');
      parseRanklistPage(dom).forEach(loadProfile);
      replaceRanklist();
    });
  });

  ajax({
    method: 'GET',
    url: `/textstatus.aspx?author=me&count=1`,
  }, response => {
    // TODO: handle errors
    console.log('me', response);
    const myId = response.split('\n')[1].split('\t')[2];
    console.log('me', myId);
    profiles[myId].me = true;
    replaceRanklist();
  });
});
<|endoftext|>


<commit_before>'use strict';

function Jeep(game, x, y) {

  // Call base constructor
  Phaser.Sprite.call(this, game, x, y, 'sprites', 'jeep/body1');

  // Animations
  this.animations.add(
    'driving',
    [
      'jeep/body6',
      'jeep/body5',
      'jeep/body4',
      'jeep/body3',
      'jeep/body2',
      'jeep/body1'
    ],
    8, true, false);
    this.animations.play('driving');

    // Anchor
    this.anchor.x = 0.5;
    this.anchor.y = 1.0;

    // Driver
    var driver = new Phaser.Sprite(this.game, -12, -16, 'sprites', 'jeep/driver');
    driver.anchor.x = 0.5;
    driver.anchor.y = 1.0;
    this.addChild(driver);

    // Grenadier
    var grenadier = new Phaser.Sprite(this.game, -2, -16, 'sprites', 'jeep/grenadier');
    grenadier.anchor.x = 0.5;
    grenadier.anchor.y = 1.0;
    this.addChild(grenadier);

    this.scale.x = 3;
    this.scale.y = 3;
}

Jeep.prototype = Object.create(Phaser.Sprite.prototype);
Jeep.prototype.constructor = Jeep;<commit_msg>use generateFrameNames<commit_after>'use strict';

function Jeep(game, x, y) {

  // Call base constructor
  Phaser.Sprite.call(this, game, x, y, 'sprites', 'jeep/body1');

  // Animations
  var drivingFrames = Phaser.Animation.generateFrameNames('jeep/body', 6, 1);
  this.animations.add('driving', drivingFrames, 8, true, false);
  this.animations.play('driving');

  // Anchor
  this.anchor.x = 0.5;
  this.anchor.y = 1.0;

  // Driver
  var driver = new Phaser.Sprite(this.game, -12, -16, 'sprites', 'jeep/driver');
  driver.anchor.x = 0.5;
  driver.anchor.y = 1.0;
  this.addChild(driver);

  // Grenadier
  var grenadier = new Phaser.Sprite(this.game, -2, -16, 'sprites', 'jeep/grenadier');
  grenadier.anchor.x = 0.5;
  grenadier.anchor.y = 1.0;
  this.addChild(grenadier);

  this.scale.x = 3;
  this.scale.y = 3;
}

Jeep.prototype = Object.create(Phaser.Sprite.prototype);
Jeep.prototype.constructor = Jeep;<|endoftext|>


<commit_before>'use strict';

var Reflux = require('reflux');
var dataSourceStore = require('../stores/dataSource.js');
var config = require('../config/config.js');
var presentationsStore = require('../stores/presentations.js');
var SourceActions = require('../actions/source.js');

module.exports = Reflux.createStore({

  // this will set up listeners to all publishers in SourceActions,
  // using onKeyname (or keyname) as callbacks
  listenables: [SourceActions],

  // Name to use for this collection
  collectionName: config.SourcesCollection.name,

  // Data storage for all collections
  dataSource: null,

  // The Loki collection transform array
  collectionTransform: [],

  // Called on Store initialisation
  init: function() {

    this.setDefaultTransform();

    // Register dataSourceStores's changes
    this.listenTo(dataSourceStore, this.dataSourceChanged);

    this.listenTo(presentationsStore, this.presentationsStoreChanged);
  },

  // Set the filteredData Object
  dataSourceChanged: function (dataSourceStore) {

    this.dataSource = dataSourceStore.dataSource;

    this.setDefaultTransform();

    // Call when the source data is updated
    this.filterStateChanged(this.filterTransform);
  },

  // Set search filter on our collectionTransform
  filterStateChanged: function(filterTransformBroadcast) {

    this.setDatesTransform();

    this.createFilterTransform(filterTransformBroadcast);
  },

  // Listener to changes on Presentations Store
  presentationsStoreChanged: function() {

    // If presentation name has been set to 'ViewingFilter', reset the presentation
    if (presentationsStore.presentationName === 'ViewingFilter') {
      this.resetFilterTransform();
    }
  },

  // Create a transform from the passed in object and save it on the collection
  createFilterTransform: function(filterTransformObject, message) {

    if (!this.dataSource) {
      return;
    }

    var collectionTransformObject = this.filterTransform[this.collectionName];
    var collectionToAddTransformTo = this.dataSource.getCollection(this.collectionName);

    if (!collectionToAddTransformTo) {
      return;
    }

    // Add filter to the transform
    this.collectionTransform = [];
    this.collectionTransform.push(collectionTransformObject.filters);
    this.collectionTransform.push(collectionTransformObject.sorting);

    // Save the transform to the collection
    if (filterTransformObject.transformName) {

      if (collectionToAddTransformTo.chain(filterTransformObject.transformName)) {
        collectionToAddTransformTo.setTransform(filterTransformObject.transformName, this.collectionTransform);
      } else {
        collectionToAddTransformTo.addTransform(filterTransformObject.transformName, this.collectionTransform);
      }

      // Apply the filter
      this.userFilteredCollection = collectionToAddTransformTo.chain(collectionToAddTransformTo.transforms[filterTransformObject.transformName][0], this.params).copy();

      // Apply the sort
      this.userFilteredCollection.simplesort(collectionTransformObject.sorting.property, collectionTransformObject.sorting.desc);

    } else {

      if (message !== 'presentationSaved') {
        this.userFilteredCollection = collectionToAddTransformTo.chain().copy();
      }
    }

    // Set viewingSource property to false
    this.viewingSource = false;
  },

  // Reset a transform on this collection
  resetFilterTransform: function() {

    var collectionToAddTransformTo;
    var transformName = 'ViewingFilter';

    if (!this.dataSource) {
      return;
    }

    collectionToAddTransformTo = this.dataSource.getCollection(this.collectionName);

    if (!collectionToAddTransformTo) {
      return;
    }

    // Update this store's filterTransform so the filters will be updated when a presentation changes
    this.filterTransform[this.collectionName].filters = this.dataSource.getCollection(this.collectionName).transforms[transformName][0];

    // Update the collection resulting from the transform
    this.userFilteredCollection = collectionToAddTransformTo.chain(transformName);

    // Set viewingSource property to false
    this.viewingSource = false;

    // Send collection object out to all listeners
    this.trigger(this);
  },

  // Set a default transform to be used immediately on the store
  setDefaultTransform: function() {

    var collectionToAddTransformTo;

    this.filterTransform = {};
    this.filterTransform[this.collectionName] = {
      filters: [{
        type: 'find',
        value: {
          '$and': []
        }
      },
      {
        type: 'where',
        value: '[%lktxp]filterDates'
      }],
      sorting: {
        type: 'simplesort',
        property: '$loki',
        desc: true
      },
      dateQueries: {
        from: [],
        to: []
      }
    };

    this.setDatesTransform();

    if (!this.dataSource) {
      return;
    }

    collectionToAddTransformTo = this.dataSource.getCollection(this.collectionName);

    if (!collectionToAddTransformTo) {
      return;
    }

    this.collectionTransform = [];
    this.collectionTransform.push(this.filterTransform[this.collectionName].filters);
    this.collectionTransform.push(this.filterTransform[this.collectionName].sorting);

    collectionToAddTransformTo.setTransform('ViewingFilter', this.collectionTransform);
  },

  // Set up functionality to perform a 'where' query on selected Date filters
  setDatesTransform: function() {

    // Get name of Field with a filter type of 'gte'
    config.SourcesCollection.fields.forEach(function(filter) {
      if (filter.filter === 'gte') {
        this.fromFilterName = filter.name;
      } else if (filter.filter === 'lte') {
        this.toFilterName = filter.name;
      }
    }.bind(this));

    // Transform Params to be used in collection chain transforms
    this.params = {
      filterDates: this.filterDates
    };
  },

  // Used by the lokijs 'where' query to filter on dates in a transform
  filterDates: function (obj) {

    var validItem;
    var fromArray = this.filterTransform[this.collectionName].dateQueries.from;
    var toArray = this.filterTransform[this.collectionName].dateQueries.to;
    var fromDefaultObject = {
      includeExclude: 'include',
      value: '1800-01-01 00:00:00'
    };
    var toDefaultObject = {
      includeExclude: 'include',
      value: '3000-01-01 00:00:00'
    };
    var fromDate = obj[this.fromFilterName];
    var toDate = obj[this.toFilterName];

    // If datastore has no date filters return
    if (!this.fromFilterName) {
      return true;
    }

    if (!fromArray.length) {
      fromArray.push(fromDefaultObject);
    } else if (!toArray.length) {
      toArray.push(toDefaultObject);
    }

    // Parse invalid dates
    if (fromDate === '' || fromDate === 'TBD') {
      fromDate = fromDefaultObject.value;
    }

    if (toDate === '' || toDate === 'TBD') {
      toDate = toDefaultObject.value;
    }

    // Sort arrays so dates are in order in each array
    fromArray = _.sortBy(fromArray, function(object) {
      return object.value;
    });

    toArray = _.sortBy(toArray, function(object) {
      return object.value;
    });

    // If more From filters than To filters
    if (fromArray.length >= toArray.length) {

      fromArray.forEach(function(fromObject, index) {

        var toObject = toArray[index];

        // If no corresponding To Date, set it to a far future date
        if (!toObject) {
          toObject = toDefaultObject;
        }

        // If the date filter is an include
        if (toObject.includeExclude === 'include') {

          if (fromDate >= fromObject.value && toDate <= toObject.value) {
            validItem = true;
          }
        } else if (toObject.includeExclude === 'exclude') {

          if (fromDate >= fromObject.value && toDate <= toObject.value) {
            validItem = true;
          }
        }
      }.bind(this));

      // Catch-all in case user adds more to filters than from filters which would be wrong anyway
    } else {

      toArray.forEach(function(toObject, index) {

        var fromObject = fromArray[index];

        // If no corresponding From Date, set it to a far past date
        if (!fromObject) {
          fromObject = fromDefaultObject;
        }

        // If the date filter is an include
        if (fromObject.includeExclude === 'include') {

          if (fromDate > fromObject.value && fromDate < toObject.value) {
            validItem = true;
          }
        } else if (fromObject.includeExclude === 'exclude') {

          if (fromDate > fromObject.value && toDate < toObject.value) {
            validItem = true;
          }
        }

      }.bind(this));
    }

    return validItem;
  },

  // Called when a user attempts to view a source file
  viewSourceFile: function(sourceObject) {

    // Set selectedSourceObject property
    this.setSelectedSourceObject(sourceObject);

    // Hack based around need to trigger pdf creation in pdf element so we broadcast a change to null
    // before sending out the object again.
    if (!sourceObject) {
      this.trigger(this);
      return;
    }

    // Set selectedSourceObject property
    this.setSelectedSourceFileType(sourceObject);

    // Set viewingSource property to true
    this.viewingSource = true;

    // Send object out to all listeners
    this.trigger(this);
  },

  // Set a property on this store object to indicate current selected source object
  setSelectedSourceObject: function(sourceObject) {
    this.selectedSourceObject = sourceObject;
  },

  // Set a property on this store object to indicate the type of file
  setSelectedSourceFileType: function(sourceObject) {

    var filePath = sourceObject['Linked File'];
    var fileExtension = filePath.substr(filePath.lastIndexOf('.') + 1);

    switch (fileExtension) {
      case 'pdf':
        this.selectedSourceRoute = 'pdf';
        this.selectedSourceFileType = 'pdf';
        break;
      case 'jpg':
        this.selectedSourceRoute = 'image';
        this.selectedSourceFileType = 'image';
        break;
      case 'jpeg':
        this.selectedSourceRoute = 'image';
        this.selectedSourceFileType = 'image';
        break;
      case 'gif':
        this.selectedSourceRoute = 'image';
        this.selectedSourceFileType = 'image';
        break;
      case 'png':
        this.selectedSourceRoute = 'image';
        this.selectedSourceFileType = 'image';
        break;
      case 'mp3':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'audio';
        break;
      case 'wav':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'audio';
        break;
      case 'avi':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'video';
        break;
      case 'mp4':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'video';
        break;
      case 'mov':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'video';
        break;
      case 'webm':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'video';
        break;
      default:
        console.warn(fileExtension + 'not a supported type');
    }
  }
});
<commit_msg>Fix for issue with navigating to events data grid redirected to source view again<commit_after>'use strict';

var Reflux = require('reflux');
var dataSourceStore = require('../stores/dataSource.js');
var config = require('../config/config.js');
var presentationsStore = require('../stores/presentations.js');
var SourceActions = require('../actions/source.js');

module.exports = Reflux.createStore({

  // this will set up listeners to all publishers in SourceActions,
  // using onKeyname (or keyname) as callbacks
  listenables: [SourceActions],

  // Name to use for this collection
  collectionName: config.SourcesCollection.name,

  // Data storage for all collections
  dataSource: null,

  // The Loki collection transform array
  collectionTransform: [],

  // Called on Store initialisation
  init: function() {

    this.setDefaultTransform();

    // Register dataSourceStores's changes
    this.listenTo(dataSourceStore, this.dataSourceChanged);

    this.listenTo(presentationsStore, this.presentationsStoreChanged);
  },

  // Set the filteredData Object
  dataSourceChanged: function (dataSourceStore) {

    this.dataSource = dataSourceStore.dataSource;

    this.setDefaultTransform();

    // Call when the source data is updated
    this.filterStateChanged(this.filterTransform);
  },

  // Set search filter on our collectionTransform
  filterStateChanged: function(filterTransformBroadcast) {

    this.setDatesTransform();

    this.createFilterTransform(filterTransformBroadcast);
  },

  // Listener to changes on Presentations Store
  presentationsStoreChanged: function() {

    // If presentation name has been set to 'ViewingFilter', reset the presentation
    if (presentationsStore.presentationName === 'ViewingFilter') {
      this.resetFilterTransform();
    }
  },

  // Create a transform from the passed in object and save it on the collection
  createFilterTransform: function(filterTransformObject, message) {

    if (!this.dataSource) {
      return;
    }

    var collectionTransformObject = this.filterTransform[this.collectionName];
    var collectionToAddTransformTo = this.dataSource.getCollection(this.collectionName);

    if (!collectionToAddTransformTo) {
      return;
    }

    // Add filter to the transform
    this.collectionTransform = [];
    this.collectionTransform.push(collectionTransformObject.filters);
    this.collectionTransform.push(collectionTransformObject.sorting);

    // Save the transform to the collection
    if (filterTransformObject.transformName) {

      if (collectionToAddTransformTo.chain(filterTransformObject.transformName)) {
        collectionToAddTransformTo.setTransform(filterTransformObject.transformName, this.collectionTransform);
      } else {
        collectionToAddTransformTo.addTransform(filterTransformObject.transformName, this.collectionTransform);
      }

      // Apply the filter
      this.userFilteredCollection = collectionToAddTransformTo.chain(collectionToAddTransformTo.transforms[filterTransformObject.transformName][0], this.params).copy();

      // Apply the sort
      this.userFilteredCollection.simplesort(collectionTransformObject.sorting.property, collectionTransformObject.sorting.desc);

    } else {

      if (message !== 'presentationSaved') {
        this.userFilteredCollection = collectionToAddTransformTo.chain().copy();
      }
    }

    // Set viewingSource property to false
    this.viewingSource = false;
  },

  // Reset a transform on this collection
  resetFilterTransform: function() {

    var collectionToAddTransformTo;
    var transformName = 'ViewingFilter';

    if (!this.dataSource) {
      return;
    }

    collectionToAddTransformTo = this.dataSource.getCollection(this.collectionName);

    if (!collectionToAddTransformTo) {
      return;
    }

    // Update this store's filterTransform so the filters will be updated when a presentation changes
    this.filterTransform[this.collectionName].filters = this.dataSource.getCollection(this.collectionName).transforms[transformName][0];

    // Update the collection resulting from the transform
    this.userFilteredCollection = collectionToAddTransformTo.chain(transformName);

    // Set viewingSource property to false
    this.viewingSource = false;

    // Send collection object out to all listeners
    this.trigger(this);
  },

  // Set a default transform to be used immediately on the store
  setDefaultTransform: function() {

    var collectionToAddTransformTo;

    this.filterTransform = {};
    this.filterTransform[this.collectionName] = {
      filters: [{
        type: 'find',
        value: {
          '$and': []
        }
      },
      {
        type: 'where',
        value: '[%lktxp]filterDates'
      }],
      sorting: {
        type: 'simplesort',
        property: '$loki',
        desc: true
      },
      dateQueries: {
        from: [],
        to: []
      }
    };

    this.setDatesTransform();

    if (!this.dataSource) {
      return;
    }

    collectionToAddTransformTo = this.dataSource.getCollection(this.collectionName);

    if (!collectionToAddTransformTo) {
      return;
    }

    this.collectionTransform = [];
    this.collectionTransform.push(this.filterTransform[this.collectionName].filters);
    this.collectionTransform.push(this.filterTransform[this.collectionName].sorting);

    collectionToAddTransformTo.setTransform('ViewingFilter', this.collectionTransform);
  },

  // Set up functionality to perform a 'where' query on selected Date filters
  setDatesTransform: function() {

    // Get name of Field with a filter type of 'gte'
    config.SourcesCollection.fields.forEach(function(filter) {
      if (filter.filter === 'gte') {
        this.fromFilterName = filter.name;
      } else if (filter.filter === 'lte') {
        this.toFilterName = filter.name;
      }
    }.bind(this));

    // Transform Params to be used in collection chain transforms
    this.params = {
      filterDates: this.filterDates
    };
  },

  // Used by the lokijs 'where' query to filter on dates in a transform
  filterDates: function (obj) {

    var validItem;
    var fromArray = this.filterTransform[this.collectionName].dateQueries.from;
    var toArray = this.filterTransform[this.collectionName].dateQueries.to;
    var fromDefaultObject = {
      includeExclude: 'include',
      value: '1800-01-01 00:00:00'
    };
    var toDefaultObject = {
      includeExclude: 'include',
      value: '3000-01-01 00:00:00'
    };
    var fromDate = obj[this.fromFilterName];
    var toDate = obj[this.toFilterName];

    // If datastore has no date filters return
    if (!this.fromFilterName) {
      return true;
    }

    if (!fromArray.length) {
      fromArray.push(fromDefaultObject);
    } else if (!toArray.length) {
      toArray.push(toDefaultObject);
    }

    // Parse invalid dates
    if (fromDate === '' || fromDate === 'TBD') {
      fromDate = fromDefaultObject.value;
    }

    if (toDate === '' || toDate === 'TBD') {
      toDate = toDefaultObject.value;
    }

    // Sort arrays so dates are in order in each array
    fromArray = _.sortBy(fromArray, function(object) {
      return object.value;
    });

    toArray = _.sortBy(toArray, function(object) {
      return object.value;
    });

    // If more From filters than To filters
    if (fromArray.length >= toArray.length) {

      fromArray.forEach(function(fromObject, index) {

        var toObject = toArray[index];

        // If no corresponding To Date, set it to a far future date
        if (!toObject) {
          toObject = toDefaultObject;
        }

        // If the date filter is an include
        if (toObject.includeExclude === 'include') {

          if (fromDate >= fromObject.value && toDate <= toObject.value) {
            validItem = true;
          }
        } else if (toObject.includeExclude === 'exclude') {

          if (fromDate >= fromObject.value && toDate <= toObject.value) {
            validItem = true;
          }
        }
      }.bind(this));

      // Catch-all in case user adds more to filters than from filters which would be wrong anyway
    } else {

      toArray.forEach(function(toObject, index) {

        var fromObject = fromArray[index];

        // If no corresponding From Date, set it to a far past date
        if (!fromObject) {
          fromObject = fromDefaultObject;
        }

        // If the date filter is an include
        if (fromObject.includeExclude === 'include') {

          if (fromDate > fromObject.value && fromDate < toObject.value) {
            validItem = true;
          }
        } else if (fromObject.includeExclude === 'exclude') {

          if (fromDate > fromObject.value && toDate < toObject.value) {
            validItem = true;
          }
        }

      }.bind(this));
    }

    return validItem;
  },

  // Called when a user attempts to view a source file
  viewSourceFile: function(sourceObject) {

    // Set selectedSourceObject property
    this.setSelectedSourceObject(sourceObject);

    // Hack based around need to trigger pdf creation in pdf element so we broadcast a change to null
    // before sending out the object again.
    if (!sourceObject) {
      this.trigger(this);
      return;
    }

    // Set selectedSourceObject property
    this.setSelectedSourceFileType(sourceObject);

    // Set viewingSource property to true
    this.viewingSource = true;

    // Send object out to all listeners
    this.trigger(this);

    // Reset viewingSource property to false
    this.viewingSource = false;
  },

  // Set a property on this store object to indicate current selected source object
  setSelectedSourceObject: function(sourceObject) {
    this.selectedSourceObject = sourceObject;
  },

  // Set a property on this store object to indicate the type of file
  setSelectedSourceFileType: function(sourceObject) {

    var filePath = sourceObject['Linked File'];
    var fileExtension = filePath.substr(filePath.lastIndexOf('.') + 1);

    switch (fileExtension) {
      case 'pdf':
        this.selectedSourceRoute = 'pdf';
        this.selectedSourceFileType = 'pdf';
        break;
      case 'jpg':
        this.selectedSourceRoute = 'image';
        this.selectedSourceFileType = 'image';
        break;
      case 'jpeg':
        this.selectedSourceRoute = 'image';
        this.selectedSourceFileType = 'image';
        break;
      case 'gif':
        this.selectedSourceRoute = 'image';
        this.selectedSourceFileType = 'image';
        break;
      case 'png':
        this.selectedSourceRoute = 'image';
        this.selectedSourceFileType = 'image';
        break;
      case 'mp3':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'audio';
        break;
      case 'wav':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'audio';
        break;
      case 'avi':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'video';
        break;
      case 'mp4':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'video';
        break;
      case 'mov':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'video';
        break;
      case 'webm':
        this.selectedSourceRoute = 'media';
        this.selectedSourceFileType = 'video';
        break;
      default:
        console.warn(fileExtension + 'not a supported type');
    }
  }
});
<|endoftext|>


<commit_before>// var express = require('express');
// app.use(express.json());

var fs   = require('fs');
var url  = require('url');
var http = require('http');
var path = require('path');
var qs = require('querystring');

function mainpage(req, res)
{
    console.log("mainpage()");
    var filename = 'rects_c.html';
    fs.readFile(filename, "binary", function(err, file) {
      if(err) {
        res.writeHead(500, {"Content-Type": "text/plain"});
        res.write(err + "\n");
        res.end();
        return;
      }
      res.writeHead(200);
      res.write(file, "binary");
      res.end();
    });
}

function getdoc(req, res)
{
    console.log("getdoc()");
    var filename = 'dnd.json';
    fs.readFile(filename, "binary", function(err, file) {
      if(err) {
        res.writeHead(500, {"Content-Type": "text/plain"});
        res.write(err + "\n");
        res.end();
        return;
      }
      res.writeHead(200);
      res.write(file, "binary");
      res.end();
    });
}

function savedoc(req, res)
{
    console.log("savedoc()");
    var method = req.method;
    if( method !== 'POST' )
    {
        res.writeHead(405, {"Content-Type": "text/plain"});
        res.write("use POST to save" + "\n");
        res.end();
        return;
    }

    var body = '';
    req.on('data', function(data){
        body += data;
    });
    req.on('end', function(){
        var POST = qs.parse(body);
        // console.log(POST);
        var filedata = POST.file;
        filedata = JSON.stringify(JSON.parse(filedata), null, '  ');
        var filename = "saved.json";
        fs.writeFile(filename, filedata, {}, function(err){
            if( err )
            {
                console.log("error saving:", err);
                res.writeHead(500);
                res.write(JSON.stringify({'success':false, 'error':err}));
                res.end();
            } else {
                res.writeHead(200);
                res.write(JSON.stringify({'success':true}));
                res.end();
            }
        });
    });
}

function dispatch(req, res)
{
    var parts = url.parse(req.url);
    switch(parts.pathname)
    {
        case "/favicon.ico":
            res.end();
            break;
        case "/getdoc":
            getdoc(req, res);
            break;
        case "/savedoc":
            savedoc(req, res);
            break;
        default:
            mainpage(req, res);
            break;
    }
}

http.createServer(function (req, res) {
    dispatch(req, res);
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
<commit_msg>switch to express.js<commit_after>#!/usr/local/bin/node

var qs         = require('querystring');
var fs         = require('fs');
// npm install express body-parser
var express    = require('express');
var bodyParser = require('body-parser');

var app = express();
app.use(bodyParser());

app.get('/favicon.ico', function(req, res){res.end();});
app.get('/',         mainpage);
app.get('/getdoc',   getdoc);
app.post('/savedoc', savedoc);

var port = 1338;
app.listen(port);
console.log("listening on ", port);

function mainpage(req, res)
{
    console.log("mainpage()");
    var filename = 'rects_c.html';
    fs.readFile(filename, "binary", function(err, file) {
      if(err) {
        res.writeHead(500, {"Content-Type": "text/plain"});
        res.write(err + "\n");
        res.end();
        return;
      }
      res.writeHead(200);
      res.write(file, "binary");
      res.end();
    });
}

function getdoc(req, res)
{
    console.log("getdoc()");
    var filename = 'dnd.json';
    fs.readFile(filename, "binary", function(err, file) {
      if(err) {
        res.writeHead(500, {"Content-Type": "text/plain"});
        res.write(err + "\n");
        res.end();
        return;
      }
      res.writeHead(200);
      res.write(file, "binary");
      res.end();
    });
}

function savedoc(req, res)
{
    console.log("savedoc()");

    var filedata = req.body.file;
    filedata = JSON.stringify(JSON.parse(filedata), null, '  ');

    var filename = "saved.json";
    fs.writeFile(filename, filedata, {}, function(err){
        if( err )
        {
            console.log("error saving:", err);
            res.writeHead(500);
            res.write(JSON.stringify({'success':false, 'error':err}));
            res.end();
        } else {
            res.writeHead(200);
            res.write(JSON.stringify({'success':true}));
            res.end();
        }
    });
}
<|endoftext|>


<commit_before>import Ember from 'ember';
import DS from 'ember-data';
import ajax from 'ic-ajax';
import moment from 'moment';

const { computed, observer, on, RSVP, isEmpty } = Ember;
const { PromiseArray } = DS;

export default Ember.Service.extend({
  store: Ember.inject.service(),
  currentUserId: null,

  model: computed('currentUserId', function(){
    let deferred = Ember.RSVP.defer();
    let currentUserId = this.get('currentUserId');
    if (!currentUserId) {
      var url = '/auth/whoami';
      ajax(url).then(data => {
        if(data.userId){
          this.set('currentUserId', data.userId);
          this.get('store').find('user', data.userId).then((user) => {
            deferred.resolve(user);
          });
        } else {
          deferred.resolve(null);
        }
      }, () => {
        deferred.resolve(null);
      });
    } else {
      this.get('store').find('user', currentUserId).then((user) => {
        deferred.resolve(user);
      });
    }

    return DS.PromiseObject.create({
      promise: deferred.promise
    });
  }),

  availableCohortsObserver: observer('availableCohorts.[]', function(){
    var self = this;
    this.get('availableCohorts').then(function(cohorts){
      if(!cohorts.contains(self.get('currentCohort'))){
        self.set('currentCohort', null);
      }
    });
  }),
  currentCohort: null,
  availableCohorts: computed('currentSchool', function(){
    var self = this;
    return new Ember.RSVP.Promise(function(resolve) {
      self.get('currentSchool').then(function(school){
        school.get('programs').then(function(programs){
          var promises = programs.map(function(program){
            return program.get('programYears');
          });
          Ember.RSVP.hash(promises).then(function(hash){
            var promises = [];
            Object.keys(hash).forEach(function(key) {
              hash[key].forEach(function(programYear){
                promises.push(programYear.get('cohort'));
              });
            });
            Ember.RSVP.hash(promises).then(function(hash){
              var cohorts = Ember.A();
              Object.keys(hash).forEach(function(key) {
                cohorts.pushObject(hash[key]);
              });
              resolve(cohorts);
            });
          });
        });
      });
    });
  }),
  userRoleTitles: computed('model.roles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('model').then(user => {
        if(!user){
          resolve([]);
        } else {
          user.get('roles').then(roles => {
            let roleTitles = roles.map(role => role.get('title').toLowerCase());
            resolve(roleTitles);
          });
        }
      });
    });
  }),
  userIsCourseDirector: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('course director'));
      });
    });
  }),
  userIsFaculty: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('faculty'));
      });
    });
  }),
  userIsDeveloper: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('developer'));
      });
    });
  }),
  userIsStudent: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('student'));
      });
    });
  }),
  userIsPublic: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('public'));
      });
    });
  }),
  userIsFormerStudent: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('former student'));
      });
    });
  }),
  //not really used other than to trigger other properties
  privileges: computed(
    'userIsCourseDirector',
    'userIsFaculty',
    'userIsDeveloper',
    'userIsFormerStudent',
    'userIsPublic',
    'userIsStudent',
  function(){
    Ember.RSVP.all([
      this.get('userIsCourseDirector'),
      this.get('userIsFaculty'),
      this.get('userIsDeveloper'),
      this.get('userIsFormerStudent'),
      this.get('userIsPublic'),
      this.get('userIsStudent'),
    ]).then(arr => {
      return arr;
    });
  }),
  //will be customizable
  preferredDashboard: 'dashboard.week',
  //Program
  canViewProgram: computed('model', function(){
    return false;
  }),
  canViewPrograms: false,
  canEditPrograms: false,
  programsPrivilegesObserver: on('init', observer('privileges',
    function(){
      Ember.RSVP.all([
        this.get('userIsCourseDirector'),
        this.get('userIsDeveloper')
      ]).then(hasRole => {
        this.set('canViewPrograms', hasRole.contains(true));
        this.set('canEditPrograms', hasRole.contains(true));
      });
  })),
  //Course
  canViewCourse: computed('model', function(){
    return false;
  }),
  canViewCourses: false,
  canEditCourses: false,
  coursesPrivilegesObserver: on('init', observer('privileges',
    function(){
      Ember.RSVP.all([
        this.get('userIsCourseDirector'),
        this.get('userIsFaculty'),
        this.get('userIsDeveloper')
      ]).then(hasRole => {
        this.set('canViewCourses', hasRole.contains(true));
        this.set('canEditCourses', hasRole.contains(true));
      });
  })),
  canViewInstructorGroups: false,
  canEditInstructorGroups: false,
  instructorGroupsPrivilegesObserver: on('init', observer('privileges',
    function(){
      Ember.RSVP.all([
        this.get('userIsCourseDirector'),
        this.get('userIsDeveloper')
      ]).then(hasRole => {
        this.set('canViewInstructorGroups', hasRole.contains(true));
        this.set('canEditInstructorGroups', hasRole.contains(true));
      });
  })),
  //Instructor Group
  canViewInstructorGroup: computed('model', function(){
    return false;
  }),
  canViewLearnerGroups: false,
  canEditLearnerGroups: false,
  learnerGroupsPrivilegesObserver: on('init', observer('privileges',
    function(){
      Ember.RSVP.all([
        this.get('userIsCourseDirector'),
        this.get('userIsDeveloper')
      ]).then(hasRole => {
        this.set('canViewLearnerGroups', hasRole.contains(true));
        this.set('canEditLearnerGroups', hasRole.contains(true));
      });
  })),
  //Learner Group
  canViewLearnerGroup: computed('model', function(){
    return false;
  }),
  //Curriculum Inventory
  canViewCurriculumInventory: computed('model', function(){
    return false;
  }),
  //Report
  canViewReport: computed('model', function(){
    return false;
  }),
  //Reports
  canViewReports: computed('model', function(){
    return false;
  }),
  canViewAdminDashboard: false,
  canViewAdminDashboardObserver: on('init', observer('privileges',
    function(){
      Ember.RSVP.all([
        this.get('userIsDeveloper')
      ]).then(hasRole => {
        this.set('canViewAdminDashboard', hasRole.contains(true));
      });
  })),
  activeRelatedCoursesInThisYearAndLastYear: computed(
    'model',
    'model.instructedOfferings.[]',
    'model.instructorGroups.[]',
    'model.instructedLearnerGroups.[]',
    'model.directedCourses.[]',
    'model.instructorIlmSessions.[]',
    function(){
      let defer = RSVP.defer();
      this.get('model').then( user => {
        if(isEmpty(user)){
          defer.resolve([]);
          return;
        }
        let currentYear = moment().format('YYYY');
        const currentMonth = parseInt(moment().format('M'));
        if(currentMonth < 6){
          currentYear--;
        }
        const previousYear = currentYear -1;
        this.get('store').query('course', {
          filters: {
            users: [user.get('id')],
            year: [previousYear, currentYear],
            locked: false,
            archived: false
          }
        }).then(filteredCourses => {
          defer.resolve(filteredCourses);
        });
      });
      return PromiseArray.create({
        promise: defer.promise
      });
    }
  )
});
<commit_msg>updated 'my courses' query in current-user service.<commit_after>import Ember from 'ember';
import DS from 'ember-data';
import ajax from 'ic-ajax';
import moment from 'moment';

const { computed, observer, on, RSVP, isEmpty } = Ember;
const { PromiseArray } = DS;

export default Ember.Service.extend({
  store: Ember.inject.service(),
  currentUserId: null,

  model: computed('currentUserId', function(){
    let deferred = Ember.RSVP.defer();
    let currentUserId = this.get('currentUserId');
    if (!currentUserId) {
      var url = '/auth/whoami';
      ajax(url).then(data => {
        if(data.userId){
          this.set('currentUserId', data.userId);
          this.get('store').find('user', data.userId).then((user) => {
            deferred.resolve(user);
          });
        } else {
          deferred.resolve(null);
        }
      }, () => {
        deferred.resolve(null);
      });
    } else {
      this.get('store').find('user', currentUserId).then((user) => {
        deferred.resolve(user);
      });
    }

    return DS.PromiseObject.create({
      promise: deferred.promise
    });
  }),

  availableCohortsObserver: observer('availableCohorts.[]', function(){
    var self = this;
    this.get('availableCohorts').then(function(cohorts){
      if(!cohorts.contains(self.get('currentCohort'))){
        self.set('currentCohort', null);
      }
    });
  }),
  currentCohort: null,
  availableCohorts: computed('currentSchool', function(){
    var self = this;
    return new Ember.RSVP.Promise(function(resolve) {
      self.get('currentSchool').then(function(school){
        school.get('programs').then(function(programs){
          var promises = programs.map(function(program){
            return program.get('programYears');
          });
          Ember.RSVP.hash(promises).then(function(hash){
            var promises = [];
            Object.keys(hash).forEach(function(key) {
              hash[key].forEach(function(programYear){
                promises.push(programYear.get('cohort'));
              });
            });
            Ember.RSVP.hash(promises).then(function(hash){
              var cohorts = Ember.A();
              Object.keys(hash).forEach(function(key) {
                cohorts.pushObject(hash[key]);
              });
              resolve(cohorts);
            });
          });
        });
      });
    });
  }),
  userRoleTitles: computed('model.roles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('model').then(user => {
        if(!user){
          resolve([]);
        } else {
          user.get('roles').then(roles => {
            let roleTitles = roles.map(role => role.get('title').toLowerCase());
            resolve(roleTitles);
          });
        }
      });
    });
  }),
  userIsCourseDirector: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('course director'));
      });
    });
  }),
  userIsFaculty: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('faculty'));
      });
    });
  }),
  userIsDeveloper: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('developer'));
      });
    });
  }),
  userIsStudent: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('student'));
      });
    });
  }),
  userIsPublic: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('public'));
      });
    });
  }),
  userIsFormerStudent: computed('useRoleTitles.[]', function(){
    return new Ember.RSVP.Promise((resolve) => {
      this.get('userRoleTitles').then(roleTitles => {
        resolve(roleTitles.contains('former student'));
      });
    });
  }),
  //not really used other than to trigger other properties
  privileges: computed(
    'userIsCourseDirector',
    'userIsFaculty',
    'userIsDeveloper',
    'userIsFormerStudent',
    'userIsPublic',
    'userIsStudent',
  function(){
    Ember.RSVP.all([
      this.get('userIsCourseDirector'),
      this.get('userIsFaculty'),
      this.get('userIsDeveloper'),
      this.get('userIsFormerStudent'),
      this.get('userIsPublic'),
      this.get('userIsStudent'),
    ]).then(arr => {
      return arr;
    });
  }),
  //will be customizable
  preferredDashboard: 'dashboard.week',
  //Program
  canViewProgram: computed('model', function(){
    return false;
  }),
  canViewPrograms: false,
  canEditPrograms: false,
  programsPrivilegesObserver: on('init', observer('privileges',
    function(){
      Ember.RSVP.all([
        this.get('userIsCourseDirector'),
        this.get('userIsDeveloper')
      ]).then(hasRole => {
        this.set('canViewPrograms', hasRole.contains(true));
        this.set('canEditPrograms', hasRole.contains(true));
      });
  })),
  //Course
  canViewCourse: computed('model', function(){
    return false;
  }),
  canViewCourses: false,
  canEditCourses: false,
  coursesPrivilegesObserver: on('init', observer('privileges',
    function(){
      Ember.RSVP.all([
        this.get('userIsCourseDirector'),
        this.get('userIsFaculty'),
        this.get('userIsDeveloper')
      ]).then(hasRole => {
        this.set('canViewCourses', hasRole.contains(true));
        this.set('canEditCourses', hasRole.contains(true));
      });
  })),
  canViewInstructorGroups: false,
  canEditInstructorGroups: false,
  instructorGroupsPrivilegesObserver: on('init', observer('privileges',
    function(){
      Ember.RSVP.all([
        this.get('userIsCourseDirector'),
        this.get('userIsDeveloper')
      ]).then(hasRole => {
        this.set('canViewInstructorGroups', hasRole.contains(true));
        this.set('canEditInstructorGroups', hasRole.contains(true));
      });
  })),
  //Instructor Group
  canViewInstructorGroup: computed('model', function(){
    return false;
  }),
  canViewLearnerGroups: false,
  canEditLearnerGroups: false,
  learnerGroupsPrivilegesObserver: on('init', observer('privileges',
    function(){
      Ember.RSVP.all([
        this.get('userIsCourseDirector'),
        this.get('userIsDeveloper')
      ]).then(hasRole => {
        this.set('canViewLearnerGroups', hasRole.contains(true));
        this.set('canEditLearnerGroups', hasRole.contains(true));
      });
  })),
  //Learner Group
  canViewLearnerGroup: computed('model', function(){
    return false;
  }),
  //Curriculum Inventory
  canViewCurriculumInventory: computed('model', function(){
    return false;
  }),
  //Report
  canViewReport: computed('model', function(){
    return false;
  }),
  //Reports
  canViewReports: computed('model', function(){
    return false;
  }),
  canViewAdminDashboard: false,
  canViewAdminDashboardObserver: on('init', observer('privileges',
    function(){
      Ember.RSVP.all([
        this.get('userIsDeveloper')
      ]).then(hasRole => {
        this.set('canViewAdminDashboard', hasRole.contains(true));
      });
  })),
  activeRelatedCoursesInThisYearAndLastYear: computed(
    'model',
    'model.instructedOfferings.[]',
    'model.instructorGroups.[]',
    'model.instructedLearnerGroups.[]',
    'model.directedCourses.[]',
    'model.instructorIlmSessions.[]',
    function(){
      let defer = RSVP.defer();
      this.get('model').then( user => {
        if(isEmpty(user)){
          defer.resolve([]);
          return;
        }
        let currentYear = moment().format('YYYY');
        const currentMonth = parseInt(moment().format('M'));
        if(currentMonth < 6){
          currentYear--;
        }
        const previousYear = currentYear -1;
        this.get('store').query('course', {
          my: true,
          filters: {
            year: [previousYear, currentYear],
            locked: false,
            archived: false
          }
        }).then(filteredCourses => {
          defer.resolve(filteredCourses);
        });
      });
      return PromiseArray.create({
        promise: defer.promise
      });
    }
  )
});
<|endoftext|>


<commit_before>/*  parseQuery:  Parses the search query
 *      @arg (String) input: The search query
 *      @returns (Array) [settings, filters, text]
 */
this.parseQuery = function (input) {
  // assumes search query is a space delimted key/value pairs.
  var options = (input.split(/\s/));

  var filters = {
    inurl: null,
    intitle: null,
    site: null
  };

  // Chrome search object.
  var searchSettings = {
    startTime: null,
    endTime: null,
    text: ''
  };

  var combined = '';

  options.forEach(function (pair) {
    if (!pair) return;
    // assume key:value
    pair = pair.split(':');
    searchSettings[pair[0]] !== undefined ?
        // pair is a search setting type
        searchSettings[pair[0]] = pair[1] :
        // pair is a filter type
        filters[pair[0]] !== undefined ?
            combined += ' ' + (filters[pair[0]] = pair[1]) :
            combined += ' ' + (pair[1] || pair[0] || '');
  });
  searchSettings.text = combined.trim();

  // delete all empty filters
  for (var prop in filters) {
    if (filters[prop] === null) {
      delete filters[prop];
    }
  }

  return {
    settings: searchSettings,
    filters: filters
  };
};<commit_msg>remove weird terinary<commit_after>/*  parseQuery:  Parses the search query
 *      @arg (String) input: The search query
 *      @returns (Array) [settings, filters, text]
 */
this.parseQuery = function (input) {
  // assumes search query is a space delimted key/value pairs.
  var options = (input.split(/\s/));

  var filters = {
    inurl: null,
    intitle: null,
    site: null
  };

  // Chrome search object.
  var searchSettings = {
    startTime: null,
    endTime: null,
    text: ''
  };

  var combined = '';

  options.forEach(function (pair) {
    if (!pair) return;
    // assume key:value
    pair = pair.split(':');
    if (searchSettings[pair[0]] !== undefined) {
      searchSettings[pair[0]] = pair[1];
    } else {
      if (filters[pair[0]] !== undefined) {
        filters[pair[0]] = pair[1]
        combined += ' ' + (pair[1]);
      } else {
        combined += ' ' + (pair[1] || pair[0] || '');
      }
    }
  });
  searchSettings.text = combined.trim();

  // delete all empty filters
  for (var prop in filters) {
    if (filters[prop] === null) {
      delete filters[prop];
    }
  }

  return {
    settings: searchSettings,
    filters: filters
  };
};
<|endoftext|>