<commit_before>'use strict';

ngRouteModule.directive('ngView', ngViewFactory);
ngRouteModule.directive('ngView', ngViewFillContentFactory);

/**
 * @ngdoc directive
 * @name ngView
 * @restrict ECA
 *
 * @description
 * # Overview
 * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
 * including the rendered template of the current route into the main layout (`index.html`) file.
 * Every time the current route changes, the included view changes with it according to the
 * configuration of the `$route` service.
 *
 * Requires the {@link ngRoute `ngRoute`} module to be installed.
 *
 * @animations
 * enter - animation is used to bring new content into the browser.
 * leave - animation is used to animate existing content away.
 *
 * The enter and leave animation occur concurrently.
 *
 * @scope
 * @priority 400
 * @param {string=} onload Expression to evaluate whenever the view updates.
 *
 * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
 *                  $anchorScroll} to scroll the viewport after the view is updated.
 *
 *                  - If the attribute is not set, disable scrolling.
 *                  - If the attribute is set without value, enable scrolling.
 *                  - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
 *                    as an expression yields a truthy value.
 * @example
    <example name="ngView-directive" module="ngViewExample"
             deps="angular-route.js;angular-animate.js"
             animations="true" fixBase="true">
      <file name="index.html">

          Choose:
          Moby |
          Moby: Ch1 |
          Gatsby |
          Gatsby: Ch4 |
          Scarlet Letter

$location.path() = {{main.$location.path()}}

$route.current.templateUrl = {{main.$route.current.templateUrl}}

$route.current.params = {{main.$route.current.params}}

$route.current.scope.name = {{main.$route.current.scope.name}}

$routeParams = {{main.$routeParams}}

      </file>

      <file name="book.html">

          controller: {{book.name}}

          Book Id: {{book.params.bookId}}

      </file>

      <file name="chapter.html">

          controller: {{chapter.name}}

          Book Id: {{chapter.params.bookId}}

          Chapter Id: {{chapter.params.chapterId}}

      </file>

      <file name="animations.css">
        .view-animate-container {
          position:relative;
          height:100px!important;
          position:relative;
          background:white;
          border:1px solid black;
          height:40px;
          overflow:hidden;
        }

        .view-animate {
          padding:10px;
        }

        .view-animate.ng-enter, .view-animate.ng-leave {
          -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
          transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;

          display:block;
          width:100%;
          border-left:1px solid black;

          position:absolute;
          top:0;
          left:0;
          right:0;
          bottom:0;
          padding:10px;
        }

        .view-animate.ng-enter {
          left:100%;
        }
        .view-animate.ng-enter.ng-enter-active {
          left:0;
        }
        .view-animate.ng-leave.ng-leave-active {
          left:-100%;
        }
      </file>

      <file name="script.js">
        angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
          .config(['$routeProvider', '$locationProvider',
            function($routeProvider, $locationProvider) {
              $routeProvider
                .when('/Book/:bookId', {
                  templateUrl: 'book.html',
                  controller: 'BookCtrl',
                  controllerAs: 'book'
                })
                .when('/Book/:bookId/ch/:chapterId', {
                  templateUrl: 'chapter.html',
                  controller: 'ChapterCtrl',
                  controllerAs: 'chapter'
                });

              // configure html5 to get links working on jsfiddle
              $locationProvider.html5Mode(true);
          }])
          .controller('MainCtrl', ['$route', '$routeParams', '$location',
            function($route, $routeParams, $location) {
              this.$route = $route;
              this.$location = $location;
              this.$routeParams = $routeParams;
          }])
          .controller('BookCtrl', ['$routeParams', function($routeParams) {
            this.name = "BookCtrl";
            this.params = $routeParams;
          }])
          .controller('ChapterCtrl', ['$routeParams', function($routeParams) {
            this.name = "ChapterCtrl";
            this.params = $routeParams;
          }]);

      </file>

      <file name="protractor.js" type="protractor">
        it('should load and compile correct template', function() {
          element(by.linkText('Moby: Ch1')).click();
          var content = element(by.css('[ng-view]')).getText();
          expect(content).toMatch(/controller\: ChapterCtrl/);
          expect(content).toMatch(/Book Id\: Moby/);
          expect(content).toMatch(/Chapter Id\: 1/);

          element(by.partialLinkText('Scarlet')).click();

          content = element(by.css('[ng-view]')).getText();
          expect(content).toMatch(/controller\: BookCtrl/);
          expect(content).toMatch(/Book Id\: Scarlet/);
        });
      </file>
    </example>
 */

/**
 * @ngdoc event
 * @name ngView#$viewContentLoaded
 * @eventType emit on the current ngView scope
 * @description
 * Emitted every time the ngView content is reloaded.
 */
ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
function ngViewFactory(   $route,   $anchorScroll,   $animate) {
  return {
    restrict: 'ECA',
    terminal: true,
    priority: 400,
    transclude: 'element',
    link: function(scope, $element, attr, ctrl, $transclude) {
        var currentScope,
            currentElement,
            previousElement,
            autoScrollExp = attr.autoscroll,
            onloadExp = attr.onload || '';

        scope.$on('$routeChangeSuccess', update);
        update();

        function cleanupLastView() {
          if(previousElement) {
            previousElement.remove();
            previousElement = null;
          }
          if(currentScope) {
            currentScope.$destroy();
            currentScope = null;
          }
          if(currentElement) {
            $animate.leave(currentElement, function() {
              previousElement = null;
            });
            previousElement = currentElement;
            currentElement = null;
          }
        }

        function update() {
          var locals = $route.current && $route.current.locals,
              template = locals && locals.$template;

          if (angular.isDefined(template)) {
            var newScope = scope.$new();
            var current = $route.current;

            // Note: This will also link all children of ng-view that were contained in the original
            // html. If that content contains controllers, ... they could pollute/change the scope.
            // However, using ng-view on an element with additional content does not make sense...
            // Note: We can't remove them in the cloneAttchFn of $transclude as that
            // function is called before linking the content, which would apply child
            // directives to non existing elements.
            var clone = $transclude(newScope, function(clone) {
              $animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
                if (angular.isDefined(autoScrollExp)
                  && (!autoScrollExp || scope.$eval(autoScrollExp))) {
                  $anchorScroll();
                }
              });
              cleanupLastView();
            });

            currentElement = clone;
            currentScope = current.scope = newScope;
            currentScope.$emit('$viewContentLoaded');
            currentScope.$eval(onloadExp);
          } else {
            cleanupLastView();
          }
        }
    }
  };
}

// This directive is called during the $transclude call of the first `ngView` directive.
// It will replace and compile the content of the element with the loaded template.
// We need this directive so that the element content is already filled when
// the link function of another directive on the same element as ngView
// is called.
ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
function ngViewFillContentFactory($compile, $controller, $route) {
  return {
    restrict: 'ECA',
    priority: -400,
    link: function(scope, $element) {
      var current = $route.current,
          locals = current.locals;

      $element.html(locals.$template);

      var link = $compile($element.contents());

      if (current.controller) {
        locals.$scope = scope;
        var controller = $controller(current.controller, locals);
        if (current.controllerAs) {
          scope[current.controllerAs] = controller;
        }
        $element.data('$ngControllerController', controller);
        $element.children().data('$ngControllerController', controller);
      }

      link(scope);
    }
  };
}
<commit_msg>docs(ngView): remove reference to scope<commit_after>'use strict';

ngRouteModule.directive('ngView', ngViewFactory);
ngRouteModule.directive('ngView', ngViewFillContentFactory);

/**
 * @ngdoc directive
 * @name ngView
 * @restrict ECA
 *
 * @description
 * # Overview
 * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
 * including the rendered template of the current route into the main layout (`index.html`) file.
 * Every time the current route changes, the included view changes with it according to the
 * configuration of the `$route` service.
 *
 * Requires the {@link ngRoute `ngRoute`} module to be installed.
 *
 * @animations
 * enter - animation is used to bring new content into the browser.
 * leave - animation is used to animate existing content away.
 *
 * The enter and leave animation occur concurrently.
 *
 * @scope
 * @priority 400
 * @param {string=} onload Expression to evaluate whenever the view updates.
 *
 * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
 *                  $anchorScroll} to scroll the viewport after the view is updated.
 *
 *                  - If the attribute is not set, disable scrolling.
 *                  - If the attribute is set without value, enable scrolling.
 *                  - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
 *                    as an expression yields a truthy value.
 * @example
    <example name="ngView-directive" module="ngViewExample"
             deps="angular-route.js;angular-animate.js"
             animations="true" fixBase="true">
      <file name="index.html">

          Choose:
          Moby |
          Moby: Ch1 |
          Gatsby |
          Gatsby: Ch4 |
          Scarlet Letter

$location.path() = {{main.$location.path()}}

$route.current.templateUrl = {{main.$route.current.templateUrl}}

$route.current.params = {{main.$route.current.params}}

$routeParams = {{main.$routeParams}}

      </file>

      <file name="book.html">

          controller: {{book.name}}

          Book Id: {{book.params.bookId}}

      </file>

      <file name="chapter.html">

          controller: {{chapter.name}}

          Book Id: {{chapter.params.bookId}}

          Chapter Id: {{chapter.params.chapterId}}

      </file>

      <file name="animations.css">
        .view-animate-container {
          position:relative;
          height:100px!important;
          position:relative;
          background:white;
          border:1px solid black;
          height:40px;
          overflow:hidden;
        }

        .view-animate {
          padding:10px;
        }

        .view-animate.ng-enter, .view-animate.ng-leave {
          -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
          transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;

          display:block;
          width:100%;
          border-left:1px solid black;

          position:absolute;
          top:0;
          left:0;
          right:0;
          bottom:0;
          padding:10px;
        }

        .view-animate.ng-enter {
          left:100%;
        }
        .view-animate.ng-enter.ng-enter-active {
          left:0;
        }
        .view-animate.ng-leave.ng-leave-active {
          left:-100%;
        }
      </file>

      <file name="script.js">
        angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
          .config(['$routeProvider', '$locationProvider',
            function($routeProvider, $locationProvider) {
              $routeProvider
                .when('/Book/:bookId', {
                  templateUrl: 'book.html',
                  controller: 'BookCtrl',
                  controllerAs: 'book'
                })
                .when('/Book/:bookId/ch/:chapterId', {
                  templateUrl: 'chapter.html',
                  controller: 'ChapterCtrl',
                  controllerAs: 'chapter'
                });

              // configure html5 to get links working on jsfiddle
              $locationProvider.html5Mode(true);
          }])
          .controller('MainCtrl', ['$route', '$routeParams', '$location',
            function($route, $routeParams, $location) {
              this.$route = $route;
              this.$location = $location;
              this.$routeParams = $routeParams;
          }])
          .controller('BookCtrl', ['$routeParams', function($routeParams) {
            this.name = "BookCtrl";
            this.params = $routeParams;
          }])
          .controller('ChapterCtrl', ['$routeParams', function($routeParams) {
            this.name = "ChapterCtrl";
            this.params = $routeParams;
          }]);

      </file>

      <file name="protractor.js" type="protractor">
        it('should load and compile correct template', function() {
          element(by.linkText('Moby: Ch1')).click();
          var content = element(by.css('[ng-view]')).getText();
          expect(content).toMatch(/controller\: ChapterCtrl/);
          expect(content).toMatch(/Book Id\: Moby/);
          expect(content).toMatch(/Chapter Id\: 1/);

          element(by.partialLinkText('Scarlet')).click();

          content = element(by.css('[ng-view]')).getText();
          expect(content).toMatch(/controller\: BookCtrl/);
          expect(content).toMatch(/Book Id\: Scarlet/);
        });
      </file>
    </example>
 */

