<commit_before>
define([
    'flight/lib/component',
    'tpl!./form',
    'tpl!./shareRow',
    'tpl!./permissions',
    'util/users/userSelect',
    'service/user',
    'service/workspace'
], function(
    defineComponent,
    template,
    shareRowTemplate,
    permissionsTemplate,
    UserSelect,
    UserService,
    WorkspaceService) {
    'use strict';

    return defineComponent(Form);

    function Form() {

        this.userService = new UserService();
        this.workspaceService = new WorkspaceService();

        this.defaultAttrs({
            titleSelector: '.workspace-title',
            shareListSelector: '.share-list',
            shareHeader: '.share-header',
            shareFormSelector: '.share-form',
            permissionsSelector: '.permissions',
            permissionsRadioSelector: '.popover input',
            deleteSelector: '.delete',
            removeAccessSelector: '.remove-access'
        });

        this.after('teardown', function() {
            $(document).off('click.permPopover');
        });

        this.after('initialize', function() {
            var self = this;

            this.on(document, 'socketMessage', this.onSocketMessage);

            this.editable = this.attr.data.isEditable;

            this.$node.html(template({
                workspace: this.attr.data,
                editable: this.editable
            }));
            this.userService.getCurrentUsers().done(this.loadUserPermissionsList.bind(this));

            if (this.editable) {

                this.on('userSelected', function(event, data) {
                    if (data && data.user) {
                        self.trigger('shareWorkspaceWithUser', {
                            workspace: self.attr.data,
                            user: data.user
                        });
                        self.trigger(this.select('shareFormSelector'), 'clearUser');
                    }
                });

                UserSelect.attachTo(this.select('shareFormSelector'), {
                    filterUserIds: _.pluck(self.attr.data.users, 'userId'),
                    placeholder: i18n('workspaces.form.sharing.placeholder')
                });

                $(document).on('click.permPopover', function(event) {
                    var $target = $(event.target);

                    if ($target.closest('.permissions').length === 0) {
                        self.$node.find('.permissions').popover('hide');
                    }
                });
                this.on('shareWorkspaceWithUser', this.onShareWorkspaceWithUser);
                this.on('click', {
                    deleteSelector: this.onDelete,
                    removeAccessSelector: this.onRevokeAccess
                });
                this.on('change', {
                    permissionsRadioSelector: this.onPermissionsChange
                });
                this.select('titleSelector').on('change keyup paste', this.onChangeTitle.bind(this));
            }
        });

        this.onSocketMessage = function(event, message) {
            if (message && ~'userStatusChange'.indexOf(message.type)) {
                var user = message.data;
                this.$node.find('.share-list > .user-row').each(function() {
                    var $this = $(this);
                    if ($this.data('userId') === user.id) {
                        $this.find('.user-status')
                            .removeClass('online offline unknown')
                            .addClass((user.status && user.status.toLowerCase()) || 'unknown');
                    }
                })
            }
        };

        var timeout;
        this.saveWorkspace = function(immediate, options) {
            var self = this,
                changes = options.changes,
                revert = options.revert,
                d = $.Deferred(),
                save = function() {
                    self.trigger(document, 'workspaceSaving', self.attr.data);
                    return self.workspaceService.save(self.attr.data.workspaceId, changes)
                        .fail(function() {
                            self.attr.data = revert;
                            self.trigger(document, 'workspaceSaved', revert);
                            d.reject();
                        })
                        .done(function(workspace) {
                            self.trigger(document, 'workspaceSaved', self.attr.data);
                            d.resolve({ workspace: self.attr.data });
                        });
                }

            if (immediate) {
                save();
            } else {
                clearTimeout(timeout);
                timeout = setTimeout(function() {
                    save();
                }, 1000);
            }

            return d;
        };

        this.loadUserPermissionsList = function(response) {
            var self = this,
                workspace = this.attr.data,
                html = $();

            this.currentUsers = response.users;

            _.sortBy(workspace.users || (workspace.users = []), function(user) {
                var user = _.findWhere(self.currentUsers, { id: user.userId });
                return user && user.displayName || 0;
            }).forEach(function(userPermission) {
                if (userPermission.userId != window.currentUser.id) {
                    var data = self.shareRowDataForPermission(userPermission);
                    if (data) {
                        html = html.add(shareRowTemplate(data));
                    }
                }
            });
            this.select('shareHeader').after(html).find('.loading').remove();
            if (this.editable) {
                this.select('shareFormSelector').show();
                this.updatePopovers();
            }
        };

        this.shareRowDataForPermission = function(userPermission, _user) {
            var user = _user || _.findWhere(this.currentUsers, { id: userPermission.userId });
            if (user) {
                return {
                    user: {
                        access: userPermission.access,
                        permissionLabel: {
                            read: i18n('workspaces.form.sharing.access.view'),
                            write: i18n('workspaces.form.sharing.access.edit')
                        }[userPermission.access.toLowerCase()],
                        userId: user.id,
                        status: user.status,
                        displayName: user.displayName,
                        email: user.email,
                        userName: user.userName
                    },
                    editable: this.editable
                };
            } else console.warn('User ' + userPermission.userId + ' in permissions is not a current user');
        };

        this.updatePopovers = function() {
            this.makePopover(this.select('permissionsSelector'));
        };

        this.makePopover = function(el) {
            el.popover({
                html: true,
                placement: 'bottom',
                container: this.$node,
                content: function() {
                    var row = $(this).closest('.user-row');
                    return $(permissionsTemplate($(this).data())).data('userRow', row);
                }
            });
        };

        this.onChangeTitle = function(event) {
            var self = this,
                $target = $(event.target),
                val = $target.val();

            if ($.trim(val).length === 0) {
                return;
            }

            if (val !== this.attr.data.title) {
                if (!this.titleRevert) {
                    this.titleRevert = $.extend(true, {}, this.attr.data);
                }
                this.attr.data.title = val;
                this.saveWorkspace(false, {
                    changes: {
                        title: val
                    },
                    revert: this.titleRevert
                }).fail(function() {
                    $target.val(self.titleRevert.title);
                }).always(function() {
                    self.titleRevert = null;
                });
            }
        };

        this.onPermissionsChange = function(event) {
            var self = this,
                $target = $(event.target),
                newPermissions = $target.data('permissions'),
                list = $target.closest('.permissions-list'),
                userRow = list.data('userRow'),
                badge = userRow.find('.permissions'),
                userId = userRow.data('userId'),
                user = _.findWhere(this.attr.data.users, { userId: userId });

            if (user) {
                var revert = $.extend(true, {}, this.attr.data);
                user.access = newPermissions;
                badge.popover('disable').addClass('loading');
                this.saveWorkspace(true, {
                    changes: {
                        userUpdates: [user]
                    },
                    revert: revert
                })
                    .done(function() {
                        var newUserRow = $(shareRowTemplate(self.shareRowDataForPermission(user)));
                        userRow.replaceWith(newUserRow);
                        self.makePopover(newUserRow.find('.badge'));
                    });
            } else console.warn('Unable to update permissions because user "' + userId + '" not found');
        };

        this.onDelete = function(event) {
            var self = this,
                workspaceId = this.attr.data.workspaceId,
                $target = $(event.target),
                previousText = $target.text();

            this.trigger('workspaceDeleting', this.attr.data);

            $target.text(i18n('workspaces.form.button.deleting')).attr('disabled', true);

            this.workspaceService['delete'](workspaceId)
                .always(function() {
                    $target.text(previousText).removeAttr('disabled');
                })
                .done(function() {
                    self.trigger('workspaceDeleted', { workspaceId: workspaceId });
                });
        };

        this.onRevokeAccess = function(event) {
            var self = this,
                list = $(event.target).closest('.permissions-list'),
                row = list.data('userRow'),
                userId = row.data('userId'),
                badge = row.find('.permissions').popover('disable').addClass('loading'),
                revert = $.extend(true, {}, this.attr.data);

            this.attr.data.users = _.reject(this.attr.data.users, function(user) {
                return user.userId === userId;
            });
            this.saveWorkspace(true, {
                changes: {
                    userDeletes: [userId]
                },
                revert: revert
            })
                .fail(function() {
                    var originalHtml = badge.html();
                    badge.removeClass('loading').addClass('badge-important').text('Error');
                    _.delay(function() {
                        badge.html(originalHtml).removeClass('badge-important').popover('enable');
                    }, 2000)
                })
                .done(function() {
                    row.remove();
                    self.updateUserSelectionFilter();
                });
        };

        this.updateUserSelectionFilter = function() {
            this.trigger(this.select('shareFormSelector'), 'updateFilterUserIds', {
                userIds: _.pluck(this.attr.data.users, 'userId')
            });
        };

        this.onShareWorkspaceWithUser = function(event, data) {

            var self = this,
                form = this.select('shareFormSelector'),
                user = {
                    userId: data.user.id,
                    access: 'READ'
                },
                row = $(shareRowTemplate(this.shareRowDataForPermission(user, data.user))).insertBefore(form),
                badge = row.find('.permissions'),
                revert = $.extend(true, {}, this.attr.data);

            this.attr.data.users.push(user);

            badge.addClass('loading');
            this.saveWorkspace(true, {
                changes: {
                    userUpdates: [user]
                },
                revert: revert
            })
                .always(function() {
                    badge.removeClass('loading');
                    badge.popover('destroy');
                })
                .fail(function() {
                    badge.addClass('badge-important').text('Error');
                    _.delay(function() {
                        row.remove();
                    }, 2000);
                })
                .done(function() {
                    _.defer(function() {
                        self.makePopover(badge);
                        self.updateUserSelectionFilter();
                    });
                });
        };

    }
});
<commit_msg>Allow permission click anywhere in row, not just radio<commit_after>
define([
    'flight/lib/component',
    'tpl!./form',
    'tpl!./shareRow',
    'tpl!./permissions',
    'util/users/userSelect',
    'service/user',
    'service/workspace'
], function(
    defineComponent,
    template,
    shareRowTemplate,
    permissionsTemplate,
    UserSelect,
    UserService,
    WorkspaceService) {
    'use strict';

    return defineComponent(Form);

    function Form() {

        this.userService = new UserService();
        this.workspaceService = new WorkspaceService();

        this.defaultAttrs({
            titleSelector: '.workspace-title',
            shareListSelector: '.share-list',
            shareHeader: '.share-header',
            shareFormSelector: '.share-form',
            permissionsSelector: '.permissions',
            permissionsRadioSelector: '.popover input',
            deleteSelector: '.delete',
            removeAccessSelector: '.remove-access'
        });

        this.after('teardown', function() {
            $(document).off('click.permPopover');
        });

        this.after('initialize', function() {
            var self = this;

            this.on(document, 'socketMessage', this.onSocketMessage);

            this.editable = this.attr.data.isEditable;

            this.$node.html(template({
                workspace: this.attr.data,
                editable: this.editable
            }));
            this.userService.getCurrentUsers().done(this.loadUserPermissionsList.bind(this));

            if (this.editable) {

                this.on('userSelected', function(event, data) {
                    if (data && data.user) {
                        self.trigger('shareWorkspaceWithUser', {
                            workspace: self.attr.data,
                            user: data.user
                        });
                        self.trigger(this.select('shareFormSelector'), 'clearUser');
                    }
                });

                UserSelect.attachTo(this.select('shareFormSelector'), {
                    filterUserIds: _.pluck(self.attr.data.users, 'userId'),
                    placeholder: i18n('workspaces.form.sharing.placeholder')
                });

                $(document).on('click.permPopover', function(event) {
                    var $target = $(event.target);

                    if ($target.closest('.permissions-list').length === 0) {
                        self.$node.find('.permissions-list').popover('hide');
                    }
                });
                this.on('shareWorkspaceWithUser', this.onShareWorkspaceWithUser);
                this.on('click', {
                    deleteSelector: this.onDelete,
                    removeAccessSelector: this.onRevokeAccess
                });
                this.on('change', {
                    permissionsRadioSelector: this.onPermissionsChange
                });
                this.select('titleSelector').on('change keyup paste', this.onChangeTitle.bind(this));
            }
        });

        this.onSocketMessage = function(event, message) {
            if (message && ~'userStatusChange'.indexOf(message.type)) {
                var user = message.data;
                this.$node.find('.share-list > .user-row').each(function() {
                    var $this = $(this);
                    if ($this.data('userId') === user.id) {
                        $this.find('.user-status')
                            .removeClass('online offline unknown')
                            .addClass((user.status && user.status.toLowerCase()) || 'unknown');
                    }
                })
            }
        };

        var timeout;
        this.saveWorkspace = function(immediate, options) {
            var self = this,
                changes = options.changes,
                revert = options.revert,
                d = $.Deferred(),
                save = function() {
                    self.trigger(document, 'workspaceSaving', self.attr.data);
                    return self.workspaceService.save(self.attr.data.workspaceId, changes)
                        .fail(function() {
                            self.attr.data = revert;
                            self.trigger(document, 'workspaceSaved', revert);
                            d.reject();
                        })
                        .done(function(workspace) {
                            self.trigger(document, 'workspaceSaved', self.attr.data);
                            d.resolve({ workspace: self.attr.data });
                        });
                }

            if (immediate) {
                save();
            } else {
                clearTimeout(timeout);
                timeout = setTimeout(function() {
                    save();
                }, 1000);
            }

            return d;
        };

        this.loadUserPermissionsList = function(response) {
            var self = this,
                workspace = this.attr.data,
                html = $();

            this.currentUsers = response.users;

            _.sortBy(workspace.users || (workspace.users = []), function(user) {
                var user = _.findWhere(self.currentUsers, { id: user.userId });
                return user && user.displayName || 0;
            }).forEach(function(userPermission) {
                if (userPermission.userId != window.currentUser.id) {
                    var data = self.shareRowDataForPermission(userPermission);
                    if (data) {
                        html = html.add(shareRowTemplate(data));
                    }
                }
            });
            this.select('shareHeader').after(html).find('.loading').remove();
            if (this.editable) {
                this.select('shareFormSelector').show();
                this.updatePopovers();
            }
        };

        this.shareRowDataForPermission = function(userPermission, _user) {
            var user = _user || _.findWhere(this.currentUsers, { id: userPermission.userId });
            if (user) {
                return {
                    user: {
                        access: userPermission.access,
                        permissionLabel: {
                            read: i18n('workspaces.form.sharing.access.view'),
                            write: i18n('workspaces.form.sharing.access.edit')
                        }[userPermission.access.toLowerCase()],
                        userId: user.id,
                        status: user.status,
                        displayName: user.displayName,
                        email: user.email,
                        userName: user.userName
                    },
                    editable: this.editable
                };
            } else console.warn('User ' + userPermission.userId + ' in permissions is not a current user');
        };

        this.updatePopovers = function() {
            this.makePopover(this.select('permissionsSelector'));
        };

        this.makePopover = function(el) {
            el.popover({
                html: true,
                placement: 'bottom',
                container: this.$node,
                content: function() {
                    var row = $(this).closest('.user-row');
                    return $(permissionsTemplate($(this).data())).data('userRow', row);
                }
            });
        };

        this.onChangeTitle = function(event) {
            var self = this,
                $target = $(event.target),
                val = $target.val();

            if ($.trim(val).length === 0) {
                return;
            }

            if (val !== this.attr.data.title) {
                if (!this.titleRevert) {
                    this.titleRevert = $.extend(true, {}, this.attr.data);
                }
                this.attr.data.title = val;
                this.saveWorkspace(false, {
                    changes: {
                        title: val
                    },
                    revert: this.titleRevert
                }).fail(function() {
                    $target.val(self.titleRevert.title);
                }).always(function() {
                    self.titleRevert = null;
                });
            }
        };

        this.onPermissionsChange = function(event) {
            var self = this,
                $target = $(event.target),
                newPermissions = $target.data('permissions'),
                list = $target.closest('.permissions-list'),
                userRow = list.data('userRow'),
                badge = userRow.find('.permissions'),
                userId = userRow.data('userId'),
                user = _.findWhere(this.attr.data.users, { userId: userId });

            if (user) {
                var revert = $.extend(true, {}, this.attr.data);
                user.access = newPermissions;
                badge.popover('hide').popover('disable').addClass('loading');
                this.saveWorkspace(true, {
                    changes: {
                        userUpdates: [user]
                    },
                    revert: revert
                })
                    .done(function() {
                        var newUserRow = $(shareRowTemplate(self.shareRowDataForPermission(user)));
                        userRow.replaceWith(newUserRow);
                        self.makePopover(newUserRow.find('.badge'));
                    });
            } else console.warn('Unable to update permissions because user "' + userId + '" not found');
        };

        this.onDelete = function(event) {
            var self = this,
                workspaceId = this.attr.data.workspaceId,
                $target = $(event.target),
                previousText = $target.text();

            this.trigger('workspaceDeleting', this.attr.data);

            $target.text(i18n('workspaces.form.button.deleting')).attr('disabled', true);

            this.workspaceService['delete'](workspaceId)
                .always(function() {
                    $target.text(previousText).removeAttr('disabled');
                })
                .done(function() {
                    self.trigger('workspaceDeleted', { workspaceId: workspaceId });
                });
        };

        this.onRevokeAccess = function(event) {
            var self = this,
                list = $(event.target).closest('.permissions-list'),
                row = list.data('userRow'),
                userId = row.data('userId'),
                badge = row.find('.permissions').popover('hide').popover('disable').addClass('loading'),
                revert = $.extend(true, {}, this.attr.data);

            this.attr.data.users = _.reject(this.attr.data.users, function(user) {
                return user.userId === userId;
            });
            this.saveWorkspace(true, {
                changes: {
                    userDeletes: [userId]
                },
                revert: revert
            })
                .fail(function() {
                    var originalHtml = badge.html();
                    badge.removeClass('loading').addClass('badge-important').text('Error');
                    _.delay(function() {
                        badge.html(originalHtml).removeClass('badge-important').popover('enable');
                    }, 2000)
                })
                .done(function() {
                    row.remove();
                    self.updateUserSelectionFilter();
                });
        };

        this.updateUserSelectionFilter = function() {
            this.trigger(this.select('shareFormSelector'), 'updateFilterUserIds', {
                userIds: _.pluck(this.attr.data.users, 'userId')
            });
        };

        this.onShareWorkspaceWithUser = function(event, data) {

            var self = this,
                form = this.select('shareFormSelector'),
                user = {
                    userId: data.user.id,
                    access: 'READ'
                },
                row = $(shareRowTemplate(this.shareRowDataForPermission(user, data.user))).insertBefore(form),
                badge = row.find('.permissions'),
                revert = $.extend(true, {}, this.attr.data);

            this.attr.data.users.push(user);

            badge.addClass('loading');
            this.saveWorkspace(true, {
                changes: {
                    userUpdates: [user]
                },
                revert: revert
            })
                .always(function() {
                    badge.removeClass('loading');
                    badge.popover('destroy');
                })
                .fail(function() {
                    badge.addClass('badge-important').text('Error');
                    _.delay(function() {
                        row.remove();
                    }, 2000);
                })
                .done(function() {
                    _.defer(function() {
                        self.makePopover(badge);
                        self.updateUserSelectionFilter();
                    });
                });
        };

    }
});
<|endoftext|>


