<commit_before>module.exports = {
  classitems: [
    '$',
    'A',
    'EXTEND_PROTOTYPES',
    'GUID_KEY',
    'GUID_PREFIX',
    'LOG_STACKTRACE_ON_DEPRECATION',
    'LOG_VERSION',
    '[]',
    '_APPLICATION_TEMPLATE_WRAPPER',
    '_DISABLE_PROPERTY_FALLBACK_DEPRECATION',
    '_DEBUG_RENDER_TREE',
    '_JQUERY_INTEGRATION',
    '_DEFAULT_ASYNC_OBSERVERS',
    '_RERENDER_LOOP_LIMIT',
    '_TEMPLATE_ONLY_GLIMMER_COMPONENTS',
    'Input',
    'LinkTo',
    'Textarea',
    '__container__',
    '_activeQPChanged',
    '_applicationInstances',
    '_deserializeQueryParam',
    '_deserializeQueryParams',
    '_document',
    '_fullyScopeQueryParams',
    '_getHashPath',
    '_getObjectsOnNamespaces',
    '_getQPMeta',
    '_globalsMode',
    '_helpers',
    '_hydrateUnsuppliedQueryParams',
    '_initializersRan',
    '_injections',
    '_internalReset',
    '_invoke',
    '_lazyInjections',
    '_logLookup',
    '_normalizeCache',
    '_onLookup',
    '_options',
    '_optionsForQueryParam',
    '_prepareForGlobalsMode',
    '_prepareQueryParams',
    '_pruneDefaultQueryParamValues',
    '_qp',
    '_qpChanged',
    '_qpDelegate',
    '_queryParamsFor',
    '_renderMode',
    '_resolveCache',
    '_serializeQueryParam',
    '_serializeQueryParams',
    '_setRouteName',
    '_stashNames',
    '_typeInjections',
    '_typeOptions',
    '_unwatchInstance',
    '_updatingQPChanged',
    '_watchInstance',
    'abort',
    'acceptsModelName',
    'action',
    'actions',
    'activate',
    'active',
    'activeClass',
    'adapter',
    'addArrayObserver',
    'addListener',
    'addObject',
    'addObjects',
    'addObserver',
    'advanceReadiness',
    'afterModel',
    'alias',
    'aliasMethod',
    'all',
    'allSettled',
    'and',
    'any',
    'append',
    'appendTo',
    'application',
    'apply',
    'ariaRole',
    'arrangedContent',
    'array',
    'arrayContentDidChange',
    'arrayContentWillChange',
    'assert',
    'assertDestroyablesDestroyed',
    'assertLinkToOrigin',
    'assign',
    'associateDestroyableChild',
    'asyncEnd',
    'asyncStart',
    'attributeBindings',
    'attributeLimit',
    'attributes',
    'autoboot',
    'beforeModel',
    'begin',
    'beginPropertyChanges',
    'bind',
    'bool',
    'boot',
    'bubbles',
    'buildChildEngineInstance',
    'buildInstance',
    'buildRegistry',
    'buildRouteInfoMetadata',
    'cache',
    'cacheFor',
    'camelize',
    'canCatalogEntriesByType',
    'cancel',
    'cancelRouterSetup',
    'canInvoke',
    'capabilities',
    'capitalize',
    'captureRenderTree',
    'catalogEntriesByType',
    'catch',
    'changeProperties',
    'checkWaiters',
    'child',
    'childViews',
    'classify',
    'classNameBindings',
    'classNames',
    'clear',
    'click',
    'cloneParentDependencies',
    'collect',
    'columnsForType',
    'compact',
    'compare',
    'component',
    'compute',
    'computed',
    'concat',
    'concatenatedProperties',
    'container',
    'containerDebugAdapter',
    'content',
    'contextDidChange',
    'controller',
    'controllerFor',
    'controllerName',
    'copy',
    'create',
    'createCache',
    'current-when',
    'currentPath',
    'currentRoute',
    'currentRouteName',
    'currentURL',
    'customEvents',
    'dasherize',
    'data',
    'deactivate',
    'debounce',
    'debug',
    'debugAbortStack',
    'debugCreationStack',
    'debugger',
    'debugPreviousTransition',
    'decamelize',
    'decrementProperty',
    'defer',
    'deferReadiness',
    'defineProperty',
    'denodeify',
    'dependentKeyCompat',
    'deprecate',
    'deprecateFunc',
    'deprecateProperty',
    'deprecatingAlias',
    'describe',
    'descriptorForProperty',
    'deserialize',
    'deserializeQueryParam',
    'destroy',
    'detect',
    'didBecomeReady',
    'didInsertElement',
    'didReceiveAttrs',
    'didRender',
    'didTransition',
    'didUpdate',
    'didUpdateAttrs',
    'disabled',
    'disabledClass',
    'disconnectOutlet',
    'document',
    'domReady',
    'each-in',
    'each',
    'eachComputedProperty',
    'element',
    'elementId',
    'empty',
    'enableDestroyableTracking',
    'end',
    'endPropertyChanges',
    'engine',
    'ensureInitializers',
    'enter',
    'equal',
    'error',
    'eventDispatcher',
    'eventName',
    'events',
    'every',
    'exception',
    'exit',
    'expandProperties',
    'extend',
    'factoryFor',
    'fallback',
    'fillIn',
    'filter',
    'filterBy',
    'finally',
    'find',
    'findBy',
    'findModel',
    'findWithAssert',
    'firstObject',
    'flushWatchers',
    'fn',
    'focusIn',
    'focusOut',
    'followRedirects',
    'forEach',
    'formatURL',
    'from',
    'fullRouteName',
    'generateController',
    'generateControllerFactory',
    'generateGuid',
    'get',
    'getChildViews',
    'getEach',
    'getEngineParent',
    'getFilters',
    'getHash',
    'getModelTypes',
    'getOwner',
    'getProperties',
    'getRecordColor',
    'getRecordColumnValues',
    'getRecordFilterValues',
    'getRecordKeywords',
    'getRecords',
    'getRootViews',
    'getURL',
    'getValue',
    'getViewBoundingClientRect',
    'getViewBounds',
    'getViewClientRects',
    'getViewElement',
    'getViewId',
    'getViewRange',
    'getWithDefault',
    'global',
    'gt',
    'gte',
    'guidFor',
    'handleEvent',
    'handleURL',
    'has',
    'hasArrayObservers',
    'hasBlock',
    'hasBlockParams',
    'hash',
    'hashSettled',
    'hasListeners',
    'hasObserverFor',
    'hasRegistration',
    'hasRoute',
    'helper',
    'helperContainer',
    'history',
    'href',
    'htmlSafe',
    'if',
    'in-element',
    'includes',
    'incrementProperty',
    'indexOf',
    'info',
    'init',
    'initializer',
    'initState',
    'inject',
    'injection',
    'injectTestHelpers',
    'input',
    'insertAt',
    'insertNewline',
    'inspect',
    'instanceInitializer',
    'instrument',
    'intermediateTransitionTo',
    'intersect',
    'invoke',
    'invokeHelper',
    'isActive',
    'isActiveIntent',
    'isAny',
    'isArray',
    'isBlank',
    'isBrowser',
    'isClassicDecorator',
    'isComputed',
    'isConst',
    'isDestroyed',
    'isDestroying',
    'isEmpty',
    'isEnabled',
    'isEqual',
    'isEvery',
    'isFulfilled',
    'isHTMLSafe',
    'isInteractive',
    'isNone',
    'isObject',
    'isPending',
    'isPresent',
    'isRejected',
    'isSettled',
    'isVisible',
    'join',
    'jQuery',
    'keyDown',
    'keyEvent',
    'keyPress',
    'keyUp',
    'knownForType',
    'lastIndexOf',
    'lastObject',
    'later',
    'layout',
    'layoutName',
    'length',
    'let',
    'link-to',
    'loading',
    'loadingClass',
    'loadingHref',
    'loc',
    'localName',
    'location',
    'log',
    'lookup',
    'lookupDescription',
    'lt',
    'lte',
    'makeArray',
    'makeToString',
    'map',
    'mapBy',
    'match',
    'matches',
    'max',
    'merge',
    'mergedProperties',
    'meta',
    'metadata',
    'metaForProperty',
    'method',
    'min',
    'mixin',
    'model',
    'modelFor',
    'models',
    'mount',
    'mut',
    'name',
    'namespace',
    'nearestOfType',
    'nearestWithProperty',
    'next',
    'none',
    'normalize',
    'normalizeFullName',
    'not',
    'notEmpty',
    'notifyPropertyChange',
    'objectAt',
    'objectAtContent',
    'objectsAt',
    'observeModelType',
    'observer',
    'observes',
    'off',
    'on',
    'once',
    'one',
    'oneWay',
    'onInjectHelpers',
    'onLoad',
    'onUpdateURL',
    'options',
    'optionsForType',
    'or',
    'originalMethods',
    'outlet',
    'ownerInjection',
    'page-title',
    'paramNames',
    'params',
    'paramsFor',
    'parent',
    'parentView',
    'parentViewDidChange',
    'parseName',
    'partial',
    'pattern',
    'pauseTest',
    'popObject',
    'positionalParams',
    'preventDefault',
    'promise',
    'property',
    'pushObject',
    'pushObjects',
    'pushState',
    'query-params',
    'query',
    'queryParams',
    'queryParamsDidChange',
    'queues',
    'race',
    'readDOMAttr',
    'readonly',
    'readOnly',
    'reads',
    'ready',
    'reason',
    'recognize',
    'recognizeAndLoad',
    'recompute',
    'recordsWatchers',
    'redirect',
    'reduce',
    'refresh',
    'register',
    'registerAsyncHelper',
    'registerDeprecationHandler',
    'registerDestructor',
    'registeredActions',
    'registeredOption',
    'registeredOptions',
    'registeredOptionsForType',
    'registerHelper',
    'registerOptions',
    'registerOptionsForType',
    'registerWaiter',
    'registerWarnHandler',
    'registrations',
    'registry',
    'reject',
    'rejectBy',
    'rel',
    'releaseMethods',
    'removeArrayObserver',
    'removeAt',
    'removeListener',
    'removeObject',
    'removeObjects',
    'removeObserver',
    'removeTestHelpers',
    'render',
    'renderTemplate',
    'reopen',
    'reopenClass',
    'replace',
    'replaceContent',
    'replaceRoute',
    'replaceState',
    'replaceURL',
    'replaceWith',
    'rerender',
    'reset',
    'resetController',
    'resolve',
    'resolveController',
    'resolveHelper',
    'resolveModel',
    'resolveOther',
    'resolver',
    'resolveRegistration',
    'resolverFor',
    'resolveRoute',
    'resolveTemplate',
    'resolveView',
    'resumeTest',
    'rethrow',
    'retry',
    'reverseObjects',
    'rootElement',
    'rootURL',
    'route',
    'routeDidChange',
    'routeName',
    'routeWillChange',
    'run',
    'runInDebug',
    'runInitializers',
    'runInstanceInitializers',
    'runLoadHooks',
    'schedule',
    'scheduleOnce',
    'send',
    'sendAction',
    'sendEvent',
    'serialize',
    'serializeQueryParam',
    'serializeQueryParamKey',
    'set',
    'setClassicDecorator',
    'setDiff',
    'setEach',
    'setEngineParent',
    'setHelperManager',
    'setObjects',
    'setOwner',
    'setProperties',
    'setup',
    'setupController',
    'setupForTesting',
    'setupHandler',
    'setupHandlerForBrowserEvent',
    'setupHandlerForEmberEvent',
    'setupRegistry',
    'setURL',
    'shiftObject',
    'shouldRender',
    'size',
    'slice',
    'sort',
    'sortBy',
    'startRouting',
    'store',
    'subscribe',
    'sum',
    'tabindex',
    'tagName',
    'target',
    'teardownViews',
    'templateName',
    'templateOnly',
    'testCheckboxClick',
    'testHelpers',
    'testing',
    'textarea',
    'then',
    'this[RENDER]',
    'throttle',
    'title',
    'to',
    'toArray',
    'toggleProperty',
    'toString',
    'tracked',
    'transitionTo',
    'transitionToRoute',
    'translateToContainerFullname',
    'trigger',
    'triggerAction',
    'triggerEvent',
    'tryInvoke',
    'trySet',
    'type',
    'typeInjection',
    'typeOf',
    'typeWatchers',
    'unbound',
    'underscore',
    'union',
    'uniq',
    'uniqBy',
    'unless',
    'unregister',
    'unregisterDestructor',
    'unregisterHelper',
    'unregisterWaiter',
    'unshiftObject',
    'unshiftObjects',
    'unsubscribe',
    'url',
    'urlFor',
    'userAgent',
    'useRouterNaming',
    'validationCache',
    'value',
    'visit',
    'volatile',
    'w',
    'wait',
    'waitForDOMReady',
    'warn',
    'watchModelTypes',
    'watchRecords',
    'willClearRender',
    'willDestroy',
    'willDestroyElement',
    'willInsertElement',
    'willRender',
    'willTransition',
    'willUpdate',
    'with',
    'without',
    'wrap',
    'wrapModelType',
    'wrapRecord',
    'yield',
  ],
};
<commit_msg>remove `with` from expected.js<commit_after>module.exports = {
  classitems: [
    '$',
    'A',
    'EXTEND_PROTOTYPES',
    'GUID_KEY',
    'GUID_PREFIX',
    'LOG_STACKTRACE_ON_DEPRECATION',
    'LOG_VERSION',
    '[]',
    '_APPLICATION_TEMPLATE_WRAPPER',
    '_DISABLE_PROPERTY_FALLBACK_DEPRECATION',
    '_DEBUG_RENDER_TREE',
    '_JQUERY_INTEGRATION',
    '_DEFAULT_ASYNC_OBSERVERS',
    '_RERENDER_LOOP_LIMIT',
    '_TEMPLATE_ONLY_GLIMMER_COMPONENTS',
    'Input',
    'LinkTo',
    'Textarea',
    '__container__',
    '_activeQPChanged',
    '_applicationInstances',
    '_deserializeQueryParam',
    '_deserializeQueryParams',
    '_document',
    '_fullyScopeQueryParams',
    '_getHashPath',
    '_getObjectsOnNamespaces',
    '_getQPMeta',
    '_globalsMode',
    '_helpers',
    '_hydrateUnsuppliedQueryParams',
    '_initializersRan',
    '_injections',
    '_internalReset',
    '_invoke',
    '_lazyInjections',
    '_logLookup',
    '_normalizeCache',
    '_onLookup',
    '_options',
    '_optionsForQueryParam',
    '_prepareForGlobalsMode',
    '_prepareQueryParams',
    '_pruneDefaultQueryParamValues',
    '_qp',
    '_qpChanged',
    '_qpDelegate',
    '_queryParamsFor',
    '_renderMode',
    '_resolveCache',
    '_serializeQueryParam',
    '_serializeQueryParams',
    '_setRouteName',
    '_stashNames',
    '_typeInjections',
    '_typeOptions',
    '_unwatchInstance',
    '_updatingQPChanged',
    '_watchInstance',
    'abort',
    'acceptsModelName',
    'action',
    'actions',
    'activate',
    'active',
    'activeClass',
    'adapter',
    'addArrayObserver',
    'addListener',
    'addObject',
    'addObjects',
    'addObserver',
    'advanceReadiness',
    'afterModel',
    'alias',
    'aliasMethod',
    'all',
    'allSettled',
    'and',
    'any',
    'append',
    'appendTo',
    'application',
    'apply',
    'ariaRole',
    'arrangedContent',
    'array',
    'arrayContentDidChange',
    'arrayContentWillChange',
    'assert',
    'assertDestroyablesDestroyed',
    'assertLinkToOrigin',
    'assign',
    'associateDestroyableChild',
    'asyncEnd',
    'asyncStart',
    'attributeBindings',
    'attributeLimit',
    'attributes',
    'autoboot',
    'beforeModel',
    'begin',
    'beginPropertyChanges',
    'bind',
    'bool',
    'boot',
    'bubbles',
    'buildChildEngineInstance',
    'buildInstance',
    'buildRegistry',
    'buildRouteInfoMetadata',
    'cache',
    'cacheFor',
    'camelize',
    'canCatalogEntriesByType',
    'cancel',
    'cancelRouterSetup',
    'canInvoke',
    'capabilities',
    'capitalize',
    'captureRenderTree',
    'catalogEntriesByType',
    'catch',
    'changeProperties',
    'checkWaiters',
    'child',
    'childViews',
    'classify',
    'classNameBindings',
    'classNames',
    'clear',
    'click',
    'cloneParentDependencies',
    'collect',
    'columnsForType',
    'compact',
    'compare',
    'component',
    'compute',
    'computed',
    'concat',
    'concatenatedProperties',
    'container',
    'containerDebugAdapter',
    'content',
    'contextDidChange',
    'controller',
    'controllerFor',
    'controllerName',
    'copy',
    'create',
    'createCache',
    'current-when',
    'currentPath',
    'currentRoute',
    'currentRouteName',
    'currentURL',
    'customEvents',
    'dasherize',
    'data',
    'deactivate',
    'debounce',
    'debug',
    'debugAbortStack',
    'debugCreationStack',
    'debugger',
    'debugPreviousTransition',
    'decamelize',
    'decrementProperty',
    'defer',
    'deferReadiness',
    'defineProperty',
    'denodeify',
    'dependentKeyCompat',
    'deprecate',
    'deprecateFunc',
    'deprecateProperty',
    'deprecatingAlias',
    'describe',
    'descriptorForProperty',
    'deserialize',
    'deserializeQueryParam',
    'destroy',
    'detect',
    'didBecomeReady',
    'didInsertElement',
    'didReceiveAttrs',
    'didRender',
    'didTransition',
    'didUpdate',
    'didUpdateAttrs',
    'disabled',
    'disabledClass',
    'disconnectOutlet',
    'document',
    'domReady',
    'each-in',
    'each',
    'eachComputedProperty',
    'element',
    'elementId',
    'empty',
    'enableDestroyableTracking',
    'end',
    'endPropertyChanges',
    'engine',
    'ensureInitializers',
    'enter',
    'equal',
    'error',
    'eventDispatcher',
    'eventName',
    'events',
    'every',
    'exception',
    'exit',
    'expandProperties',
    'extend',
    'factoryFor',
    'fallback',
    'fillIn',
    'filter',
    'filterBy',
    'finally',
    'find',
    'findBy',
    'findModel',
    'findWithAssert',
    'firstObject',
    'flushWatchers',
    'fn',
    'focusIn',
    'focusOut',
    'followRedirects',
    'forEach',
    'formatURL',
    'from',
    'fullRouteName',
    'generateController',
    'generateControllerFactory',
    'generateGuid',
    'get',
    'getChildViews',
    'getEach',
    'getEngineParent',
    'getFilters',
    'getHash',
    'getModelTypes',
    'getOwner',
    'getProperties',
    'getRecordColor',
    'getRecordColumnValues',
    'getRecordFilterValues',
    'getRecordKeywords',
    'getRecords',
    'getRootViews',
    'getURL',
    'getValue',
    'getViewBoundingClientRect',
    'getViewBounds',
    'getViewClientRects',
    'getViewElement',
    'getViewId',
    'getViewRange',
    'getWithDefault',
    'global',
    'gt',
    'gte',
    'guidFor',
    'handleEvent',
    'handleURL',
    'has',
    'hasArrayObservers',
    'hasBlock',
    'hasBlockParams',
    'hash',
    'hashSettled',
    'hasListeners',
    'hasObserverFor',
    'hasRegistration',
    'hasRoute',
    'helper',
    'helperContainer',
    'history',
    'href',
    'htmlSafe',
    'if',
    'in-element',
    'includes',
    'incrementProperty',
    'indexOf',
    'info',
    'init',
    'initializer',
    'initState',
    'inject',
    'injection',
    'injectTestHelpers',
    'input',
    'insertAt',
    'insertNewline',
    'inspect',
    'instanceInitializer',
    'instrument',
    'intermediateTransitionTo',
    'intersect',
    'invoke',
    'invokeHelper',
    'isActive',
    'isActiveIntent',
    'isAny',
    'isArray',
    'isBlank',
    'isBrowser',
    'isClassicDecorator',
    'isComputed',
    'isConst',
    'isDestroyed',
    'isDestroying',
    'isEmpty',
    'isEnabled',
    'isEqual',
    'isEvery',
    'isFulfilled',
    'isHTMLSafe',
    'isInteractive',
    'isNone',
    'isObject',
    'isPending',
    'isPresent',
    'isRejected',
    'isSettled',
    'isVisible',
    'join',
    'jQuery',
    'keyDown',
    'keyEvent',
    'keyPress',
    'keyUp',
    'knownForType',
    'lastIndexOf',
    'lastObject',
    'later',
    'layout',
    'layoutName',
    'length',
    'let',
    'link-to',
    'loading',
    'loadingClass',
    'loadingHref',
    'loc',
    'localName',
    'location',
    'log',
    'lookup',
    'lookupDescription',
    'lt',
    'lte',
    'makeArray',
    'makeToString',
    'map',
    'mapBy',
    'match',
    'matches',
    'max',
    'merge',
    'mergedProperties',
    'meta',
    'metadata',
    'metaForProperty',
    'method',
    'min',
    'mixin',
    'model',
    'modelFor',
    'models',
    'mount',
    'mut',
    'name',
    'namespace',
    'nearestOfType',
    'nearestWithProperty',
    'next',
    'none',
    'normalize',
    'normalizeFullName',
    'not',
    'notEmpty',
    'notifyPropertyChange',
    'objectAt',
    'objectAtContent',
    'objectsAt',
    'observeModelType',
    'observer',
    'observes',
    'off',
    'on',
    'once',
    'one',
    'oneWay',
    'onInjectHelpers',
    'onLoad',
    'onUpdateURL',
    'options',
    'optionsForType',
    'or',
    'originalMethods',
    'outlet',
    'ownerInjection',
    'page-title',
    'paramNames',
    'params',
    'paramsFor',
    'parent',
    'parentView',
    'parentViewDidChange',
    'parseName',
    'partial',
    'pattern',
    'pauseTest',
    'popObject',
    'positionalParams',
    'preventDefault',
    'promise',
    'property',
    'pushObject',
    'pushObjects',
    'pushState',
    'query-params',
    'query',
    'queryParams',
    'queryParamsDidChange',
    'queues',
    'race',
    'readDOMAttr',
    'readonly',
    'readOnly',
    'reads',
    'ready',
    'reason',
    'recognize',
    'recognizeAndLoad',
    'recompute',
    'recordsWatchers',
    'redirect',
    'reduce',
    'refresh',
    'register',
    'registerAsyncHelper',
    'registerDeprecationHandler',
    'registerDestructor',
    'registeredActions',
    'registeredOption',
    'registeredOptions',
    'registeredOptionsForType',
    'registerHelper',
    'registerOptions',
    'registerOptionsForType',
    'registerWaiter',
    'registerWarnHandler',
    'registrations',
    'registry',
    'reject',
    'rejectBy',
    'rel',
    'releaseMethods',
    'removeArrayObserver',
    'removeAt',
    'removeListener',
    'removeObject',
    'removeObjects',
    'removeObserver',
    'removeTestHelpers',
    'render',
    'renderTemplate',
    'reopen',
    'reopenClass',
    'replace',
    'replaceContent',
    'replaceRoute',
    'replaceState',
    'replaceURL',
    'replaceWith',
    'rerender',
    'reset',
    'resetController',
    'resolve',
    'resolveController',
    'resolveHelper',
    'resolveModel',
    'resolveOther',
    'resolver',
    'resolveRegistration',
    'resolverFor',
    'resolveRoute',
    'resolveTemplate',
    'resolveView',
    'resumeTest',
    'rethrow',
    'retry',
    'reverseObjects',
    'rootElement',
    'rootURL',
    'route',
    'routeDidChange',
    'routeName',
    'routeWillChange',
    'run',
    'runInDebug',
    'runInitializers',
    'runInstanceInitializers',
    'runLoadHooks',
    'schedule',
    'scheduleOnce',
    'send',
    'sendAction',
    'sendEvent',
    'serialize',
    'serializeQueryParam',
    'serializeQueryParamKey',
    'set',
    'setClassicDecorator',
    'setDiff',
    'setEach',
    'setEngineParent',
    'setHelperManager',
    'setObjects',
    'setOwner',
    'setProperties',
    'setup',
    'setupController',
    'setupForTesting',
    'setupHandler',
    'setupHandlerForBrowserEvent',
    'setupHandlerForEmberEvent',
    'setupRegistry',
    'setURL',
    'shiftObject',
    'shouldRender',
    'size',
    'slice',
    'sort',
    'sortBy',
    'startRouting',
    'store',
    'subscribe',
    'sum',
    'tabindex',
    'tagName',
    'target',
    'teardownViews',
    'templateName',
    'templateOnly',
    'testCheckboxClick',
    'testHelpers',
    'testing',
    'textarea',
    'then',
    'this[RENDER]',
    'throttle',
    'title',
    'to',
    'toArray',
    'toggleProperty',
    'toString',
    'tracked',
    'transitionTo',
    'transitionToRoute',
    'translateToContainerFullname',
    'trigger',
    'triggerAction',
    'triggerEvent',
    'tryInvoke',
    'trySet',
    'type',
    'typeInjection',
    'typeOf',
    'typeWatchers',
    'unbound',
    'underscore',
    'union',
    'uniq',
    'uniqBy',
    'unless',
    'unregister',
    'unregisterDestructor',
    'unregisterHelper',
    'unregisterWaiter',
    'unshiftObject',
    'unshiftObjects',
    'unsubscribe',
    'url',
    'urlFor',
    'userAgent',
    'useRouterNaming',
    'validationCache',
    'value',
    'visit',
    'volatile',
    'w',
    'wait',
    'waitForDOMReady',
    'warn',
    'watchModelTypes',
    'watchRecords',
    'willClearRender',
    'willDestroy',
    'willDestroyElement',
    'willInsertElement',
    'willRender',
    'willTransition',
    'willUpdate',
    'without',
    'wrap',
    'wrapModelType',
    'wrapRecord',
    'yield',
  ],
};
<|endoftext|>