/**
 * @ngdoc event
 * @name ngView#$viewContentLoaded
 * @eventType emit on the current ngView scope
 * @description
 * Emitted every time the ngView content is reloaded.
 */
ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
function ngViewFactory(   $route,   $anchorScroll,   $animate) {
  return {
    restrict: 'ECA',
    terminal: true,
    priority: 400,
    transclude: 'element',
    link: function(scope, $element, attr, ctrl, $transclude) {
        var currentScope,
            currentElement,
            previousElement,
            autoScrollExp = attr.autoscroll,
            onloadExp = attr.onload || '';

        scope.$on('$routeChangeSuccess', update);
        update();

        function cleanupLastView() {
          if(previousElement) {
            previousElement.remove();
            previousElement = null;
          }
          if(currentScope) {
            currentScope.$destroy();
            currentScope = null;
          }
          if(currentElement) {
            $animate.leave(currentElement, function() {
              previousElement = null;
            });
            previousElement = currentElement;
            currentElement = null;
          }
        }

        function update() {
          var locals = $route.current && $route.current.locals,
              template = locals && locals.$template;

          if (angular.isDefined(template)) {
            var newScope = scope.$new();
            var current = $route.current;

            // Note: This will also link all children of ng-view that were contained in the original
            // html. If that content contains controllers, ... they could pollute/change the scope.
            // However, using ng-view on an element with additional content does not make sense...
            // Note: We can't remove them in the cloneAttchFn of $transclude as that
            // function is called before linking the content, which would apply child
            // directives to non existing elements.
            var clone = $transclude(newScope, function(clone) {
              $animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
                if (angular.isDefined(autoScrollExp)
                  && (!autoScrollExp || scope.$eval(autoScrollExp))) {
                  $anchorScroll();
                }
              });
              cleanupLastView();
            });

            currentElement = clone;
            currentScope = current.scope = newScope;
            currentScope.$emit('$viewContentLoaded');
            currentScope.$eval(onloadExp);
          } else {
            cleanupLastView();
          }
        }
    }
  };
}

// This directive is called during the $transclude call of the first `ngView` directive.
// It will replace and compile the content of the element with the loaded template.
// We need this directive so that the element content is already filled when
// the link function of another directive on the same element as ngView
// is called.
ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
function ngViewFillContentFactory($compile, $controller, $route) {
  return {
    restrict: 'ECA',
    priority: -400,
    link: function(scope, $element) {
      var current = $route.current,
          locals = current.locals;

      $element.html(locals.$template);

      var link = $compile($element.contents());

      if (current.controller) {
        locals.$scope = scope;
        var controller = $controller(current.controller, locals);
        if (current.controllerAs) {
          scope[current.controllerAs] = controller;
        }
        $element.data('$ngControllerController', controller);
        $element.children().data('$ngControllerController', controller);
      }

      link(scope);
    }
  };
}
<|endoftext|>


<commit_before>import { Flex, IconButton } from '@hackclub/design-system'
import styled from 'styled-components'

export const SendForm = Flex.withComponent('form').extend`
  position: relative;
  z-index: 4;

  > div:first-child,
  > label:first-child {
    flex: 1 1 auto;
    margin-bottom: 0;
  }
`
SendForm.defaultProps = {
  align: 'flex-end',
  w: 1
}

export const SendButton = styled(IconButton)`
  box-shadow: ${({ theme }) => theme.boxShadows[0]} !important;
  transition: ${({ theme }) => theme.transition} box-shadow;
  &:hover,
  &:focus {
    box-shadow: ${({ theme }) => theme.boxShadows[1]} !important;
  }
`
SendButton.defaultProps = {
  type: 'submit',
  color: 'white',
  size: 20,
  ml: 3
}
<commit_msg>Add PropTypes to SendButton<commit_after>import { Flex, IconButton } from '@hackclub/design-system'
import styled from 'styled-components'
import PropTypes from 'prop-types'

export const SendForm = Flex.withComponent('form').extend`
  position: relative;
  z-index: 4;

  > div:first-child,
  > label:first-child {
    flex: 1 1 auto;
    margin-bottom: 0;
  }
`
SendForm.defaultProps = {
  align: 'flex-end',
  width: 1
}

export const SendButton = styled(IconButton)`
  box-shadow: ${({ theme }) => theme.boxShadows[0]} !important;
  transition: ${({ theme }) => theme.transition} box-shadow;
  &:hover,
  &:focus {
    box-shadow: ${({ theme }) => theme.boxShadows[1]} !important;
  }
`
SendButton.propTypes = {
  type: PropTypes.string,
  color: PropTypes.string,
  glyph: PropTypes.string,
  size: PropTypes.number
}
SendButton.defaultProps = {
  type: 'submit',
  color: 'white',
  glyph: 'send',
  size: 20,
  ml: 3
}
<|endoftext|>


<commit_before>import pump from 'pump'
import through from 'through2'
import styled from 'styled-components'
import React from 'react'
import {ipcRenderer} from 'electron'

import MapEditor from './MapEditor'
import replicate from '../lib/replicate'
import Form from './Form'
import View from './View'
import i18n from '../lib/i18n'

var SyncViewDiv = styled.div`
  text-align: center;
  max-width: 900px;
  margin: auto;
`

// turn the messages into strings once
// so the function isn't called for every row
var messages = {
  'replication-data-complete': i18n('replication-data-complete'),
  'replication-started': i18n('replication-started'),
  'replication-complete': i18n('replication-complete'),
  'replication-progress': i18n('replication-progress'),
  'replication-ready': i18n('sync-database-lead')
}

export default class SyncView extends React.Component {
  constructor (props) {
    super(props)
    var ready = 'replication-ready'
    this.state = {
      message: messages[ready],
      status: ready,
      targets: []
    }
  }

  onClose () {
    this.props.changeView(MapEditor)
  }

  onError (err) {
    this.setState({
      message: 'Error: ' + err.message,
      status: 'replication-error'
    })
  }

  replicate (target) {
    var self = this
    if (!target) return
    this.destroyed = false
    this.stream = replicate.start(target)
    pump(this.stream, through.obj(function (data, enc, next) {
      if (self.destroyed) return
      var row = JSON.parse(data)
      var status = row.topic
      if (status === 'replication-error') return this.onError(new Error(row.message))
      var message = messages[status] || row.message
      self.setState({message, status})
      next()
    }), done)

    function done (err) {
      if (err) console.error(err)
    }
  }

  componentWillUnmount () {
    this.destroyed = true
    this.stream.destroy()
    clearInterval(this.interval)
    ipcRenderer.removeListener('select-file', this.selectFile.bind(this))
  }

  selectFile (event, filename) {
    if (!filename) return
    this.replicate({filename})
  }

  componentDidMount () {
    this.interval = setInterval(this.updateTargets.bind(this), 1000)
    ipcRenderer.on('select-file', this.selectFile.bind(this))
  }

  updateTargets () {
    var self = this
    replicate.getTargets(function (err, targets) {
      if (err) return self.onError(err)
      targets = JSON.parse(targets)
      self.setState({targets})
    })
  }

  selectExisting (event) {
    event.preventDefault()
    ipcRenderer.send('open-file')
  }

  selectNew (event) {
    event.preventDefault()
    ipcRenderer.send('save-file')
  }

