<commit_before>module.exports = function addNotYetDocumentedProperty(EXPORT_DOC_TYPES, log, createDocMessage) {
  return {
    $runAfter: ['tags-parsed'],
    $runBefore: ['rendering-docs'],
    $process: function(docs) {
      docs.forEach(function(doc) {

        if (EXPORT_DOC_TYPES.indexOf(doc.docType) === -1) return;

        // NotYetDocumented means that no top level comments and no member level comments
        doc.notYetDocumented = notYetDocumented(doc);

        if (doc.constructorDoc) {
          doc.constructorDoc.notYetDocumented = notYetDocumented(doc.constructorDoc);
          doc.notYetDocumented = doc.notYetDocumented && doc.constructorDoc.notYetDocumented;
        }

        if (doc.members) {
          doc.members.forEach(function(member) {
            member.notYetDocumented = notYetDocumented(member);
            doc.notYetDocumented = doc.notYetDocumented && member.notYetDocumented;
          });
        }

        if (doc.notYetDocumented) {
          // TODO: (ericjim) should I remove this?
          log.warn(createDocMessage("Not yet documented", doc));
        }
      });

      return docs;
    }
  };
};

function notYetDocumented(doc) {
  return !doc.noDescription && doc.description.trim().length == 0;
}<commit_msg>chore(api doc gen): log 'no api docs' as info not warning closes #1860 There are too many undocumented interfaces to consider lack of API docs in a source file to be worth a warning. The original author even questions whether there should be such a warning. It is now logged at the `info` level.<commit_after>module.exports = function addNotYetDocumentedProperty(EXPORT_DOC_TYPES, log, createDocMessage) {
  return {
    $runAfter: ['tags-parsed'],
    $runBefore: ['rendering-docs'],
    $process: function(docs) {
      docs.forEach(function(doc) {

        if (EXPORT_DOC_TYPES.indexOf(doc.docType) === -1) return;

        // NotYetDocumented means that no top level comments and no member level comments
        doc.notYetDocumented = notYetDocumented(doc);

        if (doc.constructorDoc) {
          doc.constructorDoc.notYetDocumented = notYetDocumented(doc.constructorDoc);
          doc.notYetDocumented = doc.notYetDocumented && doc.constructorDoc.notYetDocumented;
        }

        if (doc.members) {
          doc.members.forEach(function(member) {
            member.notYetDocumented = notYetDocumented(member);
            doc.notYetDocumented = doc.notYetDocumented && member.notYetDocumented;
          });
        }

        if (doc.notYetDocumented) {
          log.info(createDocMessage("Not yet documented", doc));
        }
      });

      return docs;
    }
  };
};

function notYetDocumented(doc) {
  return !doc.noDescription && doc.description.trim().length == 0;
}
<|endoftext|>


<commit_before>import {lazy, Suspense, useMemo, useContext} from 'react';
import {
  Switch,
  Route,
  Redirect,
  useRouteMatch,
  useParams,
} from 'react-router-dom';
import {useResource} from '@xorkevin/substation';
import {useIntersectRoles} from '@xorkevin/turbine';
import {
  MainContent,
  Section,
  Container,
  Grid,
  Column,
  Sidebar,
  SidebarItem,
  FaIcon,
} from '@xorkevin/nuke';

import {GovUICtx} from '../../middleware';

const OrgMembers = lazy(() => import('./members'));
const OrgSettings = lazy(() => import('./settings'));

const selectAPIOrg = (api) => api.orgs.name;

const OrgDetails = ({pathOrg}) => {
  const ctx = useContext(GovUICtx);
  const match = useRouteMatch();
  const {name} = useParams();

  const [org, reexecute] = useResource(selectAPIOrg, [name], {
    orgid: '',
    name: '',
    display_name: '',
    desc: '',
    creation_time: 0,
  });

  const orgid = org.data.orgid;
  const usrRole = ctx.orgUsrRole(orgid);
  const modRole = ctx.orgModRole(orgid);
  const orgRoles = useMemo(() => {
    if (!orgid || orgid === '') {
      return [];
    }
    return [usrRole, modRole];
  }, [orgid, usrRole, modRole]);

  const [roles] = useIntersectRoles(orgRoles);
  const roleSet = useMemo(() => {
    if (!roles.success) {
      return new Set();
    }
    return new Set(roles.data);
  }, [roles]);

  const isMod = roleSet.has(modRole);

  return (
    <MainContent>

        <Container padded narrow>
          {org.success && roles.success && (
            <Grid>
              <Column fullWidth md={6}>

{org.data.display_name}

                <Sidebar>
                  <SidebarItem
                    local
                    link={`${match.url}/members`}
                    icon={<FaIcon icon="users" />}
                  >
                    Members
                  </SidebarItem>
                  {isMod && (
                    <SidebarItem
                      local
                      link={`${match.url}/settings`}
                      icon={<FaIcon icon="cog" />}
                    >
                      Settings
                    </SidebarItem>
                  )}
                </Sidebar>
              </Column>
              <Column fullWidth sm={16}>
                <Suspense fallback={ctx.fallbackView}>
                  <Switch>
                    <Route path={`${match.path}/members`}>
                      <OrgMembers org={org.data} isMod={isMod} />
                    </Route>
                    {isMod && (
                      <Route path={`${match.path}/settings`}>
                        <OrgSettings
                          org={org.data}
                          pathOrgSettings={`${pathOrg}/settings`}
                          refresh={reexecute}
                          pathHome={ctx.pathHome}
                        />
                      </Route>
                    )}
                    <Redirect to={`${match.path}/members`} />
                  </Switch>
                </Suspense>
              </Column>
            </Grid>
          )}
          {org.err &&
{org.err}
}
        </Container>

    </MainContent>
  );
};

export default OrgDetails;
<commit_msg>Fix org header<commit_after>import {lazy, Suspense, useMemo, useContext} from 'react';
import {
  Switch,
  Route,
  Redirect,
  useRouteMatch,
  useParams,
} from 'react-router-dom';
import {useResource} from '@xorkevin/substation';
import {useIntersectRoles} from '@xorkevin/turbine';
import {
  MainContent,
  Section,
  Container,
  Grid,
  Column,
  Sidebar,
  SidebarItem,
  FaIcon,
} from '@xorkevin/nuke';

import {GovUICtx} from '../../middleware';

const OrgMembers = lazy(() => import('./members'));
const OrgSettings = lazy(() => import('./settings'));

const selectAPIOrg = (api) => api.orgs.name;

const OrgDetails = ({pathOrg}) => {
  const ctx = useContext(GovUICtx);
  const match = useRouteMatch();
  const {name} = useParams();

  const [org, reexecute] = useResource(selectAPIOrg, [name], {
    orgid: '',
    name: '',
    display_name: '',
    desc: '',
    creation_time: 0,
  });

  const orgid = org.data.orgid;
  const usrRole = ctx.orgUsrRole(orgid);
  const modRole = ctx.orgModRole(orgid);
  const orgRoles = useMemo(() => {
    if (!orgid || orgid === '') {
      return [];
    }
    return [usrRole, modRole];
  }, [orgid, usrRole, modRole]);

  const [roles] = useIntersectRoles(orgRoles);
  const roleSet = useMemo(() => {
    if (!roles.success) {
      return new Set();
    }
    return new Set(roles.data);
  }, [roles]);

  const isMod = roleSet.has(modRole);

  return (
    <MainContent>

        <Container padded narrow>
          {org.success && roles.success && (
            <Grid>
              <Column fullWidth md={6}>

{org.data.name}

                <Sidebar>
                  <SidebarItem
                    local
                    link={`${match.url}/members`}
                    icon={<FaIcon icon="users" />}
                  >
                    Members
                  </SidebarItem>
                  {isMod && (
                    <SidebarItem
                      local
                      link={`${match.url}/settings`}
                      icon={<FaIcon icon="cog" />}
                    >
                      Settings
                    </SidebarItem>
                  )}
                </Sidebar>
              </Column>
              <Column fullWidth sm={16}>

{org.data.display_name}

{org.data.desc}

                <Suspense fallback={ctx.fallbackView}>
                  <Switch>
                    <Route path={`${match.path}/members`}>
                      <OrgMembers org={org.data} isMod={isMod} />
                    </Route>
                    {isMod && (
                      <Route path={`${match.path}/settings`}>
                        <OrgSettings
                          org={org.data}
                          pathOrgSettings={`${pathOrg}/settings`}
                          refresh={reexecute}
                          pathHome={ctx.pathHome}
                        />
                      </Route>
                    )}
                    <Redirect to={`${match.path}/members`} />
                  </Switch>
                </Suspense>
              </Column>
            </Grid>
          )}
          {org.err &&
{org.err}
}
        </Container>

    </MainContent>
  );
};

export default OrgDetails;
<|endoftext|>


<commit_before>import Boom from 'boom';
import rp from 'request-promise';

import config from '../utils/config';

import { resizeImage } from '../utils/image';
import { createToken, hashPassword } from '../utils/auth';
import {
  dbGetUsers,
  dbGetUser,
  dbGetOAuth2User,
  dbDelUser,
  dbUpdateUser,
  dbCreateUser,
} from '../models/users';

export const getUsers = (request, reply) => dbGetUsers().then(reply);
export const getUser = (request, reply) => {
  if (request.pre.user.scope !== 'admin' && request.pre.user.id !== request.params.userId) {
    return reply(Boom.unauthorized('Unprivileged users can only view own userId!'));
  }

  return dbGetUser(request.params.userId).then(reply);
};

export const delUser = (request, reply) => {
  if (request.pre.user.scope !== 'admin' && request.pre.user.id !== request.params.userId) {
    return reply(Boom.unauthorized('Unprivileged users can only delete own userId!'));
  }

  return dbDelUser(request.params.userId).then(reply);
};

export const updateUser = async (request, reply) => {
  if (request.pre.user.scope !== 'admin' && request.pre.user.id !== request.params.userId) {
    return reply(Boom.unauthorized('Unprivileged users can only perform updates on own userId!'));
  }

  const fields = {
    email: request.payload.email,
    description: request.payload.description,
    image: request.payload.image,
  };

  // Only admins are allowed to modify user scope
  if (request.pre.user.scope === 'admin') {
    fields.scope = request.payload.scope;
  }

  // If request contains an image, resize it to max 512x512 pixels
  if (fields.image) {
    const buf = Buffer.from(fields.image, 'base64');
    await resizeImage(buf).then(resized => (fields.image = resized));
  }

  return dbUpdateUser(request.params.userId, fields).then(reply);
};

export const authUser = (request, reply) => (
  reply(createToken(request.pre.user.id, request.pre.user.email, request.pre.user.scope))
);