<commit_before>import Ember from 'ember';
import Resolver from './resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';

let App;

Ember.MODEL_FACTORY_INJECTIONS = true;

App = Ember.Application.extend({
  modulePrefix: config.modulePrefix,
  podModulePrefix: config.podModulePrefix,
  Resolver
});

loadInitializers(App, config.modulePrefix);

export default App;
<commit_msg>remove model factory injections from dummy app<commit_after>import Ember from 'ember';
import Resolver from './resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';

let App;

App = Ember.Application.extend({
  modulePrefix: config.modulePrefix,
  podModulePrefix: config.podModulePrefix,
  Resolver
});

loadInitializers(App, config.modulePrefix);

export default App;
<|endoftext|>


<commit_before>describe('News page tests', function () {
  it('should have a title', function () {
    browser.get('http://localhost:8000/#/news');
    expect(browser.getTitle()).toEqual("Stowarzyszenie Chrześcijańsko - Patrytiotyczne Ziemi Włodawskiej");
  });

  it('should filter news list', function () {
    browser.get('http://localhost:8000/#/news');

    var news;
    //start filtering
    element(by.model('query')).sendKeys('w obronie wolnych mediów');
    news = element.all(by.repeater('post in c.posts'));
    expect(news.count()).toEqual(1);

    //clear the filtering
    element(by.model('query')).clear().then(function () {
      news = element.all(by.repeater('post in c.posts'));
      expect(news.count()).toBeGreaterThan(1);
    })

  });

  it('should sort news list', function () {
    browser.get('http://localhost:8000/#/news');

    var select = element(by.model('c.orderMode'));
    select.$('[value="date"]').click().then(function () {
      news = element.all(by.repeater('post in c.posts'));
      expect(news.count()).toBeGreaterThan(1);
    })
  });

});<commit_msg>Integration tests for sorting news<commit_after>describe('News page tests', function () {
  it('should have a title', function () {
    browser.get('http://localhost:8000/#/news');
    expect(browser.getTitle()).toEqual("Stowarzyszenie Chrześcijańsko - Patrytiotyczne Ziemi Włodawskiej");
  });

  it('should filter news list', function () {
    browser.get('http://localhost:8000/#/news');

    var news;
    //start filtering
    element(by.model('query')).sendKeys('w obronie wolnych mediów');
    news = element.all(by.repeater('post in c.posts'));
    expect(news.count()).toEqual(1);

    //clear the filtering
    element(by.model('query')).clear().then(function () {
      news = element.all(by.repeater('post in c.posts'));
      expect(news.count()).toBeGreaterThan(1);
    })

  });

  it('should sort news list from the oldest', function () {
    browser.get('http://localhost:8000/#/news');

    var select = element(by.model('c.orderMode'));
    select.$('[value="date"]').click().then(function () {
      var news = element.all(by.repeater('post in c.posts'));
      var index = 0;
      var oldestDate = news.get(index).element(by.css('.post-meta')).getText();
      expect(oldestDate).toEqual('2013-06-19');
    });
  });

  it('should sort news list from the newest', function () {
    browser.get('http://localhost:8000/#/news');

    var select = element(by.model('c.orderMode'));
    select.$('[value="-date"]').click().then(function () {
      var news = element.all(by.repeater('post in c.posts'));
      news.count().then(function (count) {
        var index = count-1;
        var oldestDate = news.get(index).element(by.css('.post-meta')).getText();
        expect(oldestDate).toEqual('2013-06-19');
      });
    });
  });

});<|endoftext|>