  render () {
    var {message, status, targets} = this.state
    const {filename} = this.props
    if (filename && status === 'replication-ready') this.selectFile(filename)

    return (
      <View>
        <SyncViewDiv>

{message}

          {status === 'replication-ready' && (

                  {targets.map(function (t) {
                    return
{t.name}

                  })}

              <Form method='POST'>

                  <input type='hidden' name='source' />
                  <button className='big' onClick={this.selectNew}>
                    {i18n('sync-database-new-button')}…
                  </button>
                  <button className='big' onClick={this.selectExisting}>
                    {i18n('sync-database-open-button')}…
                  </button>

              </Form>

          )}
          {status === 'replication-complete' && (

              <button className='big' onClick={this.onClose.bind(this)}> OK</button>

          )}
        </SyncViewDiv>
      </View>
    )
  }
}
<commit_msg>add basic sync with network view<commit_after>import pump from 'pump'
import through from 'through2'
import styled from 'styled-components'
import React from 'react'
import {ipcRenderer} from 'electron'

import MapEditor from './MapEditor'
import replicate from '../lib/replicate'
import Form from './Form'
import View from './View'
import i18n from '../lib/i18n'

var SyncViewDiv = styled.div`
  text-align: center;
  max-width: 900px;
  margin: auto;
`

// turn the messages into strings once
// so the function isn't called for every row
var messages = {
  'replication-data-complete': i18n('replication-data-complete'),
  'replication-started': i18n('replication-started'),
  'replication-complete': i18n('replication-complete'),
  'replication-progress': i18n('replication-progress'),
  'replication-ready': i18n('sync-database-lead')
}

export default class SyncView extends React.Component {
  constructor (props) {
    super(props)
    var ready = 'replication-ready'
    this.state = {
      message: messages[ready],
      status: ready,
      targets: []
    }
  }

  onClose () {
    this.props.changeView(MapEditor)
  }

  onError (err) {
    this.setState({
      message: 'Error: ' + err.message,
      status: 'replication-error'
    })
  }

  replicate (target) {
    var self = this
    if (!target) return
    this.destroyed = false
    this.stream = replicate.start(target)
    this.stream.on('data', function (data) {
      if (self.destroyed) return
      var row = JSON.parse(data)
      var status = row.topic
      if (status === 'replication-error') return this.onError(new Error(row.message))
      var message = messages[status] || row.message
      self.setState({message, status})
    })

    this.stream.on('error', function (err) {
      if (err) console.error(err)
    })
  }

  componentWillUnmount () {
    this.destroyed = true
    if (this.stream) this.stream.destroy()
    clearInterval(this.interval)
    ipcRenderer.removeListener('select-file', this.selectFile.bind(this))
  }

  selectFile (event, filename) {
    if (!filename) return
    this.replicate({filename})
  }

  componentDidMount () {
    this.interval = setInterval(this.updateTargets.bind(this), 1000)
    ipcRenderer.on('select-file', this.selectFile.bind(this))
  }

  updateTargets () {
    var self = this
    replicate.getTargets(function (err, targets) {
      if (err) return self.onError(err)
      targets = JSON.parse(targets)
      self.setState({targets})
    })
  }

  selectExisting (event) {
    event.preventDefault()
    ipcRenderer.send('open-file')
  }

  selectNew (event) {
    event.preventDefault()
    ipcRenderer.send('save-file')
  }

  render () {
    var self = this
    var {message, status, targets} = this.state
    const {filename} = this.props
    if (filename && status === 'replication-ready') this.selectFile(filename)

    return (
      <View>
        <SyncViewDiv>

{message}

          {status === 'replication-ready' && (

                  {targets.map(function (t) {
                    return (

                        {t.name} <button onClick={self.replicate.bind(self, t)}>Sync</button>

                    )
                  })}

              <Form method='POST'>

                  <input type='hidden' name='source' />
                  <button className='big' onClick={this.selectNew}>
                    {i18n('sync-database-new-button')}…
                  </button>
                  <button className='big' onClick={this.selectExisting}>
                    {i18n('sync-database-open-button')}…
                  </button>

              </Form>

          )}
          {status === 'replication-complete' && (

              <button className='big' onClick={this.onClose.bind(this)}> OK</button>

          )}
        </SyncViewDiv>
      </View>
    )
  }
}
<|endoftext|>


<commit_before>define(['scripts/modules/Mediator', 'scripts/modules/PubSub', 'scripts/modules/StorageModule'],
  function(Mediator, PubSub, Storage){
    //NOTE: Game Object is Mocked -- see test/mocks and test-main.js
    'use strict';

    describe('Mediator', function(){
      describe('constructor', function(){
        var mediator;
        beforeEach(function(){
          mediator = new Mediator();
        });

        afterEach(function(){
          mediator = undefined;
        });

        it('should create a new Mediator object', function(){
          expect(typeof mediator).toBe('object');
        });
      });
      describe('Events', function(){
        var mediator;
        beforeEach(function(){
          mediator = new Mediator();
          spyOn(PubSub, 'publish');
        });

        afterEach(function(){
          mediator = undefined;
        });

        describe('When App:Start occurs', function(){
          describe('and no game exists', function(){
            beforeEach(function(){
              localStorage.clear();
              mediator.appInit();
            });

            it('should create a new StateRegistry', function(){
              expect(mediator.stateRegistry).toBeDefined();
            });

            it('should transition to Home State', function(){
              expect(PubSub.publish).toHaveBeenCalledWith('transition', 'Home');
            });
          });

          describe('and a saved game exists', function(){
            var game, state;
            beforeEach(function(){
              game = {};
              state = 'Draw';
              spyOn(Storage, 'loadGame').and.returnValue({game:game, state:state});
              mediator.appInit();
            });

            it('it should set the game', function(){
              expect(mediator.game).toBeDefined();
            });

            it('should go to the loaded State', function(){
              expect(PubSub.publish).toHaveBeenCalledWith('transition', 'Draw');
            });
          });
        });

        describe('When Game:Start occurs', function(){
          beforeEach(function(){
            mediator.startGame();
          });

          it('should create a new game', function(){
            expect(mediator.game).toBeDefined();
          });

          it('should create a new StateRegistry', function(){
            expect(mediator.stateRegistry).toBeDefined();
          });

          it('should proceed to Draw State', function(){
            expect(PubSub.publish).toHaveBeenCalledWith('transition', 'Draw');
          });
        });

        describe('When Game:Continue occurs', function(){
          var data;
          beforeEach(function(){
            data = {game:{}, state: 'Draw'};
            spyOn(Storage, 'loadGame').and.returnValue(data);
            mediator.continueGame();
          });

          it('should load the game', function(){
            expect(Storage.loadGame).toHaveBeenCalled();
          });

          it('should transitionTo the loaded state', function(){
            expect(PubSub.publish).toHaveBeenCalledWith('transition', 'Draw');
          });
        });

        describe('When Game:TransitionTo occurs', function(){
          var state;
          beforeEach(function(){
            jasmine.clock().install();
            state = {init:jasmine.createSpy('init')};
            mediator.startGame();
            spyOn(mediator.stateRegistry, 'initState').and.returnValue(state);
          });

          afterEach(function(){
            jasmine.clock().uninstall();
          });

          describe('and the transition should wait', function(){
            beforeEach(function(){
              mediator.transitionTo('Draw', true);
            });

            it('should wait one second before transitioning', function(){
              expect(mediator.stateRegistry.initState).not.toHaveBeenCalled();
              jasmine.clock().tick(1001);
              expect(mediator.stateRegistry.initState).toHaveBeenCalledWith('Draw', mediator.game);
            });

            it('should initialize the loaded state', function(){
              expect(state.init).not.toHaveBeenCalled();
              jasmine.clock().tick(1001);
              expect(state.init).toHaveBeenCalled();
            });
          });

          describe('and the transition should not wait', function(){
            beforeEach(function(){
              mediator.transitionTo('Draw');
            });

            it('should load the requested state', function(){
              expect(mediator.stateRegistry.initState).toHaveBeenCalledWith('Draw', mediator.game);
            });

            it('should initialize the loaded state', function(){
              expect(state.init).toHaveBeenCalled();
            });
          });
        });

        describe('When Game:Save occurs', function(){
          beforeEach(function(){
            spyOn(Storage, 'saveGame');
          });

          describe('and the game exists', function(){
            var game, state;
            beforeEach(function(){
              game = {};
              state = 'Draw';
              mediator.startGame();
              mediator.saveGame(game, state);
            });

            it('should save the game', function(){
              expect(Storage.saveGame).toHaveBeenCalledWith(state, game);
            });
          });

          describe('and the game doesn\'t exist', function(){
            beforeEach(function(){
              mediator.saveGame('Draw', undefined);
            });

            it('should not save the game', function(){
              expect(Storage.saveGame).not.toHaveBeenCalled();
            });
          });
        });

        describe('When Game:Winner occurs', function(){
          var player;
          beforeEach(function(){
            player = {};
            mediator.startGame();
            mediator.setWinner(player);
          });

          it('should set the games winner', function(){
            expect(mediator.game.winner).toBe(player);
          });
        });

        describe('When Messages:Set occurs', function(){
          describe('and the message is new', function(){
            beforeEach(function(){
              mediator.startGame();
              mediator.setMessages('Testing');
            });

            it('should store the new message', function(){
              expect(mediator.game.$messages.length).toBe(1);
              expect(mediator.game.$messages[0]).toBe('Testing');
            });
          });

          describe('and the message already exists', function(){
            var message;
            beforeEach(function(){
              message = 'Testing';
              mediator.startGame();
              mediator.setMessages(message);
            });

            it('should not not the message again', function(){
              mediator.setMessages(message);
              expect(mediator.game.$messages.length).toBe(1);
              expect(mediator.game.$messages[0]).toBe('Testing');
              expect(mediator.game.$messages[1]).not.toBeDefined();
            });
          });
        });

        describe('When Messages:Clear occurs', function(){
          beforeEach(function(){
            mediator.startGame();
            mediator.setMessages('Testing');
          });

          it('should empty the messages array', function(){
            expect(mediator.game.$messages.length).toBe(1);
            mediator.clearMessages();
            expect(mediator.game.$messages.length).toBe(0);
          });
        });

        describe('When Board:Clear occurs', function(){
          beforeEach(function(){
            mediator.startGame();
            mediator.clearBoard();
          });

          it('should clear the games board', function(){
            expect(mediator.game.$board.clearBoard).toHaveBeenCalled();
            expect(mediator.game.$board.clearBoard.calls.count()).toEqual(2);
          });
        });
      });
    });
  });