<commit_before>import React from 'react'
import { connect } from 'react-redux'
import { reduxForm, Field } from 'redux-form'
import { addProblem } from '../../actions'
import { Grid, Segment, Form, Input, Button } from 'semantic-ui-react'

const renderInput = ({input, style, label}) => (

    {label}
    <Input type='text' {...input} style={style}/>

)

const renderConcepts = ({ input, concepts, label }) => (

    {label}
    <select className='ui dropdown' {...input}>
      <option>Choose...</option>
      { concepts.map((concept, index) =>
        <option key={index}>{concept}</option>
      )}
    </select>

)

let AddProblemForm = ({ handleSubmit, concepts }) => {
  return (
    <Grid padded>
      <Grid.Row>
        <Grid.Column width={10}>
          <Segment.Group style={{marginTop: 80}}>
            <Segment>
Add a Problem
</Segment>
            <Segment>

              <Form onSubmit={handleSubmit}>
                <Form.Field>
                  <Field name='concept' component={renderConcepts} label='Related Concept' concepts={concepts}/>
                </Form.Field>
                <Form.Field>
                  <Field name='topic' component={renderInput} label='Topic' /></Form.Field>
                <Form.Field>
                  <Field name='question' component={renderInput} label='Question' />
                </Form.Field>
                <Form.Field>
                  <Field name='answer' component={renderInput} label='Answer' />
                </Form.Field>
                <Button type='submit' color='grey' style={{marginTop: '15px'}}>Submit</Button>
              </Form>

            </Segment>
          </Segment.Group>
        </Grid.Column>
      </Grid.Row>
    </Grid>
  )
}

AddProblemForm = reduxForm({
  form:'addProblem',
  onSubmit: (values, dispatch) => {
    dispatch(addProblem(values))
  }
})(AddProblemForm)

const conceptsToArray = ({allConcepts: { byId }}) => {
  let conceptTitles = [];
  for (var prop in byId) {
    conceptTitles.push(byId[prop].title)
  }
  return conceptTitles
}

const mapState = (state) => {
  return {
    concepts: conceptsToArray(state)
  }
}

export default connect(mapState)(AddProblemForm)
<commit_msg>Updates styling for add problem form. #31<commit_after>import React from 'react'
import { connect } from 'react-redux'
import { reduxForm, Field } from 'redux-form'
import { addProblem } from '../../actions'
import { Grid, Segment, Form, Input, Button, Divider } from 'semantic-ui-react'

const renderInput = ({input, style, label}) => (

    {label}
    <Input type='text' {...input} style={style}/>

)

const renderConcepts = ({ input, concepts, label }) => (

    {label}
    <select className='ui dropdown' {...input}>
      <option>Choose...</option>
      { concepts.map((concept, index) =>
        <option key={index}>{concept}</option>
      )}
    </select>

)