<commit_before>import React from "react"
import cx from "classnames"
import {
  saveList,
  errorList,
  sizeClassNames,
  formGroupCx,
  label,
  inputContainerCx,
} from "../util.js"

export default class Input extends React.Component {
  displayName = "FriggingBootstrap.Input"

  static defaultProps = Object.assign(require("../default_props.js"), {
    // Bootstrap input addon texts
    prefix: undefined,
    suffix: undefined,
    inputWrapper: (inputProps) => <input {...inputProps}/>,
  })

  _inputHtml() {
    return Object.assign({}, this.props.inputHtml, {
      className: cx(this.props.className, "form-control"),
      valueLink: this.props.valueLink,
    })
  }

  _inputPrefix() {
    if (this.props.prefix == null) return ""
    return div({className: "input-group-addon"}, this.props.prefix)
  }

  _input() {
    return this.props.inputWrapper(this._inputHtml())
  }

  _inputSuffix() {
    if (this.props.suffix == null) return ""
    return
{this.props.suffix}

  }

  _inputGroup() {
    let inputLabel = label(this.props)
    let saved = saveList(this.props.saved)

    if (this.props.prefix || this.props.suffix) {
      return [
        inputLabel,

          {this._inputPrefix()}
          {this._input()}
          {saved}
          {this._inputSuffix()}

,
      ]
    }
    else {
      return (

          {inputLabel}
          {this._input()}
          {saved}

      )
    }
  }

  render() {
    return (

            {this._inputGroup()}
            {errorList(this.props.errors)}

    )
  }

}
<commit_msg>add PropTypes to Input<commit_after>import React from "react"
import cx from "classnames"
import {
  saveList,
  errorList,
  sizeClassNames,
  formGroupCx,
  label,
  inputContainerCx,
} from "../util.js"

export default class Input extends React.Component {
  displayName = "FriggingBootstrap.Input"

  static propTypes = {
    inputHtml: React.PropTypes.shape({
      type: React.PropTypes.string.isRequired,
    }).isRequired,
    inputWrapper: React.PropTypes.func.isRequired,

    valueLink: React.PropTypes.shape({
      value: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.number,
        React.PropTypes.bool,
      ]),
      requestChange: React.PropTypes.func,
    }).isRequired,

    className: React.PropTypes.string,
    prefix: React.PropTypes.string,
    suffix: React.PropTypes.string,

    saved: React.PropTypes.bool,
    errors: React.PropTypes.array,
  }

  static defaultProps = Object.assign(require("../default_props.js"), {
    // Bootstrap input addon texts
    prefix: undefined,
    suffix: undefined,
    inputWrapper: (inputProps) => <input {...inputProps}/>,
  })

  _inputHtml() {
    return Object.assign({}, this.props.inputHtml, {
      className: cx(this.props.className, "form-control"),
      valueLink: this.props.valueLink,
    })
  }

  _inputPrefix() {
    if (this.props.prefix == null) return ""
    return div({className: "input-group-addon"}, this.props.prefix)
  }

  _input() {
    return this.props.inputWrapper(this._inputHtml())
  }

  _inputSuffix() {
    if (this.props.suffix == null) return ""
    return
{this.props.suffix}

  }

  _inputGroup() {
    let inputLabel = label(this.props)
    let saved = saveList(this.props.saved)

    if (this.props.prefix || this.props.suffix) {
      return [
        inputLabel,

          {this._inputPrefix()}
          {this._input()}
          {saved}
          {this._inputSuffix()}

,
      ]
    }
    else {
      return (

          {inputLabel}
          {this._input()}
          {saved}

      )
    }
  }

  render() {
    return (

            {this._inputGroup()}
            {errorList(this.props.errors)}

    )
  }

}
<|endoftext|>


<commit_before>import React, { Component , PropTypes} from 'react'
import { sparqlConnect } from '../sparql/configure-sparql'
import { LOADED } from 'sparql-connect'

function AddButton({ disabled, hndlClick, label }) {
  return (

        <button className="form-control btn btn-default btn-sm"
        onClick={e => { e.preventDefault(); hndlClick() }}
        disabled={disabled} >

        {label}
        </button>

  )
}

AddButton.propTypes = {
  disabled: PropTypes.bool.isRequired,
  label: PropTypes.string.isRequired,
  hndlClick: PropTypes.func.isRequired
}

class AddGSIM_ extends Component {
  constructor() {
    super()
    this.state = {
      selected: ''
    }
    this.edit = () => this.setState({
      editing: true
    })
    this.hndlChange = val => this.setState({
      selected: val
    })
    this.ok = () => {
      this.setState({
        editing: false,
        selected: ''
      })
      //TODO fragile (we need to give back uri and label to make
      //`ServiceSubEntities` component work, see prop `uriName` and `label` in
      //`ServiceEditorDetails` call to `ServiceSubEntities`)
      if (!this.entitiesById) this.entitiesById = this.props.GSIMClasses.reduce(
        (_, { GSIMClass, label }) => {
          _[GSIMClass] = {
            label,
            gsimClass: GSIMClass
          }
          return _
        }, {})
      this.props.add(this.entitiesById[this.state.selected])
    }
    this.cancel = () => {
      this.setState({
        editing: false
      })
    }
  }
  render() {
    const { disabled, loaded, GSIMClasses, label } = this.props
    const { selected, editing } = this.state
    if (loaded !== LOADED) return loading...
    if (!editing) return <AddButton
      disabled={disabled} hndlClick={this.edit} label={label} />
    return (

          <select className="form-control" value={selected}
              onChange={ e => this.hndlChange(e.target.value) }>
            <option key='__empty__' value=''></option>
            {
              GSIMClasses.map(({ GSIMClass, label }) =>
                <option key={GSIMClass} value={GSIMClass}>
                  { label }
                </option> )
            }
          </select>

        <button className="small-button btn btn-primary btn-sm pull-right"
            onClick={this.ok} disabled={selected === ''}>
            OK
        </button>
        <button className="small-button btn btn-danger btn-sm pull-right"
            onClick={this.cancel} >
          Cancel
        </button>

    )
  }
}

AddGSIM_.propTypes = {
  add: PropTypes.func.isRequired,
  label: PropTypes.string.isRequired
}

export const AddGSIM = sparqlConnect.GSIMAllClasses(AddGSIM_)