<commit_msg>fix test<commit_after>define(['scripts/modules/Mediator', 'scripts/modules/PubSub', 'scripts/modules/StorageModule'],
  function(Mediator, PubSub, Storage){
    //NOTE: Game Object is Mocked -- see test/mocks and test-main.js
    'use strict';

    describe('Mediator', function(){
      describe('constructor', function(){
        var mediator;
        beforeEach(function(){
          mediator = new Mediator();
        });

        afterEach(function(){
          mediator = undefined;
        });

        it('should create a new Mediator object', function(){
          expect(typeof mediator).toBe('object');
        });
      });
      describe('Events', function(){
        var mediator;
        beforeEach(function(){
          mediator = new Mediator();
          spyOn(PubSub, 'publish');
        });

        afterEach(function(){
          mediator = undefined;
        });

        describe('When App:Start occurs', function(){
          describe('and no game exists', function(){
            beforeEach(function(){
              localStorage.clear();
              mediator.appInit();
            });

            it('should create a new StateRegistry', function(){
              expect(mediator.stateRegistry).toBeDefined();
            });

            it('should transition to Home State', function(){
              expect(PubSub.publish).toHaveBeenCalledWith('transition', 'Home');
            });
          });

          describe('and a saved game exists', function(){
            var game, state;
            beforeEach(function(){
              game = {};
              state = 'Draw';
              spyOn(Storage, 'loadGame').and.returnValue({game:game, state:state});
              mediator.appInit();
            });

            it('it should set the game', function(){
              expect(mediator.game).toBeDefined();
            });

            it('should go to the loaded State', function(){
              expect(PubSub.publish).toHaveBeenCalledWith('transition', 'Draw');
            });
          });
        });

        describe('When Game:Start occurs', function(){
          beforeEach(function(){
            mediator.startGame();
          });

          it('should create a new game', function(){
            expect(mediator.game).toBeDefined();
          });

          it('should create a new StateRegistry', function(){
            expect(mediator.stateRegistry).toBeDefined();
          });

          it('should proceed to Draw State', function(){
            expect(PubSub.publish).toHaveBeenCalledWith('transition', 'Draw');
          });
        });

        describe('When Game:Continue occurs', function(){
          var data;
          beforeEach(function(){
            data = {game:{}, state: 'Draw'};
            spyOn(Storage, 'loadGame').and.returnValue(data);
            mediator.continueGame();
          });

          it('should load the game', function(){
            expect(Storage.loadGame).toHaveBeenCalled();
          });

          it('should transitionTo the loaded state', function(){
            expect(PubSub.publish).toHaveBeenCalledWith('transition', 'Draw');
          });
        });

        describe('When Game:TransitionTo occurs', function(){
          var state;
          beforeEach(function(){
            jasmine.clock().install();
            state = {init:jasmine.createSpy('init')};
            mediator.startGame();
            spyOn(mediator.stateRegistry, 'initState').and.returnValue(state);
          });

          afterEach(function(){
            jasmine.clock().uninstall();
          });

          describe('and the transition should wait', function(){
            beforeEach(function(){
              mediator.transitionTo('Draw', true);
            });

            it('should wait one second before transitioning', function(){
              expect(mediator.stateRegistry.initState).not.toHaveBeenCalled();
              jasmine.clock().tick(1001);
              expect(mediator.stateRegistry.initState).toHaveBeenCalledWith('Draw', mediator.game);
            });

            it('should initialize the loaded state', function(){
              expect(state.init).not.toHaveBeenCalled();
              jasmine.clock().tick(1001);
              expect(state.init).toHaveBeenCalled();
            });
          });

          describe('and the transition should not wait', function(){
            beforeEach(function(){
              mediator.transitionTo('Draw');
            });

            it('should load the requested state', function(){
              expect(mediator.stateRegistry.initState).toHaveBeenCalledWith('Draw', mediator.game);
            });

            it('should initialize the loaded state', function(){
              expect(state.init).toHaveBeenCalled();
            });
          });
        });

        describe('When Game:Save occurs', function(){
          beforeEach(function(){
            spyOn(Storage, 'saveGame');
          });

          describe('and the game exists', function(){
            var game, state;
            beforeEach(function(){
              game = {};
              state = 'Draw';
              mediator.startGame();
              mediator.saveGame(game, state);
            });

            it('should save the game', function(){
              expect(Storage.saveGame).toHaveBeenCalledWith(state, game);
            });
          });

          describe('and the game doesn\'t exist', function(){
            beforeEach(function(){
              mediator.saveGame('Home', undefined);
            });

            it('should not save the game', function(){
              expect(Storage.saveGame).not.toHaveBeenCalled();
            });
          });
        });

        describe('When Game:Winner occurs', function(){
          var player;
          beforeEach(function(){
            player = {};
            mediator.startGame();
            mediator.setWinner(player);
          });

          it('should set the games winner', function(){
            expect(mediator.game.winner).toBe(player);
          });
        });

        describe('When Messages:Set occurs', function(){
          describe('and the message is new', function(){
            beforeEach(function(){
              mediator.startGame();
              mediator.setMessages('Testing');
            });

            it('should store the new message', function(){
              expect(mediator.game.$messages.length).toBe(1);
              expect(mediator.game.$messages[0]).toBe('Testing');
            });
          });

          describe('and the message already exists', function(){
            var message;
            beforeEach(function(){
              message = 'Testing';
              mediator.startGame();
              mediator.setMessages(message);
            });

            it('should not not the message again', function(){
              mediator.setMessages(message);
              expect(mediator.game.$messages.length).toBe(1);
              expect(mediator.game.$messages[0]).toBe('Testing');
              expect(mediator.game.$messages[1]).not.toBeDefined();
            });
          });
        });

        describe('When Messages:Clear occurs', function(){
          beforeEach(function(){
            mediator.startGame();
            mediator.setMessages('Testing');
          });

          it('should empty the messages array', function(){
            expect(mediator.game.$messages.length).toBe(1);
            mediator.clearMessages();
            expect(mediator.game.$messages.length).toBe(0);
          });
        });

        describe('When Board:Clear occurs', function(){
          beforeEach(function(){
            mediator.startGame();
            mediator.clearBoard();
          });

          it('should clear the games board', function(){
            expect(mediator.game.$board.clearBoard).toHaveBeenCalled();
            expect(mediator.game.$board.clearBoard.calls.count()).toEqual(2);
          });
        });
      });
    });
  });
<|endoftext|>


<commit_before>import Rx from 'rxjs/Rx';

import React from 'react';

import key from 'keymaster';

import {
  createCommOpenMessage,
  createCommMessage,
} from './comm';

import {
  createCellAfter,
  createCellBefore,
  createCellAppend,
} from '../actions';

import Popup from 'react-popup';

import {
  TelluriumError,
} from '../middlewares';

import * as uuid from 'uuid';

export function convertFileEpic(action$, store) {
  return action$.ofType('CONVERT_FILE')
    .map((action) => {
      const state = store.getState();
      const channels = state.app.channels;
      if (!channels || !channels.iopub || !channels.shell) {
        throw new Error('kernel not connected');
      }

      const identity = uuid.v4();

      const source_format = action.filetype === 'python' ? 'python' : action.filetype === 'sbml' ? 'antimony' :
        action.filetype === 'omex' ? 'omex' : action.filetype === 'cellml' ? 'cellml' :
        () => {throw new TelluriumError('Source filetype not recognized.', 'ERROR IMPORTING ARCHIVE')};
      let target_format = action.filetype === 'python' ? 'python' : action.filetype === 'sbml' ? 'antimony' :
        action.filetype === 'omex' ? 'omex' : action.filetype === 'cellml' ? 'antimony' :
        () => {throw new TelluriumError('Source filetype not recognized.', 'ERROR IMPORTING ARCHIVE')};

      const commOpen = createCommOpenMessage(identity, 'convert_file_comm', {target_format: source_format, path: action.path});
      const childMessages = channels.iopub.childOf(commOpen);

      channels.shell.next(commOpen);
      return childMessages
        .ofMessageType(['comm_msg'])
        .map((message) => {
          if (message.content.data.status === 'error') {
            const notificationSystem = state.app.get('notificationSystem');
            // notificationSystem.addNotification({
            //   title: message.content.data.error,
            //   autoDismiss: 4,
            //   level: 'error',
            // });
            if (source_format === 'antimony') {
              throw new TelluriumError(message.content.data.error, 'ERROR IMPORTING SBML');
            } else {
              throw new TelluriumError(message.content.data.error, 'ERROR IMPORTING ARCHIVE');
            }
            // return Rx.Observable.throw(new Error('Unable to import archive.'));
            // return Rx.Observable.of({
            //   type: ERROR_GENERAL,
            //   payload: message.content.data.error,
            //   error: true,
            // });
          }
          // no error - add cells to notebook
          const cells = message.content.data.content.cells;
          if (cells) {
            if (cells.length === 0) {
              throw new TelluriumError('Failed to import any COMBINE archive entries', 'ERROR IMPORTING ARCHIVE');
            }
            if (cells.length > 1) {
              throw new TelluriumError('Multiple cells returned - operation not supported', 'ERROR IMPORTING ARCHIVE');
            }
            const cell = cells[0];
            // for combine archives containing only SBML
            if (cell.type === 'antimony') {
              target_format = 'antimony';
            }
            if (action.id) {
              // we have a cell id
              if (action.position === 'below') {
                return createCellAfter(target_format, action.id, cell.source)
              } else if (action.position === 'above') {
                return createCellBefore(target_format, action.id, cell.source)
              }
            } else {
              // we don't have a cell id - just append to end
              return createCellAppend(target_format, cell.source)
            }
          } else {
            throw new TelluriumError('Could not import file - internal error', 'ERROR IMPORTING ARCHIVE');
          }
        });
    })
    .mergeAll();
}