let AddProblemForm = ({ handleSubmit, concepts }) => {
  return (
    <Grid padded>
      <Grid.Row>
        <Grid.Column width={1}>
        </Grid.Column>
        <Grid.Column width={11}>
          <Segment style={{marginTop: 120, backgroundColor: '#eaeaea'}}>
            <Segment.Group>
              <Segment>
Add a Problem
</Segment>
            </Segment.Group>
            <Segment.Group>
              <Segment>

                <Form onSubmit={handleSubmit}>
                  <Form.Field>
                    <Field name='concept' component={renderConcepts} label='Related Concept' concepts={concepts}/>
                  </Form.Field>
                  <Form.Field>
                    <Field name='topic' component={renderInput} label='Topic' />
                  </Form.Field>
                  <Form.Field>
                    <Field name='question' component={renderInput} label='Question' />
                  </Form.Field>
                  <Form.Field>
                    <Field name='answer' component={renderInput} label='Answer' />
                  </Form.Field>
                  <Divider />
                  <Button type='submit' color='grey'>Submit</Button>
                </Form>

              </Segment>
            </Segment.Group>
          </Segment>
        </Grid.Column>
      </Grid.Row>
    </Grid>
  )
}

AddProblemForm = reduxForm({
  form:'addProblem',
  onSubmit: (values, dispatch) => {
    dispatch(addProblem(values))
  }
})(AddProblemForm)

const conceptsToArray = ({allConcepts: { byId }}) => {
  let conceptTitles = [];
  for (var prop in byId) {
    conceptTitles.push(byId[prop].title)
  }
  return conceptTitles
}

const mapState = (state) => {
  return {
    concepts: conceptsToArray(state)
  }
}

export default connect(mapState)(AddProblemForm)
<|endoftext|>


<commit_before>import _ from 'lodash';

import {BaseComponent} from '../base/Base';
export class CheckBoxComponent extends BaseComponent {
  elementInfo() {
    const info = super.elementInfo();
    info.type = 'input';
    info.changeEvent = 'click';
    info.attr.type = this.component.inputType;
    info.attr.class = 'form-check-input';
    if (this.component.name) {
      info.attr.name = `data[${this.component.name}]`;
    }
    info.attr.value = this.component.value ? this.component.value : 0;
    return info;
  }

  build() {
    if (this.viewOnly) {
      return this.viewOnlyBuild();
    }

    if (!this.component.input) {
      return;
    }
    this.createElement();
    this.input = this.createInput(this.element);
    this.createLabel(this.element, this.input);
    if (!this.labelElement) {
      this.addInput(this.input, this.element);
    }
    this.createDescription(this.element);
    this.restoreValue();
    if (this.shouldDisable) {
      this.disabled = true;
    }
  }

  createElement() {
    let className = `form-check ${this.className}`;
    if (this.component.label) {
      className += ' checkbox';
    }
    this.element = this.ce('div', {
      id: this.id,
      class: className
    });
  }

  labelOnTheTopOrLeft() {
    return ['top', 'left'].includes(this.component.labelPosition);
  }

  labelOnTheTopOrBottom() {
    return ['top', 'bottom'].includes(this.component.labelPosition);
  }

  setInputLabelStyle(label) {
    if (this.component.labelPosition === 'left') {
      _.assign(label.style, {
        textAlign: 'center',
        paddingLeft: 0,
      });
    }

    if (this.labelOnTheTopOrBottom()) {
      _.assign(label.style, {
        display: 'block',
        textAlign: 'center',
        paddingLeft: 0,
      });
    }
  }

  setInputStyle(input) {
    if (this.component.labelPosition === 'left') {
      _.assign(input.style, {
        position: 'initial',
        marginLeft: '7px'
      });
    }

    if (this.labelOnTheTopOrBottom()) {
      _.assign(input.style, {
        width: '100%',
        position: 'initial',
        marginLeft: 0
      });
    }
  }

  createLabel(container, input) {
    if (!this.component.label) {
      return null;
    }

    let className = 'control-label form-check-label';
    if (this.component.input
      && !this.options.inputsOnly
      && this.component.validate
      && this.component.validate.required) {
      className += ' field-required';
    }

    this.labelElement = this.ce('label', {
      class: className
    });
    this.addShortcut();

    const labelOnTheTopOrOnTheLeft = this.labelOnTheTopOrLeft();

    // Create the SPAN around the textNode for better style hooks
    this.labelSpan = this.ce('span');

    if (this.info.attr.id) {
      this.labelElement.setAttribute('for', this.info.attr.id);
    }
    if (!this.options.inputsOnly && labelOnTheTopOrOnTheLeft) {
      this.setInputLabelStyle(this.labelElement);
      this.setInputStyle(input);
      this.labelSpan.appendChild(this.text(this.component.label));
      this.labelElement.appendChild(this.labelSpan);
    }
    this.addInput(input, this.labelElement);

    if (!this.options.inputsOnly && !labelOnTheTopOrOnTheLeft) {
      this.setInputLabelStyle(this.labelElement);
      this.setInputStyle(input);
      this.labelSpan.appendChild(this.text(this.addShortcutToLabel()));
      this.labelElement.appendChild(this.labelSpan);
    }
    this.createTooltip(this.labelElement);
    container.appendChild(this.labelElement);
  }

  createInput(container) {
    if (!this.component.input) {
      return;
    }
    const input = this.ce(this.info.type, this.info.attr);
    this.errorContainer = container;
    return input;
  }

  updateValueByName() {
    const component = this.getRoot().getComponent(this.component.name);

    if (component) {
      component.setValue(this.component.value, {changed: true});
    }
    else {
      this.data[this.component.name] = this.component.value;
    }
  }

  addInputEventListener(input) {
    this.addEventListener(input, this.info.changeEvent, () => {
      // If this input has a "name", then its other input elements are elsewhere on
      // the form. To get the correct submission object, we need to refresh the whole
      // data object.
      if (this.component.name) {
        this.updateValueByName();
        this.emit('refreshData');
      }

      this.updateValue();
    });
  }

  getValueAt(index) {
    return !!this.inputs[index].checked;
  }

  setValue(value, flags) {
    flags = this.getFlags.apply(this, arguments);
    if (!this.input) {
      return;
    }
    if (value === 'on') {
      this.input.value = 1;
      this.input.checked = 1;
    }
    else if (value === 'off') {
      this.input.value = 0;
      this.input.checked = 0;
    }
    else if (value) {
      this.input.value = 1;
      this.input.checked = 1;
    }
    else {
      this.input.value = 0;
      this.input.checked = 0;
    }
    this.updateValue(flags);
  }

  getRawValue() {
    if (this.component.name) {
      return this.data[this.component.name];
    }

    return super.getRawValue();
  }

  getView(value) {
    return value ? 'Yes' : 'No';
  }

  destroy() {
    super.destroy.apply(this, Array.prototype.slice.apply(arguments));
    this.removeShortcut();
  }
}
<commit_msg>FOR-1131: Fixed required Checkbox component.<commit_after>import _ from 'lodash';

import {BaseComponent} from '../base/Base';
export class CheckBoxComponent extends BaseComponent {
  elementInfo() {
    const info = super.elementInfo();
    info.type = 'input';
    info.changeEvent = 'click';
    info.attr.type = this.component.inputType;
    info.attr.class = 'form-check-input';
    if (this.component.name) {
      info.attr.name = `data[${this.component.name}]`;
    }
    info.attr.value = this.component.value ? this.component.value : 0;
    return info;
  }

  build() {
    if (this.viewOnly) {
      return this.viewOnlyBuild();
    }

    if (!this.component.input) {
      return;
    }
    this.createElement();
    this.input = this.createInput(this.element);
    this.createLabel(this.element, this.input);
    if (!this.labelElement) {
      this.addInput(this.input, this.element);
    }
    this.createDescription(this.element);
    this.restoreValue();
    if (this.shouldDisable) {
      this.disabled = true;
    }
  }

  createElement() {
    let className = `form-check ${this.className}`;
    if (this.component.label) {
      className += ' checkbox';
    }
    this.element = this.ce('div', {
      id: this.id,
      class: className
    });
  }

  labelOnTheTopOrLeft() {
    return ['top', 'left'].includes(this.component.labelPosition);
  }

  labelOnTheTopOrBottom() {
    return ['top', 'bottom'].includes(this.component.labelPosition);
  }

  setInputLabelStyle(label) {
    if (this.component.labelPosition === 'left') {
      _.assign(label.style, {
        textAlign: 'center',
        paddingLeft: 0,
      });
    }

    if (this.labelOnTheTopOrBottom()) {
      _.assign(label.style, {
        display: 'block',
        textAlign: 'center',
        paddingLeft: 0,
      });
    }
  }

  setInputStyle(input) {
    if (this.component.labelPosition === 'left') {
      _.assign(input.style, {
        position: 'initial',
        marginLeft: '7px'
      });
    }

    if (this.labelOnTheTopOrBottom()) {
      _.assign(input.style, {
        width: '100%',
        position: 'initial',
        marginLeft: 0
      });
    }
  }

  isEmpty(value) {
    return super.isEmpty(value) || value === false;
  }

  createLabel(container, input) {
    if (!this.component.label) {
      return null;
    }

    let className = 'control-label form-check-label';
    if (this.component.input
      && !this.options.inputsOnly
      && this.component.validate
      && this.component.validate.required) {
      className += ' field-required';
    }

    this.labelElement = this.ce('label', {
      class: className
    });
    this.addShortcut();

    const labelOnTheTopOrOnTheLeft = this.labelOnTheTopOrLeft();

    // Create the SPAN around the textNode for better style hooks
    this.labelSpan = this.ce('span');

    if (this.info.attr.id) {
      this.labelElement.setAttribute('for', this.info.attr.id);
    }
    if (!this.options.inputsOnly && labelOnTheTopOrOnTheLeft) {
      this.setInputLabelStyle(this.labelElement);
      this.setInputStyle(input);
      this.labelSpan.appendChild(this.text(this.component.label));
      this.labelElement.appendChild(this.labelSpan);
    }
    this.addInput(input, this.labelElement);

    if (!this.options.inputsOnly && !labelOnTheTopOrOnTheLeft) {
      this.setInputLabelStyle(this.labelElement);
      this.setInputStyle(input);
      this.labelSpan.appendChild(this.text(this.addShortcutToLabel()));
      this.labelElement.appendChild(this.labelSpan);
    }
    this.createTooltip(this.labelElement);
    container.appendChild(this.labelElement);
  }

  createInput(container) {
    if (!this.component.input) {
      return;
    }
    const input = this.ce(this.info.type, this.info.attr);
    this.errorContainer = container;
    return input;
  }

  updateValueByName() {
    const component = this.getRoot().getComponent(this.component.name);

    if (component) {
      component.setValue(this.component.value, {changed: true});
    }
    else {
      this.data[this.component.name] = this.component.value;
    }
  }

  addInputEventListener(input) {
    this.addEventListener(input, this.info.changeEvent, () => {
      // If this input has a "name", then its other input elements are elsewhere on
      // the form. To get the correct submission object, we need to refresh the whole
      // data object.
      if (this.component.name) {
        this.updateValueByName();
        this.emit('refreshData');
      }

      this.updateValue();
    });
  }

  getValueAt(index) {
    return !!this.inputs[index].checked;
  }

  setValue(value, flags) {
    flags = this.getFlags.apply(this, arguments);
    if (!this.input) {
      return;
    }
    if (value === 'on') {
      this.input.value = 1;
      this.input.checked = 1;
    }
    else if (value === 'off') {
      this.input.value = 0;
      this.input.checked = 0;
    }
    else if (value) {
      this.input.value = 1;
      this.input.checked = 1;
    }
    else {
      this.input.value = 0;
      this.input.checked = 0;
    }
    this.updateValue(flags);
  }