class AddGSBPM_ extends Component {
  constructor() {
    super()
    this.state = {
      selected: ''
    }
    this.edit = () => this.setState({
      editing: true
    })
    this.hndlChange = val => this.setState({
      selected: val
    })
    this.ok = () => {
      this.setState({
        editing: false,
        selected: ''
      })
      //TODO fragile (we need to give back uri and label to make
      //`ServiceSubEntities` component work, see prop `uriName` and `label` in
      //`ServiceEditorDetails` call to `ServiceSubEntities`)
      if (!this.entitiesById) this.entitiesById = this.props.subs.reduce(
        (_, { sub, label }) => {
          _[sub] = {
            label,
            sub
          }
          return _
        }, {})
      this.props.add(this.entitiesById[this.state.selected])
    }
    this.cancel = () => {
      this.setState({
        editing: false
      })
    }
  }
  render() {
    const { disabled, loaded, subs, label } = this.props
    const { selected, editing } = this.state
    if (loaded !== LOADED) return loading...
    if (!editing) return <AddButton
      disabled={disabled} hndlClick={this.edit} label={label} />
    return (

          <select className="form-control" value={selected}
              onChange={ e => this.hndlChange(e.target.value) }>
            <option key='__empty__' value=''></option>
            {
              subs.map(({ sub, label }) =>
                <option key={sub} value={sub}>
                  { label }
                </option> )
            }
          </select>

        <button className="small-button btn btn-primary btn-sm pull-right"
            onClick={this.ok} disabled={selected === ''}>
            OK
        </button>
        <button className="small-button btn btn-danger btn-sm pull-right"
            onClick={this.cancel} >
          Cancel
        </button>

    )
  }
}

AddGSBPM_.propTypes = {
  add: PropTypes.func.isRequired,
  label: PropTypes.string.isRequired
}

export const AddGSBPM = sparqlConnect.subprocesses(AddGSBPM_)
<commit_msg>Make button larger in service details<commit_after>import React, { Component , PropTypes} from 'react'
import { sparqlConnect } from '../sparql/configure-sparql'
import { LOADED } from 'sparql-connect'

function AddButton({ disabled, hndlClick, label }) {
  return (

        <button className="form-control btn btn-default btn-sm"
        onClick={e => { e.preventDefault(); hndlClick() }}
        disabled={disabled} >

        {label}
        </button>

  )
}

AddButton.propTypes = {
  disabled: PropTypes.bool.isRequired,
  label: PropTypes.string.isRequired,
  hndlClick: PropTypes.func.isRequired
}

class AddGSIM_ extends Component {
  constructor() {
    super()
    this.state = {
      selected: ''
    }
    this.edit = () => this.setState({
      editing: true
    })
    this.hndlChange = val => this.setState({
      selected: val
    })
    this.ok = () => {
      this.setState({
        editing: false,
        selected: ''
      })
      //TODO fragile (we need to give back uri and label to make
      //`ServiceSubEntities` component work, see prop `uriName` and `label` in
      //`ServiceEditorDetails` call to `ServiceSubEntities`)
      if (!this.entitiesById) this.entitiesById = this.props.GSIMClasses.reduce(
        (_, { GSIMClass, label }) => {
          _[GSIMClass] = {
            label,
            gsimClass: GSIMClass
          }
          return _
        }, {})
      this.props.add(this.entitiesById[this.state.selected])
    }
    this.cancel = () => {
      this.setState({
        editing: false
      })
    }
  }
  render() {
    const { disabled, loaded, GSIMClasses, label } = this.props
    const { selected, editing } = this.state
    if (loaded !== LOADED) return loading...
    if (!editing) return <AddButton
      disabled={disabled} hndlClick={this.edit} label={label} />
    return (

          <select className="form-control" value={selected}
              onChange={ e => this.hndlChange(e.target.value) }>
            <option key='__empty__' value=''></option>
            {
              GSIMClasses.map(({ GSIMClass, label }) =>
                <option key={GSIMClass} value={GSIMClass}>
                  { label }
                </option> )
            }
          </select>

        <button className="small-button btn btn-primary btn-sm pull-right"
            onClick={this.ok} disabled={selected === ''}>
            OK
        </button>
        <button className="small-button btn btn-danger btn-sm pull-right"
            onClick={this.cancel} >
          Cancel
        </button>

    )
  }
}

AddGSIM_.propTypes = {
  add: PropTypes.func.isRequired,
  label: PropTypes.string.isRequired
}

export const AddGSIM = sparqlConnect.GSIMAllClasses(AddGSIM_)

class AddGSBPM_ extends Component {
  constructor() {
    super()
    this.state = {
      selected: ''
    }
    this.edit = () => this.setState({
      editing: true
    })
    this.hndlChange = val => this.setState({
      selected: val
    })
    this.ok = () => {
      this.setState({
        editing: false,
        selected: ''
      })
      //TODO fragile (we need to give back uri and label to make
      //`ServiceSubEntities` component work, see prop `uriName` and `label` in
      //`ServiceEditorDetails` call to `ServiceSubEntities`)
      if (!this.entitiesById) this.entitiesById = this.props.subs.reduce(
        (_, { sub, label }) => {
          _[sub] = {
            label,
            sub
          }
          return _
        }, {})
      this.props.add(this.entitiesById[this.state.selected])
    }
    this.cancel = () => {
      this.setState({
        editing: false
      })
    }
  }
  render() {
    const { disabled, loaded, subs, label } = this.props
    const { selected, editing } = this.state
    if (loaded !== LOADED) return loading...
    if (!editing) return <AddButton
      disabled={disabled} hndlClick={this.edit} label={label} />
    return (

          <select className="form-control" value={selected}
              onChange={ e => this.hndlChange(e.target.value) }>
            <option key='__empty__' value=''></option>
            {
              subs.map(({ sub, label }) =>
                <option key={sub} value={sub}>
                  { label }
                </option> )
            }
          </select>

        <button className="small-button btn btn-primary btn-sm pull-right"
            onClick={this.ok} disabled={selected === ''}>
            OK
        </button>
        <button className="small-button btn btn-danger btn-sm pull-right"
            onClick={this.cancel} >
          Cancel
        </button>

    )
  }
}

AddGSBPM_.propTypes = {
  add: PropTypes.func.isRequired,
  label: PropTypes.string.isRequired
}

export const AddGSBPM = sparqlConnect.subprocesses(AddGSBPM_)
<|endoftext|>


<commit_before>import classNames from "classnames";
import mixin from "reactjs-mixin";
import { Hooks } from "PluginSDK";
import { Link, routerShape } from "react-router";
import { MountService } from "foundation-ui";
/* eslint-disable no-unused-vars */
import React from "react";
/* eslint-enable no-unused-vars */
import { StoreMixin } from "mesosphere-shared-reactjs";

import FieldAutofocus from "#SRC/js/components/form/FieldAutofocus";
import AlertPanel from "../../components/AlertPanel";
import AlertPanelHeader from "../../components/AlertPanelHeader";
import Breadcrumb from "../../components/Breadcrumb";
import BreadcrumbTextContent from "../../components/BreadcrumbTextContent";
import CosmosErrorMessage from "../../components/CosmosErrorMessage";
import CosmosPackagesStore from "../../stores/CosmosPackagesStore";
import CreateServiceModalCatalogPanelOption
  from "../../components/CreateServiceModalCatalogPanelOption";
import defaultServiceImage
  from "../../../../plugins/services/src/img/icon-service-default-medium@2x.png";
import FilterInputText from "../../components/FilterInputText";
import Image from "../../components/Image";
import Loader from "../../components/Loader";
import Page from "../../components/Page";
import StringUtil from "../../utils/StringUtil";
import CatalogPackageOption from "./CatalogPackageOption";

const PackagesBreadcrumbs = () => {
  const crumbs = [
    <Breadcrumb key={0} title="Catalog">
      <BreadcrumbTextContent>
        <Link to="/catalog/packages">Catalog</Link>
      </BreadcrumbTextContent>
    </Breadcrumb>
  ];

  return <Page.Header.Breadcrumbs iconID="catalog" breadcrumbs={crumbs} />;
};

const METHODS_TO_BIND = ["handleSearchStringChange"];

const shouldRenderCatalogOption = Hooks.applyFilter(
  "hasCapability",
  true,
  "packageAPI"
);

if (shouldRenderCatalogOption) {
  MountService.MountService.registerComponent(
    CreateServiceModalCatalogPanelOption,
    "CreateService:ServicePicker:GridOptions",
    0
  );
}

class PackagesTab extends mixin(StoreMixin) {
  constructor() {
    super();

    this.state = {
      errorMessage: false,
      installModalPackage: null,
      isLoading: true,
      searchString: ""
    };

    this.store_listeners = [
      {
        name: "cosmosPackages",
        events: ["availableError", "availableSuccess"],
        suppressUpdate: true
      }
    ];

    METHODS_TO_BIND.forEach(method => {
      this[method] = this[method].bind(this);
    });
  }

  componentDidMount() {
    super.componentDidMount(...arguments);
    CosmosPackagesStore.fetchAvailablePackages();
  }

  onCosmosPackagesStoreAvailableError(errorMessage) {
    this.setState({ errorMessage });
  }

  onCosmosPackagesStoreAvailableSuccess() {
    this.setState({ errorMessage: false, isLoading: false });
  }

  handleDetailOpen(cosmosPackage, event) {
    event.stopPropagation();
    this.context.router.push({
      pathname: `/catalog/packages/${cosmosPackage.getName()}`,
      query: {
        version: cosmosPackage.getVersion()
      }
    });
  }

  handleSearchStringChange(searchString = "") {
    this.setState({ searchString });
  }

  getErrorScreen() {
    const { errorMessage } = this.state;

    return (
      <AlertPanel>
        <AlertPanelHeader>An Error Occurred</AlertPanelHeader>
        <CosmosErrorMessage error={errorMessage} flushBottom={true} />
      </AlertPanel>
    );
  }

  getIcon(cosmosPackage) {
    return (

        <Image
          fallbackSrc={defaultServiceImage}
          src={cosmosPackage.getIcons()["icon-medium"]}
        />

    );
  }

  getLoadingScreen() {
    return <Loader />;
  }

  getPackageGrid(packages) {
    return packages.getItems().map((cosmosPackage, index) => {
      return (
        <CatalogPackageOption
          image={this.getIcon(cosmosPackage)}
          key={index}
          label={this.getPackageOptionBadge(cosmosPackage)}
          onOptionSelect={this.handleDetailOpen.bind(this, cosmosPackage)}
        >

            {cosmosPackage.getName()}

            {cosmosPackage.getVersion()}

        </CatalogPackageOption>
      );
    });
  }

  getPackageOptionBadge(cosmosPackage) {
    const isCertified = cosmosPackage.isCertified();
    const copy = isCertified ? "Certified" : "Community";
    const classes = classNames("badge", {
      "badge--primary": isCertified
    });

    return {copy};
  }

  getCertifiedPackagesGrid(packages) {
    if (this.state.searchString || packages.getItems().length === 0) {
      return null;
    }

    return (

Certified

          Certified packages are verified by Mesosphere for interoperability with DC/OS.

          {this.getPackageGrid(packages)}

    );
  }

  getCommunityPackagesGrid(packages) {
    if (packages.getItems().length === 0) {
      return null;
    }

    let subtitle = (

        Community packages are unverified and unreviewed content from the community.

    );
    let title = "Community";
    const isSearchActive = this.state.searchString !== "";
    const titleClasses = classNames("flush-top", {
      short: !isSearchActive,
      tall: isSearchActive
    });

    if (isSearchActive) {
      const foundPackagesLength = packages.getItems().length;
      const packagesWord = StringUtil.pluralize("service", foundPackagesLength);

      subtitle = null;
      title = `${packages.getItems().length} ${packagesWord} found`;
    }

    return (

{title}

        {subtitle}

          {this.getPackageGrid(packages)}

    );
  }

  render() {
    const { state } = this;
    let content;

    if (state.errorMessage) {
      content = this.getErrorScreen();
    } else if (state.isLoading) {
      content = this.getLoadingScreen();
    } else {
      const packages = CosmosPackagesStore.getAvailablePackages();
      const splitPackages = packages.getSelectedAndNonSelectedPackages();

      let communityPackages = splitPackages.nonSelectedPackages;
      const selectedPackages = splitPackages.selectedPackages;

      if (state.searchString) {
        communityPackages = packages.filterItemsByText(state.searchString);
      }

      content = (

            <FieldAutofocus>
              <FilterInputText
                className="flex-grow"
                placeholder="Search catalog"
                searchString={state.searchString}
                handleFilterChange={this.handleSearchStringChange}
              />
            </FieldAutofocus>

          {this.getCertifiedPackagesGrid(selectedPackages)}
          {this.getCommunityPackagesGrid(communityPackages)}

      );
    }

    return (
      <Page>
        <Page.Header breadcrumbs={<PackagesBreadcrumbs />} />
        {content}
      </Page>
    );
  }
}