export const registerUser = (request, reply) => (
  hashPassword(request.payload.password)
    .then(password => dbCreateUser({ ...request.payload, password, scope: 'user' })
    .then(reply))
    .catch((err) => {
      if (err.constraint === 'users_email_unique') {
        reply(Boom.conflict('Account already exists'));
      } else {
        reply(Boom.badImplementation(err));
      }
    })
);

export const oauth2Authenticate = async (request, reply) => {
  if (!request.auth.isAuthenticated) {
    return reply(`Authentication failed due to: ${request.auth.error.message}`);
  }

  try {
    const token = request.auth.credentials.token;

    let oa2User = await rp({
      uri: config.oauth2.userEndpoint,
      qs: { access_token: token },
    });

    // NOTE: server returns Content-Type: text/html, not application/json. Must parse manually.
    oa2User = JSON.parse(oa2User).user;

    let registeredUser = await dbGetOAuth2User(oa2User.id);

    if (!registeredUser) {
      registeredUser = await dbCreateUser({
        scope: 'expert',
        name: `${oa2User.first_name} ${oa2User.last_name}`,
        email: oa2User.email,
        locale: oa2User.lang_name,
        oauth2Id: oa2User.id,
        imageUrl: oa2User.avatar_thumb,
      });
    }

    return reply(createToken(registeredUser.id, registeredUser.email, registeredUser.scope));
  } catch (err) {
    if (err.constraint === 'users_email_unique') {
      return reply(Boom.conflict('Account already exists'));
    }

    return reply(Boom.badImplementation(err));
  }
};
<commit_msg>OAuth2 flow creates user with scope 'user'<commit_after>import Boom from 'boom';
import rp from 'request-promise';

import config from '../utils/config';

import { resizeImage } from '../utils/image';
import { createToken, hashPassword } from '../utils/auth';
import {
  dbGetUsers,
  dbGetUser,
  dbGetOAuth2User,
  dbDelUser,
  dbUpdateUser,
  dbCreateUser,
} from '../models/users';

export const getUsers = (request, reply) => dbGetUsers().then(reply);
export const getUser = (request, reply) => {
  if (request.pre.user.scope !== 'admin' && request.pre.user.id !== request.params.userId) {
    return reply(Boom.unauthorized('Unprivileged users can only view own userId!'));
  }

  return dbGetUser(request.params.userId).then(reply);
};

export const delUser = (request, reply) => {
  if (request.pre.user.scope !== 'admin' && request.pre.user.id !== request.params.userId) {
    return reply(Boom.unauthorized('Unprivileged users can only delete own userId!'));
  }

  return dbDelUser(request.params.userId).then(reply);
};

export const updateUser = async (request, reply) => {
  if (request.pre.user.scope !== 'admin' && request.pre.user.id !== request.params.userId) {
    return reply(Boom.unauthorized('Unprivileged users can only perform updates on own userId!'));
  }

  const fields = {
    email: request.payload.email,
    description: request.payload.description,
    image: request.payload.image,
  };

  // Only admins are allowed to modify user scope
  if (request.pre.user.scope === 'admin') {
    fields.scope = request.payload.scope;
  }

  // If request contains an image, resize it to max 512x512 pixels
  if (fields.image) {
    const buf = Buffer.from(fields.image, 'base64');
    await resizeImage(buf).then(resized => (fields.image = resized));
  }

  return dbUpdateUser(request.params.userId, fields).then(reply);
};

export const authUser = (request, reply) => (
  reply(createToken(request.pre.user.id, request.pre.user.email, request.pre.user.scope))
);

export const registerUser = (request, reply) => (
  hashPassword(request.payload.password)
    .then(password => dbCreateUser({ ...request.payload, password, scope: 'user' })
    .then(reply))
    .catch((err) => {
      if (err.constraint === 'users_email_unique') {
        reply(Boom.conflict('Account already exists'));
      } else {
        reply(Boom.badImplementation(err));
      }
    })
);

export const oauth2Authenticate = async (request, reply) => {
  if (!request.auth.isAuthenticated) {
    return reply(`Authentication failed due to: ${request.auth.error.message}`);
  }

  try {
    const token = request.auth.credentials.token;

    let oa2User = await rp({
      uri: config.oauth2.userEndpoint,
      qs: { access_token: token },
    });

    // NOTE: server returns Content-Type: text/html, not application/json. Must parse manually.
    oa2User = JSON.parse(oa2User).user;

    let registeredUser = await dbGetOAuth2User(oa2User.id);

    if (!registeredUser) {
      registeredUser = await dbCreateUser({
        scope: 'user',
        name: `${oa2User.first_name} ${oa2User.last_name}`,
        email: oa2User.email,
        locale: oa2User.lang_name,
        oauth2Id: oa2User.id,
        imageUrl: oa2User.avatar_thumb,
      });
    }

    return reply(createToken(registeredUser.id, registeredUser.email, registeredUser.scope));
  } catch (err) {
    if (err.constraint === 'users_email_unique') {
      return reply(Boom.conflict('Account already exists'));
    }

    return reply(Boom.badImplementation(err));
  }
};
<|endoftext|>