// used for saving non-notebook files
export function saveFileEpic(action$, store) {
  return action$.ofType('SAVE_FILE_FROM_STRING')
    .map((action) => {
      const state = store.getState();
      const channels = state.app.channels;
      if (!channels || !channels.iopub || !channels.shell) {
        throw new Error('kernel not connected');
      }

      const identity = uuid.v4();

      const source_format = action.source_format;
      const target_format = action.target_format;
      const source_str = action.source_str;
      const path = action.path;

      const commOpen = createCommOpenMessage(identity, 'save_file_comm', {
        source_format: source_format,
        target_format: target_format,
        source_str:    source_str,
        path: path});

      const childMessages = channels.iopub.childOf(commOpen);

      channels.shell.next(commOpen);

      return childMessages
        .ofMessageType(['comm_msg'])
        .map((message) => {
          // TODO: throw here on error
          if (message.content.data.status === 'okay') {
            // success
            const notificationSystem = state.app.get('notificationSystem');
            notificationSystem.addNotification({
              title: `Saved ${message.content.data.file}`,
              autoDismiss: 2,
              level: 'success',
            });
            return Rx.Observable.of({
              type: 'ERROR_SAVING',
              payload: 'error saving',
              error: true,
            });
          } else {
            throw new TelluriumError(message.content.data.error, 'ERROR SAVING');
          }
        }); // TODO: add take until
    })
    .mergeAll()
    .filter(() => false);
}

// used for saving non-notebook files
export function getNotebookPathEpic(action$, store) {
  return action$.ofType('COMM_OPEN')
    .filter((message) => message.target_name == "get_notebook_location")
    .map((message) => {
      const state = store.getState();
      const channels = state.app.channels;
      if (!channels || !channels.iopub || !channels.shell) {
        throw new Error('kernel not connected');
      }
      // console.log('open ', message.comm_id);
      // console.log('filename ', state.metadata.get('filename'));

      const reply = createCommMessage(message.comm_id, {location: state.metadata.get('filename') || ''});
      channels.shell.next(reply);
      // console.log('sent reply');
      return reply;
    })
    .filter(() => false);
}

/** The prompt content component */
class Prompt extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            value: this.props.defaultValue
        };

        this.onChange = (e) => this._onChange(e);
    }

    // https://stackoverflow.com/questions/28889826/react-set-focus-on-input-after-render
    componentDidMount() {
      this.inputElt.focus();
    }

    componentDidUpdate(prevProps, prevState) {
        if (prevState.value !== this.state.value) {
            this.props.onChange(this.state.value);
        }
    }

    componentWillUnmount() {
      key.unbind('esc');
      key.unbind('enter');
    }

    _onChange(e) {
        let value = e.target.value;

        this.setState({value: value});
    }

    render() {
        return <input type="text" placeholder={this.props.placeholder}
          className="mm-popup__input"
          value={this.state.value}
          onChange={this.onChange}
          ref={(input) => {this.inputElt = input;}} />;
    }
}

// key('esc', () => {
//   Popup.close();
// });

/** Prompt plugin */
Popup.registerPlugin('prompt', function (defaultValue, placeholder, find_callback, replace_callback) {
    let promptValue = null;
    let promptChange = function (value) {
        promptValue = value;
    };

    key('esc', () => {
      Popup.close();
    });

    key('enter', () => {
      console.log('enter key');
      find_callback(promptValue);
      Popup.close();
    });

    key.filter = (event) => true;

    this.create({
        title: 'Find in Notebook',
        content: <Prompt onChange={promptChange} placeholder={placeholder} value={defaultValue} />,
        buttons: {
            left: [
              {
                text: 'cancel',
                action: () => { Popup.close() },
              }
            ],
            right: [
              {
                text: 'Replace All',
                className: 'danger',
                action: () => {
                    replace_callback(promptValue);
                    Popup.close();
                }
              },
              {
                text: 'Find All',
                action: () => {
                    find_callback(promptValue);
                    Popup.close();
                }
            },
            ]
        }
    });
});

// find in notebook feature
export function findInNotebookEpic(action$, store) {
  return action$.ofType('FIND_IN_NOTEBOOK')
    .do(() => {
      Popup.plugins().prompt('default', 'Find in Notebook',
        (value) => {
          Popup.alert('Find ' + value)
        },
        (value) => {
          Popup.alert('Replace ' + value)
        },
        );
    })
    .filter(() => false);
}
<commit_msg>fix uncontrolled comp issue<commit_after>import Rx from 'rxjs/Rx';

import React from 'react';

import key from 'keymaster';

import {
  createCommOpenMessage,
  createCommMessage,
} from './comm';

import {
  createCellAfter,
  createCellBefore,
  createCellAppend,
} from '../actions';

import Popup from 'react-popup';

import {
  TelluriumError,
} from '../middlewares';

import * as uuid from 'uuid';

export function convertFileEpic(action$, store) {
  return action$.ofType('CONVERT_FILE')
    .map((action) => {
      const state = store.getState();
      const channels = state.app.channels;
      if (!channels || !channels.iopub || !channels.shell) {
        throw new Error('kernel not connected');
      }

      const identity = uuid.v4();

      const source_format = action.filetype === 'python' ? 'python' : action.filetype === 'sbml' ? 'antimony' :
        action.filetype === 'omex' ? 'omex' : action.filetype === 'cellml' ? 'cellml' :
        () => {throw new TelluriumError('Source filetype not recognized.', 'ERROR IMPORTING ARCHIVE')};
      let target_format = action.filetype === 'python' ? 'python' : action.filetype === 'sbml' ? 'antimony' :
        action.filetype === 'omex' ? 'omex' : action.filetype === 'cellml' ? 'antimony' :
        () => {throw new TelluriumError('Source filetype not recognized.', 'ERROR IMPORTING ARCHIVE')};

      const commOpen = createCommOpenMessage(identity, 'convert_file_comm', {target_format: source_format, path: action.path});
      const childMessages = channels.iopub.childOf(commOpen);

      channels.shell.next(commOpen);
      return childMessages
        .ofMessageType(['comm_msg'])
        .map((message) => {
          if (message.content.data.status === 'error') {
            const notificationSystem = state.app.get('notificationSystem');
            // notificationSystem.addNotification({
            //   title: message.content.data.error,
            //   autoDismiss: 4,
            //   level: 'error',
            // });
            if (source_format === 'antimony') {
              throw new TelluriumError(message.content.data.error, 'ERROR IMPORTING SBML');
            } else {
              throw new TelluriumError(message.content.data.error, 'ERROR IMPORTING ARCHIVE');
            }
            // return Rx.Observable.throw(new Error('Unable to import archive.'));
            // return Rx.Observable.of({
            //   type: ERROR_GENERAL,
            //   payload: message.content.data.error,
            //   error: true,
            // });
          }
          // no error - add cells to notebook
          const cells = message.content.data.content.cells;
          if (cells) {
            if (cells.length === 0) {
              throw new TelluriumError('Failed to import any COMBINE archive entries', 'ERROR IMPORTING ARCHIVE');
            }
            if (cells.length > 1) {
              throw new TelluriumError('Multiple cells returned - operation not supported', 'ERROR IMPORTING ARCHIVE');
            }
            const cell = cells[0];
            // for combine archives containing only SBML
            if (cell.type === 'antimony') {
              target_format = 'antimony';
            }
            if (action.id) {
              // we have a cell id
              if (action.position === 'below') {
                return createCellAfter(target_format, action.id, cell.source)
              } else if (action.position === 'above') {
                return createCellBefore(target_format, action.id, cell.source)
              }
            } else {
              // we don't have a cell id - just append to end
              return createCellAppend(target_format, cell.source)
            }
          } else {
            throw new TelluriumError('Could not import file - internal error', 'ERROR IMPORTING ARCHIVE');
          }
        });
    })
    .mergeAll();
}

// used for saving non-notebook files
export function saveFileEpic(action$, store) {
  return action$.ofType('SAVE_FILE_FROM_STRING')
    .map((action) => {
      const state = store.getState();
      const channels = state.app.channels;
      if (!channels || !channels.iopub || !channels.shell) {
        throw new Error('kernel not connected');
      }

      const identity = uuid.v4();

      const source_format = action.source_format;
      const target_format = action.target_format;
      const source_str = action.source_str;
      const path = action.path;

      const commOpen = createCommOpenMessage(identity, 'save_file_comm', {
        source_format: source_format,
        target_format: target_format,
        source_str:    source_str,
        path: path});

      const childMessages = channels.iopub.childOf(commOpen);

      channels.shell.next(commOpen);

      return childMessages
        .ofMessageType(['comm_msg'])
        .map((message) => {
          // TODO: throw here on error
          if (message.content.data.status === 'okay') {
            // success
            const notificationSystem = state.app.get('notificationSystem');
            notificationSystem.addNotification({
              title: `Saved ${message.content.data.file}`,
              autoDismiss: 2,
              level: 'success',
            });
            return Rx.Observable.of({
              type: 'ERROR_SAVING',
              payload: 'error saving',
              error: true,
            });
          } else {
            throw new TelluriumError(message.content.data.error, 'ERROR SAVING');
          }
        }); // TODO: add take until
    })
    .mergeAll()
    .filter(() => false);
}