PackagesTab.contextTypes = {
  router: routerShape
};

module.exports = PackagesTab;
<commit_msg>feat(PackagesTab): adds empty state behavior to Packages<commit_after>import classNames from "classnames";
import mixin from "reactjs-mixin";
import { Hooks } from "PluginSDK";
import { Link, routerShape } from "react-router";
import { MountService } from "foundation-ui";
/* eslint-disable no-unused-vars */
import React from "react";
/* eslint-enable no-unused-vars */
import { StoreMixin } from "mesosphere-shared-reactjs";

import FieldAutofocus from "#SRC/js/components/form/FieldAutofocus";
import AlertPanel from "../../components/AlertPanel";
import AlertPanelHeader from "../../components/AlertPanelHeader";
import Breadcrumb from "../../components/Breadcrumb";
import BreadcrumbTextContent from "../../components/BreadcrumbTextContent";
import CosmosErrorMessage from "../../components/CosmosErrorMessage";
import CosmosPackagesStore from "../../stores/CosmosPackagesStore";
import CreateServiceModalCatalogPanelOption
  from "../../components/CreateServiceModalCatalogPanelOption";
import defaultServiceImage
  from "../../../../plugins/services/src/img/icon-service-default-medium@2x.png";
import FilterInputText from "../../components/FilterInputText";
import Image from "../../components/Image";
import Loader from "../../components/Loader";
import Page from "../../components/Page";
import StringUtil from "../../utils/StringUtil";
import CatalogPackageOption from "./CatalogPackageOption";
import MetadataStore from "../../stores/MetadataStore";

const PackagesBreadcrumbs = () => {
  const crumbs = [
    <Breadcrumb key={0} title="Catalog">
      <BreadcrumbTextContent>
        <Link to="/catalog/packages">Catalog</Link>
      </BreadcrumbTextContent>
    </Breadcrumb>
  ];

  return <Page.Header.Breadcrumbs iconID="catalog" breadcrumbs={crumbs} />;
};

const PackagesEmptyState = () => {
  return (
    <AlertPanel>
      <AlertPanelHeader>No package repositories</AlertPanelHeader>

        You need at least one package repository with some packages to be
        able to install packages. For more {" "}
        <Link
          target="_blank"
          to={MetadataStore.buildDocsURI("/administering-clusters/repo")}
        >
          information on repositories
        </Link>
        .

        <Link to="/settings/repositories" className="button button-primary">
          Add Package Repository
        </Link>

    </AlertPanel>
  );
};

const METHODS_TO_BIND = ["handleSearchStringChange"];

const shouldRenderCatalogOption = Hooks.applyFilter(
  "hasCapability",
  true,
  "packageAPI"
);

if (shouldRenderCatalogOption) {
  MountService.MountService.registerComponent(
    CreateServiceModalCatalogPanelOption,
    "CreateService:ServicePicker:GridOptions",
    0
  );
}

class PackagesTab extends mixin(StoreMixin) {
  constructor() {
    super();

    this.state = {
      errorMessage: false,
      installModalPackage: null,
      isLoading: true,
      searchString: ""
    };

    this.store_listeners = [
      {
        name: "cosmosPackages",
        events: ["availableError", "availableSuccess"],
        suppressUpdate: true
      }
    ];

    METHODS_TO_BIND.forEach(method => {
      this[method] = this[method].bind(this);
    });
  }

  componentDidMount() {
    super.componentDidMount(...arguments);
    CosmosPackagesStore.fetchAvailablePackages();
  }

  onCosmosPackagesStoreAvailableError(errorMessage) {
    this.setState({ errorMessage });
  }

  onCosmosPackagesStoreAvailableSuccess() {
    this.setState({ errorMessage: false, isLoading: false });
  }

  handleDetailOpen(cosmosPackage, event) {
    event.stopPropagation();
    this.context.router.push({
      pathname: `/catalog/packages/${cosmosPackage.getName()}`,
      query: {
        version: cosmosPackage.getVersion()
      }
    });
  }

  handleSearchStringChange(searchString = "") {
    this.setState({ searchString });
  }

  getErrorScreen() {
    const { errorMessage } = this.state;

    return (
      <AlertPanel>
        <AlertPanelHeader>An Error Occurred</AlertPanelHeader>
        <CosmosErrorMessage error={errorMessage} flushBottom={true} />
      </AlertPanel>
    );
  }

  getIcon(cosmosPackage) {
    return (

        <Image
          fallbackSrc={defaultServiceImage}
          src={cosmosPackage.getIcons()["icon-medium"]}
        />

    );
  }

  getLoadingScreen() {
    return <Loader />;
  }

  getPackageGrid(packages) {
    return packages.getItems().map((cosmosPackage, index) => {
      return (
        <CatalogPackageOption
          image={this.getIcon(cosmosPackage)}
          key={index}
          label={this.getPackageOptionBadge(cosmosPackage)}
          onOptionSelect={this.handleDetailOpen.bind(this, cosmosPackage)}
        >

            {cosmosPackage.getName()}

            {cosmosPackage.getVersion()}

        </CatalogPackageOption>
      );
    });
  }

  getPackageOptionBadge(cosmosPackage) {
    const isCertified = cosmosPackage.isCertified();
    const copy = isCertified ? "Certified" : "Community";
    const classes = classNames("badge", {
      "badge--primary": isCertified
    });

    return {copy};
  }

  getCertifiedPackagesGrid(packages) {
    if (this.state.searchString || packages.getItems().length === 0) {
      return null;
    }

    return (

Certified

          Certified packages are verified by Mesosphere for interoperability with DC/OS.

          {this.getPackageGrid(packages)}

    );
  }

  getCommunityPackagesGrid(packages) {
    if (packages.getItems().length === 0) {
      return null;
    }

    let subtitle = (

        Community packages are unverified and unreviewed content from the community.

    );
    let title = "Community";
    const isSearchActive = this.state.searchString !== "";
    const titleClasses = classNames("flush-top", {
      short: !isSearchActive,
      tall: isSearchActive
    });

    if (isSearchActive) {
      const foundPackagesLength = packages.getItems().length;
      const packagesWord = StringUtil.pluralize("service", foundPackagesLength);

      subtitle = null;
      title = `${packages.getItems().length} ${packagesWord} found`;
    }

    return (

{title}

        {subtitle}

          {this.getPackageGrid(packages)}

    );
  }

  render() {
    const { state } = this;
    let content;

    if (state.errorMessage) {
      content = this.getErrorScreen();
    } else if (state.isLoading) {
      content = this.getLoadingScreen();
    } else {
      const packages = CosmosPackagesStore.getAvailablePackages();

      if (packages.list == null || packages.list.length === 0) {
        content = <PackagesEmptyState />;
      } else {
        const splitPackages = packages.getSelectedAndNonSelectedPackages();

        let communityPackages = splitPackages.nonSelectedPackages;
        const selectedPackages = splitPackages.selectedPackages;

        if (state.searchString) {
          communityPackages = packages.filterItemsByText(state.searchString);
        }

        content = (

              <FieldAutofocus>
                <FilterInputText
                  className="flex-grow"
                  placeholder="Search catalog"
                  searchString={state.searchString}
                  handleFilterChange={this.handleSearchStringChange}
                />
              </FieldAutofocus>

            {this.getCertifiedPackagesGrid(selectedPackages)}
            {this.getCommunityPackagesGrid(communityPackages)}

        );
      }
    }

    return (
      <Page>
        <Page.Header breadcrumbs={<PackagesBreadcrumbs />} />
        {content}
      </Page>
    );
  }
}

PackagesTab.contextTypes = {
  router: routerShape
};

module.exports = PackagesTab;
<|endoftext|>


<commit_before>/**
 * @fileoverview LineTypeSeriesBase is base class for line type series.
 * @author NHN Ent.
 *         FE Development Lab <dl_javascript@nhnent.com>
 */

'use strict';

var seriesTemplate = require('./seriesTemplate');
var chartConst = require('../const');
var predicate = require('../helpers/predicate');
var renderUtil = require('../helpers/renderUtil');
var Series = require('./series');

var concat = Array.prototype.concat;

/**
 * @classdesc LineTypeSeriesBase is base class for line type series.
 * @class LineTypeSeriesBase
 * @mixin
 */