  getRawValue() {
    if (this.component.name) {
      return this.data[this.component.name];
    }

    return super.getRawValue();
  }

  getView(value) {
    return value ? 'Yes' : 'No';
  }

  destroy() {
    super.destroy.apply(this, Array.prototype.slice.apply(arguments));
    this.removeShortcut();
  }
}
<|endoftext|>


<commit_before>app
.factory('localizedMessageService', '$cookies' [function($cookies) {
	return
	{
		getDropdown: function()
		{
			return [
				{text: 'English', click: '$cookies.put("language","en")'},
				{text: 'Polish', click: '$cookies.put("language","pl")'}
			  ];
		},

		getLocalizedMessage: function(messageCode)
		{
			var langCode = $cookies.get('language');

			switch(langCode)
			{
				case "en":
					return getEnValue(messageCode);
					break;
				case "pl":
					return getPlValue(messageCode);
					break;
			}

			return "Localization service error";
		},

		getEnValue: function(messageCode)
		{
			switch(messageCode)
			{
				case "settings.header":
					return "SETTINGS";
			}

			return "Localization service error getting English value";
		},

		getPlValue: function(messageCode)
		{
			switch(messageCode)
			{
				case "settings.header":
					return "USTAWIENIA"
			}

			return "Localization service error getting Polish value";
		}
	}
}]);<commit_msg>Bugfix<commit_after>app
.factory('localizedMessageService', ['$cookies', function($cookies) {
	return
	{
		getDropdown: function()
		{
			return [
				{text: 'English', click: '$cookies.put("language","en")'},
				{text: 'Polish', click: '$cookies.put("language","pl")'}
			  ];
		},

		getLocalizedMessage: function(messageCode)
		{
			var langCode = $cookies.get('language');

			switch(langCode)
			{
				case "en":
					return getEnValue(messageCode);
					break;
				case "pl":
					return getPlValue(messageCode);
					break;
			}

			return "Localization service error";
		},

		getEnValue: function(messageCode)
		{
			switch(messageCode)
			{
				case "settings.header":
					return "SETTINGS";
			}

			return "Localization service error getting English value";
		},

		getPlValue: function(messageCode)
		{
			switch(messageCode)
			{
				case "settings.header":
					return "USTAWIENIA"
			}

			return "Localization service error getting Polish value";
		}
	}
}]);<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Kagilum SAS.
 *
 * This file is part of iceScrum.
 *
 * iceScrum is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License.
 *
 * iceScrum is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with iceScrum.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *
 * Vincent Barrier (vbarrier@kagilum.com)
 * Nicolas Noullet (nnoullet@kagilum.com)
 * Colin Bontemps (cbontemps@kagilum.com)
 *
 */
function isTouchOnlyDevice() { //not the best place... but there isn't a best place for that
    return /iP(ad|hone|od)/.test(navigator.userAgent) || navigator.userAgent.indexOf('Android') > 0;
}

isApplication
    .constant('SERVER_ERRORS', {
        loginFailed: 'is:auth-login-failed',
        sessionTimeout: 'is:auth-session-timeout',
        notAuthenticated: 'is:auth-not-authenticated',
        notAuthorized: 'is:auth-not-authorized',
        clientError: 'is:client-error',
        serverError: 'is:server-error'
    })
    .constant('BacklogCodes', {
        SANDBOX: 'sandbox',
        BACKLOG: 'backlog',
        DONE: 'done',
        ALL: 'all'
    })
    .constant('StoryStatesByName', {
        SUGGESTED: 1,
        ACCEPTED: 2,
        ESTIMATED: 3,
        PLANNED: 4,
        IN_PROGRESS: 5,
        DONE: 7
    })
    .constant('StoryTypesByName', {
        USER_STORY: 0,
        DEFECT: 2,
        TECHNICAL_STORY: 3
    })
    .constant('TaskStatesByName', {
        TODO: 0,
        IN_PROGRESS: 1,
        DONE: 2
    })
    .constant('TaskTypesByName', {
        RECURRENT: 10,
        URGENT: 11
    })
    .constant('AcceptanceTestStatesByName', {
        TOCHECK: 1,
        FAILED: 5,
        SUCCESS: 10
    })
    .constant('SprintStatesByName', {
        TODO: 1,
        IN_PROGRESS: 2,
        DONE: 3
    })
    .constant('FeatureStatesByName', {
        TODO: 0,
        IN_PROGRESS: 1,
        DONE: 2
    })
    .constant('FeatureTypesByName', {
        FUNCTIONAL: 0,
        ARCHITECTURAL: 1
    })
    .constant('ReleaseStatesByName', {
        TODO: 1,
        IN_PROGRESS: 2,
        DONE: 3
    })
    .constant('IceScrumEventType', {
        CREATE: 'CREATE',
        UPDATE: 'UPDATE',
        DELETE: 'DELETE'
    })
    .constant('TaskConstants', {
        ORDER_BY: [function(task) { return -task.type }, 'parentStory.rank', 'state', 'rank']
    })
    .constant('ActivityCodeByName', {
        SAVE: 'save',
        UPDATE: 'update',
        DELETE: 'delete'
    });<commit_msg>Fix merge issue<commit_after>/*
 * Copyright (c) 2017 Kagilum SAS.
 *
 * This file is part of iceScrum.
 *
 * iceScrum is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License.
 *
 * iceScrum is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with iceScrum.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *
 * Vincent Barrier (vbarrier@kagilum.com)
 * Nicolas Noullet (nnoullet@kagilum.com)
 * Colin Bontemps (cbontemps@kagilum.com)
 *
 */

isApplication
    .constant('SERVER_ERRORS', {
        loginFailed: 'is:auth-login-failed',
        sessionTimeout: 'is:auth-session-timeout',
        notAuthenticated: 'is:auth-not-authenticated',
        notAuthorized: 'is:auth-not-authorized',
        clientError: 'is:client-error',
        serverError: 'is:server-error'
    })
    .constant('BacklogCodes', {
        SANDBOX: 'sandbox',
        BACKLOG: 'backlog',
        DONE: 'done',
        ALL: 'all'
    })
    .constant('StoryStatesByName', {
        SUGGESTED: 1,
        ACCEPTED: 2,
        ESTIMATED: 3,
        PLANNED: 4,
        IN_PROGRESS: 5,
        DONE: 7
    })
    .constant('StoryTypesByName', {
        USER_STORY: 0,
        DEFECT: 2,
        TECHNICAL_STORY: 3
    })
    .constant('TaskStatesByName', {
        TODO: 0,
        IN_PROGRESS: 1,
        DONE: 2
    })
    .constant('TaskTypesByName', {
        RECURRENT: 10,
        URGENT: 11
    })
    .constant('AcceptanceTestStatesByName', {
        TOCHECK: 1,
        FAILED: 5,
        SUCCESS: 10
    })
    .constant('SprintStatesByName', {
        TODO: 1,
        IN_PROGRESS: 2,
        DONE: 3
    })
    .constant('FeatureStatesByName', {
        TODO: 0,
        IN_PROGRESS: 1,
        DONE: 2
    })
    .constant('FeatureTypesByName', {
        FUNCTIONAL: 0,
        ARCHITECTURAL: 1
    })
    .constant('ReleaseStatesByName', {
        TODO: 1,
        IN_PROGRESS: 2,
        DONE: 3
    })
    .constant('IceScrumEventType', {
        CREATE: 'CREATE',
        UPDATE: 'UPDATE',
        DELETE: 'DELETE'
    })
    .constant('TaskConstants', {
        ORDER_BY: [function(task) { return -task.type }, 'parentStory.rank', 'state', 'rank']
    })
    .constant('ActivityCodeByName', {
        SAVE: 'save',
        UPDATE: 'update',
        DELETE: 'delete'
    });<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import Reflux from 'reflux';
import Codemirror from 'react-codemirror';

import CMInstance from 'codemirror';
import CT3000 from '../../config/codemirrorCustomMode';

import 'codemirror/addon/mode/simple';
import 'codemirror/addon/selection/active-line';

import ObjectActions from '../../actions/object';
import ObjectStore from '../../stores/object';

export default class EditorPane extends React.Component {

  constructor(props) {
    super(props);

    this.updateCode = this.updateCode.bind(this);
    this.parseUntilLine = this.parseUntilLine.bind(this);

    this.lineInterval = null;
    this.lineTimeoutDuration = 500;

    this.state = {
      code: '',
      mode: '',
      languageInitiated: false
    };
  }

  componentDidMount() {
    this.unsubscribe = ObjectStore.listen((data) => {
      this.onUpdate(data);
    });

    this.cm = this.refs.editor.getCodeMirror();
    this.setLineInterval();

    // Example 'syntax error':
    // const doc = this.cm.getDoc();
    // doc.addLineClass(0,"wrap","syntax-error");
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  onUpdate(data) {
    if(!this.state.languageInitiated) {
      this.initLanguage();
    }
  }

  initLanguage() {
    let availableObjects = ObjectStore.getAvailableObjects();
    let availableValues = ObjectStore.getAvailableValues();

    var language = new CT3000();
    CMInstance.defineSimpleMode('ct-3000', language.getMode(availableObjects, availableValues));
    this.setState({
      mode: 'ct-3000',
      languageInitiated: true
    });
  }

  updateCode(newCode) {
    this.setState({
      code: newCode
    });
  }

  setLineInterval() {
    this.clearLineInterval();
    this.lineInterval = setInterval(this.parseUntilLine, this.lineTimeoutDuration);
  }

  clearLineInterval() {
    clearInterval(this.lineInterval);
  }

  parseUntilLine() {
    const currentLineNr = this.cm.getCursor().line;

    this.cm.eachLine(0, currentLineNr, (handle) => {
      const lineNr = this.cm.getLineNumber(handle);
      setTimeout(() => {
        this.parseLine(this.cm.getLineNumber(handle));
      }, 10 * lineNr);
    });

    setTimeout(() => {
      this.parseLine(currentLineNr, true);
    }, 10 * currentLineNr);
  }

  parseLine(lineNr, assign = false) {
    const lineContent = this.cm.getLine(lineNr);
    ObjectActions.parse(lineContent, assign);
  }

  render() {
    var options = {
      lineNumbers: true,
      lineWrapping: true,
      indentUnit: 2,
      tabSize: 2,
      theme: 'monokai',
      styleActiveLine: true,
      mode: this.state.mode
    };

    return (

        <Codemirror ref="editor" value={ this.state.code } onChange={ this.updateCode } options={ options } />

    );
  }

}
<commit_msg>Updates editor parse triggering<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import Reflux from 'reflux';
import Codemirror from 'react-codemirror';

import CMInstance from 'codemirror';
import CT3000 from '../../config/codemirrorCustomMode';

import 'codemirror/addon/mode/simple';
import 'codemirror/addon/selection/active-line';

import ObjectActions from '../../actions/object';
import ObjectStore from '../../stores/object';

export default class EditorPane extends React.Component {

  constructor(props) {
    super(props);

    this.updateCode = this.updateCode.bind(this);
    this.parseUntilLine = this.parseUntilLine.bind(this);

    this.state = {
      code: '',
      mode: '',
      languageInitiated: false
    };
  }