<commit_before>define([
    'jquery',
    'gizmo/superdesk',
    'livedesk/views/provider-edit',

    'tmpl!livedesk>layouts/livedesk',
    'tmpl!core>layouts/footer',
    'tmpl!core>layouts/footer-static',
    'tmpl!livedesk>manage-feeds',
    'tmpl!livedesk>manage-feeds-provider',
    'tmpl!livedesk>manage-feeds-external-blog',
], function ($, Gizmo, EditProviderView) {

    var PROVIDER_TYPE = 'blog provider';
    var BLOG_TYPE = 'chained blog';

    var fetchOptions = {headers: {'X-Filter': 'Id, Name, URI'}, reset: true};

    /**
     * Get gizmo url for given path
     *
     * @param {string} path
     * @return {string}
     */
    function getGizmoUrl(path)
    {
        var url = new Gizmo.Url(path);
        return url.get();
    }

    /**
     * Get id from given url
     *
     * @param {string} url
     * @return {string}
     */
    function parseId(url)
    {
        return url.split('/').slice(-1)[0];
    }

    /**
     * Source Model
     */
    var Source = Backbone.Model.extend({
        idAttribute: 'Id',

        defaults: {
            Type: BLOG_TYPE,
            IsModifiable: 'True'
        },

        parse: function(response) {
            if (response === null) {
                return;
            }

            if ('href' in response) {
                this.url = response.href;
                delete response.href
            }

            return response;
        }
    });

    /**
     * Stored sources
     */
    var SourceCollection = Backbone.Collection.extend({
        model: Source,

        /**
         * Test if source is active for blog
         *
         * @param {ExternalBlog} blog
         * @return {boolean}
         */
        hasBlog: function(blog) {
            return this.findBlog(blog) !== undefined;
        },

        /**
         * Add given source to blog sources
         *
         * @param {ExternalBlog} blog
         */
        addBlog: function(blog) {
            var source = this.findBlog(blog);
            if (source) {
                return;
            }

            this.create({
                Name: blog.get('Title'),
                URI: blog.get('href'),
                Provider: blog.provider
            });
        },

        /**
         * Remove given source from blog sources
         *
         * @param {ExternalBlog} blog
         */
        removeBlog: function(blog) {
            var source = this.findBlog(blog);
            if (source) {
                this.remove(source);
                source.destroy();
            }
        },

        /**
         * Find model for given source
         *
         * @param {ExternalBlog} blog
         * @return {BlogSource}
         */
        findBlog: function(blog) {
            return this.findWhere({URI: blog.get('href')});
        },

        parse: function(response) {
            return response.SourceList;
        }
    });

    /**
     * Provider Model
     */
    var Provider = Source.extend({
        urlRoot: getGizmoUrl('Data/Source'),

        defaults: {
            Type: PROVIDER_TYPE,
            IsModifiable: 'True'
        },

        validate: function(attributes) {
            if (!attributes.Name) {
                return _('Please set the Name');
            }

            if (!attributes.URI) {
                return _('Please set the URL');
            }
        },

        getBlogs: function() {
            return new ExternalBlogCollection([], {url: this.get('URI')});
        },

        parse: function(response) {
            if (response === null) {
                return;
            }

            if ('URI' in response) {
                response.URI = response.URI.href;
            }

            return response;
        },

        render: function() {
            return {
                id: this.id,
                name: this.get('Name'),
                uri: this.get('URI')
            };
        }
    });

    /**
     * Global External Blog Provider Collection
     */
    var ProviderCollection = Backbone.Collection.extend({
        model: Provider,

        xfilter: {'X-Filter': 'Id, Name, URI'},

        comparator: function(model) {
            return -1 * model.get('Id');
        },

        parse: function(response) {
            return response.SourceList;
        }
    });

    /**
     * External Blog
     */
    var ExternalBlog = Backbone.Model.extend({
        isActive: function() {
            return sources.hasBlog(this);
        },

        activate: function() {
            sources.addBlog(this);
        },

        deactivate: function() {
            sources.removeBlog(this);
        }
    });

    /**
     * External Blog Collection holds blogs from single provider
     */
    var ExternalBlogCollection = Backbone.Collection.extend({
        model: ExternalBlog,

        parse: function(response) {
            return response.BlogList;
        }
    });

    /**
     * Single External Blog View - a list item.
     */
    var ExternalBlogView = Backbone.View.extend({
        tagName: 'li',

        events: {
            'change input:checkbox': 'change',
            'click .sf-checkbox-custom': 'toggleCheckbox'
        },

        render: function() {
            var data = this.model.clone().attributes;
            data.cid = this.model.cid;
            $(this.el).
                tmpl('livedesk>manage-feeds-external-blog', data).
                addClass('chain-blog');

            $(this.el).find('.sf-checkbox').each(function(i, val) {
                $(val).after('');
                $(val).hide();
            });

            var $box = $(this.el).find('input:checkbox');
            $box.prop('checked', this.model.isActive());
            $box.change();

            return this;
        },

        change: function(e) {
            var checked = $(e.target).prop('checked');

            if (checked) {
                this.model.activate();
            } else {
                this.model.deactivate();
            }

            this.renderCheckbox(checked);
        },

        renderCheckbox: function(checked) {
            var $li = $(this.el);
            var $box = $(this.el).find('.sf-checkbox-custom');

            if (checked) {
                $li.addClass('active-bg');
                $box.addClass('sf-checked');
            } else {
                $li.removeClass('active-bg');
                $box.removeClass('sf-checked');
            }
        },

        /**
         * Change value and trigger change event
         */
        toggleCheckbox: function() {
            $input = $(this.el).find('input:checkbox');
            $input.prop('checked', ! $input.prop('checked'));
            $input.change();
        }
    });

    /**
     * Provider View
     */
    var ProviderView = Backbone.View.extend({
        tagName: 'li',

        events: {
            'click .remove': 'delete',
            'click .edit': 'edit'
        },

        initialize: function() {
            this.model.on('change', this.render, this);
        },

        render: function() {
            this.renderProvider();
            this.fetchBlogs();
            return this;
        },

        renderProvider: function() {
            var data = {Name: this.model.get('Name')};
            this.$el.tmpl('livedesk>manage-feeds-provider', data).addClass('chain-source');
        },

        fetchBlogs: function() {
            this.collection = this.model.getBlogs();
            this.collection.on('reset', this.renderBlogs, this);
            this.collection.fetch({headers: {'X-Filter': 'Title, Description'}, reset: true});
        },

        renderBlogs: function() {
            this.$el.find('.chain-source-count').text(this.collection.length);
            var list = $(this.el).find('.chain-source-content').empty();
            var provider = this.model;

            this.collection.each(function(blog) {
                blog.provider = provider.id;
                var view = new ExternalBlogView({model: blog});
                list.append(view.render().el);
            });
        },

        delete: function(e) {
            e.preventDefault();
            this.remove();
            this.model.destroy();
        },

        edit: function(e) {
            e.preventDefault();
            var view = new EditProviderView({model: this.model});
            this.$el.closest('#area-main').append(view.render().el);
        }
    });

    /**
     * Main View
     */
    var MainView = Backbone.View.extend({
        events: {
            'click a[href="#AddSource"]': 'renderAdd',
            'change .sf-searchbox > input': 'search',
            'click .sf-searchbox > a': 'clearSearch'
        },

        initialize: function() {
            this.collection.on('reset', this.render, this);
            this.collection.on('add', this.renderList, this);
        },

        render: function() {
            this.renderMain();
            this.renderList();
            return this;
        },

        renderMain: function() {
            var data = this.model.feed();
            data.ui = {
                content: 'is-content=1',
                side: 'is-side=1',
                submenu: 'is-submenu',
                submenuActive4: 'active'
            };

            $(this.el).tmpl('livedesk>manage-feeds', data);
        },

        renderList: function() {
            var list = $(this.el).find('#provider-list').empty();

            this.collection.each(function(provider) {
                var view = new ProviderView({model: provider});
                list.append(view.render().el);
            });

            if (!this.collection.length) {
                list.append($('
').text(_("So far there are no providers. Start with Add New Provider button.")));
            }

            return this;
        },

        renderAdd: function(e) {
            e.preventDefault();
            var view = new EditProviderView({collection: this.collection});
            this.$el.append(view.render().el);
        },

        search: function(e) {
            var q = $(e.target).val();
            var sources = $(this.el).find('.chain-blog').each(function() {
                var show = true;
                if (q.length) {
                    var text = $(this).text();
                    var reg = new RegExp(q, 'i');
                    show = reg.test(text);
                }

                if (show) {
                    $(this).show();
                } else {
                    $(this).hide();
                }
            });
        },

        clearSearch: function(e) {
            e.preventDefault();
            $(this.el).find('.sf-searchbox > input').val('').change();
        }
    });

    // blog sources
    var sources = new SourceCollection();

    return function(blogHref) {
        var blog = Gizmo.Auth(new Gizmo.Register.Blog(blogHref));
        blog.sync().done(function() {
            // we need blog specific sources
            sources.url = blog.get('Source').href;

            // we need sources before rendering providers, so start rendering when sources are ready
            sources.on('reset', function() {
                var providers = new ProviderCollection();
                providers.url = getGizmoUrl('Data/SourceType/' + PROVIDER_TYPE + '/Source');

                new MainView({model: blog, collection: providers, el: '#area-main'});
                providers.fetch(fetchOptions);
            });

            // start
            sources.fetch(fetchOptions);
        });
    };
});
<commit_msg>LB-499: Add provider no action<commit_after>define([
    'jquery',
    'gizmo/superdesk',
    'livedesk/views/provider-edit',

    'tmpl!livedesk>layouts/livedesk',
    'tmpl!core>layouts/footer',
    'tmpl!core>layouts/footer-static',
    'tmpl!livedesk>manage-feeds',
    'tmpl!livedesk>manage-feeds-provider',
    'tmpl!livedesk>manage-feeds-external-blog',
], function ($, Gizmo, EditProviderView) {

    var PROVIDER_TYPE = 'blog provider';
    var BLOG_TYPE = 'chained blog';

    var fetchOptions = {headers: {'X-Filter': 'Id, Name, URI'}, reset: true};

    /**
     * Get gizmo url for given path
     *
     * @param {string} path
     * @return {string}
     */
    function getGizmoUrl(path)
    {
        var url = new Gizmo.Url(path);
        return url.get();
    }

    /**
     * Get id from given url
     *
     * @param {string} url
     * @return {string}
     */
    function parseId(url)
    {
        return url.split('/').slice(-1)[0];
    }

    /**
     * Source Model
     */
    var Source = Backbone.Model.extend({
        idAttribute: 'Id',

        defaults: {
            Type: BLOG_TYPE,
            IsModifiable: 'True'
        },

        parse: function(response) {
            if (response === null) {
                return;
            }

            if ('href' in response) {
                this.url = response.href;
                delete response.href
            }

            if ('URI' in response) {
                response.URI = response.URI.href;
            }

            return response;
        }
    });

    /**
     * Stored sources
     */
    var SourceCollection = Backbone.Collection.extend({
        model: Source,

        /**
         * Test if source is active for blog
         *
         * @param {ExternalBlog} blog
         * @return {boolean}
         */
        hasBlog: function(blog) {
            return this.findBlog(blog) !== undefined;
        },

        /**
         * Add given source to blog sources
         *
         * @param {ExternalBlog} blog
         */
        addBlog: function(blog) {
            var source = this.findBlog(blog);
            if (source) {
                return;
            }

            this.create({
                Name: blog.get('Title'),
                URI: blog.get('href'),
                Provider: blog.provider
            });
        },

        /**
         * Remove given source from blog sources
         *
         * @param {ExternalBlog} blog
         */
        removeBlog: function(blog) {
            var source = this.findBlog(blog);
            if (source) {
                this.remove(source);
                source.destroy();
            }
        },

        /**
         * Find model for given source
         *
         * @param {ExternalBlog} blog
         * @return {BlogSource}
         */
        findBlog: function(blog) {
            return this.findWhere({URI: blog.get('href')});
        },

        parse: function(response) {
            return response.SourceList;
        }
    });

    /**
     * Provider Model
     */
    var Provider = Source.extend({
        urlRoot: getGizmoUrl('Data/Source'),

        defaults: {
            Type: PROVIDER_TYPE,
            IsModifiable: 'True'
        },

        validate: function(attributes) {
            if (!attributes.Name) {
                return _('Please set the Name');
            }

            if (!attributes.URI) {
                return _('Please set the URL');
            }
        },

        getBlogs: function() {
            return new ExternalBlogCollection([], {url: this.get('URI')});
        },

        parse: function(response) {
            if (response === null) {
                return;
            }

            if ('URI' in response) {
                response.URI = response.URI.href;
            }

            return response;
        },

        render: function() {
            return {
                id: this.id,
                name: this.get('Name'),
                uri: this.get('URI')
            };
        }
    });

    /**
     * Global External Blog Provider Collection
     */
    var ProviderCollection = Backbone.Collection.extend({
        model: Provider,

        xfilter: {'X-Filter': 'Id, Name, URI'},

        comparator: function(model) {
            return -1 * model.get('Id');
        },

        parse: function(response) {
            return response.SourceList;
        }
    });

    /**
     * External Blog
     */
    var ExternalBlog = Backbone.Model.extend({
        isActive: function() {
            return sources.hasBlog(this);
        },

        activate: function() {
            sources.addBlog(this);
        },

        deactivate: function() {
            sources.removeBlog(this);
        }
    });

    /**
     * External Blog Collection holds blogs from single provider
     */
    var ExternalBlogCollection = Backbone.Collection.extend({
        model: ExternalBlog,

        parse: function(response) {
            return response.BlogList;
        }
    });

    /**
     * Single External Blog View - a list item.
     */
    var ExternalBlogView = Backbone.View.extend({
        tagName: 'li',

        events: {
            'change input:checkbox': 'change',
            'click .sf-checkbox-custom': 'toggleCheckbox'
        },

        render: function() {
            var data = this.model.clone().attributes;
            data.cid = this.model.cid;
            $(this.el).
                tmpl('livedesk>manage-feeds-external-blog', data).
                addClass('chain-blog');

            $(this.el).find('.sf-checkbox').each(function(i, val) {
                $(val).after('');
                $(val).hide();
            });

            var $box = $(this.el).find('input:checkbox');
            $box.prop('checked', this.model.isActive());
            $box.change();

            return this;
        },

        change: function(e) {
            var checked = $(e.target).prop('checked');

            if (checked) {
                this.model.activate();
            } else {
                this.model.deactivate();
            }

            this.renderCheckbox(checked);
        },

        renderCheckbox: function(checked) {
            var $li = $(this.el);
            var $box = $(this.el).find('.sf-checkbox-custom');

            if (checked) {
                $li.addClass('active-bg');
                $box.addClass('sf-checked');
            } else {
                $li.removeClass('active-bg');
                $box.removeClass('sf-checked');
            }
        },

        /**
         * Change value and trigger change event
         */
        toggleCheckbox: function() {
            $input = $(this.el).find('input:checkbox');
            $input.prop('checked', ! $input.prop('checked'));
            $input.change();
        }
    });

    /**
     * Provider View
     */
    var ProviderView = Backbone.View.extend({
        tagName: 'li',

        events: {
            'click .remove': 'delete',
            'click .edit': 'edit'
        },

        initialize: function() {
            this.model.on('change', this.render, this);
        },

        render: function() {
            this.renderProvider();
            this.fetchBlogs();
            return this;
        },

        renderProvider: function() {
            var data = {Name: this.model.get('Name')};
            this.$el.tmpl('livedesk>manage-feeds-provider', data).addClass('chain-source');
        },

        fetchBlogs: function() {
            this.collection = this.model.getBlogs();
            this.collection.on('reset', this.renderBlogs, this);
            this.collection.fetch({headers: {'X-Filter': 'Title, Description'}, reset: true});
        },

        renderBlogs: function() {
            this.$el.find('.chain-source-count').text(this.collection.length);
            var list = $(this.el).find('.chain-source-content').empty();
            var provider = this.model;

            this.collection.each(function(blog) {
                blog.provider = provider.id;
                var view = new ExternalBlogView({model: blog});
                list.append(view.render().el);
            });
        },

        delete: function(e) {
            e.preventDefault();
            this.remove();
            this.model.destroy();
        },

        edit: function(e) {
            e.preventDefault();
            var view = new EditProviderView({model: this.model});
            this.$el.closest('#area-main').append(view.render().el);
        }
    });

    /**
     * Main View
     */
    var MainView = Backbone.View.extend({
        events: {
            'click a[href="#AddSource"]': 'renderAdd',
            'change .sf-searchbox > input': 'search',
            'click .sf-searchbox > a': 'clearSearch'
        },

        initialize: function() {
            this.collection.on('reset', this.render, this);
            this.collection.on('add', this.renderList, this);
        },

        render: function() {
            this.renderMain();
            this.renderList();
            return this;
        },

        renderMain: function() {
            var data = this.model.feed();
            data.ui = {
                content: 'is-content=1',
                side: 'is-side=1',
                submenu: 'is-submenu',
                submenuActive4: 'active'
            };

            $(this.el).tmpl('livedesk>manage-feeds', data);
        },

        renderList: function() {
            var list = $(this.el).find('#provider-list').empty();

            this.collection.each(function(provider) {
                var view = new ProviderView({model: provider});
                list.append(view.render().el);
            });

            if (!this.collection.length) {
                list.append($('
').text(_("So far there are no providers. Start with Add New Provider button.")));
            }

            return this;
        },

        renderAdd: function(e) {
            e.preventDefault();
            var view = new EditProviderView({collection: this.collection});
            this.$el.append(view.render().el);
        },

        search: function(e) {
            var q = $(e.target).val();
            var sources = $(this.el).find('.chain-blog').each(function() {
                var show = true;
                if (q.length) {
                    var text = $(this).text();
                    var reg = new RegExp(q, 'i');
                    show = reg.test(text);
                }

                if (show) {
                    $(this).show();
                } else {
                    $(this).hide();
                }
            });
        },

        clearSearch: function(e) {
            e.preventDefault();
            $(this.el).find('.sf-searchbox > input').val('').change();
        }
    });

    // blog sources
    var sources = new SourceCollection();

    return function(blogHref) {
        var blog = Gizmo.Auth(new Gizmo.Register.Blog(blogHref));
        blog.sync().done(function() {
            // we need blog specific sources
            sources.url = blog.get('Source').href;

            // we need sources before rendering providers, so start rendering when sources are ready
            sources.on('reset', function() {
                var providers = new ProviderCollection();
                providers.url = getGizmoUrl('Data/SourceType/' + PROVIDER_TYPE + '/Source');

                new MainView({model: blog, collection: providers, el: '#area-main'});
                providers.fetch(fetchOptions);
            });

            // start
            sources.fetch(fetchOptions);
        });
    };
});
<|endoftext|>


<commit_before>
;(function( FooFighter ){

function EnemyUFO ( gameState, group ) {
    this.gameState = gameState;
    this.game = gameState.game;
    this.vent = gameState.vent;
    this.group = group;
    this.sprite = null;
}

var proto = EnemyUFO.prototype;

proto.create = function(){
    var game = this.game,
        player = this.gameState.entities.player.sprite;

    this.sprite = this.group.create(
        game.world.width * Math.random(),
        -20,
        'sprites',
        'enemyUFO.png'
    );
    this.sprite.anchor = {
        x: 0.5,
        y: 0.5
    };
    this.sprite.outOfBoundsKill = true;
    this.game.physics.accelerateToXY(
        this.sprite,
        player.x,
        player.y,
        300,
        600
    );
    this.bindEvents();
};

proto.bindEvents = function(){
    this.sprite.events.onKilled.add(function(){
        this.game.time.events.add(
            5000,
            this.sprite.destroy.bind(this.sprite)
        );
    }.bind(this));
};

FooFighter.EnemyUFO = EnemyUFO;

})(FooFighter);
<commit_msg>add docstring<commit_after>/**
 * EnemyUFO.js
 *
 * FooFighter.js — EnemyUFO entity
 *
 * This class represents the display entity and data structure for an
 * enemy UFO unit. The UFO will accelerate towards the player in a
 * kamikaze-esque move.
 */

;(function( FooFighter ){

function EnemyUFO ( gameState, group ) {
    this.gameState = gameState;
    this.game = gameState.game;
    this.vent = gameState.vent;
    this.group = group;
    this.sprite = null;
}

var proto = EnemyUFO.prototype;

proto.create = function(){
    var game = this.game,
        player = this.gameState.entities.player.sprite;

    this.sprite = this.group.create(
        game.world.width * Math.random(),
        -20,
        'sprites',
        'enemyUFO.png'
    );
    this.sprite.anchor = {
        x: 0.5,
        y: 0.5
    };
    this.sprite.outOfBoundsKill = true;
    this.game.physics.accelerateToXY(
        this.sprite,
        player.x,
        player.y,
        300,
        600
    );
    this.bindEvents();
};

proto.bindEvents = function(){
    this.sprite.events.onKilled.add(function(){
        this.game.time.events.add(
            5000,
            this.sprite.destroy.bind(this.sprite)
        );
    }.bind(this));
};

FooFighter.EnemyUFO = EnemyUFO;

})(FooFighter);
<|endoftext|>


<commit_before>import isFunction from './isFunction';

export default function (...args) {
  let result = [];
  for (let i = 0; i < args.length; i += 1) {
    const arg = args[i];
    if (isFunction(arg)) result.push(arg);
    else if (Array.isArray(arg)) result = result.concat(arg.filter(isFunction));
  }
  return result.length === 0 ? undefined : result;
}
<commit_msg>Shorter extractFunctions<commit_after>import isFunction from './isFunction';

const concat = Array.prototype.concat;
export default function () {
  const fns = concat.apply([], arguments).filter(isFunction);
  return fns.length === 0 ? undefined : fns;
}
<|endoftext|>


<commit_before>import path from 'path';

import matchAll from 'string.prototype.matchall';

const URL_PATTERN = /url\(['"]?(\/?[^)"']+)['"]?\)/g;

export default function findCSSAssetPaths({ css, source }) {
  const paths = Array.from(matchAll(css, URL_PATTERN))
    .map((match) => match[1])
    .filter((url) => !/^http|\/\//.test(url));
  if (!source) {
    return paths.map((p) => ({ assetPath: p, resolvePath: p }));
  }
  const dir = path.dirname(source);
  return paths.map((url) => {
    if (url.startsWith('/')) {
      // absolute url
      return { assetPath: url, resolvePath: url };
    }
    const assetPath = path.join(dir, url);
    return { assetPath, resolvePath: url };
  });
}
<commit_msg>Add some jsdoc to explain findCSSAssetPaths<commit_after>import path from 'path';

import matchAll from 'string.prototype.matchall';

const URL_PATTERN = /url\(['"]?(\/?[^)"']+)['"]?\)/g;

/**
 * @param {string} css - The css code, e.g. ".foo { background: url(/foo.png); }"
 * @param {string} [source] - An optional path to the css file where the css is
 *   coming from. This is used to make the resulting `resolvePath` relative to
 *   the css file.
 * @return {object} an object containing an `assetPath` and a `resolvePath`. The
 *   assetPath is the path as it's described in the css. The resolvePath is the
 *   path where we should attempt to locate the file in the filesystem.
 */
export default function findCSSAssetPaths({ css, source }) {
  const paths = Array.from(matchAll(css, URL_PATTERN))
    .map((match) => match[1])
    .filter((url) => !/^http|\/\//.test(url));
  if (!source) {
    return paths.map((p) => ({ assetPath: p, resolvePath: p }));
  }
  const dir = path.dirname(source);
  return paths.map((url) => {
    if (url.startsWith('/')) {
      // absolute url
      return { assetPath: url, resolvePath: url };
    }
    const assetPath = path.join(dir, url);
    return { assetPath, resolvePath: url };
  });
}
<|endoftext|>


<commit_before>import * as googleFirebase from "firebase";

import config from './config';

class Firebase {
    constructor() {
        googleFirebase.initializeApp(config)
        return googleFirebase
    }
}

export let firebase = new Firebase();<commit_msg>update firebase<commit_after>import * as googleFirebase from "firebase";

import config from './config';

class Firebase {
    constructor () {
        googleFirebase.initializeApp(config)
        return googleFirebase
    }
}

export let firebase = new Firebase();<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.INTERFACE({
  refines: 'foam.dao.Sink',

  methods: [
    {
      name: 'put',
      javaReturns: 'void',
      args: [
        {
          name: 'obj',
          javaType: 'foam.core.FObject'
        },
        {
          name: 'sub',
          javaType: 'foam.core.Detachable'
        }
      ]
    },
    {
      name: 'remove',
      javaReturns: 'void',
      args: [
        {
          name: 'obj',
          javaType: 'foam.core.FObject'
        },
        {
          name: 'sub',
          javaType: 'foam.core.Detachable'
        },
      ]
    },
    {
      name: 'eof',
      javaReturns: 'void'
    },
    {
      name: 'reset',
      javaReturns: 'void',
      args: [
        {
          name: 'sub',
          javaType: 'foam.core.Detachable'
        }
      ]
    }
  ]
});

foam.CLASS({
  refines: 'foam.dao.AbstractSink',
  methods: [
    // TODO: have a method of put() that doesn't include the Detachable argument
    {
      name: 'put',
      javaCode: 'return;'
    },
    {
      name: 'remove',
      javaCode: 'return;'
    },
    {
      name: 'eof',
      javaCode: 'return;'
    },
    {
      name: 'reset',
      javaCode: 'return;'
    }
  ]
});

foam.CLASS({
  refines: 'foam.dao.PredicatedSink',

  methods: [
    {
      name: 'put',
      javaCode: 'if ( getPredicate().f(obj) ) getDelegate().put(obj, sub);'
    },
    {
      name: 'remove',
      javaCode: 'if ( getPredicate().f(obj) ) getDelegate().remove(obj, sub);'
    }
  ]
});

foam.CLASS({
  refines: 'foam.dao.LimitedSink',

  methods: [
    {
      name: 'put',
      javaCode: 'if ( getCount() >= getLimit() ) {\n'
              + '  if ( sub != null ) sub.detach();\n'
              + '} else {\n'
              + '  setCount(getCount() + 1);\n'
              + '  getDelegate().put(obj, sub);\n'
              + '}\n'
    },
    {
      name: 'remove',
      javaCode: 'if ( getCount() >= getLimit() ) {\n'
              + '  if ( sub != null ) sub.detach();\n'
              + '} else {'
              + '  setCount(getCount() + 1);\n'
              + '  getDelegate().put(obj, sub);\n'
              + '}\n'
    }
  ]
});

foam.CLASS({
  refines: 'foam.dao.SkipSink',
  methods: [
    {
      name: 'put',
      javaCode: 'if ( getCount() < getSkip() ) {\n'
              + '  setCount(getCount() + 1);\n'
              + '  return;'
              + '}\n'
              + 'getDelegate().put(obj, sub);'
    },
    {
      name: 'remove',
      javaCode: 'if ( getCount() < getSkip() ) {\n'
              + '  setCount(getCount() + 1);\n'
              + '  return;'
              + '}\n'
              + 'getDelegate().remove(obj, sub);'
    }
  ]
});

foam.CLASS({
  refines: 'foam.dao.OrderedSink',

  methods: [
    {
      name: 'put',
      javaCode: 'if ( getArray() == null ) setArray(new java.util.ArrayList());\n'
                + 'getArray().add(obj);'
    },
    {
      name: 'eof',
      javaCode: 'if ( getArray() == null ) setArray(new java.util.ArrayList());\n'
                + 'java.util.Collections.sort(getArray(), comparator_);\n'
                + 'foam.dao.Subscription sub = getX().create(foam.dao.Subscription.class);\n'
                + 'for ( Object o : getArray() ) {\n'
                + '  if ( sub.getDetached() ) {\n'
                + '    break;\n'
                + '  }\n'
                + '  getDelegate().put((foam.core.FObject)o, sub);\n'
                + '}'
    }
  ]
});
<commit_msg>Formatting SinkJava (String concatenation -> ES6 Multiline)<commit_after>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.INTERFACE({
  refines: 'foam.dao.Sink',

  methods: [
    {
      name: 'put',
      javaReturns: 'void',
      args: [
        {
          name: 'obj',
          javaType: 'foam.core.FObject'
        },
        {
          name: 'sub',
          javaType: 'foam.core.Detachable'
        }
      ]
    },
    {
      name: 'remove',
      javaReturns: 'void',
      args: [
        {
          name: 'obj',
          javaType: 'foam.core.FObject'
        },
        {
          name: 'sub',
          javaType: 'foam.core.Detachable'
        },
      ]
    },
    {
      name: 'eof',
      javaReturns: 'void'
    },
    {
      name: 'reset',
      javaReturns: 'void',
      args: [
        {
          name: 'sub',
          javaType: 'foam.core.Detachable'
        }
      ]
    }
  ]
});

foam.CLASS({
  refines: 'foam.dao.AbstractSink',
  methods: [
    // TODO: have a method of put() that doesn't include the Detachable argument
    {
      name: 'put',
      javaCode: 'return;'
    },
    {
      name: 'remove',
      javaCode: 'return;'
    },
    {
      name: 'eof',
      javaCode: 'return;'
    },
    {
      name: 'reset',
      javaCode: 'return;'
    }
  ]
});

foam.CLASS({
  refines: 'foam.dao.PredicatedSink',

  methods: [
    {
      name: 'put',
      javaCode: 'if ( getPredicate().f(obj) ) getDelegate().put(obj, sub);'
    },
    {
      name: 'remove',
      javaCode: 'if ( getPredicate().f(obj) ) getDelegate().remove(obj, sub);'
    }
  ]
});

foam.CLASS({
  refines: 'foam.dao.LimitedSink',

  methods: [
    {
      name: 'put',
      javaCode:
`if ( getCount() >= getLimit() ) {
  if ( sub != null ) sub.detach();
} else {
  setCount(getCount() + 1);
  getDelegate().put(obj, sub);
}`
    },
    {
      name: 'remove',
      javaCode:
`if ( getCount() >= getLimit() ) {
  if ( sub != null ) sub.detach();
} else {
  setCount(getCount() + 1);
  getDelegate().put(obj, sub);
}`
    }
  ]
});

foam.CLASS({
  refines: 'foam.dao.SkipSink',
  methods: [
    {
      name: 'put',
      javaCode:
`if ( getCount() < getSkip() ) {
  setCount(getCount() + 1);
  return;
}
getDelegate().put(obj, sub);`
    },
    {
      name: 'remove',
      javaCode:
`if ( getCount() < getSkip() ) {
  setCount(getCount() + 1);
  return;
}
getDelegate().remove(obj, sub);`
    }
  ]
});

foam.CLASS({
  refines: 'foam.dao.OrderedSink',

  methods: [
    {
      name: 'put',
      javaCode:
`if ( getArray() == null ) setArray(new java.util.ArrayList());
getArray().add(obj);`
    },
    {
      name: 'eof',
      javaCode:
`if ( getArray() == null ) setArray(new java.util.ArrayList());
java.util.Collections.sort(getArray(), comparator_);
foam.dao.Subscription sub = getX().create(foam.dao.Subscription.class);

for ( Object o : getArray() ) {
  if ( sub.getDetached() ) {
    break;
  }

  getDelegate().put((foam.core.FObject)o, sub);
}`
    }
  ]
});
<|endoftext|>


<commit_before>
import React, { Component } from 'react';
import { Form, Segment, Radio } from 'semantic-ui-react';

// Our Components
import {
  FormPartsContainer, MassiveToggle
} from './formHelpers';

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
const CitizenshipContent = (props) => {

	var origin = props.origin,
      client = origin.pageState;

  return (
    <wrapper className={'field-aligner'}>
      <Form.Field>
        <Radio
          label='US Citizen / National'
          name='citizenshipStatus'
          value='citizen'
          checked={client.citizenshipStatus === 'citizen'}
          onChange={origin.storeComplex}
        />
      </Form.Field>

      <Form.Field>
        <Radio
          label='Lawfully present immigrant / AWSS'
          name='citizenshipStatus'
          value='immigrant'
          checked={client.citizenshipStatus === 'immigrant'}
          onChange={origin.storeComplex}
        />
      </Form.Field>

      <Form.Field>
        <Radio
          label="Don't Know"
          name='citizenshipStatus'
          value='unknown'
          checked={client.citizenshipStatus === 'unknown'}
          onChange={origin.storeComplex}
        />
      </Form.Field>
    </wrapper>
  );  // end return

};  // End CitizenshipContent()

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
// `props` is a cloned version of the original props. References broken.
const CitizenshipStep = function ( props ) {

  return (
    <Form className='citizenship-form'>
      <FormPartsContainer
        title     = {'Citizenship Status'}
        clarifier = {'Select your citizenship status.'}
        next      = {props.nextStep}
        prev      = {props.previousStep} >
        <CitizenshipContent origin={props}/>
      </FormPartsContainer>
    </Form>
  );

};  // End CitizenshipStep()

export { CitizenshipStep };
<commit_msg>Cleans up imports for CitizenshipStep<commit_after>
import React, { Component } from 'react';
import { Form, Segment, Radio } from 'semantic-ui-react';

// Our Components
import {
  FormPartsContainer
} from './formHelpers';

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
const CitizenshipContent = (props) => {

	var origin = props.origin,
      client = origin.pageState;

  return (
    <wrapper className={'field-aligner'}>
      <Form.Field>
        <Radio
          label='US Citizen / National'
          name='citizenshipStatus'
          value='citizen'
          checked={client.citizenshipStatus === 'citizen'}
          onChange={origin.storeComplex}
        />
      </Form.Field>

      <Form.Field>
        <Radio
          label='Lawfully present immigrant / AWSS'
          name='citizenshipStatus'
          value='immigrant'
          checked={client.citizenshipStatus === 'immigrant'}
          onChange={origin.storeComplex}
        />
      </Form.Field>

      <Form.Field>
        <Radio
          label="Don't Know"
          name='citizenshipStatus'
          value='unknown'
          checked={client.citizenshipStatus === 'unknown'}
          onChange={origin.storeComplex}
        />
      </Form.Field>
    </wrapper>
  );  // end return

};  // End CitizenshipContent()

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
// `props` is a cloned version of the original props. References broken.
const CitizenshipStep = function ( props ) {

  return (
    <Form className='citizenship-form'>
      <FormPartsContainer
        title     = {'Citizenship Status'}
        clarifier = {'Select your citizenship status.'}
        next      = {props.nextStep}
        prev      = {props.previousStep} >
        <CitizenshipContent origin={props}/>
      </FormPartsContainer>
    </Form>
  );

};  // End CitizenshipStep()

export { CitizenshipStep };
<|endoftext|>


<commit_before>// Works until you get into the lowest x-axis unit
// allowed, at which point only y gets zoomed in

/** Proportional zooming in charts. Mutator.
 *
 * @param {object} event Whatever event highchart sends. Should have a `.altKey`
 * @param {object} chart Highcharts `chart` object for showing reset zoom button.
 * @param {object} valuesAtMouse
 * @param {number} valuesAtMouse.x X-axis graph value (earnings) at mouse position.
 * @param {number} valuesAtMouse.y Y-axis graph value (total in) at mouse position.
 * @param {object} axes
 * @param {object} axes.x Highcharts `xAxis` object
 * @param {object} axes.y Highcharts `yAxis` object
 *
 * @returns nothing */
const zoom = function (event, chart, valuesAtMouse, axes) {
  // Don't mess with panning
  if (event.altKey === true) {
    return true;  // continue with what you were doing?
  }

  let xVal     = valuesAtMouse.x,
      yVal     = valuesAtMouse.y,
      xAxis    = axes.x,
      yAxis    = axes.y,
      xExtremes = xAxis.getExtremes(),
      yExtremes = yAxis.getExtremes(),
      xAxisMin = xExtremes.min,
      xAxisMax = xExtremes.max,
      yAxisMin = yExtremes.min,
      yAxisMax = yExtremes.max;

  xAxisMin = Math.max(0, xAxisMin);
  xAxisMax = Math.min(xAxis.dataMax, xAxisMax);
  yAxisMin = Math.max(0, yAxisMin);
  yAxisMax = Math.min(yAxis.dataMax, yAxisMax);

  // Trim off a proportionally equal amount from each edge
  // to keep the right ratio of the dimensions of the graph
  // so it doesn't get warped.
  const ZOOM_BASE_X = 1 / 6 * (xAxisMax - xAxisMin),
        ZOOM_BASE_Y = 1 / 6 * (yAxisMax - yAxisMin);

  let xRaw = {
        min: xVal - ZOOM_BASE_X,
        max: xVal + ZOOM_BASE_X,
      },
      yRaw = {
        min: yVal - ZOOM_BASE_Y,
        max: yVal + ZOOM_BASE_Y,
      },
      xMin = Math.max(0, xRaw.min),
      xMax = Math.min(xAxis.dataMax, xRaw.max),
      yMin = Math.max(0, yRaw.min),
      yMax = Math.min(yAxis.dataMax, yRaw.max);

  // If we had to crop off a side, our zoom rectangle doesn't
  // match the graph rectangle ratios any more. Get back to the
  // right ratio.
  if (xMin > xRaw.min) {
    xMax += Math.abs(xMin - xRaw.min);
  }
  if (xMax < xRaw.max) {
    xMin -= Math.abs(xRaw.max - xMax);
  }
  if (yMin > yRaw.min) {
    yMax += Math.abs(yMin - yRaw.min);
  }
  if (yMax < yRaw.max) {
    yMin -= Math.abs(yRaw.max - yMax);
  }

  xAxis.setExtremes(xMin, xMax);
  yAxis.setExtremes(yMin, yMax);

  chart.showResetZoom();

};

export { zoom };
<commit_msg>Trigger new netlify build<commit_after>// Works until you get into the lowest x-axis unit
// allowed, at which point only y gets zoomed in

/** Proportional zooming in charts. Mutator.
 *
 * @param {object} event Whatever event highchart sends. Should have a `.altKey`
 * @param {object} chart Highcharts `chart` object to show reset zoom button.
 * @param {object} valuesAtMouse
 * @param {number} valuesAtMouse.x X-axis graph value (earnings) at mouse position.
 * @param {number} valuesAtMouse.y Y-axis graph value (total in) at mouse position.
 * @param {object} axes
 * @param {object} axes.x Highcharts `xAxis` object
 * @param {object} axes.y Highcharts `yAxis` object
 *
 * @returns nothing */
const zoom = function (event, chart, valuesAtMouse, axes) {
  // Don't mess with panning
  if (event.altKey === true) {
    return true;  // continue with what you were doing?
  }

  let xVal     = valuesAtMouse.x,
      yVal     = valuesAtMouse.y,
      xAxis    = axes.x,
      yAxis    = axes.y,
      xExtremes = xAxis.getExtremes(),
      yExtremes = yAxis.getExtremes(),
      xAxisMin = xExtremes.min,
      xAxisMax = xExtremes.max,
      yAxisMin = yExtremes.min,
      yAxisMax = yExtremes.max;

  xAxisMin = Math.max(0, xAxisMin);
  xAxisMax = Math.min(xAxis.dataMax, xAxisMax);
  yAxisMin = Math.max(0, yAxisMin);
  yAxisMax = Math.min(yAxis.dataMax, yAxisMax);

  // Trim off a proportionally equal amount from each edge
  // to keep the right ratio of the dimensions of the graph
  // so it doesn't get warped.
  const ZOOM_BASE_X = 1 / 6 * (xAxisMax - xAxisMin),
        ZOOM_BASE_Y = 1 / 6 * (yAxisMax - yAxisMin);

  let xRaw = {
        min: xVal - ZOOM_BASE_X,
        max: xVal + ZOOM_BASE_X,
      },
      yRaw = {
        min: yVal - ZOOM_BASE_Y,
        max: yVal + ZOOM_BASE_Y,
      },
      xMin = Math.max(0, xRaw.min),
      xMax = Math.min(xAxis.dataMax, xRaw.max),
      yMin = Math.max(0, yRaw.min),
      yMax = Math.min(yAxis.dataMax, yRaw.max);

  // If we had to crop off a side, our zoom rectangle doesn't
  // match the graph rectangle ratios any more. Get back to the
  // right ratio.
  if (xMin > xRaw.min) {
    xMax += Math.abs(xMin - xRaw.min);
  }
  if (xMax < xRaw.max) {
    xMin -= Math.abs(xRaw.max - xMax);
  }
  if (yMin > yRaw.min) {
    yMax += Math.abs(yMin - yRaw.min);
  }
  if (yMax < yRaw.max) {
    yMin -= Math.abs(yRaw.max - yMax);
  }

  xAxis.setExtremes(xMin, xMax);
  yAxis.setExtremes(yMin, yMax);

  chart.showResetZoom();

};

export { zoom };
<|endoftext|>


<commit_before>import superagent from 'superagent';
import config from '../config';

const methods = ['get', 'post', 'put', 'patch', 'del'];

function formatUrl(path) {
  const adjustedPath = path[0] !== '/' ? '/' + path : path;
  if (__SERVER__) {
    // Prepend host and port of the API server to the path.
    return 'http://localhost:' + config.apiPort + adjustedPath;
  }
  // Prepend `/api` to relative URL, to proxy to API server.
  return '/api' + adjustedPath;
}

export default class ApiClient {
  constructor(req) {
    methods.forEach((method) =>
      this[method] = (path, { params, data } = {}) => new Promise((resolve, reject) => {
        const request = superagent[method](formatUrl(path));

        if (params) request.query(params);

        if (__SERVER__ && req.get('cookie')) {
          request.set('cookie', req.get('cookie'));
        }

        if (data) request.send(data);

        request.end((err, { body } = {}) => err ? reject(body || err) : resolve(body));
      }));
  }
}
<commit_msg>Surround if block with curly brackets.<commit_after>import superagent from 'superagent';
import config from '../config';

const methods = ['get', 'post', 'put', 'patch', 'del'];

function formatUrl(path) {
  const adjustedPath = path[0] !== '/' ? '/' + path : path;
  if (__SERVER__) {
    // Prepend host and port of the API server to the path.
    return 'http://localhost:' + config.apiPort + adjustedPath;
  }
  // Prepend `/api` to relative URL, to proxy to API server.
  return '/api' + adjustedPath;
}

export default class ApiClient {
  constructor(req) {
    methods.forEach((method) =>
      this[method] = (path, { params, data } = {}) => new Promise((resolve, reject) => {
        const request = superagent[method](formatUrl(path));

        if (params) {
          request.query(params);
        }

        if (__SERVER__ && req.get('cookie')) {
          request.set('cookie', req.get('cookie'));
        }

        if (data) {
          request.send(data);
        }

        request.end((err, { body } = {}) => err ? reject(body || err) : resolve(body));
      }));
  }
}
<|endoftext|>


<commit_before>// @flow

/**
 * Strip the unit from a given CSS value, returning just the number. (or the original value if an invalid string was passed)
 *
 * @example
 * // Styles as object usage
 * const styles = {
 *   '--dimension': stripUnit(100px)
 * }
 *
 * // styled-components usage
 * const div = styled.div`
 *   --dimension: ${stripUnit(100px)}
 * `
 *
 * // CSS in JS Output
 *
 * element {
 *   '--dimension': 100
 * }
 */

function stripUnit(value: string): number | string {
  const unitlessValue = parseFloat(value)
  if (isNaN(unitlessValue)) return value
  return unitlessValue
}

export default stripUnit
<commit_msg>docs(stripUnit): add quotes to strings in example (#233)<commit_after>// @flow

/**
 * Strip the unit from a given CSS value, returning just the number. (or the original value if an invalid string was passed)
 *
 * @example
 * // Styles as object usage
 * const styles = {
 *   '--dimension': stripUnit('100px')
 * }
 *
 * // styled-components usage
 * const div = styled.div`
 *   --dimension: ${stripUnit('100px')}
 * `
 *
 * // CSS in JS Output
 *
 * element {
 *   '--dimension': 100
 * }
 */

function stripUnit(value: string): number | string {
  const unitlessValue = parseFloat(value)
  if (isNaN(unitlessValue)) return value
  return unitlessValue
}

export default stripUnit
<|endoftext|>


<commit_before>// @flow

const cssRegex = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/

/**
 * Returns a given CSS value minus its unit of measure.
 *
 * @deprecated - stripUnit's unitReturn functionality has been marked for deprecation in polished 4.0. It's functionality has been been moved to getUnitAndValue.
 *
 * @example
 * // Styles as object usage
 * const styles = {
 *   '--dimension': stripUnit('100px')
 * }
 *
 * // styled-components usage
 * const div = styled.div`
 *   --dimension: ${stripUnit('100px')};
 * `
 *
 * // CSS in JS Output
 *
 * element {
 *   '--dimension': 100
 * }
 */
export default function stripUnit(
  value: string | number,
  unitReturn?: boolean,
): any {
  if (typeof value !== 'string') return unitReturn ? [value, undefined] : value
  const matchedValue = value.match(cssRegex)

  if (unitReturn) {
    // eslint-disable-next-line no-console
    console.warn(
      "stripUnit's unitReturn functionality has been marked for deprecation in polished 4.0. It's functionality has been been moved to getUnitAndValue.",
    )
    if (matchedValue) return [parseFloat(value), matchedValue[2]]
    return [value, undefined]
  }

  if (matchedValue) return parseFloat(value)
  return value
}
<commit_msg>docs: fix wrong `getUnitAndValue` replacing it by `getValueAndUnit` both  in docs and  warning<commit_after>// @flow

const cssRegex = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/

/**
 * Returns a given CSS value minus its unit of measure.
 *
 * @deprecated - stripUnit's unitReturn functionality has been marked for deprecation in polished 4.0. It's functionality has been been moved to getValueAndUnit.
 *
 * @example
 * // Styles as object usage
 * const styles = {
 *   '--dimension': stripUnit('100px')
 * }
 *
 * // styled-components usage
 * const div = styled.div`
 *   --dimension: ${stripUnit('100px')};
 * `
 *
 * // CSS in JS Output
 *
 * element {
 *   '--dimension': 100
 * }
 */
export default function stripUnit(
  value: string | number,
  unitReturn?: boolean,
): any {
  if (typeof value !== 'string') return unitReturn ? [value, undefined] : value
  const matchedValue = value.match(cssRegex)

  if (unitReturn) {
    // eslint-disable-next-line no-console
    console.warn(
      "stripUnit's unitReturn functionality has been marked for deprecation in polished 4.0. It's functionality has been been moved to getValueAndUnit.",
    )
    if (matchedValue) return [parseFloat(value), matchedValue[2]]
    return [value, undefined]
  }

  if (matchedValue) return parseFloat(value)
  return value
}
<|endoftext|>


<commit_before>App.TagValuesGrid = Ext.extend(Ext.grid.EditorGridPanel, {
	border: false
	,closable: true
	,title: 'Tag values'
	,loadMask: true
	,oid: null
	,initComponent: function(){
		this.sm = new Ext.grid.RowSelectionModel({singleSelect:true});
		this.store = gridstore = new Ext.data.GroupingStore({
			proxy: new Ext.data.DirectProxy({
				directFn: direct.TagValuesFetch
				,paramsAsHash: false
				,paramOrder: 'oid'
			})
			,autoDestroy: true
			,groupField: 'ns'
			,sortInfo: {field: 'tag', direction: 'ASC'}
			,remoteSort: false
			,reader: new Ext.data.JsonReader({
				root: 'tags'
				,idProperty: 'tag'
				,fields: ['ns', 'tag', 'value', 'readonly', 'type']
			})
		});
		this.view = new Ext.grid.GroupingView({
			forceFit: true
			,groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
			,emptyText: 'Nothing to display'
		});
		this.tbar = [
			{text: 'Refresh', iconCls: 'icon-refresh', handler: this.onRefresh, scope: this}
			,{text: 'Load all tag values', iconCls: 'icon-fetch-all', handler: this.onLoadAllTags, scope: this}
			,{text: 'Add a tag', iconCls: 'icon-tag-add', handler: this.onAddTag, scope: this}
			,'-'
			,{text: 'View visual representation', iconCls: 'icon-eye', handler: function(){ window.open("http://abouttag.appspot.com/id/butterfly/"+this.oid);}, scope: this}
		];
		this.action = new Ext.ux.grid.RowActions({
			actions: [
				{iconCls: 'icon-refresh', tooltip: 'Load tag value'}
				,{iconCls: 'icon-tag-remove', tooltip: 'Remove tag'}
			]
			,callbacks:{
				'icon-refresh': this.onRefreshRow.createDelegate(this)
				,'icon-tag-remove': this.onDeleteTag.createDelegate(this)
			}
		});
		this.colModel = new Ext.grid.ColumnModel({
			columns: [
				this.action
				,{header:'Namespace', dataIndex: 'ns', hidden: true}
				,{id:'tag', header:'Tag', width: 230, dataIndex: 'tag', sortable: true}
				,{header: 'Value', width: 600, dataIndex: 'value', sortable: true, renderer: {fn: this.valueRenderer, scope: this}, editor: {xtype: 'textfield'}}
			]
			,isCellEditable: function(col, row) {
				var record = gridstore.getAt(row);
				if (record.get('readonly')) {
					return false;
				}
				return Ext.grid.ColumnModel.prototype.isCellEditable.call(this, col, row);
			}
		});

		this.plugins = [this.action];
		App.TagValuesGrid.superclass.initComponent.call(this);

		this.on('cellclick', this.onCellClick, this);
	}
	,afterRender: function(){
		App.TagValuesGrid.superclass.afterRender.apply(this, arguments);

		if (this.oid) {
			this.store.load({params: {oid: this.oid}});
		}

		this.on('afteredit', this.onAfterEdit, this);
		this.body.on('click', this.onClick, this);
	}
	,onAfterEdit: function(e){
		var tag = e.record.data.tag;
		var value = e.value;

		direct.TagObject(this.oid, tag, value, function(){e.record.commit();});
	}
	,onAddTag: function(){
		var tag = window.prompt('Please enter full tag path');
		var value = window.prompt('Value');

		store = this.store;
		direct.TagObject(this.oid, tag,  value, function(){store.reload();});
	}
	,onLoadAllTags: function(a){
		this.store.each(this.setTag.createDelegate(this));
	}
	,onRefresh: function(){
		this.store.reload();
	}
	,onRefreshRow: function(g, r, action, row, col){
		this.setTag(r);
	}
	,onDeleteTag: function(g, r, action, row, col){
		r.set('value', 'removing tag...');
		direct.DeleteTagValue(this.oid, r.data.tag, function(){g.store.remove(r);});
	}
	,setTag: function(r){
		r.set('type', 'primitive');
		r.set('value', 'loading...');
		oid = this.oid;
		direct.GetTagValue(oid, r.data.tag, function(json){
			type = json.type;

			if (type == 'primitive') {
				value = json.value;
			}
			else if (type == 'empty') {
				// TODO: Add color and/or icon
				value = 'empty';
			}
			else if (type == 'opaque') {
				value = 'Opaque value with content-type: "' + json.value + '" open';
			}
			else {
				value = 'Unsupported type: "' + type + '"';
			}
			r.set('value', value);
			r.set('type', type);
			r.set('readonly', json.readonly);
			r.commit();
		});
	}
	,valueRenderer: function(value, metaData, rec) {
		type = rec.data.type;
		if (type == 'notfetch') {
			metaData.css = 'gridclicktofetch';
			return 'Click to load tag value';
		}

		if (value.match(/^https?:\/\//)) {
			return '' + value + '';
		}

		if (!value.match(/^Opaque value with content-type/)) {
			value = value.replace(/(([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12})/g, '$1');
		}

		return value;
	}
	,onCellClick: function(grid, rowIndex, columnIndex, e) {
		if (columnIndex != 3) {
			return;
		}

		var rec = grid.getStore().getAt(rowIndex);
		if (rec.data.type == 'notfetch') {
			this.setTag(rec);
		}
	}
	,onClick: function(e, target) {
		if (target = e.getTarget('.openobject', 2)) {
			e.stopEvent();
			objid = Ext.fly(target).getAttributeNS('expl', 'objectid');
			Ext.getCmp('mainpanel').openObject(objid);
		}
	}
});

Ext.reg('app.tagvaluesgrid', App.TagValuesGrid);

<commit_msg>TagValueGrid: make the 'Click to load tag value' clickable<commit_after>App.TagValuesGrid = Ext.extend(Ext.grid.EditorGridPanel, {
	border: false
	,closable: true
	,title: 'Tag values'
	,loadMask: true
	,oid: null
	,initComponent: function(){
		this.sm = new Ext.grid.RowSelectionModel({singleSelect:true});
		this.store = gridstore = new Ext.data.GroupingStore({
			proxy: new Ext.data.DirectProxy({
				directFn: direct.TagValuesFetch
				,paramsAsHash: false
				,paramOrder: 'oid'
			})
			,autoDestroy: true
			,groupField: 'ns'
			,sortInfo: {field: 'tag', direction: 'ASC'}
			,remoteSort: false
			,reader: new Ext.data.JsonReader({
				root: 'tags'
				,idProperty: 'tag'
				,fields: ['ns', 'tag', 'value', 'readonly', 'type']
			})
		});
		this.view = new Ext.grid.GroupingView({
			forceFit: true
			,groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
			,emptyText: 'Nothing to display'
		});
		this.tbar = [
			{text: 'Refresh', iconCls: 'icon-refresh', handler: this.onRefresh, scope: this}
			,{text: 'Load all tag values', iconCls: 'icon-fetch-all', handler: this.onLoadAllTags, scope: this}
			,{text: 'Add a tag', iconCls: 'icon-tag-add', handler: this.onAddTag, scope: this}
			,'-'
			,{text: 'View visual representation', iconCls: 'icon-eye', handler: function(){ window.open("http://abouttag.appspot.com/id/butterfly/"+this.oid);}, scope: this}
		];
		this.action = new Ext.ux.grid.RowActions({
			actions: [
				{iconCls: 'icon-refresh', tooltip: 'Load tag value'}
				,{iconCls: 'icon-tag-remove', tooltip: 'Remove tag'}
			]
			,callbacks:{
				'icon-refresh': this.onRefreshRow.createDelegate(this)
				,'icon-tag-remove': this.onDeleteTag.createDelegate(this)
			}
		});
		this.colModel = new Ext.grid.ColumnModel({
			columns: [
				this.action
				,{header:'Namespace', dataIndex: 'ns', hidden: true}
				,{id:'tag', header:'Tag', width: 230, dataIndex: 'tag', sortable: true}
				,{header: 'Value', width: 600, dataIndex: 'value', sortable: true, renderer: {fn: this.valueRenderer, scope: this}, editor: {xtype: 'textfield'}}
			]
			,isCellEditable: function(col, row) {
				var record = gridstore.getAt(row);
				if (record.get('readonly')) {
					return false;
				}
				return Ext.grid.ColumnModel.prototype.isCellEditable.call(this, col, row);
			}
		});

		this.plugins = [this.action];
		App.TagValuesGrid.superclass.initComponent.call(this);

		// TODO: See why cellclick can't be used (like App.ResultsGrid)
		this.on('cellmousedown', this.onCellClick, this);
	}
	,afterRender: function(){
		App.TagValuesGrid.superclass.afterRender.apply(this, arguments);

		if (this.oid) {
			this.store.load({params: {oid: this.oid}});
		}

		this.on('afteredit', this.onAfterEdit, this);
		this.body.on('click', this.onClick, this);
	}
	,onAfterEdit: function(e){
		var tag = e.record.data.tag;
		var value = e.value;

		direct.TagObject(this.oid, tag, value, function(){e.record.commit();});
	}
	,onAddTag: function(){
		var tag = window.prompt('Please enter full tag path');
		var value = window.prompt('Value');

		store = this.store;
		direct.TagObject(this.oid, tag,  value, function(){store.reload();});
	}
	,onLoadAllTags: function(a){
		this.store.each(this.setTag.createDelegate(this));
	}
	,onRefresh: function(){
		this.store.reload();
	}
	,onRefreshRow: function(g, r, action, row, col){
		this.setTag(r);
	}
	,onDeleteTag: function(g, r, action, row, col){
		r.set('value', 'removing tag...');
		direct.DeleteTagValue(this.oid, r.data.tag, function(){g.store.remove(r);});
	}
	,setTag: function(r){
		r.set('type', 'primitive');
		r.set('value', 'loading...');
		oid = this.oid;
		direct.GetTagValue(oid, r.data.tag, function(json){
			type = json.type;

			if (type == 'primitive') {
				value = json.value;
			}
			else if (type == 'empty') {
				// TODO: Add color and/or icon
				value = 'empty';
			}
			else if (type == 'opaque') {
				value = 'Opaque value with content-type: "' + json.value + '" open';
			}
			else {
				value = 'Unsupported type: "' + type + '"';
			}
			r.set('value', value);
			r.set('type', type);
			r.set('readonly', json.readonly);
			r.commit();
		});
	}
	,valueRenderer: function(value, metaData, rec) {
		type = rec.data.type;
		if (type == 'notfetch') {
			metaData.css = 'gridclicktofetch';
			return 'Click to load tag value';
		}

		if (value.match(/^https?:\/\//)) {
			return '' + value + '';
		}

		if (!value.match(/^Opaque value with content-type/)) {
			value = value.replace(/(([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12})/g, '$1');
		}

		return value;
	}
	,onCellClick: function(grid, rowIndex, columnIndex, e) {
		if (columnIndex != 3) {
			return;
		}

		var rec = grid.getStore().getAt(rowIndex);
		if (rec.data.type == 'notfetch') {
			this.setTag(rec);
		}
	}
	,onClick: function(e, target) {
		if (target = e.getTarget('.openobject', 2)) {
			e.stopEvent();
			objid = Ext.fly(target).getAttributeNS('expl', 'objectid');
			Ext.getCmp('mainpanel').openObject(objid);
		}
	}
});

Ext.reg('app.tagvaluesgrid', App.TagValuesGrid);

<|endoftext|>


<commit_before>$(document).ready(function() {
    'use strict';

    var MAX_NAME_LENGTH = 50;
    var BANNER_HEIGHT = 160;

    // Prep templates located in the HTML
    var name_tmpl = $('#name_tmpl').html();
    var progress_tmpl = $('#progress_tmpl').html();
    var progress_container_tmpl = $('#progress_container_tmpl').html();
    var progress_popover_tmpl = $('#progress_popover_tmpl').html();

    // Compile templates for speedup
    Mustache.parse(name_tmpl);
    Mustache.parse(progress_tmpl);
    Mustache.parse(progress_container_tmpl);
    Mustache.parse(progress_popover_tmpl);

    // Handle vertical resizing of the table
    function calcHeight() {
        return $(window).height() - BANNER_HEIGHT;
    }

    $(window).on('resize', function() {
        // The joy of fitting vertically!
        $('.dataTables_scrollBody').height(calcHeight()).css('max-height', 'inherit');
    });

    // Cluster status table.
    var cluster_table = $("#yarn_status").DataTable({
        ajax: YARNITOR_BASE_URL+"/api/cluster",
        paging: false,
        searching: false,
        ordering: false,
        dom: 't',
        columns: [
            {
                data: "activeNodes",
                title: "Nodes",
                render: function(data, type, row) {
                    return (data - row['unhealthyNodes']) + ' / ' + data;
                }
            },
            {
                data: "totalVirtualCores",
                title: "VCPUs",
                render: function(data, type, row) {
                    return row['availableVirtualCores'] + ' / ' + data;
                }
            },
            {
               data: "totalMB",
               title: "RAM (GB)",
               render: function(data, type, row) {
                    return Math.round(row['availableMB'] / 1024) + ' / ' + Math.round(data / 1024);
               }
            }
        ]
    });

    // Main applications table
    var table = $('#yarn_applications').DataTable({
        ajax: YARNITOR_BASE_URL+"/api/applications",
        rowId: "id",
        scrollX: true,
        scrollY: calcHeight(),
        paging: false,
        order: [4, 'desc'],
        language: {
            "search": "",
            "searchPlaceholder": "Filter records"
        },
        dom: ("<'row'<'col-xs-8'l><'col-xs-4'f>>" +
             "<'row'<'col-xs-12'tr>>" +
             "<'row'<'col-xs-6'i><'col-xs-6 dataTables_refreshed'>>"),
        columns: [
            {
                data: "name",
                title: "Name",
                render: function(data, type, row, meta) {
                    if(data.length > MAX_NAME_LENGTH) {
                        data = data.substr(0, MAX_NAME_LENGTH) + '...';
                    }
                    var html = Mustache.render(name_tmpl, {
                        name: data,
                        trackingUrl: row.trackingUrl,
                        id: row.id
                    });
                    return html;
                }
            },
            {data: "user", title: "User"},
            {data: "state", title: "State"},
            {
                title: "Progress",
                render: function(data, type, row, meta) {
                    // progress bars
                    var bar_htmls = row.progress.map(function(progress) {
                        var total = progress.completed + progress.running + progress.failed;
                        total = (progress.total > total) ? progress.total : total;
                        var args = {
                            completed: progress.completed,
                            completed_ratio: progress.completed / progress.total * 100,
                            running: progress.running,
                            running_ratio: progress.running / progress.total * 100,
                            failed: progress.failed,
                            failed_ratio: progress.failed / progress.total * 100,
                            total: progress.total
                        };

                        return Mustache.render(progress_tmpl, args);
                    });

                    return Mustache.render(progress_container_tmpl, {
                        progress_html: bar_htmls.join('\n'),
                        popover_html : Mustache.render(progress_popover_tmpl, row)
                    });
                }
            },
            {data: "allocatedVCores", title: "VCPUs"},
            {
                data: "allocatedMB",
                title: "Memory (GB)",
                render: function(data) {
                    return Math.round(data / 1024);
                }
            },
            {
              "title": "Mem/VCPU Ratio",
              "render": function(data, type, row, meta) {
                return (row.allocatedMB / row.allocatedVCores / 1024).toFixed(2);
              }
            },
            {"data": "applicationType", "title": "Job Type"},
            {"data": "queue", "title": "Queue"},
            {
                "data": "startedTime",
                "title": "Local Start Time",
                "render": function(data, type, row, meta) {
                    return (new Date(data)).toLocaleString();
                }
            },
        ]
    });

    var pageScrollPos = 0;

    table.on('draw.dt', function() {
        console.log('yarnitor:draw.dt');
        // Remove shown popovers
        $('.popover').remove();
        $('[data-toggle="popover"]').popover();
        // rescroll
        $('div.dataTables_scrollBody').scrollTop(pageScrollPos);
    });

    table.on('xhr.dt', function() {
        console.log('yarnitor:xhr.dt');
        // destroy the popovers before the draw phase kicks in.
        $('[data-toggle="popover"]').popover("destroy");
        pageScrollPos = $('div.dataTables_scrollBody').scrollTop();
    });

    var reload_datetime = function() {
        $.get({
            url: YARNITOR_BASE_URL+"/api/status",
            dataType: 'json'
        }).done(function(data) {
            // Show datetime data was last refreshed from the YARN API
            // if that information is available, else leave the display alone
            if(data.refresh_datetime) {
                var d = (new Date(data.refresh_datetime)).toLocaleString();
                $('.dataTables_refreshed').text('Showing data from ' + d);
            }
        });
    }

    setInterval(function() {
        console.log('yarnitor:refresh');
        table.ajax.reload();
        cluster_table.ajax.reload();
        reload_datetime();
    }, YARNITOR_REFRESH_INTERVAL_S * 1000);

    // Throw exceptions in the console, not in alert dialogs
    $.fn.dataTable.ext.errMode = 'throw';
    // Immediately try to fetch datetime of last data refresh
    reload_datetime();

    console.log('yarnitor:dom-ready');
});
<commit_msg>Fix incorrect nodes summary<commit_after>$(document).ready(function() {
    'use strict';

    var MAX_NAME_LENGTH = 50;
    var BANNER_HEIGHT = 160;

    // Prep templates located in the HTML
    var name_tmpl = $('#name_tmpl').html();
    var progress_tmpl = $('#progress_tmpl').html();
    var progress_container_tmpl = $('#progress_container_tmpl').html();
    var progress_popover_tmpl = $('#progress_popover_tmpl').html();

    // Compile templates for speedup
    Mustache.parse(name_tmpl);
    Mustache.parse(progress_tmpl);
    Mustache.parse(progress_container_tmpl);
    Mustache.parse(progress_popover_tmpl);

    // Handle vertical resizing of the table
    function calcHeight() {
        return $(window).height() - BANNER_HEIGHT;
    }

    $(window).on('resize', function() {
        // The joy of fitting vertically!
        $('.dataTables_scrollBody').height(calcHeight()).css('max-height', 'inherit');
    });

    // Cluster status table.
    var cluster_table = $("#yarn_status").DataTable({
        ajax: YARNITOR_BASE_URL+"/api/cluster",
        paging: false,
        searching: false,
        ordering: false,
        dom: 't',
        columns: [
            {
                data: "totalNodes",
                title: "Nodes",
                render: function(data, type, row) {
                    return (data - row['unhealthyNodes']) + ' / ' + data;
                }
            },
            {
                data: "totalVirtualCores",
                title: "VCPUs",
                render: function(data, type, row) {
                    return row['availableVirtualCores'] + ' / ' + data;
                }
            },
            {
               data: "totalMB",
               title: "RAM (GB)",
               render: function(data, type, row) {
                    return Math.round(row['availableMB'] / 1024) + ' / ' + Math.round(data / 1024);
               }
            }
        ]
    });

    // Main applications table
    var table = $('#yarn_applications').DataTable({
        ajax: YARNITOR_BASE_URL+"/api/applications",
        rowId: "id",
        scrollX: true,
        scrollY: calcHeight(),
        paging: false,
        order: [4, 'desc'],
        language: {
            "search": "",
            "searchPlaceholder": "Filter records"
        },
        dom: ("<'row'<'col-xs-8'l><'col-xs-4'f>>" +
             "<'row'<'col-xs-12'tr>>" +
             "<'row'<'col-xs-6'i><'col-xs-6 dataTables_refreshed'>>"),
        columns: [
            {
                data: "name",
                title: "Name",
                render: function(data, type, row, meta) {
                    if(data.length > MAX_NAME_LENGTH) {
                        data = data.substr(0, MAX_NAME_LENGTH) + '...';
                    }
                    var html = Mustache.render(name_tmpl, {
                        name: data,
                        trackingUrl: row.trackingUrl,
                        id: row.id
                    });
                    return html;
                }
            },
            {data: "user", title: "User"},
            {data: "state", title: "State"},
            {
                title: "Progress",
                render: function(data, type, row, meta) {
                    // progress bars
                    var bar_htmls = row.progress.map(function(progress) {
                        var total = progress.completed + progress.running + progress.failed;
                        total = (progress.total > total) ? progress.total : total;
                        var args = {
                            completed: progress.completed,
                            completed_ratio: progress.completed / progress.total * 100,
                            running: progress.running,
                            running_ratio: progress.running / progress.total * 100,
                            failed: progress.failed,
                            failed_ratio: progress.failed / progress.total * 100,
                            total: progress.total
                        };

                        return Mustache.render(progress_tmpl, args);
                    });

                    return Mustache.render(progress_container_tmpl, {
                        progress_html: bar_htmls.join('\n'),
                        popover_html : Mustache.render(progress_popover_tmpl, row)
                    });
                }
            },
            {data: "allocatedVCores", title: "VCPUs"},
            {
                data: "allocatedMB",
                title: "Memory (GB)",
                render: function(data) {
                    return Math.round(data / 1024);
                }
            },
            {
              "title": "Mem/VCPU Ratio",
              "render": function(data, type, row, meta) {
                return (row.allocatedMB / row.allocatedVCores / 1024).toFixed(2);
              }
            },
            {"data": "applicationType", "title": "Job Type"},
            {"data": "queue", "title": "Queue"},
            {
                "data": "startedTime",
                "title": "Local Start Time",
                "render": function(data, type, row, meta) {
                    return (new Date(data)).toLocaleString();
                }
            },
        ]
    });

    var pageScrollPos = 0;

    table.on('draw.dt', function() {
        console.log('yarnitor:draw.dt');
        // Remove shown popovers
        $('.popover').remove();
        $('[data-toggle="popover"]').popover();
        // rescroll
        $('div.dataTables_scrollBody').scrollTop(pageScrollPos);
    });

    table.on('xhr.dt', function() {
        console.log('yarnitor:xhr.dt');
        // destroy the popovers before the draw phase kicks in.
        $('[data-toggle="popover"]').popover("destroy");
        pageScrollPos = $('div.dataTables_scrollBody').scrollTop();
    });

    var reload_datetime = function() {
        $.get({
            url: YARNITOR_BASE_URL+"/api/status",
            dataType: 'json'
        }).done(function(data) {
            // Show datetime data was last refreshed from the YARN API
            // if that information is available, else leave the display alone
            if(data.refresh_datetime) {
                var d = (new Date(data.refresh_datetime)).toLocaleString();
                $('.dataTables_refreshed').text('Showing data from ' + d);
            }
        });
    }

    setInterval(function() {
        console.log('yarnitor:refresh');
        table.ajax.reload();
        cluster_table.ajax.reload();
        reload_datetime();
    }, YARNITOR_REFRESH_INTERVAL_S * 1000);

    // Throw exceptions in the console, not in alert dialogs
    $.fn.dataTable.ext.errMode = 'throw';
    // Immediately try to fetch datetime of last data refresh
    reload_datetime();

    console.log('yarnitor:dom-ready');
});
<|endoftext|>