var LineTypeSeriesBase = tui.util.defineClass(/** @lends LineTypeSeriesBase.prototype */ {
    /**
     * Render series component.
     * @override
     */
    render: function() {
        this.beforeAxes = this.scaleModel.getAxisDataMap();

        return Series.prototype.render.apply(this, arguments);
    },
    /**
     * Make positions for default data type.
     * @param {?number} seriesWidth - width of series area
     * @returns {Array.<Array.<object>>}
     * @private
     */
    _makePositionsForDefaultType: function(seriesWidth) {
        var dimension = this.boundsMaker.getDimension('series');
        var seriesDataModel = this._getSeriesDataModel();
        var width = seriesWidth || dimension.width || 0;
        var height = dimension.height;
        var len = seriesDataModel.getGroupCount();
        var start = chartConst.SERIES_EXPAND_SIZE;
        var step;

        if (this.data.aligned) {
            step = width / (len - 1);
        } else {
            step = width / len;
            start += (step / 2);
        }

        return seriesDataModel.map(function(seriesGroup) {
            return seriesGroup.map(function(seriesItem, index) {
                var position = {
                    left: start + (step * index),
                    top: height - (seriesItem.ratio * height) + chartConst.SERIES_EXPAND_SIZE
                };

                if (tui.util.isExisty(seriesItem.startRatio)) {
                    position.startTop = height - (seriesItem.startRatio * height) + chartConst.SERIES_EXPAND_SIZE;
                }

                return position;
            });
        }, true);
    },

    /**
     * Make positions for coordinate data type.
     * @param {?number} seriesWidth - width of series area
     * @returns {Array.<Array.<object>>}
     * @private
     */
    _makePositionForCoordinateType: function(seriesWidth) {
        var dimension = this.boundsMaker.getDimension('series');
        var seriesDataModel = this._getSeriesDataModel();
        var width = seriesWidth || dimension.width || 0;
        var height = dimension.height;
        var xAxis = this.scaleModel.getAxisDataMap().xAxis;
        var additionalLeft = 0;

        if (xAxis.sizeRatio) {
            additionalLeft = tui.util.multiply(width, xAxis.positionRatio);
            width = tui.util.multiply(width, xAxis.sizeRatio);
        }

        return seriesDataModel.map(function(seriesGroup) {
            return seriesGroup.map(function(seriesItem) {
                var position = {
                    left: (seriesItem.ratioMap.x * width) + additionalLeft + chartConst.SERIES_EXPAND_SIZE,
                    top: height - (seriesItem.ratioMap.y * height) + chartConst.SERIES_EXPAND_SIZE
                };

                if (tui.util.isExisty(seriesItem.ratioMap.start)) {
                    position.startTop = height - (seriesItem.ratioMap.start * height) + chartConst.SERIES_EXPAND_SIZE;
                }

                return position;
            });
        }, true);
    },

    /**
     * Make basic positions for rendering line graph.
     * @param {?number} seriesWidth - width of series area
     * @returns {Array.<Array.<object>>}
     * @private
     */
    _makeBasicPositions: function(seriesWidth) {
        var positions;

        if (this.dataProcessor.isCoordinateType()) {
            positions = this._makePositionForCoordinateType(seriesWidth);
        } else {
            positions = this._makePositionsForDefaultType(seriesWidth);
        }

        return positions;
    },

    /**
     * Calculate label position top.
     * @param {{top: number, startTop: number}} basePosition - base position
     * @param {number} value - value of seriesItem
     * @param {number} labelHeight - label height
     * @param {boolean} isStart - whether start value of seriesItem or not
     * @returns {number} position top
     * @private
     */
    _calculateLabelPositionTop: function(basePosition, value, labelHeight, isStart) {
        var baseTop = basePosition.top,
            top;

        if (predicate.isValidStackOption(this.options.stackType)) {
            top = (basePosition.startTop + baseTop - labelHeight) / 2 + 1;
        } else if ((value >= 0 && !isStart) || (value < 0 && isStart)) {
            top = baseTop - labelHeight - chartConst.SERIES_LABEL_PADDING;
        } else {
            top = baseTop + chartConst.SERIES_LABEL_PADDING;
        }

        return top;
    },

    /**
     * Make label position for rendering label of series area.
     * @param {{left: number, top: number, startTop: ?number}} basePosition - base position for calculating
     * @param {number} labelHeight - label height
     * @param {(string | number)} label - label of seriesItem
     * @param {number} value - value of seriesItem
     * @param {boolean} isStart - whether start label position or not
     * @returns {{left: number, top: number}}
     * @private
     */
    _makeLabelPosition: function(basePosition, labelHeight, label, value, isStart) {
        var labelWidth = renderUtil.getRenderedLabelWidth(label, this.theme.label);
        var dimension = this.boundsMaker.getDimension('extendedSeries');

        return {
            left: (basePosition.left - (labelWidth / 2)) / dimension.width * 100,
            top: this._calculateLabelPositionTop(basePosition, value, labelHeight, isStart) / dimension.height * 100
        };
    },

    /**
     * Make html for series label for line type chart.
     * @param {number} groupIndex - index of seriesDataModel.groups
     * @param {number} index - index of seriesGroup.items
     * @param {SeriesItem} seriesItem - series item
     * @param {number} labelHeight - label height
     * @param {boolean} isStart - whether start label position or not
     * @returns {string}
     * @private
     */
    _makeSeriesLabelHtmlForLineType: function(groupIndex, index, seriesItem, labelHeight, isStart) {
        var basePosition = tui.util.extend({}, this.seriesData.groupPositions[groupIndex][index]),
            label, position;

        if (isStart) {
            label = seriesItem.startLabel;
            basePosition.top = basePosition.startTop;
        } else {
            label = seriesItem.endLabel || seriesItem.label;
        }

        position = this._makeLabelPosition(basePosition, labelHeight, label, seriesItem.value || seriesItem.y, isStart);

        return this._makeSeriesLabelHtml(position, label, groupIndex, seriesTemplate.tplCssTextForLineType, isStart);
    },

    /**
     * Render series label.
     * @param {HTMLElement} elSeriesLabelArea series label area element
     * @private
     */
    _renderSeriesLabel: function(elSeriesLabelArea) {
        var self = this,
            seriesDataModel = this._getSeriesDataModel(),
            firstLabel = seriesDataModel.getFirstItemLabel(),
            labelHeight = renderUtil.getRenderedLabelHeight(firstLabel, this.theme.label),
            htmls;

        htmls = seriesDataModel.map(function(seriesGroup, groupIndex) {
            return seriesGroup.map(function(seriesItem, index) {
                var labelHtml = self._makeSeriesLabelHtmlForLineType(groupIndex, index, seriesItem, labelHeight);

                if (seriesItem.isRange) {
                    labelHtml += self._makeSeriesLabelHtmlForLineType(groupIndex, index, seriesItem, labelHeight, true);
                }

                return labelHtml;
            }).join('');
        }, true);

        elSeriesLabelArea.innerHTML = htmls.join('');
    },

    /**
     * To call showGroupTooltipLine function of graphRenderer.
     * @param {{
     *      dimension: {width: number, height: number},
     *      position: {left: number, top: number}
     * }} bound bound
     */
    onShowGroupTooltipLine: function(bound) {
        if (!this.graphRenderer.showGroupTooltipLine) {
            return;
        }

        this.graphRenderer.showGroupTooltipLine(bound);
    },

    /**
     * To call hideGroupTooltipLine function of graphRenderer.
     */
    onHideGroupTooltipLine: function() {
        if (!this.graphRenderer.hideGroupTooltipLine) {
            return;
        }
        this.graphRenderer.hideGroupTooltipLine();
    },

    /**
     * Zoom by mouse drag.
     * @param {object} data - data
     * @returns {{container: HTMLElement, paper: object}}
     */
    zoom: function(data) {
        var paper;

        this._cancelMovingAnimation();
        this._clearContainer(data.paper);
        paper = this._renderSeriesArea(this.seriesContainer, data, tui.util.bind(this._renderGraph, this));
        this._showGraphWithoutAnimation();

        if (!tui.util.isNull(this.selectedLegendIndex)) {
            this.graphRenderer.selectLegend(this.selectedLegendIndex);
        }

        return {
            container: this.seriesContainer,
            paper: paper
        };
    },

    /**
     * Whether changed or not.
     * @param {{min: number, max: number}} before - before limit
     * @param {{min: number, max: number}} after - after limit
     * @returns {boolean}
     * @private
     */
    _isChangedLimit: function(before, after) {
        return before.min !== after.min || before.max !== after.max;
    },

    /**
     * Whether changed axis limit(min, max) or not.
     * @returns {boolean}
     * @private
     */
    _isChangedAxisLimit: function() {
        var beforeAxes = this.beforeAxes;
        var axisDataMap = this.scaleModel.getAxisDataMap();
        var changed = true;

        this.beforeAxes = axisDataMap;

        if (beforeAxes) {
            changed = this._isChangedLimit(beforeAxes.yAxis.limit, axisDataMap.yAxis.limit);

            if (axisDataMap.xAxis.limit) {
                changed = changed || this._isChangedLimit(beforeAxes.xAxis.limit, axisDataMap.xAxis.limit);
            }
        }

        return changed;
    },

    /**
     * Animate for motion of series area.
     * @param {function} callback - callback function
     * @private
     */
    _animate: function(callback) {
        var self = this;
        var duration = chartConst.ADDING_DATA_ANIMATION_DURATION;
        var changedLimit = this._isChangedAxisLimit();

        if (changedLimit && this.seriesLabelContainer) {
            this.seriesLabelContainer.innerHTML = '';
        }

        if (!callback) {
            return;
        }

        this.movingAnimation = renderUtil.startAnimation(duration, callback, function() {
            self.movingAnimation = null;
        });
    },

    /**
     * Pick first label elements.
     * @returns {Array.<HTMLElement>}
     * @private
     */
    _pickFirstLabelElements: function() {
        var itemCount = this.dataProcessor.getCategoryCount() - 1;
        var seriesLabelContainer = this.seriesLabelContainer;
        var labelElements = seriesLabelContainer.childNodes;
        var filteredElements = [];
        var firstLabelElements;

        tui.util.forEachArray(labelElements, function(element) {
            if (!element.getAttribute('data-range')) {
                filteredElements.push(element);
            }
        });
        filteredElements = tui.util.filter(filteredElements, function(element, index) {
            return ((parseInt(index, 10) + 1) % itemCount) === 1;
        });
        firstLabelElements = tui.util.map(filteredElements, function(element) {
            var nextElement = element.nextSibling;
            var elements = [element];

            if (nextElement && nextElement.getAttribute('data-range')) {
                elements.push(nextElement);
            }

            return elements;
        });

        return concat.apply([], firstLabelElements);
    },

    /**
     * Hide first labels.
     * @private
     */
    _hideFirstLabels: function() {
        var seriesLabelContainer = this.seriesLabelContainer;
        var firsLabelElements;

        if (!seriesLabelContainer) {
            return;
        }

        firsLabelElements = this._pickFirstLabelElements();
        tui.util.forEachArray(firsLabelElements, function(element) {
            seriesLabelContainer.removeChild(element);
        });
    },

    /**
     * Animate for moving of graph container.
     * @param {number} interval - interval for moving
     * @private
     */
    _animateForMoving: function(interval) {
        var graphRenderer = this.graphRenderer;
        var childrenForMoving = this.seriesContainer.childNodes;
        var areaWidth = this.boundsMaker.getDimension('extendedSeries').width;
        var beforeLeft = 0;

        this._hideFirstLabels();

        if (childrenForMoving.length) {
            beforeLeft = parseInt(childrenForMoving[0].style.left, 10) || 0;
        }

        this._animate(function(ratio) {
            var left = interval * ratio;

            tui.util.forEachArray(childrenForMoving, function(child) {
                child.style.left = (beforeLeft - left) + 'px';
            });

            graphRenderer.setSize(areaWidth + left);
        });
    },

    /**
     * Animate for resizing of label container.
     * @param {number} interval - interval for stacking
     * @private
     */
    _animateForResizing: function(interval) {
        var seriesLabelContainer = this.seriesLabelContainer;
        var animateLabel, areaWidth;

        if (!seriesLabelContainer) {
            return;
        }

        areaWidth = this.boundsMaker.getDimension('extendedSeries').width;

        if (!this.dataProcessor.isCoordinateType()) {
            animateLabel = function(ratio) {
                var left = interval * ratio;

                seriesLabelContainer.style.width = (areaWidth - left) + 'px';
            };
        }

        this._animate(animateLabel);
    },

    /**
     * Make top of zero point for adding data.
     * @returns {number}
     * @private
     * @override
     */
    _makeZeroTopForAddingData: function() {
        var seriesHeight = this.boundsMaker.getDimension('series').height;
        var limit = this.scaleModel.getAxisDataMap().yAxis.limit;

        return this._getLimitDistanceFromZeroPoint(seriesHeight, limit).toMax + chartConst.SERIES_EXPAND_SIZE;
    },

    /**
     * Animate for adding data.
     * @param {{tickSize: number}} params - parameters for adding data.
     */
    animateForAddingData: function(params) {
        var seriesData = this._makeSeriesData();
        var dimension = this.boundsMaker.getDimension('extendedSeries');
        var seriesWidth = this.boundsMaker.getDimension('series').width;
        var paramsForRendering = this._makeParamsForGraphRendering(dimension, seriesData);
        var tickSize = params.tickSize;
        var shiftingOption = this.options.shifting;
        var groupPositions, zeroTop;

        if (shiftingOption) {
            seriesWidth += tickSize;
        }

        groupPositions = this._makePositions(seriesWidth);
        zeroTop = this._makeZeroTopForAddingData();

        this.graphRenderer.animateForAddingData(paramsForRendering, tickSize, groupPositions, shiftingOption, zeroTop);

        if (shiftingOption) {
            this._animateForMoving(tickSize);
        } else {
            this._animateForResizing(tickSize);
        }
    },

    /**
     * Cancel moving animation.
     * @private
     */
    _cancelMovingAnimation: function() {
        if (this.movingAnimation) {
            cancelAnimationFrame(this.movingAnimation.id);
            this.movingAnimation = null;
        }
    }
});

LineTypeSeriesBase.mixin = function(func) {
    tui.util.extend(func.prototype, LineTypeSeriesBase.prototype);
};

module.exports = LineTypeSeriesBase;
<commit_msg>fix: Fix not hiding first label, when adding dynamic data<commit_after>/**
 * @fileoverview LineTypeSeriesBase is base class for line type series.
 * @author NHN Ent.
 *         FE Development Lab <dl_javascript@nhnent.com>
 */

'use strict';

var seriesTemplate = require('./seriesTemplate');
var chartConst = require('../const');
var predicate = require('../helpers/predicate');
var renderUtil = require('../helpers/renderUtil');
var Series = require('./series');

var concat = Array.prototype.concat;

/**
 * @classdesc LineTypeSeriesBase is base class for line type series.
 * @class LineTypeSeriesBase
 * @mixin
 */