  componentDidMount() {
    this.unsubscribe = ObjectStore.listen((data) => {
      this.onUpdate(data);
    });

    this.cm = this.refs.editor.getCodeMirror();
    this.cm.on('cursorActivity', () => {
      this.parseUntilLine();
    });

    // Example 'syntax error':
    // const doc = this.cm.getDoc();
    // doc.addLineClass(0,"wrap","syntax-error");
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  onUpdate(data) {
    if(!this.state.languageInitiated) {
      this.initLanguage();
    }
  }

  initLanguage() {
    let availableObjects = ObjectStore.getAvailableObjects();
    let availableValues = ObjectStore.getAvailableValues();

    var language = new CT3000();
    CMInstance.defineSimpleMode('ct-3000', language.getMode(availableObjects, availableValues));
    this.setState({
      mode: 'ct-3000',
      languageInitiated: true
    });
  }

  updateCode(newCode) {
    this.setState({
      code: newCode
    });
  }

  parseUntilLine() {
    const currentLineNr = this.cm.getCursor().line;
    let lines = {};

    this.cm.eachLine(0, currentLineNr + 1, (handle) => {
      const lineNr = this.cm.getLineNumber(handle);
      const line = this.cm.getLine(lineNr);

      if(line && line.length > 0) {
        lines[lineNr] = {
          code: line,
          current: currentLineNr === lineNr
        }
      }
    });

    if(Object.keys(lines).length > 0) {
      ObjectActions.parseMulti(lines);
    }
  }

  render() {
    var options = {
      lineNumbers: true,
      lineWrapping: true,
      indentUnit: 2,
      tabSize: 2,
      theme: 'monokai',
      styleActiveLine: true,
      mode: this.state.mode
    };

    return (

        <Codemirror ref="editor" value={ this.state.code } onChange={ this.updateCode } options={ options } />

    );
  }

}
<|endoftext|>


<commit_before>/**
 * @ngdoc service
 * @name $ionicModal
 * @module meteoric
 * @description
 *
 * Related: {@link meteoric.controller:ionicModal ionicModal controller}.
 *
 * The Modal is a content pane that can go over the user's main view
 * temporarily.  Usually used for making a choice or editing an item.
 *
 * Put the content of the modal inside of an `<ion-modal-view>` element.
 *
 * @usage
 *
 * In your modal template, you place the contents of your modal dialogue:
 *
 * ```handlebars
 <template name="_myModal">
   {{#ionModal title="My Modal"}}
     <div class="padding">
       Modal Content Goes Here
     </div>
   {{/ionModal}}
 </template>
 * ```
 *
 * In your button, `data-ion-modal` set it to `_myModal`, the name of your `ionModal`.
 *
 * ```handlebars
   {{#ionContent}}
     <div class="padding">
       <button class="button button-large button-stable" data-ion-modal="_myModal">Open Modal</button>
     </div>
   {{/ionContent}}
 * ```
 */

$ionModal = {
  transitionEndEvent: 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd',
  animationEndEvent: 'animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd',
  enterClasses: ['ng-enter', 'slide-in-up'],
  enterActiveClass: 'ng-enter-active',
  leaveClasses: ['ng-leave', 'slide-in-up'],
  leaveActiveClass: 'ng-leave-active',
  view: {},
  views: [],
  open: function (templateName, data) {

    Meteor.setTimeout(function () {

      this.template = Template[templateName];
      this.views.push(templateName);
      if (!this.view[templateName]) this.view[templateName] = [];

      var view = Blaze.renderWithData(this.template, data, $('.ionic-body').get(0));
      this.view[templateName].push(view);

      var $modalBackdrop = $(view.firstNode());
      var $modal = $('.modal', $modalBackdrop);

      if (this.views.length === 1) {
        $modalBackdrop.addClass('active');
      }

      $modal.addClass(this.enterClasses.join(' '));
      Meteor.setTimeout(function () {
        $modal.addClass(this.enterActiveClass);
      }.bind(this), 50);

    }.bind(this), 0);

  },
  close: function (templateName) {

    this.templateClosed = templateName;
    Meteor.setTimeout(function () {

      var templateName = this.templateClosed || this.views.slice(-1)[0];
      delete this.templateClosed;

      var view = (this.view[templateName] || []).slice(-1)[0];
      if (!view) return;

      var $modalBackdrop = $(view.firstNode());
      var $modal = $('.modal', $modalBackdrop);

      $modal.addClass(this.leaveClasses.join(' '));
      Meteor.setTimeout(function () {
        $modal.addClass(this.leaveActiveClass);
      }.bind(this), 50);

      $modalBackdrop.fadeOut(500, function() {
        $('body').removeClass('modal-open');
      });

    }.bind(this), 0);

  }
};

$(document).delegate('.modal', $ionModal.transitionEndEvent, function(e) {
  var $modal = $(e.currentTarget);
  if ($modal.hasClass($ionModal.enterClasses.join(' ')) || $modal.hasClass($ionModal.enterActiveClasse)) {
    $modal.removeClass($ionModal.enterClasses.join(' ')).removeClass($ionModal.enterActiveClass);
    $('body').addClass('modal-open');
  } else if ($modal.hasClass($ionModal.leaveClasses.join(' ')) || $modal.hasClass($ionModal.leaveActiveClasse)) {
    var firstChild = $modal.children().first();
    var templateName = getElementModalTemplateName(firstChild);
    $ionModal.views = _.without($ionModal.views, templateName);
    var view = $ionModal.view[templateName].pop();
    var $modalBackdrop = $(view.firstNode());
    $modalBackdrop.removeClass('active');
    $modal.removeClass($ionModal.leaveClasses.join(' ')).removeClass($ionModal.leaveActiveClass).off($ionModal.transitionEndEvent);
    $('body').removeClass('modal-open');
    $(e.target).parents('.modal-backdrop').remove();
    Blaze.remove(view);
  }
});

Template.ionModal.created = function () {
  this.data = this.data || {};
  this.customTemplate = this.data.customTemplate || false;
  this.title = this.data.title;
  this.title = this.data.closeText;
  this.focusFirstInput = _.isUndefined(this.data.focusFirstInput) ? true : this.data.focusFirstInput;
  this.animation = this.data.animation || 'slide-in-up';
};

Template.ionModal.rendered = function () {
  if (this.focusFirstInput) {
    Meteor.setTimeout(function () {
      if (!this._domrange) return;
      this.$('input:first').focus();
    }.bind(this), 600);
  }
  $(window).on('keyup.ionModal', function(event) {
    event.stopImmediatePropagation();
    if (event.which == 27) {
      $ionModal.close();
    }
  });
};

Template.ionModal.destroyed = function () {
  if (!$ionModal.views.length) {
    $(window).off('keyup.ionModal');
  }
};

Template.ionModal.helpers({
  barClass: function () {
    var defaultClasses = ['bar', 'bar-header', 'bar-stable'].join(' ');
    var customClasses = _.isString(this.barClass) ? this.barClass : '';
    return [defaultClasses, customClasses].join(' ');
  },

  titleClass: function () {
    var classes = ['title'];

    if (ionic.Platform.isAndroid()) {
      classes.push('title-left');
    }

    return classes.join(' ');
  },

  title: function () {
    return this.title;
  },

  closeText: function () {
    return this.closeText;
  },

  animation: function () {
    return this.animation || 'slide-in-up';
  },

  customTemplate: function () {
    return this.customTemplate;
  },

  classes: function () {
    var classes = ['modal'];

    if (this.class) {
      classes.push(this.class);
    }

    return classes.join(' ');
  }

});

Template.ionModal.events({
  // Handle clicking the backdrop
  'click': function (event, template) {
    if ($(event.target).hasClass('modal-backdrop')) {
      $ionModal.close();
    }
  },
  'click [data-dismiss=modal]': function (event, template) {
    var tplName = getElementModalTemplateName(event.currentTarget);
    $ionModal.close(tplName);
  }
});

var getElementModalTemplateName = function(element) {
  var modal = $(element).parents('.modal').get(0);
  var modalView = Blaze.getView(modal);
  var tplView = Meteor._get(modalView, 'parentView', 'parentView'); // Twice because the parent view is a #with block
  var tplName = tplView.name.slice('Template.'.length, tplView.name.length);
  return tplName;
};

// todo: Try to use the attribute-directive library.
$('body').on('click', '[data-ion-modal]', function(e) {
  let modal_template = $(e.target).data('ion-modal');
  $ionModal.open(modal_template, $(e.target).data());
});<commit_msg>ionModal anchors to a non-existent .ionic-body class. This is changed to just body.<commit_after>/**
 * @ngdoc service
 * @name $ionicModal
 * @module meteoric
 * @description
 *
 * Related: {@link meteoric.controller:ionicModal ionicModal controller}.
 *
 * The Modal is a content pane that can go over the user's main view
 * temporarily.  Usually used for making a choice or editing an item.
 *
 * Put the content of the modal inside of an `<ion-modal-view>` element.
 *
 * @usage
 *
 * In your modal template, you place the contents of your modal dialogue:
 *
 * ```handlebars
 <template name="_myModal">
   {{#ionModal title="My Modal"}}
     <div class="padding">
       Modal Content Goes Here
     </div>
   {{/ionModal}}
 </template>
 * ```
 *
 * In your button, `data-ion-modal` set it to `_myModal`, the name of your `ionModal`.
 *
 * ```handlebars
   {{#ionContent}}
     <div class="padding">
       <button class="button button-large button-stable" data-ion-modal="_myModal">Open Modal</button>
     </div>
   {{/ionContent}}
 * ```
 */

$ionModal = {
  transitionEndEvent: 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd',
  animationEndEvent: 'animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd',
  enterClasses: ['ng-enter', 'slide-in-up'],
  enterActiveClass: 'ng-enter-active',
  leaveClasses: ['ng-leave', 'slide-in-up'],
  leaveActiveClass: 'ng-leave-active',
  view: {},
  views: [],
  open: function (templateName, data) {

    Meteor.setTimeout(function () {

      this.template = Template[templateName];
      this.views.push(templateName);
      if (!this.view[templateName]) this.view[templateName] = [];

      var view = Blaze.renderWithData(this.template, data, $('body').get(0));
      this.view[templateName].push(view);

      var $modalBackdrop = $(view.firstNode());
      var $modal = $('.modal', $modalBackdrop);

      if (this.views.length === 1) {
        $modalBackdrop.addClass('active');
      }

      $modal.addClass(this.enterClasses.join(' '));
      Meteor.setTimeout(function () {
        $modal.addClass(this.enterActiveClass);
      }.bind(this), 50);

    }.bind(this), 0);

  },
  close: function (templateName) {

    this.templateClosed = templateName;
    Meteor.setTimeout(function () {

      var templateName = this.templateClosed || this.views.slice(-1)[0];
      delete this.templateClosed;

      var view = (this.view[templateName] || []).slice(-1)[0];
      if (!view) return;

      var $modalBackdrop = $(view.firstNode());
      var $modal = $('.modal', $modalBackdrop);

      $modal.addClass(this.leaveClasses.join(' '));
      Meteor.setTimeout(function () {
        $modal.addClass(this.leaveActiveClass);
      }.bind(this), 50);

      $modalBackdrop.fadeOut(500, function() {
        $('body').removeClass('modal-open');
      });

    }.bind(this), 0);

  }
};

$(document).delegate('.modal', $ionModal.transitionEndEvent, function(e) {
  var $modal = $(e.currentTarget);
  if ($modal.hasClass($ionModal.enterClasses.join(' ')) || $modal.hasClass($ionModal.enterActiveClasse)) {
    $modal.removeClass($ionModal.enterClasses.join(' ')).removeClass($ionModal.enterActiveClass);
    $('body').addClass('modal-open');
  } else if ($modal.hasClass($ionModal.leaveClasses.join(' ')) || $modal.hasClass($ionModal.leaveActiveClasse)) {
    var firstChild = $modal.children().first();
    var templateName = getElementModalTemplateName(firstChild);
    $ionModal.views = _.without($ionModal.views, templateName);
    var view = $ionModal.view[templateName].pop();
    var $modalBackdrop = $(view.firstNode());
    $modalBackdrop.removeClass('active');
    $modal.removeClass($ionModal.leaveClasses.join(' ')).removeClass($ionModal.leaveActiveClass).off($ionModal.transitionEndEvent);
    $('body').removeClass('modal-open');
    $(e.target).parents('.modal-backdrop').remove();
    Blaze.remove(view);
  }
});

Template.ionModal.created = function () {
  this.data = this.data || {};
  this.customTemplate = this.data.customTemplate || false;
  this.title = this.data.title;
  this.title = this.data.closeText;
  this.focusFirstInput = _.isUndefined(this.data.focusFirstInput) ? true : this.data.focusFirstInput;
  this.animation = this.data.animation || 'slide-in-up';
};

Template.ionModal.rendered = function () {
  if (this.focusFirstInput) {
    Meteor.setTimeout(function () {
      if (!this._domrange) return;
      this.$('input:first').focus();
    }.bind(this), 600);
  }
  $(window).on('keyup.ionModal', function(event) {
    event.stopImmediatePropagation();
    if (event.which == 27) {
      $ionModal.close();
    }
  });
};

Template.ionModal.destroyed = function () {
  if (!$ionModal.views.length) {
    $(window).off('keyup.ionModal');
  }
};

Template.ionModal.helpers({
  barClass: function () {
    var defaultClasses = ['bar', 'bar-header', 'bar-stable'].join(' ');
    var customClasses = _.isString(this.barClass) ? this.barClass : '';
    return [defaultClasses, customClasses].join(' ');
  },

  titleClass: function () {
    var classes = ['title'];

    if (ionic.Platform.isAndroid()) {
      classes.push('title-left');
    }

    return classes.join(' ');
  },

  title: function () {
    return this.title;
  },

  closeText: function () {
    return this.closeText;
  },

  animation: function () {
    return this.animation || 'slide-in-up';
  },

  customTemplate: function () {
    return this.customTemplate;
  },

  classes: function () {
    var classes = ['modal'];

    if (this.class) {
      classes.push(this.class);
    }

    return classes.join(' ');
  }

});

Template.ionModal.events({
  // Handle clicking the backdrop
  'click': function (event, template) {
    if ($(event.target).hasClass('modal-backdrop')) {
      $ionModal.close();
    }
  },
  'click [data-dismiss=modal]': function (event, template) {
    var tplName = getElementModalTemplateName(event.currentTarget);
    $ionModal.close(tplName);
  }
});

var getElementModalTemplateName = function(element) {
  var modal = $(element).parents('.modal').get(0);
  var modalView = Blaze.getView(modal);
  var tplView = Meteor._get(modalView, 'parentView', 'parentView'); // Twice because the parent view is a #with block
  var tplName = tplView.name.slice('Template.'.length, tplView.name.length);
  return tplName;
};

// todo: Try to use the attribute-directive library.
$('body').on('click', '[data-ion-modal]', function(e) {
  let modal_template = $(e.target).data('ion-modal');
  $ionModal.open(modal_template, $(e.target).data());
});<|endoftext|>


<commit_before>import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';

import { Patients } from '../api/patients.js';

import './patient_info.html';
import './patient_info.css';

// This dumy patient is just to represent the "empty template"
// meaning giving "fake" context data to the template
const dummy_patient = {
	"_id" : '000',
	"lastName" : "last name",
	"firstName" : "first name",
	"gender" : "male",
	"birthDate" : new Date(),
	"maritalStatus" : "single",
	"race" : "white",
	"allergies" : "none",
	"height" : 180,
	"weight" : 80
}

Template.patient_info.helpers({
   patient() {
   	//return a single patient for template data context
   	const instance = Template.instance();
    if (instance.state.get('patientID')) {//check patient that has been selected on the dropdown
      const patientID = instance.state.get('patientID');
      return Patients.findOne({'patientID' : Number(patientID)});
    }
    return Patients.findOne();
    // return dummy_patient;
  },
   patients() {
    // return Patients.find({});
    return Patients.find({}, {sort : {'lastName':1, 'firstName' : 1} });
  },
  calc_age() {
//calculate age. See http://stackoverflow.com/a/21984136/3961519
	if (this.birthDate == undefined)
	return '' ;

  	const ageDifMs = Date.now() - this.birthDate.getTime();
    const ageDate = new Date(ageDifMs); // miliseconds from epoch
    return Math.abs(ageDate.getUTCFullYear() - 1970);
  }
  ,hasAllergies () {
  	return patientHasAllergies(this);
  }
  ,noAllergies(){
  	return !patientHasAllergies(this);
  }

  // retruns a patient assesment base on their metrics
  // this function returns a JSON object with
  //  - color : background color to display in the UI:
  //		Healthy green : textcolor: '#0f3d0f, backgroundcolor : '#33cc33',
  //		Alert Yellow  : textcolor: #8a6d3b,  backgroundcolor: #ffff00;
  //		Danger Red    : textcolor: #fff, 	 backgroundcolor: #ff0000;
  //		Info blue     : textcolor: #31708f;  backgroundcolor: #d9edf7;
  //  - message : message to display to the clinical staff
  ,patientAssesment() {
  	return {
  		backgroundcolor : '#33cc33',
  		textcolor: '#0f3d0f',
  		// alert : 'alert-danger',
  		message : 'Patient OK'
  	}
  }

});

// Auxiliarify function to reuse functionality.
// returns 'true' if the patient has allergies
// (the parameter patient object has an allergies field and its content is not 'none')
patientHasAllergies = function(patient){
	if (patient === undefined || patient.allergies === undefined)
  		return false;
  	if (patient.allergies == null || patient.allergies.trim() === '' || patient.allergies === 'none')
  		return false;

  	return true;
}

Template.patient_info.events({
	 "change #patient-select": function (event, template) {
        var patientID = template.$(event.currentTarget).val();
        template.state.set('patientID', patientID);
        // console.log(patientID);
    }

});

Template.patient_info.onCreated(function piOnCreated() {
  Meteor.subscribe('patients_demo');
  this.state = new ReactiveDict();

});<commit_msg>modified the patient assesment function<commit_after>import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';

import { Patients } from '../api/patients.js';

import './patient_info.html';
import './patient_info.css';

// This dumy patient is just to represent the "empty template"
// meaning giving "fake" context data to the template
const dummy_patient = {
	"_id" : '000',
	"lastName" : "last name",
	"firstName" : "first name",
	"gender" : "male",
	"birthDate" : new Date(),
	"maritalStatus" : "single",
	"race" : "white",
	"allergies" : "none",
	"height" : 180,
	"weight" : 80
}

Template.patient_info.helpers({
   patient() {
   	//return a single patient for template data context
   	const instance = Template.instance();
    if (instance.state.get('patientID')) {//check patient that has been selected on the dropdown
      const patientID = instance.state.get('patientID');
      return Patients.findOne({'patientID' : Number(patientID)});
    }
    return Patients.findOne();
    // return dummy_patient;
  },
   patients() {
    // return Patients.find({});
    return Patients.find({}, {sort : {'lastName':1, 'firstName' : 1} });
  },
  calc_age() {
//calculate age. See http://stackoverflow.com/a/21984136/3961519
	if (this.birthDate == undefined)
	return '' ;

  	const ageDifMs = Date.now() - this.birthDate.getTime();
    const ageDate = new Date(ageDifMs); // miliseconds from epoch
    return Math.abs(ageDate.getUTCFullYear() - 1970);
  }
  ,hasAllergies () {
  	return patientHasAllergies(this);
  }
  ,noAllergies(){
  	return !patientHasAllergies(this);
  }

  // returns a patient assesment base on their metrics
  // this function returns a JSON object with
  //  - color : background color to display in the UI:
  //		Healthy green : textcolor: '#0f3d0f, backgroundcolor : '#33cc33',
  //		Alert Yellow  : textcolor: #8a6d3b,  backgroundcolor: #ffff00;
  //		Danger Red    : textcolor: #fff, 	 backgroundcolor: #ff0000;
  //		Info blue     : textcolor: #31708f;  backgroundcolor: #d9edf7;
  //  - message : message to display to the clinical staff
  ,patientAssesment() {
  	return {
  		backgroundcolor : '#33cc33',
  		textcolor: '#0f3d0f',
  		// alert : 'alert-danger',
  		message : 'Patient OK',
  		status : 'Healthy' // healthy, alert, danger, info.
  	}
  }

});

// Auxiliarify function to reuse functionality.
// returns 'true' if the patient has allergies
// (the parameter patient object has an allergies field and its content is not 'none')
patientHasAllergies = function(patient){
	if (patient === undefined || patient.allergies === undefined)
  		return false;
  	if (patient.allergies == null || patient.allergies.trim() === '' || patient.allergies === 'none')
  		return false;

  	return true;
}

Template.patient_info.events({
	 "change #patient-select": function (event, template) {
        var patientID = template.$(event.currentTarget).val();
        template.state.set('patientID', patientID);
        // console.log(patientID);
    }

});

Template.patient_info.onCreated(function piOnCreated() {
  Meteor.subscribe('patients_demo');
  this.state = new ReactiveDict();

});<|endoftext|>


<commit_before>/**
 * @constructor
 */
function WindowController() {
  this.currentTab_ = null;
  $('#window-close').click(this.close_.bind(this));
  $('#window-maximize').click(this.maximize_.bind(this));
  $('#toggle-sidebar').click(this.toggleSidebar_.bind(this));
  $(document).bind('switchtab', this.onChangeTab_.bind(this));
  $(document).bind('tabrenamed', this.onChangeTab_.bind(this));
  $(document).bind('tabchange', this.onTabChange_.bind(this));
  $(document).bind('tabsave', this.onTabChange_.bind(this));
}

WindowController.prototype.close_ = function() {
  window.close();
};

WindowController.prototype.maximize_ = function() {
  var maximized = window.outerHeight == window.screen.availHeight &&
                  window.outerWidth == window.screen.availWidth;

  if (maximized) {
    window.chrome.app.window.current().restore();
  } else {
    window.chrome.app.window.current().maximize();
  }
};

WindowController.prototype.toggleSidebar_ = function() {
  $('body').toggleClass('sidebar-open');
  setTimeout(function() {$.event.trigger('resize');}, 200);
};

WindowController.prototype.onChangeTab_ = function(e, tab) {
  this.currentTab_ = tab;
  $('#title-filename').text(tab.getName());
};

WindowController.prototype.onTabChange_ = function(e, tab) {
  if (this.currentTab_.isSaved()) {
    $('#title-filename').removeClass('unsaved');
  } else {
    $('#title-filename').addClass('unsaved');
  }
};
<commit_msg>Change sidebar toggle button title to Open/Close sidebar depending on whether it is open.<commit_after>/**
 * @constructor
 */
function WindowController() {
  this.currentTab_ = null;
  $('#window-close').click(this.close_.bind(this));
  $('#window-maximize').click(this.maximize_.bind(this));
  $('#toggle-sidebar').click(this.toggleSidebar_.bind(this));
  $(document).bind('switchtab', this.onChangeTab_.bind(this));
  $(document).bind('tabrenamed', this.onChangeTab_.bind(this));
  $(document).bind('tabchange', this.onTabChange_.bind(this));
  $(document).bind('tabsave', this.onTabChange_.bind(this));
}

WindowController.prototype.close_ = function() {
  window.close();
};

WindowController.prototype.maximize_ = function() {
  var maximized = window.outerHeight == window.screen.availHeight &&
                  window.outerWidth == window.screen.availWidth;

  if (maximized) {
    window.chrome.app.window.current().restore();
  } else {
    window.chrome.app.window.current().maximize();
  }
};

WindowController.prototype.toggleSidebar_ = function() {
  $('body').toggleClass('sidebar-open');
  $('#editor textarea').focus();
  if ($('body').hasClass('sidebar-open')) {
    $('#toggle-sidebar').attr('title', 'Close sidebar');
  } else {
    $('#toggle-sidebar').attr('title', 'Open sidebar');
  }
  setTimeout(function() {$.event.trigger('resize');}, 200);
};

WindowController.prototype.onChangeTab_ = function(e, tab) {
  this.currentTab_ = tab;
  $('#title-filename').text(tab.getName());
};

WindowController.prototype.onTabChange_ = function(e, tab) {
  if (this.currentTab_.isSaved()) {
    $('#title-filename').removeClass('unsaved');
  } else {
    $('#title-filename').addClass('unsaved');
  }
};
<|endoftext|>


<commit_before>'use strict';

/* Controllers */
var vanavaniControllers = angular.module('vanavaniControllers');

vanavaniControllers.controller('studentsCtrl',
        function($scope, $location, $http) {

		$scope.toggleModal = function(imageName) {
			console.log(imageName);
			var name = imageName;
			name = name.replace("_medium.jpg", "");
			name = name.replace("_medium.JPG", "");
		    $scope.modalDialogImage = "images/students/" + name;

		    $scope.modalShown = !$scope.modalShown;
		};

		$scope.filterOptions = {
        	        filterText: "",
        	        useExternalFilter: false
        	    };
          $scope.totalServerItems = 0;
          $scope.pagingOptions = {
              pageSizes: [10, 250, 500, 1000],
              pageSize: 10,
              currentPage: 1
          };
          $scope.setPagingData = function(data, page, pageSize){
        	  $scope.myData = data;
              if (!$scope.$$phase) {
                  $scope.$apply();
              }
          };
          $scope.getPagedDataAsync = function (pageSize, page, searchText) {
              setTimeout(function () {
                  var data;
                  var url = 'jsondata/studentsDetails.json';

                  if (searchText) {
                      var ft = searchText.toLowerCase();
                      $http.get(url).success(function (largeLoad) {
                          data = largeLoad.filter(function(item) {
                              return JSON.stringify(item).toLowerCase().indexOf(ft) != -1;
                          });
                          $scope.setPagingData(data,page,pageSize);
                      });
                  } else {
                      $http.get(url).success(function (largeLoad) {
                          $scope.setPagingData(largeLoad,page,pageSize);
                      });
                  }
              }, 100);
          };
          $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);
          $scope.$watch('pagingOptions', function (newVal, oldVal) {
              if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {
                $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
              }
          }, true);
          $scope.$watch('filterOptions', function (newVal, oldVal) {
              if (newVal !== oldVal) {
                $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
              }
          }, true);
          $scope.gridOptions = {
        	        data: 'myData',
        	        enablePaging: false,
        			showFooter: true,
        	        totalServerItems: 'totalServerItems',
        	        filterOptions: $scope.filterOptions,
        	        showFilter: true,
        	        enableColumnResize: true,
        	        enableColumnReordering: true,
        	        showColumnMenu: true,
        	        showGroupPanel: true,
        	        rowHeight: 90,
        	        columnDefs: [
     	        	            {field: "StudentName", width: 200},
     	        	            {field: "PhotoFileName", width: 200,
     	        	            	cellTemplate: '
<button ng-click="toggleModal(row.getProperty(col.field))"></button>
'},
     	        	            {field: "Class", width: 50},
     	        	            {field: "FatherOccupation", width: 120},
     	        	            {field: "siblings", width: 100},
     	        	            {field: "TV", width: 100},
     	        	            {field: "newspaper", width: 100},
     	        	            {field: "Internet", width: 100},
     	        	            {field: "vehicle", width: 100},
     	        	            {field: "Readinghabit", width: 100},
     	        	            {field: "TVProgramName", width: 150},
     	        	            {field: "FatherName", width: 125, visible: false},
     	        	            {field: "MotherName", width: 125, visible: false},
     	        	            {field: "MotherOccupation", width: 100, visible: false},
     	        	            {field: "VacationActivity", width:125, visible: false}
     	        	        ]
        	    };

        });

<commit_msg>modal dialog<commit_after>'use strict';

/* Controllers */
var vanavaniControllers = angular.module('vanavaniControllers');

vanavaniControllers.controller('studentsCtrl',
        function($scope, $location, $http) {

		$scope.toggleModal = function(imageName) {
			var name = imageName;
			name = name.replace("_medium.jpg", "");
			name = name.replace("_medium.JPG", "");
		    $scope.modalDialogImage = "images/students/" + name;

		    $scope.modalShown = !$scope.modalShown;
		};

		$scope.filterOptions = {
        	        filterText: "",
        	        useExternalFilter: false
        	    };
          $scope.totalServerItems = 0;
          $scope.pagingOptions = {
              pageSizes: [10, 250, 500, 1000],
              pageSize: 10,
              currentPage: 1
          };
          $scope.setPagingData = function(data, page, pageSize){
        	  $scope.myData = data;
              if (!$scope.$$phase) {
                  $scope.$apply();
              }
          };
          $scope.getPagedDataAsync = function (pageSize, page, searchText) {
              setTimeout(function () {
                  var data;
                  var url = 'jsondata/studentsDetails.json';

                  if (searchText) {
                      var ft = searchText.toLowerCase();
                      $http.get(url).success(function (largeLoad) {
                          data = largeLoad.filter(function(item) {
                              return JSON.stringify(item).toLowerCase().indexOf(ft) != -1;
                          });
                          $scope.setPagingData(data,page,pageSize);
                      });
                  } else {
                      $http.get(url).success(function (largeLoad) {
                          $scope.setPagingData(largeLoad,page,pageSize);
                      });
                  }
              }, 100);
          };
          $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);
          $scope.$watch('pagingOptions', function (newVal, oldVal) {
              if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {
                $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
              }
          }, true);
          $scope.$watch('filterOptions', function (newVal, oldVal) {
              if (newVal !== oldVal) {
                $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
              }
          }, true);
          $scope.gridOptions = {
        	        data: 'myData',
        	        enablePaging: false,
        			showFooter: true,
        	        totalServerItems: 'totalServerItems',
        	        filterOptions: $scope.filterOptions,
        	        showFilter: true,
        	        enableColumnResize: true,
        	        enableColumnReordering: true,
        	        showColumnMenu: true,
        	        showGroupPanel: true,
        	        rowHeight: 90,
        	        columnDefs: [
     	        	            {field: "StudentName", width: 200},
     	        	            {field: "PhotoFileName", width: 200,
     	        	            	cellTemplate: '
<button ng-click="toggleModal(row.getProperty(col.field))"></button>
'},
     	        	            {field: "Class", width: 50},
     	        	            {field: "FatherOccupation", width: 120},
     	        	            {field: "siblings", width: 100},
     	        	            {field: "TV", width: 100},
     	        	            {field: "newspaper", width: 100},
     	        	            {field: "Internet", width: 100},
     	        	            {field: "vehicle", width: 100},
     	        	            {field: "Readinghabit", width: 100},
     	        	            {field: "TVProgramName", width: 150},
     	        	            {field: "FatherName", width: 125, visible: false},
     	        	            {field: "MotherName", width: 125, visible: false},
     	        	            {field: "MotherOccupation", width: 100, visible: false},
     	        	            {field: "VacationActivity", width:125, visible: false}
     	        	        ]
        	    };

        });

<|endoftext|>


<commit_before>/**
 * Event Dispatcher
 *
 * Event model designed to bring events into line with DOM events and those
 * found in HTML DOM, jQuery and ActionScript 2 & 3, offering a more
 * predictable, object based approach to event dispatching and handling
 *
 * Should be used as the base class for any class that won't be used for
 * data binding
 *
 * @class		conbo.EventDispatcher
 * @augments	conbo.Class
 * @author		Neil Rackett
 * @param 		{object} options - Object containing optional initialisation options, including 'context'
 */
conbo.EventDispatcher = conbo.ConboClass.extend(
/** @lends conbo.EventDispatcher.prototype */
{
	/**
	 * Do not override: use initialize
	 * @private
	 */
	__construct: function(options)
	{
		if (!!options.context)
		{
			this.context = options.context;
		}
	},

	/**
	 * Add a listener for a particular event type
	 *
	 * @param type		{string}	Type of event ('change') or events ('change blur')
	 * @param handler	{function}	Function that should be called
	 * @param scope		{object}	The scope in which to run the event handler (optional)
	 * @param priority	{number}	The event handler's priority when the event is dispatached (default: 0)
	 * @param once		{boolean}	Should the event listener automatically be removed after it has been called once? (default: false)
	 */
	addEventListener: function(type, handler, scope, priority, once)
	{
		if (!type) throw new Error('Event type undefined');
		if (!handler || !conbo.isFunction(handler)) throw new Error('Event handler is undefined or not a function');

		if (conbo.isString(type)) type = type.split(' ');
		if (conbo.isArray(type)) conbo.forEach(type, function(value, index, list) { this.__addEventListener(value, handler, scope, priority, !!once); }, this);

		return this;
	},

	/**
	 * Remove a listener for a particular event type
	 *
	 * @param type		{string}	Type of event ('change') or events ('change blur') (optional: if not specified, all listeners will be removed)
	 * @param handler	{function}	Function that should be called (optional: if not specified, all listeners of the specified type will be removed)
	 * @param scope		{object} 	The scope in which the handler is set to run (optional)
	 */
	removeEventListener: function(type, handler, scope)
	{
		if (!arguments.length)
		{
			__defineUnenumerableProperty(this, '__queue', {});
			return this;
		}

		if (conbo.isString(type)) type = type.split(' ');
		if (!conbo.isArray(type)) type = [undefined];

		conbo.forEach(type, function(value, index, list)
		{
			this.__removeEventListener(value, handler, scope);
		},
		this);

		return this;
	},

	/**
	 * Does this object have an event listener of the specified type?
	 *
	 * @param type		{string}	Type of event (e.g. 'change')
	 * @param handler	{function}	Function that should be called (optional)
	 * @param scope		{object} 	The scope in which the handler is set to run (optional)
	 */
	hasEventListener: function(type, handler, scope)
	{
		if (!this.__queue
			|| !this.__queue[type]
			|| !this.__queue[type].length)
		{
			return false;
		}

		var queue = this.__queue[type];
		var length = queue.length;

		for (var i=0; i<length; i++)
		{
			if ((!handler || queue[i].handler == handler)
				&& (!scope || queue[i].scope == scope))
			{
				return true;
			}
		}

		return false;
	},

	/**
	 * Dispatch the event to listeners
	 * @param event		conbo.Event class instance or event type (e.g. 'change')
	 */
	dispatchEvent: function(event)
	{
		if (!event) throw new Error('Event undefined');

		var isString = conbo.isString(event);

		if (isString)
		{
			conbo.warn('Use of dispatchEvent("'+event+'") is deprecated, please use dispatchEvent(new conbo.Event("'+event+'"))');
		}

		if (isString || !(event instanceof conbo.Event))
		{
			event = new conbo.Event(event);
		}

		if (!this.__queue || (!(event.type in this.__queue) && !this.__queue.all)) return this;

		if (!event.target) event.target = this;
		event.currentTarget = this;

		var queue = conbo.union(this.__queue[event.type] || [], this.__queue.all || []);
		if (!queue || !queue.length) return this;

		for (var i=0, length=queue.length; i<length; ++i)
		{
			var value = queue[i];
			var returnValue = value.handler.call(value.scope || this, event);
			if (value.once) this.__removeEventListener(event.type, value.handler, value.scope);
			if (returnValue === false || event.immediatePropagationStopped) break;
		}

		return this;
	},

	/**
	 * Dispatch a change event for one or more changed properties
	 * @param propName
	 */
	dispatchChange: function()
	{
		conbo.forEach(arguments, function(propName)
		{
			__dispatchChange(this, propName);
		},
		this);

		return this;
	},

	toString: function()
	{
		return 'conbo.EventDispatcher';
	},

	/**
	 * @private
	 */
	__addEventListener: function(type, handler, scope, priority, once)
	{
		if (type == '*') type = 'all';
		if (!this.__queue) __defineUnenumerableProperty(this, '__queue', {});

		if (!this.hasEventListener(type, handler, scope))
		{
			if (!(type in this.__queue)) this.__queue[type] = [];
			this.__queue[type].push({handler:handler, scope:scope, once:once, priority:priority||0});
			this.__queue[type].sort(function(a,b){return b.priority-a.priority;});
		}
	},

	/**
	 * @private
	 */
	__removeEventListener: function(type, handler, scope)
	{
		if (type == '*') type = 'all';
		if (!this.__queue || !(type in this.__queue)) return this;

		var queue = this.__queue[type];

		if (arguments.length == 1)
		{
			delete this.__queue[type];
			return this;
		}

		for (var i=0; i<queue.length; i++)
		{
			if ((!queue[i].handler || queue[i].handler == handler)
				&& (!queue[i].scope || queue[i].scope == scope))
			{
				queue.splice(i--, 1);
			}
		}

		if (!queue.length)
		{
			delete this.__queue[type];
		}

		return this;
	},

}).implement(conbo.IInjectable);

__defineUnenumerableProperty(conbo.EventDispatcher.prototype, 'bindable');
__denumerate(conbo.EventDispatcher.prototype);
<commit_msg>Updated removeEventListener<commit_after>/**
 * Event Dispatcher
 *
 * Event model designed to bring events into line with DOM events and those
 * found in HTML DOM, jQuery and ActionScript 2 & 3, offering a more
 * predictable, object based approach to event dispatching and handling
 *
 * Should be used as the base class for any class that won't be used for
 * data binding
 *
 * @class		conbo.EventDispatcher
 * @augments	conbo.Class
 * @author		Neil Rackett
 * @param 		{object} options - Object containing optional initialisation options, including 'context'
 */
conbo.EventDispatcher = conbo.ConboClass.extend(
/** @lends conbo.EventDispatcher.prototype */
{
	/**
	 * Do not override: use initialize
	 * @private
	 */
	__construct: function(options)
	{
		if (!!options.context)
		{
			this.context = options.context;
		}
	},

	/**
	 * Add a listener for a particular event type
	 *
	 * @param type		{string}	Type of event ('change') or events ('change blur')
	 * @param handler	{function}	Function that should be called
	 * @param scope		{object}	The scope in which to run the event handler (optional)
	 * @param priority	{number}	The event handler's priority when the event is dispatached (default: 0)
	 * @param once		{boolean}	Should the event listener automatically be removed after it has been called once? (default: false)
	 */
	addEventListener: function(type, handler, scope, priority, once)
	{
		if (!type) throw new Error('Event type undefined');
		if (!handler || !conbo.isFunction(handler)) throw new Error('Event handler is undefined or not a function');

		if (conbo.isString(type)) type = type.split(' ');
		if (conbo.isArray(type)) conbo.forEach(type, function(value, index, list) { this.__addEventListener(value, handler, scope, priority, !!once); }, this);

		return this;
	},

	/**
	 * Remove a listener for a particular event type
	 *
	 * @param type		{string}	Type of event ('change') or events ('change blur') (optional: if not specified, all listeners will be removed)
	 * @param handler	{function}	Function that should be called (optional: if not specified, all listeners of the specified type will be removed)
	 * @param scope		{object} 	The scope in which the handler is set to run (optional)
	 */
	removeEventListener: function(type, handler, scope)
	{
		if (!arguments.length)
		{
			__defineUnenumerableProperty(this, '__queue', {});
			return this;
		}

		if (conbo.isString(type)) type = type.split(' ');
		if (!conbo.isArray(type)) type = [undefined];

		conbo.forEach(type, function(value, index, list)
		{
			this.__removeEventListener(value, handler, scope);
		},
		this);

		return this;
	},

	/**
	 * Does this object have an event listener of the specified type?
	 *
	 * @param type		{string}	Type of event (e.g. 'change')
	 * @param handler	{function}	Function that should be called (optional)
	 * @param scope		{object} 	The scope in which the handler is set to run (optional)
	 */
	hasEventListener: function(type, handler, scope)
	{
		if (!this.__queue
			|| !(type in this.__queue)
			|| !this.__queue[type].length)
		{
			return false;
		}

		var queue = this.__queue[type];
		var length = queue.length;

		for (var i=0; i<length; i++)
		{
			if ((!handler || queue[i].handler == handler)
				&& (!scope || queue[i].scope == scope))
			{
				return true;
			}
		}

		return false;
	},

	/**
	 * Dispatch the event to listeners
	 * @param event		conbo.Event class instance or event type (e.g. 'change')
	 */
	dispatchEvent: function(event)
	{
		if (!event) throw new Error('Event undefined');

		var isString = conbo.isString(event);

		if (isString)
		{
			conbo.warn('Use of dispatchEvent("'+event+'") is deprecated, please use dispatchEvent(new conbo.Event("'+event+'"))');
		}

		if (isString || !(event instanceof conbo.Event))
		{
			event = new conbo.Event(event);
		}

		if (!this.__queue || (!(event.type in this.__queue) && !this.__queue.all)) return this;

		if (!event.target) event.target = this;
		event.currentTarget = this;

		var queue = conbo.union(this.__queue[event.type] || [], this.__queue.all || []);
		if (!queue || !queue.length) return this;

		for (var i=0, length=queue.length; i<length; ++i)
		{
			var value = queue[i];
			var returnValue = value.handler.call(value.scope || this, event);
			if (value.once) this.__removeEventListener(event.type, value.handler, value.scope);
			if (returnValue === false || event.immediatePropagationStopped) break;
		}

		return this;
	},

	/**
	 * Dispatch a change event for one or more changed properties
	 * @param propName
	 */
	dispatchChange: function()
	{
		conbo.forEach(arguments, function(propName)
		{
			__dispatchChange(this, propName);
		},
		this);

		return this;
	},

	toString: function()
	{
		return 'conbo.EventDispatcher';
	},

	/**
	 * @private
	 */
	__addEventListener: function(type, handler, scope, priority, once)
	{
		if (type == '*') type = 'all';
		if (!this.__queue) __defineUnenumerableProperty(this, '__queue', {});

		if (!this.hasEventListener(type, handler, scope))
		{
			if (!(type in this.__queue)) this.__queue[type] = [];
			this.__queue[type].push({handler:handler, scope:scope, once:once, priority:priority||0});
			this.__queue[type].sort(function(a,b){return b.priority-a.priority;});
		}
	},

	/**
	 * @private
	 */
	__removeEventListener: function(type, handler, scope)
	{
		if (type == '*') type = 'all';
		if (!this.__queue) return;

		var queue,
			i,
			self = this;

		var removeFromQueue = function(queue, key)
		{
			for (i=0; i<queue.length; i++)
			{
				if ((!queue[i].handler || queue[i].handler == handler)
					&& (!queue[i].scope || queue[i].scope == scope))
				{
					queue.splice(i--, 1);
				}
			}

			if (!queue.length)
			{
				delete self.__queue[key];
			}
		};

		if (type in this.__queue)
		{
			queue = this.__queue[type];
			removeFromQueue(queue, type);
		}
		else if (type == undefined)
		{
			conbo.forEach(this.__queue, function(queue, key)
			{
				removeFromQueue(queue, key);
			});
		}
	},

}).implement(conbo.IInjectable);

__defineUnenumerableProperty(conbo.EventDispatcher.prototype, 'bindable');
__denumerate(conbo.EventDispatcher.prototype);
<|endoftext|>


<commit_before>Posts = new Mongo.Collection('posts');

NonEmptyString = Match.Where(function (x) {
  check(x, String);
  return x.length > 0;
});

Meteor.methods({
  postInsert: function(postAttributes) {
    check(Meteor.userId(), String);
    check(postAttributes, {
      title: NonEmptyString,
      url: NonEmptyString,
      slug: NonEmptyString
    });

    var postWithSameLink = Posts.findOne({url: postAttributes.url});
    if (postWithSameLink) {
      return {
        postExists: true,
        _id: postWithSameLink._id
      }
    }

    var user = Meteor.user();
    var post = _.extend(postAttributes, {
      userId: user._id,
      author: user.emails[0].address,
      submitted: new Date()
    });

    var postId = Posts.insert(post);
    return {
      _id: postId
    };

  }
});<commit_msg>Lookup slug instead of URL as this must be unique<commit_after>Posts = new Mongo.Collection('posts');

NonEmptyString = Match.Where(function (x) {
  check(x, String);
  return x.length > 0;
});

Meteor.methods({
  postInsert: function(postAttributes) {
    check(Meteor.userId(), String);
    check(postAttributes, {
      title: NonEmptyString,
      url: NonEmptyString,
      slug: NonEmptyString
    });

    var postWithSameLink = Posts.findOne({slug: postAttributes.slug});
    if (postWithSameLink) {
      return {
        postExists: true,
        slug: postWithSameLink.slug
      }
    }

    var user = Meteor.user();
    var post = _.extend(postAttributes, {
      userId: user._id,
      author: user.emails[0].address,
      submitted: new Date()
    });

    var postId = Posts.insert(post);
    return {
      _id: postId
    };

  }
});<|endoftext|>