// used for saving non-notebook files
export function getNotebookPathEpic(action$, store) {
  return action$.ofType('COMM_OPEN')
    .filter((message) => message.target_name == "get_notebook_location")
    .map((message) => {
      const state = store.getState();
      const channels = state.app.channels;
      if (!channels || !channels.iopub || !channels.shell) {
        throw new Error('kernel not connected');
      }
      // console.log('open ', message.comm_id);
      // console.log('filename ', state.metadata.get('filename'));

      const reply = createCommMessage(message.comm_id, {location: state.metadata.get('filename') || ''});
      channels.shell.next(reply);
      // console.log('sent reply');
      return reply;
    })
    .filter(() => false);
}

/** The prompt content component */
class Prompt extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            value: this.props.defaultValue
        };

        this.onChange = (e) => this._onChange(e);
    }

    // https://stackoverflow.com/questions/28889826/react-set-focus-on-input-after-render
    componentDidMount() {
      this.inputElt.focus();
    }

    componentDidUpdate(prevProps, prevState) {
        if (prevState.value !== this.state.value) {
            this.props.onChange(this.state.value);
        }
    }

    componentWillUnmount() {
      key.unbind('esc');
      key.unbind('enter');
    }

    _onChange(e) {
        let value = e.target.value;

        this.setState({value: value});
    }

    render() {
        return <input type="text" placeholder={this.props.placeholder}
          className="mm-popup__input"
          defaultValue={this.state.value}
          onChange={this.onChange}
          ref={(input) => {this.inputElt = input;}} />;
    }
}

// key('esc', () => {
//   Popup.close();
// });

/** Prompt plugin */
Popup.registerPlugin('prompt', function (defaultValue, placeholder, find_callback, replace_callback) {
    let promptValue = null;
    let promptChange = function (value) {
        promptValue = value;
    };

    key('esc', () => {
      Popup.close();
    });

    key('enter', () => {
      console.log('enter key');
      if (promptValue !== null && promptValue !== '') {
        find_callback(promptValue);
        Popup.close();
      }
    });

    key.filter = (event) => true;

    this.create({
        title: 'Find in Notebook',
        content: <Prompt onChange={promptChange} placeholder={placeholder} value={defaultValue} />,
        buttons: {
            left: [
              {
                text: 'cancel',
                action: () => { Popup.close() },
              }
            ],
            right: [
              {
                text: 'Replace All',
                className: 'danger',
                action: () => {
                    replace_callback(promptValue);
                    Popup.close();
                }
              },
              {
                text: 'Find All',
                action: () => {
                    find_callback(promptValue);
                    Popup.close();
                }
            },
            ]
        }
    });
});

// find in notebook feature
export function findInNotebookEpic(action$, store) {
  return action$.ofType('FIND_IN_NOTEBOOK')
    .do(() => {
      Popup.plugins().prompt('default', 'Find in Notebook',
        (value) => {
          Popup.alert('Find ' + value)
        },
        (value) => {
          Popup.alert('Replace ' + value)
        },
        );
    })
    .filter(() => false);
}
<|endoftext|>


<commit_before>"use strict";

angular
.module("gpConnect")
.controller("AppointmentsStructuredCtrl", function(
    $scope,
    $http,
    PatientService,
    $stateParams,
    $modal
) {
    $scope.MedicationListList = [];
    $scope.AllMedications = {};
    $scope.IsDisabled = true;
    $scope.ActiveAllergiesList = [];
    $scope.ResolvedAllergiesList = [];
    $scope.patientsAllergies = [];
    $scope.dropdwonListValue = '';
    $scope.allergies = [];
    $scope.highlightValues = false;
    $scope.data = {"Iodine (substance)": "Iodine allergy"};
    $scope.MedicationRequest = [];
    $scope.MedicationStatement = [];
    $scope.historicMedications = [];

    $scope.currentMedications = [];
    $scope.search = {};
    $scope.search.startDate = "";
    $scope.search.endDate ="";
    $scope.includeResolvedAllergies = true;
    $scope.includePrescriptionIssues = true;

    $scope.dateInvalid = false;

    initShowHide();

    $scope.openDatePicker = function ($event, name) {
        $event.preventDefault();
        $event.stopPropagation();
        $scope.startDate = false;
        $scope.endDate = false;
        $scope[name] = true;
        highlightMonth();
    };

    var highlightMonth = function(){
        $(".text-muted").parent().addClass("otherMonth");
        $("button").unbind('click', highlightMonth);
        $("button").bind('click', highlightMonth);
    };

    function initGetAllergies() {
        PatientService.allergyDetialsByPatient($stateParams.patientId
        ).then(function(allergySummaryResponse) {
            $scope.patientsAllergies = allergySummaryResponse;
        });
    }

    $scope.onChange = function(item) {
        $scope.IsDisabled = false;
        $scope.allergies = $scope.AllMedications[item];
        $scope.selectedMedication =item;

    };

    $scope.styleFunction = function(index) {
        if($scope.allergies.includes(index)) {
            return{
                "background-color": "yellow"
            }
        }
        else {
            return{
                "background-color": "white"
            }
        }
    };

    $scope.addNewMedication = function () {
        var data = {
            "medication": $scope.selectedMedication,
            "nhsNumber":$stateParams.patientId
        };
        PatientService.addMedication(data ).then(function(response) {
            initGetMedicationData();
            if(response.status == "200") {
                console.log("Everything went fine.");
            }
        });
    };

    $scope.getAllergyData = function (start, end, includePrescriptionIssues, includeResolvedAllergies) {
        $scope.dateInvalid = false;
        if(start === undefined || start == null){
            start = "";
        }

        if(end === undefined || end == null){
            end = "";
        }

        var createDate = function(stringDate){
            var date = new Date(stringDate);
            date.setTime(date.getTime() + (60*60*1000));

            return date;
        };

        if(start !== "" && end !== ""){
            var startDate = createDate(start);

            var endDate = new Date(end);
            endDate.setTime(endDate.getTime() + (60*60*1000));

            if(isNaN(startDate) || isNaN(endDate) || startDate > endDate){
                $scope.dateInvalid = true;
                return;
            }

            start = startDate.toISOString().split('T')[0];
            end = endDate.toISOString().split('T')[0];
        } else {
            if(start === "" && end !== ""){
                var endDate = createDate(end);
                if(isNaN(endDate)){
                    $scope.dateInvalid = true;
                    return;
                }

                end = endDate.toISOString().split('T')[0];

            }

            if(start !== "" && end === ""){
                var startDate = new Date(start);

                if(isNaN(startDate)){
                    $scope.dateInvalid = true;
                    return;
                }
                start = startDate.toISOString().split('T')[0];

            }
        }

        {

            $scope.patient = {
                name: "",
                id: "",
                birthDate: ""
            };
            $scope.practitioner = {
                name: "",
                id: ""
            };
            $scope.organization = {
                name: "",
                id: ""
            };

            $scope.allergyIntolerance = {
                assertedDate: "",
                category: "",
                clinicalStatus: "",
                patient: "",
                reaction: "",
                resolvedDate: ""
            };
            PatientService.structured($stateParams.patientId, start, end, includePrescriptionIssues, includeResolvedAllergies).then(function(
                patientSummaryResponse
            ) {
                $scope.ActiveAllergiesList = [];
                $scope.ResolvedAllergiesList=[];

                $scope.MedicationStatement=[];
                $scope.MedicationListList=[];
                $scope.currentMedications=[];
                $scope.historicMedications=[];
                $scope.MedicationRequest = [];
                const medicationWarningCodeSet = new Set();
                const activewarningCodeSet = new Set();
                const resolvedwarningCodeSet = new Set();
                $scope.MedicationWarningCodes = [];
                $scope.ActiveAllergiesWarningCodes = [];
                $scope.ResolvedAllergisWarningCodes = [];

                for (
                    var i = 0;
                    i < patientSummaryResponse.entry.length;
                    i++
                ) {
                    var resource = patientSummaryResponse.entry[i].resource;

                    if (resource.resourceType == "Patient") {
                        $scope.patient = {
                            name: resource.name[0].text,
                            id: resource.id,
                            birthDate: resource.birthDate
                        };
                    } else if (
                        patientSummaryResponse.entry[i].resource
                        .resourceType == "Organization"
                    ) {
                        $scope.organization = {
                            name: resource.name,
                            id: resource.id
                        };
                    } else if (resource.resourceType == "Practitioner") {
                        $scope.practitioner = {
                            name: resource.name,
                            id: resource.id
                        };
                    } else if (
                        resource.resourceType == "AllergyIntolerance"
                    ) {
                        if (resource.clinicalStatus == "active") {
                            $scope.ActiveAllergiesList.push(resource);
                        }

                    }else if(
                        resource.title == "Resolved Allergies" && 'contained' in resource
                    ) {
                        $scope.ResolvedAllergiesList=  $scope.ResolvedAllergiesList.concat(resource.contained);
                    } else if(
                        resource.resourceType =="MedicationRequest"
                    ) {
                        $scope.MedicationRequest.push(resource);
                    } else if(
                        resource.resourceType =="MedicationStatement"
                    ) {
                        // console.log(resource);
                        $scope.MedicationStatement.push(resource);

                    }

                    if (resource.resourceType == "Medication") {
                        $scope.MedicationListList.push(resource);
                    }
                    if(resource.resourceType == "List" && resource.extension != null) {
                        var warningCodeUrl = "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-CareConnect-GPC-ListWarningCode-1";
                        var extentionList = resource.extension;
                        for(var j =0; j <extentionList.length; j++) {
                                if(extentionList[j].url == warningCodeUrl) {
                                    if(extentionList[j].valueCoding.display == "Medications and medical devices") {
                                        medicationWarningCodeSet.add(extentionList[j].valueCoding.code);
                                    }
                                   else  if(extentionList[j].valueCoding.display == "Active Allergies") {
                                        activewarningCodeSet.add(extentionList[j].valueCoding.code);
                                    }
                                    else if(extentionList[j].valueCoding.display == "Resolved Allergies") {
                                        resolvedwarningCodeSet.add(extentionList[j].valueCoding.code);
                                    }
                                }
                        }
                    }

                }

                for(let entry of medicationWarningCodeSet.values()) {
                    if(entry == "confidential-items") {
                        $scope.MedicationWarningCodes.push("Confidential items");
                    }
                    else if(entry == "data-in-transit") {
                        $scope.MedicationWarningCodes.push("Data in transit");
                    }
                    else if(entry == "data-awaiting-filing") {
                        $scope.MedicationWarningCodes.push("Data awaiting filing");
                    }
                }

                for(let entry of activewarningCodeSet.values()) {
                    if(entry == "confidential-items") {
                        $scope.ActiveAllergiesWarningCodes.push("Confidential items");
                    }
                    else if(entry == "data-in-transit") {
                        $scope.ActiveAllergiesWarningCodes.push("Data in transit");
                    }
                    else if(entry == "data-awaiting-filing") {
                        $scope.ActiveAllergiesWarningCodes.push("Data awaiting filing");
                    }
                }

                for(let entry of resolvedwarningCodeSet.values()) {
                    if(entry == "confidential-items") {
                        $scope.ResolvedAllergisWarningCodes.push("Confidential items");
                    }
                }

                initgetPastMedication();

                // $scope.MedicationStatement.forEach(medicationStatement => {
                $scope.MedicationStatement.forEach(function(medicationStatement)  {

                    var medicationId = medicationStatement.medicationReference.reference.split("/").pop();
                    var medication = $scope.MedicationListList.find(function(medication){ return medication.id === medicationId});

                    var medHelpObj = {};
                    medHelpObj.statement = medicationStatement;
                    medHelpObj.medication = medication;

                    $scope.currentMedications.push(medHelpObj);
                });

            });

        }
    }

    function initShowHide() {
        PatientService.allMedications($stateParams.patientId).then(function (mediacations) {
            console.log(mediacations);
            $scope.AllMedications = mediacations;
        });
    }

    function initgetPastMedication() {
        $scope.MedicationStatement.forEach(function(medicationStatement) {
            // historic ID
            var historicId = medicationStatement.basedOn[0].reference.split("/").pop();

            $scope.MedicationRequest.forEach(function(MedicationRequest) {
                // check if the historic id matches anything in medication request
                if(historicId == MedicationRequest.id) {
                    //get the medication name
                    var medicationId = medicationStatement.medicationReference.reference.split("/").pop();

                    var medication = $scope.MedicationListList.find(function(x) { return x.id === medicationId});

                    var historyObj = {};
                    historyObj.medication = medication;
                    historyObj.statement = medicationStatement;
                    $scope.historicMedications.push(historyObj);
                }
            })
        });
    }

    $scope.showForm = function (listType) {
        $scope.listType = listType;

        if(listType.resourceType == "Medication") {
            $scope.showMedDetail = true;
            $scope.showAllergyDetail = false;
            $scope.showResAllergyDetail = false;

            $scope.actualMedicationRequestWithIssue = {issues: []};

            for(var i=0; i < $scope.MedicationRequest.length; i++) {
                if(listType.id == $scope.MedicationRequest[i].medicationReference.reference.split("/").pop()) {
                    if($scope.MedicationRequest[i].intent === "plan"){
                        $scope.actualMedicationRequestWithIssue.plan = $scope.MedicationRequest[i];
                        if(!$scope.includePrescriptionIssues){
                            break;
                        }
                    } else {
                        $scope.actualMedicationRequestWithIssue.issues.push($scope.MedicationRequest[i]);
                    }
                }
            }

            var extensionArray =  $scope.actualMedicationRequestWithIssue.plan.extension;

            var requestType = extensionArray.find(function(element){
                return element.url === "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-CareConnect-GPC-PrescriptionType-1";
            }).valueCodeableConcept.coding[0].display;

            $scope.actualMedicationRequestWithIssue.requestType = requestType;

            if(requestType === "Repeat"){
                $scope.actualMedicationRequestWithIssue.repeat = extensionArray.find(function(element){
                    return element.url === "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-CareConnect-GPC-MedicationRepeatInformation-1";
                }).extension;
            }

            $scope.MedicationName = listType.code.coding[0].extension[0].extension[1].valueString;
            $scope.practitionername = $scope.practitioner.name[0].prefix[0]+" "+$scope.practitioner.name[0].given[0] + " "+ $scope.practitioner.name[0].family;

            var medName = listType.code.coding[0].extension[0].extension[1].valueString == "Transfer-degraded medication entry" ? listType.code.text :  listType.code.coding[0].extension[0].extension[1].valueString
            $scope.title = "Medication Detail: "+medName;

        }
        else if (listType.resourceType == "AllergyIntolerance" && listType.clinicalStatus == "active") {
            $scope.showAllergyDetail = true;
            $scope.showMedDetail = false;
            $scope.showResAllergyDetail = false;
            $scope.title = "Allergy Detail: "+listType.code.coding[0].display;
        }
        else if (listType.resourceType == "AllergyIntolerance" && listType.clinicalStatus == "resolved") {
            $scope.showResAllergyDetail = true;
            $scope.showAllergyDetail = false;
            $scope.showMedDetail = false;
            $scope.title = "Allergy Detail: "+listType.code.coding[0].display;
        }

        $scope.message = "Show Form Button Clicked";

        var modalInstance = $modal.open({
            templateUrl: '../views/access-record/modal.html',
            scope: $scope,
            resolve: {
                params: function () {
                    return {
                    };
                }
            }
        });

        $scope.closeModalInstance = function(){
            modalInstance.close();
        }

        modalInstance.result.then(function (selectedItem) {
            $scope.selected = selectedItem;
        }, function () {
        });
    };

    $scope.getAllergyData("", "", true, true);

});