var LineTypeSeriesBase = tui.util.defineClass(/** @lends LineTypeSeriesBase.prototype */ {
    /**
     * Render series component.
     * @override
     */
    render: function() {
        this.beforeAxes = this.scaleModel.getAxisDataMap();

        return Series.prototype.render.apply(this, arguments);
    },
    /**
     * Make positions for default data type.
     * @param {?number} seriesWidth - width of series area
     * @returns {Array.<Array.<object>>}
     * @private
     */
    _makePositionsForDefaultType: function(seriesWidth) {
        var dimension = this.boundsMaker.getDimension('series');
        var seriesDataModel = this._getSeriesDataModel();
        var width = seriesWidth || dimension.width || 0;
        var height = dimension.height;
        var len = seriesDataModel.getGroupCount();
        var start = chartConst.SERIES_EXPAND_SIZE;
        var step;

        if (this.data.aligned) {
            step = width / (len - 1);
        } else {
            step = width / len;
            start += (step / 2);
        }

        return seriesDataModel.map(function(seriesGroup) {
            return seriesGroup.map(function(seriesItem, index) {
                var position = {
                    left: start + (step * index),
                    top: height - (seriesItem.ratio * height) + chartConst.SERIES_EXPAND_SIZE
                };

                if (tui.util.isExisty(seriesItem.startRatio)) {
                    position.startTop = height - (seriesItem.startRatio * height) + chartConst.SERIES_EXPAND_SIZE;
                }

                return position;
            });
        }, true);
    },

    /**
     * Make positions for coordinate data type.
     * @param {?number} seriesWidth - width of series area
     * @returns {Array.<Array.<object>>}
     * @private
     */
    _makePositionForCoordinateType: function(seriesWidth) {
        var dimension = this.boundsMaker.getDimension('series');
        var seriesDataModel = this._getSeriesDataModel();
        var width = seriesWidth || dimension.width || 0;
        var height = dimension.height;
        var xAxis = this.scaleModel.getAxisDataMap().xAxis;
        var additionalLeft = 0;

        if (xAxis.sizeRatio) {
            additionalLeft = tui.util.multiply(width, xAxis.positionRatio);
            width = tui.util.multiply(width, xAxis.sizeRatio);
        }

        return seriesDataModel.map(function(seriesGroup) {
            return seriesGroup.map(function(seriesItem) {
                var position = {
                    left: (seriesItem.ratioMap.x * width) + additionalLeft + chartConst.SERIES_EXPAND_SIZE,
                    top: height - (seriesItem.ratioMap.y * height) + chartConst.SERIES_EXPAND_SIZE
                };

                if (tui.util.isExisty(seriesItem.ratioMap.start)) {
                    position.startTop = height - (seriesItem.ratioMap.start * height) + chartConst.SERIES_EXPAND_SIZE;
                }

                return position;
            });
        }, true);
    },

    /**
     * Make basic positions for rendering line graph.
     * @param {?number} seriesWidth - width of series area
     * @returns {Array.<Array.<object>>}
     * @private
     */
    _makeBasicPositions: function(seriesWidth) {
        var positions;

        if (this.dataProcessor.isCoordinateType()) {
            positions = this._makePositionForCoordinateType(seriesWidth);
        } else {
            positions = this._makePositionsForDefaultType(seriesWidth);
        }

        return positions;
    },

    /**
     * Calculate label position top.
     * @param {{top: number, startTop: number}} basePosition - base position
     * @param {number} value - value of seriesItem
     * @param {number} labelHeight - label height
     * @param {boolean} isStart - whether start value of seriesItem or not
     * @returns {number} position top
     * @private
     */
    _calculateLabelPositionTop: function(basePosition, value, labelHeight, isStart) {
        var baseTop = basePosition.top,
            top;

        if (predicate.isValidStackOption(this.options.stackType)) {
            top = (basePosition.startTop + baseTop - labelHeight) / 2 + 1;
        } else if ((value >= 0 && !isStart) || (value < 0 && isStart)) {
            top = baseTop - labelHeight - chartConst.SERIES_LABEL_PADDING;
        } else {
            top = baseTop + chartConst.SERIES_LABEL_PADDING;
        }

        return top;
    },

    /**
     * Make label position for rendering label of series area.
     * @param {{left: number, top: number, startTop: ?number}} basePosition - base position for calculating
     * @param {number} labelHeight - label height
     * @param {(string | number)} label - label of seriesItem
     * @param {number} value - value of seriesItem
     * @param {boolean} isStart - whether start label position or not
     * @returns {{left: number, top: number}}
     * @private
     */
    _makeLabelPosition: function(basePosition, labelHeight, label, value, isStart) {
        var labelWidth = renderUtil.getRenderedLabelWidth(label, this.theme.label);
        var dimension = this.boundsMaker.getDimension('extendedSeries');

        return {
            left: (basePosition.left - (labelWidth / 2)) / dimension.width * 100,
            top: this._calculateLabelPositionTop(basePosition, value, labelHeight, isStart) / dimension.height * 100
        };
    },

    /**
     * Make html for series label for line type chart.
     * @param {number} groupIndex - index of seriesDataModel.groups
     * @param {number} index - index of seriesGroup.items
     * @param {SeriesItem} seriesItem - series item
     * @param {number} labelHeight - label height
     * @param {boolean} isStart - whether start label position or not
     * @returns {string}
     * @private
     */
    _makeSeriesLabelHtmlForLineType: function(groupIndex, index, seriesItem, labelHeight, isStart) {
        var basePosition = tui.util.extend({}, this.seriesData.groupPositions[groupIndex][index]),
            label, position;

        if (isStart) {
            label = seriesItem.startLabel;
            basePosition.top = basePosition.startTop;
        } else {
            label = seriesItem.endLabel || seriesItem.label;
        }

        position = this._makeLabelPosition(basePosition, labelHeight, label, seriesItem.value || seriesItem.y, isStart);

        return this._makeSeriesLabelHtml(position, label, groupIndex, seriesTemplate.tplCssTextForLineType, isStart);
    },

    /**
     * Render series label.
     * @param {HTMLElement} elSeriesLabelArea series label area element
     * @private
     */
    _renderSeriesLabel: function(elSeriesLabelArea) {
        var self = this,
            seriesDataModel = this._getSeriesDataModel(),
            firstLabel = seriesDataModel.getFirstItemLabel(),
            labelHeight = renderUtil.getRenderedLabelHeight(firstLabel, this.theme.label),
            htmls;

        htmls = seriesDataModel.map(function(seriesGroup, groupIndex) {
            return seriesGroup.map(function(seriesItem, index) {
                var labelHtml = self._makeSeriesLabelHtmlForLineType(groupIndex, index, seriesItem, labelHeight);

                if (seriesItem.isRange) {
                    labelHtml += self._makeSeriesLabelHtmlForLineType(groupIndex, index, seriesItem, labelHeight, true);
                }

                return labelHtml;
            }).join('');
        }, true);

        elSeriesLabelArea.innerHTML = htmls.join('');
    },

    /**
     * To call showGroupTooltipLine function of graphRenderer.
     * @param {{
     *      dimension: {width: number, height: number},
     *      position: {left: number, top: number}
     * }} bound bound
     */
    onShowGroupTooltipLine: function(bound) {
        if (!this.graphRenderer.showGroupTooltipLine) {
            return;
        }

        this.graphRenderer.showGroupTooltipLine(bound);
    },

    /**
     * To call hideGroupTooltipLine function of graphRenderer.
     */
    onHideGroupTooltipLine: function() {
        if (!this.graphRenderer.hideGroupTooltipLine) {
            return;
        }
        this.graphRenderer.hideGroupTooltipLine();
    },

    /**
     * Zoom by mouse drag.
     * @param {object} data - data
     * @returns {{container: HTMLElement, paper: object}}
     */
    zoom: function(data) {
        var paper;

        this._cancelMovingAnimation();
        this._clearContainer(data.paper);
        paper = this._renderSeriesArea(this.seriesContainer, data, tui.util.bind(this._renderGraph, this));
        this._showGraphWithoutAnimation();

        if (!tui.util.isNull(this.selectedLegendIndex)) {
            this.graphRenderer.selectLegend(this.selectedLegendIndex);
        }

        return {
            container: this.seriesContainer,
            paper: paper
        };
    },

    /**
     * Whether changed or not.
     * @param {{min: number, max: number}} before - before limit
     * @param {{min: number, max: number}} after - after limit
     * @returns {boolean}
     * @private
     */
    _isChangedLimit: function(before, after) {
        return before.min !== after.min || before.max !== after.max;
    },

    /**
     * Whether changed axis limit(min, max) or not.
     * @returns {boolean}
     * @private
     */
    _isChangedAxisLimit: function() {
        var beforeAxes = this.beforeAxes;
        var axisDataMap = this.scaleModel.getAxisDataMap();
        var changed = true;

        this.beforeAxes = axisDataMap;

        if (beforeAxes) {
            changed = this._isChangedLimit(beforeAxes.yAxis.limit, axisDataMap.yAxis.limit);

            if (axisDataMap.xAxis.limit) {
                changed = changed || this._isChangedLimit(beforeAxes.xAxis.limit, axisDataMap.xAxis.limit);
            }
        }

        return changed;
    },

    /**
     * Animate for motion of series area.
     * @param {function} callback - callback function
     * @private
     */
    _animate: function(callback) {
        var self = this;
        var duration = chartConst.ADDING_DATA_ANIMATION_DURATION;
        var changedLimit = this._isChangedAxisLimit();

        if (changedLimit && this.seriesLabelContainer) {
            this.seriesLabelContainer.innerHTML = '';
        }

        if (!callback) {
            return;
        }

        this.movingAnimation = renderUtil.startAnimation(duration, callback, function() {
            self.movingAnimation = null;
        });
    },

    /**
     * Pick first label elements.
     * @returns {Array.<HTMLElement>}
     * @private
     */
    _pickFirstLabelElements: function() {
        var itemCount = this.dataProcessor.getCategoryCount();
        var seriesLabelContainer = this.seriesLabelContainer;
        var labelElements = seriesLabelContainer.childNodes;
        var filteredElements = [];
        var firstLabelElements;

        tui.util.forEachArray(labelElements, function(element) {
            if (!element.getAttribute('data-range')) {
                filteredElements.push(element);
            }
        });
        filteredElements = tui.util.filter(filteredElements, function(element, index) {
            return ((parseInt(index, 10) + 1) % itemCount) === 1;
        });
        firstLabelElements = tui.util.map(filteredElements, function(element) {
            var nextElement = element.nextSibling;
            var elements = [element];

            if (nextElement && nextElement.getAttribute('data-range')) {
                elements.push(nextElement);
            }

            return elements;
        });

        return concat.apply([], firstLabelElements);
    },

    /**
     * Hide first labels.
     * @private
     */
    _hideFirstLabels: function() {
        var seriesLabelContainer = this.seriesLabelContainer;
        var firsLabelElements;

        if (!seriesLabelContainer) {
            return;
        }

        firsLabelElements = this._pickFirstLabelElements();
        tui.util.forEachArray(firsLabelElements, function(element) {
            seriesLabelContainer.removeChild(element);
        });
    },

    /**
     * Animate for moving of graph container.
     * @param {number} interval - interval for moving
     * @private
     */
    _animateForMoving: function(interval) {
        var graphRenderer = this.graphRenderer;
        var childrenForMoving = this.seriesContainer.childNodes;
        var areaWidth = this.boundsMaker.getDimension('extendedSeries').width;
        var beforeLeft = 0;

        this._hideFirstLabels();

        if (childrenForMoving.length) {
            beforeLeft = parseInt(childrenForMoving[0].style.left, 10) || 0;
        }

        this._animate(function(ratio) {
            var left = interval * ratio;

            tui.util.forEachArray(childrenForMoving, function(child) {
                child.style.left = (beforeLeft - left) + 'px';
            });

            graphRenderer.setSize(areaWidth + left);
        });
    },

    /**
     * Animate for resizing of label container.
     * @param {number} interval - interval for stacking
     * @private
     */
    _animateForResizing: function(interval) {
        var seriesLabelContainer = this.seriesLabelContainer;
        var animateLabel, areaWidth;

        if (!seriesLabelContainer) {
            return;
        }

        areaWidth = this.boundsMaker.getDimension('extendedSeries').width;

        if (!this.dataProcessor.isCoordinateType()) {
            animateLabel = function(ratio) {
                var left = interval * ratio;

                seriesLabelContainer.style.width = (areaWidth - left) + 'px';
            };
        }

        this._animate(animateLabel);
    },

    /**
     * Make top of zero point for adding data.
     * @returns {number}
     * @private
     * @override
     */
    _makeZeroTopForAddingData: function() {
        var seriesHeight = this.boundsMaker.getDimension('series').height;
        var limit = this.scaleModel.getAxisDataMap().yAxis.limit;

        return this._getLimitDistanceFromZeroPoint(seriesHeight, limit).toMax + chartConst.SERIES_EXPAND_SIZE;
    },

    /**
     * Animate for adding data.
     * @param {{tickSize: number}} params - parameters for adding data.
     */
    animateForAddingData: function(params) {
        var seriesData = this._makeSeriesData();
        var dimension = this.boundsMaker.getDimension('extendedSeries');
        var seriesWidth = this.boundsMaker.getDimension('series').width;
        var paramsForRendering = this._makeParamsForGraphRendering(dimension, seriesData);
        var tickSize = params.tickSize;
        var shiftingOption = this.options.shifting;
        var groupPositions, zeroTop;

        if (shiftingOption) {
            seriesWidth += tickSize;
        }

        groupPositions = this._makePositions(seriesWidth);
        zeroTop = this._makeZeroTopForAddingData();

        this.graphRenderer.animateForAddingData(paramsForRendering, tickSize, groupPositions, shiftingOption, zeroTop);

        if (shiftingOption) {
            this._animateForMoving(tickSize);
        } else {
            this._animateForResizing(tickSize);
        }
    },

    /**
     * Cancel moving animation.
     * @private
     */
    _cancelMovingAnimation: function() {
        if (this.movingAnimation) {
            cancelAnimationFrame(this.movingAnimation.id);
            this.movingAnimation = null;
        }
    }
});