<commit_msg>Updated the frontend to make it compatiable with ECMAScript5.  #76<commit_after>"use strict";

angular
.module("gpConnect")
.controller("AppointmentsStructuredCtrl", function(
    $scope,
    $http,
    PatientService,
    $stateParams,
    $modal
) {
    $scope.MedicationListList = [];
    $scope.AllMedications = {};
    $scope.IsDisabled = true;
    $scope.ActiveAllergiesList = [];
    $scope.ResolvedAllergiesList = [];
    $scope.patientsAllergies = [];
    $scope.dropdwonListValue = '';
    $scope.allergies = [];
    $scope.highlightValues = false;
    $scope.data = {"Iodine (substance)": "Iodine allergy"};
    $scope.MedicationRequest = [];
    $scope.MedicationStatement = [];
    $scope.historicMedications = [];

    $scope.currentMedications = [];
    $scope.search = {};
    $scope.search.startDate = "";
    $scope.search.endDate ="";
    $scope.includeResolvedAllergies = true;
    $scope.includePrescriptionIssues = true;

    $scope.dateInvalid = false;

    initShowHide();

    $scope.openDatePicker = function ($event, name) {
        $event.preventDefault();
        $event.stopPropagation();
        $scope.startDate = false;
        $scope.endDate = false;
        $scope[name] = true;
        highlightMonth();
    };

    var highlightMonth = function(){
        $(".text-muted").parent().addClass("otherMonth");
        $("button").unbind('click', highlightMonth);
        $("button").bind('click', highlightMonth);
    };

    function initGetAllergies() {
        PatientService.allergyDetialsByPatient($stateParams.patientId
        ).then(function(allergySummaryResponse) {
            $scope.patientsAllergies = allergySummaryResponse;
        });
    }

    $scope.onChange = function(item) {
        $scope.IsDisabled = false;
        $scope.allergies = $scope.AllMedications[item];
        $scope.selectedMedication =item;

    };

    $scope.styleFunction = function(index) {
        if($scope.allergies.includes(index)) {
            return{
                "background-color": "yellow"
            }
        }
        else {
            return{
                "background-color": "white"
            }
        }
    };

    $scope.addNewMedication = function () {
        var data = {
            "medication": $scope.selectedMedication,
            "nhsNumber":$stateParams.patientId
        };
        PatientService.addMedication(data ).then(function(response) {
            initGetMedicationData();
            if(response.status == "200") {
                console.log("Everything went fine.");
            }
        });
    };

    $scope.getAllergyData = function (start, end, includePrescriptionIssues, includeResolvedAllergies) {
        $scope.dateInvalid = false;
        if(start === undefined || start == null){
            start = "";
        }

        if(end === undefined || end == null){
            end = "";
        }

        var createDate = function(stringDate){
            var date = new Date(stringDate);
            date.setTime(date.getTime() + (60*60*1000));

            return date;
        };

        if(start !== "" && end !== ""){
            var startDate = createDate(start);

            var endDate = new Date(end);
            endDate.setTime(endDate.getTime() + (60*60*1000));

            if(isNaN(startDate) || isNaN(endDate) || startDate > endDate){
                $scope.dateInvalid = true;
                return;
            }

            start = startDate.toISOString().split('T')[0];
            end = endDate.toISOString().split('T')[0];
        } else {
            if(start === "" && end !== ""){
                var endDate = createDate(end);
                if(isNaN(endDate)){
                    $scope.dateInvalid = true;
                    return;
                }

                end = endDate.toISOString().split('T')[0];

            }

            if(start !== "" && end === ""){
                var startDate = new Date(start);

                if(isNaN(startDate)){
                    $scope.dateInvalid = true;
                    return;
                }
                start = startDate.toISOString().split('T')[0];

            }
        }

        {

            $scope.patient = {
                name: "",
                id: "",
                birthDate: ""
            };
            $scope.practitioner = {
                name: "",
                id: ""
            };
            $scope.organization = {
                name: "",
                id: ""
            };

            $scope.allergyIntolerance = {
                assertedDate: "",
                category: "",
                clinicalStatus: "",
                patient: "",
                reaction: "",
                resolvedDate: ""
            };
            PatientService.structured($stateParams.patientId, start, end, includePrescriptionIssues, includeResolvedAllergies).then(function(
                patientSummaryResponse
            ) {
                $scope.ActiveAllergiesList = [];
                $scope.ResolvedAllergiesList=[];

                $scope.MedicationStatement=[];
                $scope.MedicationListList=[];
                $scope.currentMedications=[];
                $scope.historicMedications=[];
                $scope.MedicationRequest = [];
                const medicationWarningCodeSet = new Set();
                const activewarningCodeSet = new Set();
                const resolvedwarningCodeSet = new Set();
                $scope.MedicationWarningCodes = [];
                $scope.ActiveAllergiesWarningCodes = [];
                $scope.ResolvedAllergisWarningCodes = [];

                for (
                    var i = 0;
                    i < patientSummaryResponse.entry.length;
                    i++
                ) {
                    var resource = patientSummaryResponse.entry[i].resource;

                    if (resource.resourceType == "Patient") {
                        $scope.patient = {
                            name: resource.name[0].text,
                            id: resource.id,
                            birthDate: resource.birthDate
                        };
                    } else if (
                        patientSummaryResponse.entry[i].resource
                        .resourceType == "Organization"
                    ) {
                        $scope.organization = {
                            name: resource.name,
                            id: resource.id
                        };
                    } else if (resource.resourceType == "Practitioner") {
                        $scope.practitioner = {
                            name: resource.name,
                            id: resource.id
                        };
                    } else if (
                        resource.resourceType == "AllergyIntolerance"
                    ) {
                        if (resource.clinicalStatus == "active") {
                            $scope.ActiveAllergiesList.push(resource);
                        }

                    }else if(
                        resource.title == "Resolved Allergies" && 'contained' in resource
                    ) {
                        $scope.ResolvedAllergiesList=  $scope.ResolvedAllergiesList.concat(resource.contained);
                    } else if(
                        resource.resourceType =="MedicationRequest"
                    ) {
                        $scope.MedicationRequest.push(resource);
                    } else if(
                        resource.resourceType =="MedicationStatement"
                    ) {
                        // console.log(resource);
                        $scope.MedicationStatement.push(resource);

                    }

                    if (resource.resourceType == "Medication") {
                        $scope.MedicationListList.push(resource);
                    }
                    if(resource.resourceType == "List" && resource.extension != null) {
                        var warningCodeUrl = "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-CareConnect-GPC-ListWarningCode-1";
                        var extentionList = resource.extension;
                        for(var j =0; j <extentionList.length; j++) {
                                if(extentionList[j].url == warningCodeUrl) {
                                    if(extentionList[j].valueCoding.display == "Medications and medical devices") {
                                        medicationWarningCodeSet.add(extentionList[j].valueCoding.code);
                                    }
                                   else  if(extentionList[j].valueCoding.display == "Active Allergies") {
                                        activewarningCodeSet.add(extentionList[j].valueCoding.code);
                                    }
                                    else if(extentionList[j].valueCoding.display == "Resolved Allergies") {
                                        resolvedwarningCodeSet.add(extentionList[j].valueCoding.code);
                                    }
                                }
                        }
                    }

                }

                medicationWarningCodeSet.forEach(function (value) {
                    if(value == "confidential-items") {
                        $scope.MedicationWarningCodes.push("Confidential items");
                    }
                    else if(value == "data-in-transit") {
                        $scope.MedicationWarningCodes.push("Data in transit");
                    }
                    else if(value == "data-awaiting-filing") {
                        $scope.MedicationWarningCodes.push("Data awaiting filing");
                    }
                });

                activewarningCodeSet.forEach(function (value) {
                    if(value == "confidential-items") {
                        $scope.ActiveAllergiesWarningCodes.push("Confidential items");
                    }
                    else if(value == "data-in-transit") {
                        $scope.ActiveAllergiesWarningCodes.push("Data in transit");
                    }
                    else if(value == "data-awaiting-filing") {
                        $scope.ActiveAllergiesWarningCodes.push("Data awaiting filing");
                    }
                });

                resolvedwarningCodeSet.forEach(function (value) {
                    if(value == "confidential-items") {
                        $scope.ResolvedAllergisWarningCodes.push("Confidential items");
                    }
                    else if(value == "data-in-transit") {
                        $scope.ResolvedAllergisWarningCodes.push("Data in transit");
                    }
                    else if(value == "data-awaiting-filing") {
                        $scope.ResolvedAllergisWarningCodes.push("Data awaiting filing");
                    }
                });

                initgetPastMedication();

                // $scope.MedicationStatement.forEach(medicationStatement => {
                $scope.MedicationStatement.forEach(function(medicationStatement)  {

                    var medicationId = medicationStatement.medicationReference.reference.split("/").pop();
                    var medication = $scope.MedicationListList.find(function(medication){ return medication.id === medicationId});

                    var medHelpObj = {};
                    medHelpObj.statement = medicationStatement;
                    medHelpObj.medication = medication;

                    $scope.currentMedications.push(medHelpObj);
                });

            });

        }
    }

    function initShowHide() {
        PatientService.allMedications($stateParams.patientId).then(function (mediacations) {
            console.log(mediacations);
            $scope.AllMedications = mediacations;
        });
    }

    function initgetPastMedication() {
        $scope.MedicationStatement.forEach(function(medicationStatement) {
            // historic ID
            var historicId = medicationStatement.basedOn[0].reference.split("/").pop();

            $scope.MedicationRequest.forEach(function(MedicationRequest) {
                // check if the historic id matches anything in medication request
                if(historicId == MedicationRequest.id) {
                    //get the medication name
                    var medicationId = medicationStatement.medicationReference.reference.split("/").pop();

                    var medication = $scope.MedicationListList.find(function(x) { return x.id === medicationId});

                    var historyObj = {};
                    historyObj.medication = medication;
                    historyObj.statement = medicationStatement;
                    $scope.historicMedications.push(historyObj);
                }
            })
        });
    }

    $scope.showForm = function (listType) {
        $scope.listType = listType;

        if(listType.resourceType == "Medication") {
            $scope.showMedDetail = true;
            $scope.showAllergyDetail = false;
            $scope.showResAllergyDetail = false;

            $scope.actualMedicationRequestWithIssue = {issues: []};

            for(var i=0; i < $scope.MedicationRequest.length; i++) {
                if(listType.id == $scope.MedicationRequest[i].medicationReference.reference.split("/").pop()) {
                    if($scope.MedicationRequest[i].intent === "plan"){
                        $scope.actualMedicationRequestWithIssue.plan = $scope.MedicationRequest[i];
                        if(!$scope.includePrescriptionIssues){
                            break;
                        }
                    } else {
                        $scope.actualMedicationRequestWithIssue.issues.push($scope.MedicationRequest[i]);
                    }
                }
            }

            var extensionArray =  $scope.actualMedicationRequestWithIssue.plan.extension;

            var requestType = extensionArray.find(function(element){
                return element.url === "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-CareConnect-GPC-PrescriptionType-1";
            }).valueCodeableConcept.coding[0].display;

            $scope.actualMedicationRequestWithIssue.requestType = requestType;

            if(requestType === "Repeat"){
                $scope.actualMedicationRequestWithIssue.repeat = extensionArray.find(function(element){
                    return element.url === "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-CareConnect-GPC-MedicationRepeatInformation-1";
                }).extension;
            }

            $scope.MedicationName = listType.code.coding[0].extension[0].extension[1].valueString;
            $scope.practitionername = $scope.practitioner.name[0].prefix[0]+" "+$scope.practitioner.name[0].given[0] + " "+ $scope.practitioner.name[0].family;

            var medName = listType.code.coding[0].extension[0].extension[1].valueString == "Transfer-degraded medication entry" ? listType.code.text :  listType.code.coding[0].extension[0].extension[1].valueString
            $scope.title = "Medication Detail: "+medName;

        }
        else if (listType.resourceType == "AllergyIntolerance" && listType.clinicalStatus == "active") {
            $scope.showAllergyDetail = true;
            $scope.showMedDetail = false;
            $scope.showResAllergyDetail = false;
            $scope.title = "Allergy Detail: "+listType.code.coding[0].display;
        }
        else if (listType.resourceType == "AllergyIntolerance" && listType.clinicalStatus == "resolved") {
            $scope.showResAllergyDetail = true;
            $scope.showAllergyDetail = false;
            $scope.showMedDetail = false;
            $scope.title = "Allergy Detail: "+listType.code.coding[0].display;
        }

        $scope.message = "Show Form Button Clicked";

        var modalInstance = $modal.open({
            templateUrl: '../views/access-record/modal.html',
            scope: $scope,
            resolve: {
                params: function () {
                    return {
                    };
                }
            }
        });

        $scope.closeModalInstance = function(){
            modalInstance.close();
        }

        modalInstance.result.then(function (selectedItem) {
            $scope.selected = selectedItem;
        }, function () {
        });
    };

    $scope.getAllergyData("", "", true, true);

});

<|endoftext|>