LineTypeSeriesBase.mixin = function(func) {
    tui.util.extend(func.prototype, LineTypeSeriesBase.prototype);
};

module.exports = LineTypeSeriesBase;
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var TagMatcher = require('./tag-matcher');

// types and their default display counts
var MEDIA_TYPES = {
    image: 3,
    text: 1,
    video: 1,
    audio: 1
};

var DEFAULT_STATIC_DISPLAY_DURATION = 10;

function RandomScenePlayer (elementManager) {
    var queue;

    this._playing = false;

    this._elementManager = elementManager;

    // default tag matching to all
    this._tagMatcher = new TagMatcher();

    this._scene = undefined;

    // contains arrays keyed by mediaObject type.  These are the random
    // generated lists of assets to display
    this._displayQueue = {};

    // total number of active items being displayed
    this._typeCounts = {};

    this.setMediaObjectQueue = function(newQueue) {
        queue = newQueue;
    }
}

function incrementTypeCount (self, type) {
    if (self._typeCounts[type]) {
        self._typeCounts[type] += 1;
    } else {
        self._typeCounts[type] = 1;
    }
}

function decrementTypeCount (self, type) {
    self._typeCounts[type] -= 1;
}

function getTypeCount(self, type) {
    return self._typeCounts[type] || 0;
}

function filterMediaScene(mediaScene, tagMatcher, mediaType) {
    return _.filter(mediaScene.scene, function (obj) {
        return (! mediaType || obj.type === mediaType) && tagMatcher.match(obj.tags);
    });
}

function parseTagString (tagString) {
    return _.uniq(_.map(tagString.split(','), function(s) { return s.trim(); }));
}

function getMaximumTypeCount(scene, type) {
    var maximum,
        defaultCount = MEDIA_TYPES[type];
    // wrap in try catch incase attribute is missing from the json
    try {
        maximum = parseInt(scene.maximumOnScreen[type]);
    } catch (e) {
        if (e instanceof TypeError) {
            // do nothing, this just means there is no specified maximumOnScreen object in the scene
            // we just go with the default then
        } else {
            throw e;
        }
    } finally {
        if (isNaN(maximum)){
            maximum = defaultCount;
        }
        return maximum;
    }
}

function getStaticMediaTypeDisplayDuration (scene, mediaObject) {
    // be gentle on the poor user, parse their ints
    var duration = parseInt(scene.displayDuration);

    if (isNaN(duration)) {
        duration = DEFAULT_STATIC_DISPLAY_DURATION;
    }

    return duration;
}

// handles intelligent per type behavior for mediaObjects, dispatching to the proper methods for
// their display
function showElementsOfType (self, mediaObjectType) {
    var displayDuration;
    var obj = nextMediaObject(self, mediaObjectType);

    if (obj) {
        incrementTypeCount(self, mediaObjectType);
        switch(mediaObjectType) {
            case 'image':
                displayDuration = getStaticMediaTypeDisplayDuration(self._scene, obj) * 1000;
                self._elementManager.showImage(obj.url, displayDuration, function() {
                    decrementTypeCount(self, mediaObjectType);
                    showElementsOfType(self, mediaObjectType);
                });
                break;

            case 'text':
                displayDuration = getStaticMediaTypeDisplayDuration(self._scene, obj) * 1000;
                self._elementManager.showText(obj.text, displayDuration, function() {
                    decrementTypeCount(self, mediaObjectType);
                    showElementsOfType(self, mediaObjectType);
                });
                break;

            case 'video':
                displayDuration = 3 * 1000;
                self._elementManager.playVideo(obj.url, obj.volume || 0, function() {
                    decrementTypeCount(self, mediaObjectType);
                    showElementsOfType(self, mediaObjectType);
                });
                break;

            case 'audio':
                displayDuration = 3 * 1000;
                self._elementManager.playAudio(obj.url, obj.volume || 100, function() {
                    decrementTypeCount(self, mediaObjectType);
                    showElementsOfType(self, mediaObjectType);
                });
        }

        // guess the duration to wait based on how many could be shown and for how long
        var wait = displayDuration / getMaximumTypeCount(self._scene, mediaObjectType);
        setTimeout(function() {
            showElementsOfType(self, mediaObjectType);
        }, wait);
    }
}

// if there's room in the scene,
// return the next media object from the _displayQueue.  Refill the queue if needed
function nextMediaObject (self, type) {
    if (getTypeCount(self, type) < getMaximumTypeCount(self._scene, type)) {
        var value = self._displayQueue[type];
        if (Array.isArray(value) && value.length > 0) {
            return value.pop();
        } else {
            // regenerate the list
            regenerateDisplayQueue(self, type);
            return self._displayQueue[type].pop();
        }
    }

}

function regenerateDisplayQueue (self, type) {
    // body...
    self._displayQueue[type] = filterMediaScene(self._scene, self._tagMatcher, type);
}

RandomScenePlayer.prototype.setScene = function(newScene) {
    var scene = _.cloneDeep(newScene);

    // best to parse the tag string up front, rather than every time a new media object is selected
    _.forEach(scene.scene, function(mediaObject) {
        mediaObject.tags = parseTagString(mediaObject.tags);
    });

    this._scene = scene;

    if (this._playing) {
        this._showNewMedia();
    }
};

RandomScenePlayer.prototype.setTagMatcher = function(newTagMatcher) {
    if (! this._tagMatcher.equalTo(newTagMatcher) ) {
        this._tagMatcher = newTagMatcher;
        // clearing existing queues will force it to regenerate with new tags
        this._displayQueue = {};
    }
};

RandomScenePlayer.prototype._showNewMedia = function() {
    _.chain(MEDIA_TYPES).keys().forEach(function(type) {
        showElementsOfType(this, type);
    }.bind(this));
    // showStaticElements(this, 'image');
    // showStaticElements(this, 'text');
    // showNewVideo(this);
};

RandomScenePlayer.prototype.start = function() {
    if (! this._playing) {
        this._playing = true;

        this._showNewMedia();
    }
};

module.exports = RandomScenePlayer;<commit_msg>refactor random-scene-player to use crockford style private methods<commit_after>'use strict';

var _ = require('lodash');
var TagMatcher = require('./tag-matcher');

// types and their default display counts
var MEDIA_TYPES = {
    image: 3,
    text: 1,
    video: 1,
    audio: 1
};

var DEFAULT_STATIC_DISPLAY_DURATION = 10;

function RandomScenePlayer (newElementManager) {
    var queue,
        scene,
        playing = false,
        elementManager = newElementManager,
        tagMatcher = new TagMatcher(),
        displayQueue = {},
        // total number of active items being displayed
        typeCounts = {};

    function showNewMedia () {
        _.chain(MEDIA_TYPES).keys().forEach(function(type) {
            showElementsOfType(type);
        });
    }

    // handles intelligent per type behavior for mediaObjects, dispatching to the proper methods for
    // their display
    function showElementsOfType (mediaObjectType) {
        var displayDuration;
        var obj = nextMediaObject(mediaObjectType);

        if (obj) {
            incrementTypeCount(mediaObjectType);
            switch(mediaObjectType) {
                case 'image':
                    displayDuration = getStaticMediaTypeDisplayDuration(scene, obj) * 1000;
                    elementManager.showImage(obj.url, displayDuration, function() {
                        decrementTypeCount(mediaObjectType);
                        showElementsOfType(mediaObjectType);
                    });
                    break;

                case 'text':
                    displayDuration = getStaticMediaTypeDisplayDuration(scene, obj) * 1000;
                    elementManager.showText(obj.text, displayDuration, function() {
                        decrementTypeCount(mediaObjectType);
                        showElementsOfType(mediaObjectType);
                    });
                    break;

                case 'video':
                    displayDuration = 3 * 1000;
                    elementManager.playVideo(obj.url, obj.volume || 0, function() {
                        decrementTypeCount(mediaObjectType);
                        showElementsOfType(mediaObjectType);
                    });
                    break;

                case 'audio':
                    displayDuration = 3 * 1000;
                    elementManager.playAudio(obj.url, obj.volume || 100, function() {
                        decrementTypeCount(mediaObjectType);
                        showElementsOfType(mediaObjectType);
                    });
            }

            // guess the duration to wait based on how many could be shown and for how long
            var wait = displayDuration / getMaximumTypeCount(mediaObjectType);
            setTimeout(function() {
                showElementsOfType(mediaObjectType);
            }, wait);
        }
    }

    function incrementTypeCount (type) {
        if (typeCounts[type]) {
            typeCounts[type] += 1;
        } else {
            typeCounts[type] = 1;
        }
    }

    function decrementTypeCount (type) {
        typeCounts[type] -= 1;
    }

    function getTypeCount(type) {
        return typeCounts[type] || 0;
    }

    function filterMediaScene(tagMatcher, mediaType) {
        return _.filter(scene.scene, function (obj) {
            return (! mediaType || obj.type === mediaType) && tagMatcher.match(obj.tags);
        });
    }

    // if there's room in the scene,
    // return the next media object from the _displayQueue.  Refill the queue if needed
    function nextMediaObject (type) {
        if (getTypeCount(type) < getMaximumTypeCount(type)) {
            var value = displayQueue[type];
            if (Array.isArray(value) && value.length > 0) {
                return value.pop();
            } else {
                // regenerate the list
                regenerateDisplayQueue(type);
                return displayQueue[type].pop();
            }
        }

    }

    function regenerateDisplayQueue (type) {
        displayQueue[type] = filterMediaScene(tagMatcher, type);
    }

    function parseTagString (tagString) {
        return _.uniq(_.map(tagString.split(','), function(s) { return s.trim(); }));
    }

    function getMaximumTypeCount(type) {
        var maximum,
            defaultCount = MEDIA_TYPES[type];
        // wrap in try catch incase attribute is missing from the json
        try {
            maximum = parseInt(scene.maximumOnScreen[type]);
        } catch (e) {
            if (e instanceof TypeError) {
                // do nothing, this just means there is no specified maximumOnScreen object in the scene
                // we just go with the default then
            } else {
                throw e;
            }
        } finally {
            if (isNaN(maximum)){
                maximum = defaultCount;
            }
            return maximum;
        }
    }

    function getStaticMediaTypeDisplayDuration (mediaObject) {
        // be gentle on the poor user, parse their ints
        var duration = parseInt(scene.displayDuration);

        if (isNaN(duration)) {
            duration = DEFAULT_STATIC_DISPLAY_DURATION;
        }

        return duration;
    }

    this.setMediaObjectQueue = function(newQueue) {
        queue = newQueue;
    };

    this.setScene = function(newScene) {
        scene = _.cloneDeep(newScene);

        // best to parse the tag string up front, rather than every time a new media object is selected
        _.forEach(scene.scene, function(mediaObject) {
            mediaObject.tags = parseTagString(mediaObject.tags);
        });

        if (playing) {
            showNewMedia();
        }
    };

    this.setTagMatcher = function(newTagMatcher) {
        if (! tagMatcher.equalTo(newTagMatcher) ) {
            tagMatcher = newTagMatcher;
            // clearing existing queues will force it to regenerate with new tags
            displayQueue = {};
        }
    };

    this.start = function() {
        if (! playing) {
            playing = true;

            showNewMedia();
        }
    };

}

module.exports = RandomScenePlayer;<|endoftext|>