<commit_before>import _ from 'underscore';
import console from '../lib/helpers/consoleHelpers.js';

class MetadataProvider {

    /**
     * Validates a field metadata
     * @param metadata
     * @private
     */
    validateFieldMetadata(metadata) {
        if (!metadata) throw Error('metadata should not be null or undefined');
        if (!metadata.name) throw Error('metadata\'s "name" property is required');
        if (!metadata.type) throw Error('metadata\'s "type" property is required');
    }

    getEntity(schema, entityName) {
        if (schema === null || schema === undefined) {
            throw new Error(`Parameter should not be not or undefined. Parameter name: schema`);
        }

        if (schema.entities === undefined || schema.entities === null) {
            throw new Error('Parameter should not be null or undefined. Parameter: ' + schema.entity);
        }

        if (entityName === null || entityName === undefined) {
            throw new Error(`Parameter should not be not or undefined. Parameter name: entityName`);
        }
        let entity = _.find(schema.entities, e => e.name === entityName);
        if (!entity) {
            throw new Error(`Could not find entity. Entity name: ${entityName}`);
        }
        return entity;
    }

    getLayout(entity, layoutName) {
        if (entity === null || entity === undefined) {
            throw new Error(`Parameter should not be not or undefined. Parameter name: entity`);
        }
        let layout = _.find(entity.layouts, l => l.name === layoutName);
        if (!layout) {
            throw new Error(`Could not find layout. Layout name: ${layoutName}`);
        }
        return layout;
    }

    getEntityAndLayout(schema, entityName, layoutName) {

        let entity = this.getEntity(schema, entityName);
        let layout = this.getLayout(entity, layoutName);

        return {
            entity: entity,
            layout: layout
        }
    }

    getFieldsInternal(schema, entity, layout, partialResult) {

        if(!entity) {
            throw Error('Paramater is fucked');
        }

        if (!partialResult) {
            partialResult = [];
        }

        let thisGroupFields = [];

        if (!layout.fields && !layout.groups) {
            throw Error('a layout can either have fields or groups. Never both.');
        }

        if (layout.groups) {
            for (let i = 0; i < layout.groups.length; i++) {
                thisGroupFields = _.union(thisGroupFields, this.getFieldsInternal(schema, entity, layout.groups[i], partialResult));
            }
        }
        else if (layout.fields) {

            for (let i = 0; i < layout.fields.length; i++) {

                let groupField = layout.fields[i];

                let existingEntityProperty = _.find(entity.fields, field => field.name == groupField.name);

                if (!existingEntityProperty) {
                    throw Error(`cannot find entity field. Field: ${groupField.name}. Group: ${layout}`);
                }

                let field = _.extend({}, existingEntityProperty, groupField);
                this.validateFieldMetadata(field);

                thisGroupFields.push(field);

                if (field.type == 'entity') {
                    if (!field.entityName) {
                        throw Error('when a field is of type \'entity\', it needs to specify an \'entityName\'')
                    }
                    if (!field.layoutName) {
                        throw Error('when a field is of type \'entity\', it needs to specify a \'layoutName\'');
                    }

                    let entityAndLayout = this.getEntityAndLayout(schema, field.entityName, field.layoutName);
                    field.layout = this.processLayout(schema, field.entityName, field.layoutName);
                    field.fields = this.getFieldsInternal(schema, entityAndLayout.entity, entityAndLayout.layout, partialResult);
                }
            }
        }
        else {
            throw Error('a layout must have either fields or groups.');
        }
        return _.union(partialResult, thisGroupFields);

    }

    /**
     * Merges the given field collection
     * @param schema
     * @param entityName
     * @layoutName layoutName
     */
    getFields(schema, entityName, layoutName) {
        let entityAndLayout = this.getEntityAndLayout(schema, entityName, layoutName);
        return this.getFieldsInternal(schema, entityAndLayout.entity, entityAndLayout.layout);
    }

    processLayoutGroup(layoutGroup) {
        let layoutGroupCopy = _.extend({}, layoutGroup);
        if (layoutGroupCopy.fields) {
            for (let i = 0; i < layoutGroupCopy.fields.length; i++) {
                layoutGroupCopy.fields[i] = { name: layoutGroupCopy.fields[i].name };
            }
        }
        else if (layoutGroupCopy.groups) {
            for (let i = 0; i < layoutGroupCopy.groups.length; i++) {
                layoutGroupCopy.groups[i] = this.processLayoutGroup(layoutGroupCopy.groups[i]);
            }
        }

        // remove every property that is not 'groups' and 'fields'
        _.each(_.keys(layoutGroupCopy), i => {
            if (i == 'groups' || i == 'fields') {
                return;
            }
            delete layoutGroupCopy[i];
        });

        return layoutGroupCopy;
    }

    processLayout(schema, entityName, layoutName) {
        let entityAndLayout = this.getEntityAndLayout(schema, entityName, layoutName);
        return this.processLayoutGroup(entityAndLayout.layout);
    }
}

export default new MetadataProvider();
<commit_msg>More optimizations on the MetadataProvider<commit_after>import _ from 'underscore';
import console from '../lib/helpers/consoleHelpers.js';

class MetadataProvider {

    /**
     * Validates a field metadata
     * @param metadata
     * @private
     */
    validateFieldMetadata(metadata) {
        if (!metadata) throw Error('metadata should not be null or undefined');
        if (!metadata.name) throw Error('metadata\'s "name" property is required');
        if (!metadata.type) throw Error('metadata\'s "type" property is required');
    }

    getEntity(schema, entityName) {
        if (schema === null || schema === undefined) {
            throw new Error(`Parameter should not be not or undefined. Parameter name: schema`);
        }

        if (schema.entities === undefined || schema.entities === null) {
            throw new Error('Parameter should not be null or undefined. Parameter: ' + schema.entity);
        }

        if (entityName === null || entityName === undefined) {
            throw new Error(`Parameter should not be not or undefined. Parameter name: entityName`);
        }
        let entity = _.find(schema.entities, e => e.name === entityName);
        if (!entity) {
            throw new Error(`Could not find entity. Entity name: ${entityName}`);
        }
        return entity;
    }

    getLayout(entity, layoutName) {
        if (entity === null || entity === undefined) {
            throw new Error(`Parameter should not be not or undefined. Parameter name: entity`);
        }
        let layout = _.find(entity.layouts, l => l.name === layoutName);
        if (!layout) {
            throw new Error(`Could not find layout. Layout name: ${layoutName}`);
        }
        return layout;
    }

    getEntityAndLayout(schema, entityName, layoutName) {

        let entity = this.getEntity(schema, entityName);
        let layout = this.getLayout(entity, layoutName);

        return {
            entity: entity,
            layout: layout
        }
    }

    getFieldsInternal(schema, entity, layout, partialResult) {

        if(!entity) {
            throw Error('Paramater is fucked');
        }

        if (!partialResult) {
            partialResult = [];
        }

        let thisGroupFields = [];

        if (!layout.fields && !layout.groups) {
            throw Error('a layout can either have fields or groups. Never both.');
        }

        if (layout.groups) {
            for (let i = 0; i < layout.groups.length; i++) {
                thisGroupFields = _.union(thisGroupFields, this.getFieldsInternal(schema, entity, layout.groups[i], partialResult));
            }
        }
        else if (layout.fields) {

            for (let i = 0; i < layout.fields.length; i++) {

                let groupField = layout.fields[i];

                let existingEntityProperty = _.find(entity.fields, field => field.name == groupField.name);

                if (!existingEntityProperty) {
                    throw Error(`cannot find entity field. Field: ${groupField.name}. Group: ${layout}`);
                }

                let field = _.extend({}, existingEntityProperty, groupField);
                this.validateFieldMetadata(field);

                thisGroupFields.push(field);

                if (field.type == 'entity') {
                    if (!field.entityName) {
                        throw Error('when a field is of type \'entity\', it needs to specify an \'entityName\'')
                    }
                    if (!field.layoutName) {
                        throw Error('when a field is of type \'entity\', it needs to specify a \'layoutName\'');
                    }

                    let entityAndLayout = this.getEntityAndLayout(schema, field.entityName, field.layoutName);
                    field.layout = this.processLayout(schema, entityAndLayout.entity, entityAndLayout.layout);
                    field.fields = this.getFieldsInternal(schema, entityAndLayout.entity, entityAndLayout.layout, partialResult);
                }
            }
        }
        else {
            throw Error('a layout must have either fields or groups.');
        }
        return _.union(partialResult, thisGroupFields);

    }

    /**
     * Merges the given field collection
     * @param schema
     * @param entityName
     * @layoutName layoutName
     */
    getFields(schema, entityName, layoutName) {
        let entityAndLayout = this.getEntityAndLayout(schema, entityName, layoutName);
        return this.getFieldsInternal(schema, entityAndLayout.entity, entityAndLayout.layout);
    }

    processLayoutGroup(layoutGroup) {
        let layoutGroupCopy = _.extend({}, layoutGroup);
        if (layoutGroupCopy.fields) {
            for (let i = 0; i < layoutGroupCopy.fields.length; i++) {
                layoutGroupCopy.fields[i] = { name: layoutGroupCopy.fields[i].name };
            }
        }
        else if (layoutGroupCopy.groups) {
            for (let i = 0; i < layoutGroupCopy.groups.length; i++) {
                layoutGroupCopy.groups[i] = this.processLayoutGroup(layoutGroupCopy.groups[i]);
            }
        }

        // remove every property that is not 'groups' and 'fields'
        _.each(_.keys(layoutGroupCopy), i => {
            if (i == 'groups' || i == 'fields') {
                return;
            }
            delete layoutGroupCopy[i];
        });

        return layoutGroupCopy;
    }

    processLayout(schema, entity, layout) {
        if (typeof entity === 'string') {
            entity = this.getEntity(schema, entity);
        }
        if (typeof layout === 'string') {
            layout = this.getLayout(entity, layout);
        }
        return this.processLayoutGroup(layout);
    }
}

export default new MetadataProvider();
<|endoftext|>


<commit_before>import { createApiPromise, createPostingApiPromise, acceptParams } from '../apiUtil';

export function topicsList(linkId) {
  return createApiPromise('/api/topics/listFilterCascade', linkId ? { linkId } : undefined);
}

export function topicsPublicList() {
  return createApiPromise('/api/topics/list');
}

export function topicSummary(topicId) {
  return createApiPromise(`/api/topics/${topicId}/summary`);
}

export function topicTopStories(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'sort', 'limit', 'q', 'linkId']);
  return createApiPromise(`/api/topics/${topicId}/stories`, acceptedParams);
}

export function topicTopMedia(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'sort', 'limit', 'linkId']);
  return createApiPromise(`/api/topics/${topicId}/media`, acceptedParams);
}

export function topicTopWords(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'withTotals']);
  return createApiPromise(`/api/topics/${topicId}/words`, acceptedParams);
}

export function topicSnapshotsList(topicId) {
  return createApiPromise(`/api/topics/${topicId}/snapshots/list`);
}

export function topicTimespansList(topicId, snapshotId, params) {
  const acceptedParams = acceptParams(params, ['focusId']);
  return createApiPromise(`/api/topics/${topicId}/snapshots/${snapshotId}/timespans/list`, acceptedParams);
}

export function topicSentenceCounts(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/sentences/count`, acceptedParams);
}

export function story(topicId, storiesId) {
  return createApiPromise(`/api/topics/${topicId}/stories/${storiesId}`);
}

export function storyWords(topicId, storiesId) {
  return createApiPromise(`/api/topics/${topicId}/stories/${storiesId}/words`);
}

export function storyInlinks(topicId, storiesId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/stories/${storiesId}/inlinks`, acceptedParams);
}

export function storyOutlinks(topicId, storiesId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/stories/${storiesId}/outlinks`, acceptedParams);
}

export function media(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}`, acceptedParams);
}

export function mediaSentenceCounts(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}/sentences/count`, acceptedParams);
}

export function mediaStories(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'sort', 'limit']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}/stories`, acceptedParams);
}

export function mediaInlinks(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'sort', 'limit']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}/inlinks`, acceptedParams);
}

export function mediaOutlinks(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'sort', 'limit']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}/outlinks`, acceptedParams);
}

export function mediaWords(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}/words`, acceptedParams);
}

export function topicFocalSetsList(topicId, snapshotId) {
  return createApiPromise(`/api/topics/${topicId}/focal-sets/list`, { snapshotId });
}

export function listFocalSetDefinitions(topicId) {
  return createApiPromise(`api/topics/${topicId}/focal-set-definitions/list`);
}

export function updateOrCreateFocusDefinition(topicId, params) {
  const acceptedParams = acceptParams(params, [
    'foci_id',
    'focalSetName', 'focalSetDescription', 'focalTechnique',
    'focusName', 'focusDescription', 'focalSetDefinitionId', 'keywords',
  ]);
  return createPostingApiPromise(`/api/topics/${topicId}/focus-definitions/update-or-create`, acceptedParams);
}

export function deleteFocalSetDefinition(topicId, focalSetDefinitionId) {
  return createApiPromise(`/api/topics/${topicId}/focal-set-definitions/${focalSetDefinitionId}/delete`, null, 'delete');
}

export function deleteFocusDefinition(topicId, focusDefinitionId) {
  return createApiPromise(`/api/topics/${topicId}/focus-definitions/${focusDefinitionId}/delete`, null, 'delete');
}

export function topicGenerateSnapshot(topicId, params) {
  const acceptedParams = acceptParams(params, ['note']);
  return createPostingApiPromise(`/api/topics/${topicId}/snapshots/generate`, acceptedParams);
}

export function topicUpdatePermission(topicId, email, permission) {
  return createPostingApiPromise(`/api/topics/${topicId}/permissions/update`, { email, permission }, 'put');
}

export function topicListPermissions(topicId) {
  return createApiPromise(`/api/topics/${topicId}/permissions/list`);
}

export function topicSetFavorite(topicId, favorite) {
  return createPostingApiPromise(`/api/topics/${topicId}/favorite`, { favorite: (favorite) ? 1 : 0 }, 'put');
}

export function favoriteTopics() {
  return createApiPromise('/api/topics/favorite');
}

export function topicStoryCounts(topicId, params) {
  // important to include snapshot id here, so the server can use it
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/stories/counts`, acceptedParams);
}

export function topicEnglishStoryCounts(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/stories/english-counts`, acceptedParams);
}

export function topicUndateableStoryCounts(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/stories/undateable-counts`, acceptedParams);
}

export function topicFocalSetSentenceCounts(topicId, focalSetId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'focusId', 'timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/sentences/focal-set/${focalSetId}/count`, acceptedParams);
}

export function word(topicId, wordstem) {
  return createApiPromise(`/api/topics/${topicId}/words/${wordstem}`);
}

export function wordSentenceCounts(topicId, wordstem, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/words/${wordstem}*/sentences/count`, acceptedParams);
}

export function wordStories(topicId, wordstem, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'sort', 'limit']);
  return createApiPromise(`/api/topics/${topicId}/words/${wordstem}*/stories`, acceptedParams);
}

export function wordWords(topicId, wordstem, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/words/${wordstem}*/words`, acceptedParams);
}

export function wordSampleSentences(topicId, wordstem, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/words/${wordstem}*/sample-usage`, acceptedParams);
}

/*
export function wordMedia(topicId, word, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/words/${word}/media`, acceptedParams);
}
*/

export function createTopic(params) {
  const acceptedParams = acceptParams(params, ['name', 'description', 'solr_seed_query', 'is_public', 'max_iterations', 'ch_monitor_id', 'start_date', 'end_date', 'spidered', 'sources[]', 'collections[]']);
  return createPostingApiPromise('/api/topics/create', acceptedParams, 'put');
}

export function fetchStoryCountByQuery(params) {
  const acceptedParams = acceptParams(params, ['q', 'start_date', 'end_date', 'sources[]', 'collections[]']);
  return createPostingApiPromise('/api/topics/create/preview/story/count', acceptedParams);
}

export function fetchAttentionByQuery(params) {
  const acceptedParams = acceptParams(params, ['q', 'start_date', 'end_date', 'sources[]', 'collections[]']);
  return createPostingApiPromise('/api/topics/create/preview/sentences/count', acceptedParams);
}

export function fetchStorySampleByQuery(params) {
  const acceptedParams = acceptParams(params, ['q', 'start_date', 'end_date', 'sources[]', 'collections[]']);
  return createPostingApiPromise('/api/topics/create/preview/stories/sample', acceptedParams);
}

export function fetchWordsByQuery(params) {
  const acceptedParams = acceptParams(params, ['q', 'start_date', 'end_date', 'sources[]', 'collections[]']);
  return createPostingApiPromise('/api/topics/create/preview/words/count', acceptedParams);
}

export function updateTopic(topicId, params) {
  const acceptedParams = acceptParams(params, ['name', 'description', 'solr_seed_query', 'is_public', 'max_iterations', 'ch_monitor_id', 'start_date', 'end_date', 'spidered', 'sources[]', 'collections[]']);
  return createPostingApiPromise(`/api/topics/${topicId}/update`, acceptedParams, 'put');
}

export function topicMapFiles(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/map-files`, acceptedParams);
}

export function fetchCustomMap(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'color_field', 'num_media', 'include_weights', 'num_links_per_medium']);
  return createApiPromise(`/api/topics/${topicId}/map-files/fetchCustomMap`, acceptedParams);
}

export function fetchTopicSearchResults(searchStr) {
  return createApiPromise('/api/topics/search', { searchStr });
}

export function topicNytTaggedStoryCoverage(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/nyt-tags/coverage`, acceptedParams);
}

export function topicNytTaggedStoryCounts(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/nyt-tags/counts`, acceptedParams);
}

export function topicGeocodedStoryCoverage(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/geo-tags/coverage`, acceptedParams);
}

export function topicGeocodedStoryCounts(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/geo-tags/counts`, acceptedParams);
}

export function topicSpider(topicId) {
  return createPostingApiPromise(`/api/topics/${topicId}/spider`);
}

export function userQueuedAndRunningTopics() {
  return createApiPromise('/api/topics/queued-and-running');
}

export function topicStoryEntities(topicId, storyId) {
  return createApiPromise(`/api/topics/${topicId}/stories/${storyId}/entities`);
}

export function topicPreviewRetweetPartisanshipStoryCounts(topicId) {
  return createApiPromise(`/api/topics/${topicId}/focal-sets/retweet-partisanship/preview/story-counts`);
}

export function topicPreviewRetweetPartisanshipCoverage(topicId) {
  return createApiPromise(`/api/topics/${topicId}/focal-sets/retweet-partisanship/preview/coverage`);
}

export function createRetweetFocalSet(topicId, params) {
  const acceptedParams = acceptParams(params, ['focalSetName', 'focalSetDescription']);
  return createPostingApiPromise(`/api/topics/${topicId}/focal-sets/retweet-partisanship/create`, acceptedParams);

export function topicWord2Vec(topicId) {
  return createApiPromise(`/api/topics/${topicId}/word2vec`);
}
<commit_msg>fix syntax error in merge<commit_after>import { createApiPromise, createPostingApiPromise, acceptParams } from '../apiUtil';

export function topicsList(linkId) {
  return createApiPromise('/api/topics/listFilterCascade', linkId ? { linkId } : undefined);
}

export function topicsPublicList() {
  return createApiPromise('/api/topics/list');
}

export function topicSummary(topicId) {
  return createApiPromise(`/api/topics/${topicId}/summary`);
}

export function topicTopStories(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'sort', 'limit', 'q', 'linkId']);
  return createApiPromise(`/api/topics/${topicId}/stories`, acceptedParams);
}

export function topicTopMedia(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'sort', 'limit', 'linkId']);
  return createApiPromise(`/api/topics/${topicId}/media`, acceptedParams);
}

export function topicTopWords(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'withTotals']);
  return createApiPromise(`/api/topics/${topicId}/words`, acceptedParams);
}

export function topicSnapshotsList(topicId) {
  return createApiPromise(`/api/topics/${topicId}/snapshots/list`);
}

export function topicTimespansList(topicId, snapshotId, params) {
  const acceptedParams = acceptParams(params, ['focusId']);
  return createApiPromise(`/api/topics/${topicId}/snapshots/${snapshotId}/timespans/list`, acceptedParams);
}

export function topicSentenceCounts(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/sentences/count`, acceptedParams);
}

export function story(topicId, storiesId) {
  return createApiPromise(`/api/topics/${topicId}/stories/${storiesId}`);
}

export function storyWords(topicId, storiesId) {
  return createApiPromise(`/api/topics/${topicId}/stories/${storiesId}/words`);
}

export function storyInlinks(topicId, storiesId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/stories/${storiesId}/inlinks`, acceptedParams);
}

export function storyOutlinks(topicId, storiesId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/stories/${storiesId}/outlinks`, acceptedParams);
}

export function media(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}`, acceptedParams);
}

export function mediaSentenceCounts(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}/sentences/count`, acceptedParams);
}

export function mediaStories(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'sort', 'limit']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}/stories`, acceptedParams);
}

export function mediaInlinks(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'sort', 'limit']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}/inlinks`, acceptedParams);
}

export function mediaOutlinks(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'sort', 'limit']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}/outlinks`, acceptedParams);
}

export function mediaWords(topicId, mediaId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/media/${mediaId}/words`, acceptedParams);
}

export function topicFocalSetsList(topicId, snapshotId) {
  return createApiPromise(`/api/topics/${topicId}/focal-sets/list`, { snapshotId });
}

export function listFocalSetDefinitions(topicId) {
  return createApiPromise(`api/topics/${topicId}/focal-set-definitions/list`);
}

export function updateOrCreateFocusDefinition(topicId, params) {
  const acceptedParams = acceptParams(params, [
    'foci_id',
    'focalSetName', 'focalSetDescription', 'focalTechnique',
    'focusName', 'focusDescription', 'focalSetDefinitionId', 'keywords',
  ]);
  return createPostingApiPromise(`/api/topics/${topicId}/focus-definitions/update-or-create`, acceptedParams);
}

export function deleteFocalSetDefinition(topicId, focalSetDefinitionId) {
  return createApiPromise(`/api/topics/${topicId}/focal-set-definitions/${focalSetDefinitionId}/delete`, null, 'delete');
}

export function deleteFocusDefinition(topicId, focusDefinitionId) {
  return createApiPromise(`/api/topics/${topicId}/focus-definitions/${focusDefinitionId}/delete`, null, 'delete');
}

export function topicGenerateSnapshot(topicId, params) {
  const acceptedParams = acceptParams(params, ['note']);
  return createPostingApiPromise(`/api/topics/${topicId}/snapshots/generate`, acceptedParams);
}

export function topicUpdatePermission(topicId, email, permission) {
  return createPostingApiPromise(`/api/topics/${topicId}/permissions/update`, { email, permission }, 'put');
}

export function topicListPermissions(topicId) {
  return createApiPromise(`/api/topics/${topicId}/permissions/list`);
}

export function topicSetFavorite(topicId, favorite) {
  return createPostingApiPromise(`/api/topics/${topicId}/favorite`, { favorite: (favorite) ? 1 : 0 }, 'put');
}

export function favoriteTopics() {
  return createApiPromise('/api/topics/favorite');
}

export function topicStoryCounts(topicId, params) {
  // important to include snapshot id here, so the server can use it
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/stories/counts`, acceptedParams);
}

export function topicEnglishStoryCounts(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/stories/english-counts`, acceptedParams);
}

export function topicUndateableStoryCounts(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/stories/undateable-counts`, acceptedParams);
}

export function topicFocalSetSentenceCounts(topicId, focalSetId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'focusId', 'timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/sentences/focal-set/${focalSetId}/count`, acceptedParams);
}

export function word(topicId, wordstem) {
  return createApiPromise(`/api/topics/${topicId}/words/${wordstem}`);
}

export function wordSentenceCounts(topicId, wordstem, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/words/${wordstem}*/sentences/count`, acceptedParams);
}

export function wordStories(topicId, wordstem, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q', 'sort', 'limit']);
  return createApiPromise(`/api/topics/${topicId}/words/${wordstem}*/stories`, acceptedParams);
}

export function wordWords(topicId, wordstem, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/words/${wordstem}*/words`, acceptedParams);
}

export function wordSampleSentences(topicId, wordstem, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/words/${wordstem}*/sample-usage`, acceptedParams);
}

/*
export function wordMedia(topicId, word, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/words/${word}/media`, acceptedParams);
}
*/

export function createTopic(params) {
  const acceptedParams = acceptParams(params, ['name', 'description', 'solr_seed_query', 'is_public', 'max_iterations', 'ch_monitor_id', 'start_date', 'end_date', 'spidered', 'sources[]', 'collections[]']);
  return createPostingApiPromise('/api/topics/create', acceptedParams, 'put');
}

export function fetchStoryCountByQuery(params) {
  const acceptedParams = acceptParams(params, ['q', 'start_date', 'end_date', 'sources[]', 'collections[]']);
  return createPostingApiPromise('/api/topics/create/preview/story/count', acceptedParams);
}

export function fetchAttentionByQuery(params) {
  const acceptedParams = acceptParams(params, ['q', 'start_date', 'end_date', 'sources[]', 'collections[]']);
  return createPostingApiPromise('/api/topics/create/preview/sentences/count', acceptedParams);
}

export function fetchStorySampleByQuery(params) {
  const acceptedParams = acceptParams(params, ['q', 'start_date', 'end_date', 'sources[]', 'collections[]']);
  return createPostingApiPromise('/api/topics/create/preview/stories/sample', acceptedParams);
}

export function fetchWordsByQuery(params) {
  const acceptedParams = acceptParams(params, ['q', 'start_date', 'end_date', 'sources[]', 'collections[]']);
  return createPostingApiPromise('/api/topics/create/preview/words/count', acceptedParams);
}

export function updateTopic(topicId, params) {
  const acceptedParams = acceptParams(params, ['name', 'description', 'solr_seed_query', 'is_public', 'max_iterations', 'ch_monitor_id', 'start_date', 'end_date', 'spidered', 'sources[]', 'collections[]']);
  return createPostingApiPromise(`/api/topics/${topicId}/update`, acceptedParams, 'put');
}

export function topicMapFiles(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/map-files`, acceptedParams);
}

export function fetchCustomMap(topicId, params) {
  const acceptedParams = acceptParams(params, ['snapshotId', 'timespanId', 'focusId', 'color_field', 'num_media', 'include_weights', 'num_links_per_medium']);
  return createApiPromise(`/api/topics/${topicId}/map-files/fetchCustomMap`, acceptedParams);
}

export function fetchTopicSearchResults(searchStr) {
  return createApiPromise('/api/topics/search', { searchStr });
}

export function topicNytTaggedStoryCoverage(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/nyt-tags/coverage`, acceptedParams);
}

export function topicNytTaggedStoryCounts(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/nyt-tags/counts`, acceptedParams);
}

export function topicGeocodedStoryCoverage(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/geo-tags/coverage`, acceptedParams);
}

export function topicGeocodedStoryCounts(topicId, params) {
  const acceptedParams = acceptParams(params, ['timespanId', 'q']);
  return createApiPromise(`/api/topics/${topicId}/geo-tags/counts`, acceptedParams);
}

export function topicSpider(topicId) {
  return createPostingApiPromise(`/api/topics/${topicId}/spider`);
}

export function userQueuedAndRunningTopics() {
  return createApiPromise('/api/topics/queued-and-running');
}

export function topicStoryEntities(topicId, storyId) {
  return createApiPromise(`/api/topics/${topicId}/stories/${storyId}/entities`);
}

export function topicPreviewRetweetPartisanshipStoryCounts(topicId) {
  return createApiPromise(`/api/topics/${topicId}/focal-sets/retweet-partisanship/preview/story-counts`);
}

export function topicPreviewRetweetPartisanshipCoverage(topicId) {
  return createApiPromise(`/api/topics/${topicId}/focal-sets/retweet-partisanship/preview/coverage`);
}

export function createRetweetFocalSet(topicId, params) {
  const acceptedParams = acceptParams(params, ['focalSetName', 'focalSetDescription']);
  return createPostingApiPromise(`/api/topics/${topicId}/focal-sets/retweet-partisanship/create`, acceptedParams);
}

export function topicWord2Vec(topicId) {
  return createApiPromise(`/api/topics/${topicId}/word2vec`);
}
<|endoftext|>


<commit_before>var PAGE = (function() {

	var options = { debugMode : true }
		, Page  = function() {}         // base constructor
		, dog   = Page.prototype = {}   // base prototype
		, puppy = new Page()            // base instance

	function log(thing) {
		if (typeof console === "object" && options.debugMode) {
			console.log(thing)
		}
	}

	var add = dog.add = function(path, obj) {
		if (typeof path === "undefined") return
		var arr = path.split(".")
		if (arr.length < 2) return
		var group = arr[0]
			, item = arr[1]
		if (!puppy[group]) puppy[group] = {}
		return puppy[group][item] = obj
	}

	var waitLoad = dog.waitLoad = function(group, name, callback) {
			var limit = 1000
				, count = 0
				, interval

			if (puppy[group] && puppy[group][name]) {
				return callback(puppy[group][name])
			}

			interval = setInterval(function() {
				if (count > limit) {
					console.error("could not find " + group + ":" + name)
					clearInterval(interval)
					return
				}
				if (count > limit || (puppy[group] && puppy[group][name])) {
					if (typeof callback === "function") {
						callback(puppy[group][name])
					}
					clearInterval(interval)
				}
				count++
			}, 10)
		}

	, wait = dog.wait = function(path, callback) {
		if (typeof path === "undefined") return
		var arr = path.split(".")
		if (arr.length < 2) return
		var group = arr[0]
			, item = arr[1]
		return waitLoad(group, item, callback)
	}

	, addModule = dog.addModule = function(name, obj) {
		return add("Modules." + name, obj)
	}

	, addConstructor = dog.addConstructor = function(name, obj) {
		return add("Constructors." + name, obj)
	}

	, addFunction = dog.addFunction = function(name, obj) {
		return add("Functions." + name, obj)
	}

	, addProperty = dog.addProperty = function(name, obj) {
		return add("Properties." + name, obj)
	}

	, extend = dog.extend = function(callback) {
		typeof callback === "function" && callback(puppy, dog, log)
	}

	return puppy

}())
<commit_msg>Adding prototype access to new extend function<commit_after>var PAGE = (function() {

	var options = { debugMode : true }
		, Page  = function(){}          // base constructor
		, dog   = Page.prototype = {}   // base prototype
		, puppy = new Page()            // base instance

	function log(thing) {
		if (typeof console === "object" && options.debugMode) {
			console.log(thing)
		}
	}

	var add = dog.add = function(path, obj) {
		if (typeof path === "undefined") return
		var arr = path.split(".")
		if (arr.length < 2) return
		var group = arr[0]
			, item = arr[1]
		if (!puppy[group]) puppy[group] = {}
		return puppy[group][item] = obj
	}

	var waitProto = dog.waitProto = function(name, callback) {
		var limit = 1000
			, count = 0
			, interval

		if (dog[name]) {
			return callback(dog[name])
		}

		interval = setInterval(function() {
			if (count > limit) {
				console.error("could not find prototype " + name)
				clearInterval(interval)
				return
			}
			if (count > limit || (dog[name])) {
				if (typeof callback === "function") {
					callback(dog[name])
				}
				clearInterval(interval)
			}
			count++
		}, 10)
	}

	var waitLoad = dog.waitLoad = function(group, name, callback) {
			var limit = 1000
				, count = 0
				, interval

			if (puppy[group] && puppy[group][name]) {
				return callback(puppy[group][name])
			}

			interval = setInterval(function() {
				if (count > limit) {
					console.error("could not find " + group + ":" + name)
					clearInterval(interval)
					return
				}
				if (count > limit || (puppy[group] && puppy[group][name])) {
					if (typeof callback === "function") {
						callback(puppy[group][name])
					}
					clearInterval(interval)
				}
				count++
			}, 10)
		}

	, wait = dog.wait = function(path, callback) {
		if (typeof path === "undefined") return
		var arr = path.split(".")
		if (arr.length < 1) return
		if (arr.length < 2) return waitProto(arr[0], callback)
		return waitLoad(arr[0], arr[1], callback)
	}

	, addModule = dog.addModule = function(name, obj) {
		return add("Modules." + name, obj)
	}

	, addConstructor = dog.addConstructor = function(name, obj) {
		return add("Constructors." + name, obj)
	}

	, addFunction = dog.addFunction = function(name, obj) {
		return add("Functions." + name, obj)
	}

	, addProperty = dog.addProperty = function(name, obj) {
		return add("Properties." + name, obj)
	}

	, extend = dog.extend = function(callback) {
		typeof callback === "function" && callback(puppy, dog, log)
	}

	return puppy

}())

<|endoftext|>


<commit_before>const log = require('electron-log/main');
const { Util } = require('./util');

const megabyte = 1048576;

log.transports.file.format = "[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] {text}";
log.transports.console.format = "{text}";
log.transports.file.maxSize = 4 * megabyte;

if (Util.isDevMode()) {
    log.transports.file.level = 'debug';
    log.transports.console.level = 'debug';
} else {
    log.transports.file.level = 'warn';
    log.transports.console.level = false;
}

log.filename = function() {
    return log.transports.file.findLogPath();
}

module.exports = log;
<commit_msg>Added log notes<commit_after>const log = require('electron-log/main');
const { Util } = require('./util');

const megabyte = 1048576;

log.transports.file.format = "[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] {text}";
log.transports.console.format = "{text}";
log.transports.file.maxSize = 4 * megabyte;

if (Util.isDevMode()) {
    log.transports.file.level = 'debug';
    log.transports.console.level = 'debug';
} else {
    log.transports.file.level = 'warn';
    log.transports.console.level = false;
}

log.filename = function() {
    return log.transports.file.findLogPath();
}

// Use log.info("message")
//     log.warn("message")
//     log.error("message")
//     log.debug("message")

module.exports = log;
<|endoftext|>


<commit_before>var config = require('../config'),
  log = require('../log'),
  ioc = require('../ioc'),
  winjsHelper = require('../helper/winjs');

modules.export = function(options, callback) {
  // Load Item domain
  var domain = config.get("domain");
  if (domain) {
    for(var modelKey in domain){
      var view = config.get("domain:" + modelKey + ":view");
      var viewClassDef;
      if (view) {
        viewClassDef = require(view);
        ioc.registerItemView(modelKey, viewClassDef);
      }

      var template = config.get("domain:" + modelKey + ":template");
      if (template) {
        winjsHelper.pageDefine(modelKey, template, viewClassDef);
      }

      var viewModel = config.get("domain:" + modelKey + ":view-model");
      if (viewModel) {
        var viewModelClassDef = require(viewModel);
        ioc.registerItemViewModel(modelKey, viewModelClassDef);
      }

      var model = config.get("domain:" + modelKey + ":model");
      if (model) {
        var modelClassDef = require(model);
        ioc.registerItemModel(modelKey, model);
      }
    };
  }

  // Load Pages
  var pages = config.get("pages");
  if (pages) {
    for(var pageKey in pages) {
      var view = config.get("page:" + pageKey + ":view");
      var viewClassDef;
      if (view) {
        viewClassDef = require(view);
        ioc.registerView(pageKey, viewClassDef);
      }

      var template = config.get("page:" + pageKey + ":template");
      if (template) {
        winjsHelper.pageDefine(pageKey, template, viewClassDef);
      }

      var viewModel = config.get("page:" + pageKey + ":view-model");
      if (viewModel) {
        var viewModelClassDef = require(viewModel);
        ioc.registerViewModel(pageKey, viewModelClassDef);
      }
    };
  }

  return callback();
}
<commit_msg>Update client-loader.js<commit_after>var config = require('../config'),
  log = require('../log'),
  ioc = require('../ioc'),
  winjsHelper = require('../helper/winjs');

module.exports = function(options, callback) {
  // Load Item domain
  var domain = config.get("domain");
  if (domain) {
    for(var modelKey in domain){
      var view = config.get("domain:" + modelKey + ":view");
      var viewClassDef;
      if (view) {
        viewClassDef = require(view);
        ioc.registerItemView(modelKey, viewClassDef);
      }

      var template = config.get("domain:" + modelKey + ":template");
      if (template) {
        winjsHelper.pageDefine(modelKey, template, viewClassDef);
      }

      var viewModel = config.get("domain:" + modelKey + ":view-model");
      if (viewModel) {
        var viewModelClassDef = require(viewModel);
        ioc.registerItemViewModel(modelKey, viewModelClassDef);
      }

      var model = config.get("domain:" + modelKey + ":model");
      if (model) {
        var modelClassDef = require(model);
        ioc.registerItemModel(modelKey, model);
      }
    };
  }

  // Load Pages
  var pages = config.get("pages");
  if (pages) {
    for(var pageKey in pages) {
      var view = config.get("page:" + pageKey + ":view");
      var viewClassDef;
      if (view) {
        viewClassDef = require(view);
        ioc.registerView(pageKey, viewClassDef);
      }

      var template = config.get("page:" + pageKey + ":template");
      if (template) {
        winjsHelper.pageDefine(pageKey, template, viewClassDef);
      }

      var viewModel = config.get("page:" + pageKey + ":view-model");
      if (viewModel) {
        var viewModelClassDef = require(viewModel);
        ioc.registerViewModel(pageKey, viewModelClassDef);
      }
    };
  }

  return callback();
}
<|endoftext|>


<commit_before>// @flow
import * as React from 'react'
import {Text, View, ScrollView, StyleSheet} from 'react-native'
import {sendEmail} from '../../../components/send-email'
import {callPhone} from '../../../components/call-phone'
import {Card} from '../../../components/card'
import moment from 'moment'
import {openUrl} from '@frogpond/open-url'
import * as c from '@frogpond/colors'
import type {JobType} from './types'
import {ShareButton} from '../../../components/nav-buttons'
import {shareJob} from './lib'

const styles = StyleSheet.create({
	name: {
		textAlign: 'center',
		marginTop: 20,
		marginBottom: 15,
		paddingHorizontal: 5,
		color: c.black,
		fontSize: 32,
		fontWeight: '300',
	},
	subtitle: {
		textAlign: 'center',
		marginBottom: 15,
		paddingHorizontal: 5,
		color: c.black,
		fontSize: 16,
		fontWeight: '300',
	},
	card: {
		marginBottom: 20,
	},
	cardBody: {
		color: c.black,
		paddingTop: 13,
		paddingBottom: 13,
		paddingLeft: 16,
		paddingRight: 16,
		fontSize: 16,
	},
	lastUpdated: {
		paddingBottom: 20,
	},
	footer: {
		fontSize: 10,
		color: c.iosDisabledText,
		textAlign: 'center',
	},
})

function Title({job}: {job: JobType}) {
	return job.title || job.type ? (
		<View>
			<Text style={styles.name}>{job.title}</Text>
			<Text style={styles.subtitle}>{job.type}</Text>
		</View>
	) : null
}

function Contact({job}: {job: JobType}) {
	const contactName = job.contactName
	const contactEmail = job.contactEmail
	const contactNumber = job.contactPhone
	const contactOffice = job.office

	return contactName || contactEmail || contactNumber || contactOffice ? (
		<Card header="Contact" style={styles.card}>
			<Text style={styles.cardBody}>{contactName}</Text>

			{contactEmail ? (
				<Text
					onPress={() =>
						job.contactEmail
							? sendEmail({to: [contactEmail], subject: job.title, body: ''})
							: null
					}
					style={styles.cardBody}
				>
					{contactEmail}
				</Text>
			) : null}

			{contactNumber ? (
				<Text
					onPress={() => (job.contactPhone ? callPhone(contactNumber) : null)}
					style={styles.cardBody}
				>
					{contactNumber}
				</Text>
			) : null}

			{contactOffice ? (
				<Text style={styles.cardBody}>{contactOffice}</Text>
			) : null}
		</Card>
	) : null
}

function Hours({job}: {job: JobType}) {
	const ending = job.hoursPerWeek === 'Full-time' ? '' : ' hrs/week'
	return job.timeOfHours && job.hoursPerWeek ? (
		<Card header="Hours" style={styles.card}>
			<Text style={styles.cardBody}>
				{job.timeOfHours}
				{'\n'}
				{job.hoursPerWeek + ending}
			</Text>
		</Card>
	) : null
}

function GeneralInfo({job}: {job: JobType}) {
	return job.year || job.openPositions ? (
		<Card header="General" style={styles.card}>
			<Text style={styles.cardBody}>
				{job.year ? `${job.year}\n\n` : null}
				{job.openPositions ? `Positions: ${job.openPositions}\n\n` : null}
				{job.goodForIncomingStudents
					? 'Appropriate for First Year Students'
					: 'Not Appropriate for First Year Students'}
			</Text>
		</Card>
	) : null
}

function Description({job}: {job: JobType}) {
	return job.description ? (
		<Card header="Description" style={styles.card}>
			<Text style={styles.cardBody}>{job.description}</Text>
		</Card>
	) : null
}

function Skills({job}: {job: JobType}) {
	return job.skills ? (
		<Card header="Skills" style={styles.card}>
			<Text style={styles.cardBody}>{job.skills}</Text>
		</Card>
	) : null
}

function Comments({job}: {job: JobType}) {
	return job.comments ? (
		<Card header="Comments" style={styles.card}>
			<Text style={styles.cardBody}>{job.comments}</Text>
		</Card>
	) : null
}

function HowToApply({job}: {job: JobType}) {
	return job.howToApply ? (
		<Card header="How To Apply" style={styles.card}>
			<Text style={styles.cardBody}>{job.howToApply}</Text>
		</Card>
	) : null
}

function Timeline({job}: {job: JobType}) {
	return job.timeline ? (
		<Card header="Timeline" style={styles.card}>
			<Text style={styles.cardBody}>{job.timeline}</Text>
		</Card>
	) : null
}

function Links({job}: {job: JobType}) {
	const {links} = job
	return links.length ? (
		<Card header="LINKS" style={styles.card}>
			{links.map(url => (
				<Text key={url} onPress={() => openUrl(url)} style={styles.cardBody}>
					{url}
				</Text>
			))}
		</Card>
	) : null
}

function LastUpdated({when}: {when: string}) {
	return when ? (
		<Text selectable={true} style={[styles.footer, styles.lastUpdated]}>
			Last updated: {moment(when, 'YYYY/MM/DD').calendar()}
			{'\n'}
			Powered by St. Olaf Student Employment job postings
		</Text>
	) : null
}

type Props = {
	navigation: {state: {params: {job: JobType}}},
}

export class JobDetailView extends React.PureComponent<Props> {
	static navigationOptions = ({navigation}: any) => {
		const {job} = navigation.state.params
		return {
			title: job.title,
			headerRight: <ShareButton onPress={() => shareJob(job)} />,
		}
	}

	render() {
		const job = this.props.navigation.state.params.job

		return (
			<ScrollView>
				<Title job={job} />
				<Contact job={job} />
				<GeneralInfo job={job} />
				<Hours job={job} />
				<Description job={job} />
				<Skills job={job} />
				<Comments job={job} />
				<Timeline job={job} />
				<HowToApply job={job} />
				<Links job={job} />
				<LastUpdated when={job.lastModified} />
			</ScrollView>
		)
	}
}
<commit_msg>rename sections on android job detail<commit_after>// @flow
import * as React from 'react'
import {Text, View, ScrollView, StyleSheet} from 'react-native'
import {sendEmail} from '../../../components/send-email'
import {callPhone} from '../../../components/call-phone'
import {Card} from '../../../components/card'
import moment from 'moment'
import {openUrl} from '@frogpond/open-url'
import * as c from '@frogpond/colors'
import type {JobType} from './types'
import {ShareButton} from '../../../components/nav-buttons'
import {shareJob} from './lib'

const styles = StyleSheet.create({
	name: {
		textAlign: 'center',
		marginTop: 20,
		marginBottom: 15,
		paddingHorizontal: 5,
		color: c.black,
		fontSize: 32,
		fontWeight: '300',
	},
	subtitle: {
		textAlign: 'center',
		marginBottom: 15,
		paddingHorizontal: 5,
		color: c.black,
		fontSize: 16,
		fontWeight: '300',
	},
	card: {
		marginBottom: 20,
	},
	cardBody: {
		color: c.black,
		paddingTop: 13,
		paddingBottom: 13,
		paddingLeft: 16,
		paddingRight: 16,
		fontSize: 16,
	},
	lastUpdated: {
		paddingBottom: 20,
	},
	footer: {
		fontSize: 10,
		color: c.iosDisabledText,
		textAlign: 'center',
	},
})

function Title({job}: {job: JobType}) {
	return job.title || job.type ? (
		<View>
			<Text style={styles.name}>{job.title}</Text>
			<Text style={styles.subtitle}>{job.type}</Text>
		</View>
	) : null
}

function ContactInformation({job}: {job: JobType}) {
	const contactName = job.contactName
	const contactEmail = job.contactEmail
	const contactNumber = job.contactPhone
	const contactOffice = job.office

	return contactName || contactEmail || contactNumber || contactOffice ? (
		<Card header="Contact Information" style={styles.card}>
			<Text style={styles.cardBody}>{contactName}</Text>

			{contactEmail ? (
				<Text
					onPress={() =>
						job.contactEmail
							? sendEmail({to: [contactEmail], subject: job.title, body: ''})
							: null
					}
					style={styles.cardBody}
				>
					{contactEmail}
				</Text>
			) : null}

			{contactNumber ? (
				<Text
					onPress={() => (job.contactPhone ? callPhone(contactNumber) : null)}
					style={styles.cardBody}
				>
					{contactNumber}
				</Text>
			) : null}

			{contactOffice ? (
				<Text style={styles.cardBody}>{contactOffice}</Text>
			) : null}
		</Card>
	) : null
}

function Hours({job}: {job: JobType}) {
	const ending = job.hoursPerWeek === 'Full-time' ? '' : ' hrs/week'
	return job.timeOfHours && job.hoursPerWeek ? (
		<Card header="Hours" style={styles.card}>
			<Text style={styles.cardBody}>
				{job.timeOfHours}
				{'\n'}
				{job.hoursPerWeek + ending}
			</Text>
		</Card>
	) : null
}

function JobInformation({job}: {job: JobType}) {
	return job.year || job.openPositions ? (
		<Card header="Job Information" style={styles.card}>
			<Text style={styles.cardBody}>
				{job.year ? `${job.year}\n\n` : null}
				{job.openPositions ? `Positions: ${job.openPositions}\n\n` : null}
				{job.goodForIncomingStudents
					? 'Appropriate for First Year Students'
					: 'Not Appropriate for First Year Students'}
			</Text>
		</Card>
	) : null
}

function Description({job}: {job: JobType}) {
	return job.description ? (
		<Card header="Description" style={styles.card}>
			<Text style={styles.cardBody}>{job.description}</Text>
		</Card>
	) : null
}

function Skills({job}: {job: JobType}) {
	return job.skills ? (
		<Card header="Skills" style={styles.card}>
			<Text style={styles.cardBody}>{job.skills}</Text>
		</Card>
	) : null
}

function Comments({job}: {job: JobType}) {
	return job.comments ? (
		<Card header="Comments" style={styles.card}>
			<Text style={styles.cardBody}>{job.comments}</Text>
		</Card>
	) : null
}

function HowToApply({job}: {job: JobType}) {
	return job.howToApply ? (
		<Card header="How To Apply" style={styles.card}>
			<Text style={styles.cardBody}>{job.howToApply}</Text>
		</Card>
	) : null
}

function Timeline({job}: {job: JobType}) {
	return job.timeline ? (
		<Card header="Timeline" style={styles.card}>
			<Text style={styles.cardBody}>{job.timeline}</Text>
		</Card>
	) : null
}

function Links({job}: {job: JobType}) {
	const {links} = job
	return links.length ? (
		<Card header="LINKS" style={styles.card}>
			{links.map(url => (
				<Text key={url} onPress={() => openUrl(url)} style={styles.cardBody}>
					{url}
				</Text>
			))}
		</Card>
	) : null
}

function LastUpdated({when}: {when: string}) {
	return when ? (
		<Text selectable={true} style={[styles.footer, styles.lastUpdated]}>
			Last updated: {moment(when, 'YYYY/MM/DD').calendar()}
			{'\n'}
			Powered by St. Olaf Student Employment job postings
		</Text>
	) : null
}

type Props = {
	navigation: {state: {params: {job: JobType}}},
}

export class JobDetailView extends React.PureComponent<Props> {
	static navigationOptions = ({navigation}: any) => {
		const {job} = navigation.state.params
		return {
			title: job.title,
			headerRight: <ShareButton onPress={() => shareJob(job)} />,
		}
	}

	render() {
		const job = this.props.navigation.state.params.job

		return (
			<ScrollView>
				<Title job={job} />
				<ContactInformation job={job} />
				<JobInformation job={job} />
				<Hours job={job} />
				<Description job={job} />
				<Skills job={job} />
				<Comments job={job} />
				<Timeline job={job} />
				<HowToApply job={job} />
				<Links job={job} />
				<LastUpdated when={job.lastModified} />
			</ScrollView>
		)
	}
}
<|endoftext|>


<commit_before>angular.module('mwFileUpload')

  .directive('mwFileUploadButton', function ($q, $timeout, mwMimetype) {
    return {
      restrict: 'A',
      scope: {
        uploaderOptions: '=?',
        maxFileSizeByte: '=?',
        dropZoneElement: '=?',
        onBeforeUploadCallback: '=?',
        onProgressCallback: '=?',
        onSuccessCallback: '=?',
        onErrorCallback: '=?',
        onAbortCallback: '=?',
        abortFlag: '=?',
        accepts: '@?',
      },
      transclude: true,
      templateUrl: 'uikit/templates/mwFileUpload/mwFileUploadButton.html',
      link: function (scope, elm) {

        var hiddenfileEl = elm.find('input[type=file]'),
          userHasCanceled = false,
          uploadXhr;

        scope.mimeTypeGroup = mwMimetype.getMimeTypeGroup(scope.accepts);

        scope.file = null;

        if (!scope.mimeTypeGroup) {
          scope.inputValidator = '*/*';
        } else {
          scope.inputValidator = scope.accepts;
        }

        var error = function (xhr, type, result) {
          if (typeof scope.onErrorCallback === 'function') {
            $timeout(scope.onErrorCallback.bind(this, {type: type, xhr: xhr, result: result}));
          }
        };

        var getFileFromResponse = function (response) {
          if (response && response.results && _.isArray(response.results) && response.results.length > 0) {
            response = response.results[0];
          }
          return response;
        };

        var success = function (xhr, result) {
          if (typeof scope.onSuccessCallback === 'function') {
            $timeout(scope.onSuccessCallback.bind(this, {
              xhr: xhr,
              file: getFileFromResponse(result),
              response: result
            }));
          }
        };

        var abort = function () {
          if (typeof scope.onAbortCallback === 'function') {
            $timeout(scope.onAbortCallback.bind(this));
          }
        };

        var stateChange = function (data) {
          if (data && typeof scope.onProgressCallback === 'function') {
            var dataLoaded = data.loaded;
            var dataTotal = data.total;
            var progress = parseInt(dataLoaded / dataTotal * 100, 10);
            $timeout(scope.onProgressCallback.bind(this, {
                data: data,
                progress: progress,
                total: dataTotal,
                loaded: dataLoaded
              }
            ));
          }
        };

        var validateFileSize = function (files) {
          var isValid = true;
          if (scope.maxFileSizeByte) {
            // check each file if it is too large to upload.
            angular.forEach(files, function (file) {
              if (file.size > scope.maxFileSizeByte) {
                isValid = false;
              }
            });
          }
          return isValid;
        };

        scope.abort = function () {
          if (uploadXhr) {
            userHasCanceled = true;
            uploadXhr.abort();
          }
        };

        hiddenfileEl.fileupload({
          url: scope.url,
          dataType: 'json',
          formData: scope.formData,
          autoUpload: false
        });

        hiddenfileEl.bind('fileuploadadd', function (e, data) {
          if (!data || !angular.isArray(data.files) || data.files.length === 0) {
            return;
          }
          scope.file = data.files;
          userHasCanceled = false;

          if (typeof scope.onBeforeUploadCallback === 'function') {
            var result = scope.onBeforeUploadCallback(data.files);
            if (result === false) {
              error(this, 'CUSTOM_VALIDATION_FAILED', {
                files: data.files,
                response: null
              });
              scope.file = null;
              return;
            }
          }

          if (!validateFileSize(data.files)) {
            error(this, 'FILE_TOO_BIG', {
              files: data.files,
              response: null
            });
            scope.file = null;
            return;
          }

          uploadXhr = data.submit();
        });

        hiddenfileEl.bind('fileuploadstart', function () {
          scope.abortFlag = false;
        });

        hiddenfileEl.bind('fileuploadprogress', function (e, data) {
          stateChange(data);
        });

        hiddenfileEl.bind('fileuploaddone', function (e, data) {
          success(data, data.result);
        });

        hiddenfileEl.bind('fileuploadfail', function (e, data) {
          if (!userHasCanceled) {
            scope.uploadError = data.statusText;
            error(this, 'SERVER', {
              files: null,
              response: data.responseJSON
            });
          } else {
            abort();
          }
        });

        scope.triggerUploadDialog = function () {
          /*Unbind listener to prevent loop, prevent bubbling of event does not work */
          elm.off('click', scope.triggerUploadDialog);
          /*Make sure to use selector to have correct reference because the blueimpfileuplaoder changes reference*/
          elm.find('input[type=file]').click();
          elm.on('click', scope.triggerUploadDialog);
        };

        /*
          {
            url: ''
            formData: {}
          }
        */
        scope.$watch('uploaderOptions', function (val) {
          if (val) {
            hiddenfileEl.fileupload('option', val);
          }
        }, true);

        scope.$watch('abortFlag', function (abortFlag) {
          if (abortFlag) {
            scope.abort();
          }
        });

        scope.$watch('dropZoneElement', function (val) {
          if (val) {
            hiddenfileEl.fileupload('option', {
              dropZone: val
            });
          }
        });

        elm.on('click', scope.triggerUploadDialog);

        scope.$on('$destroy', function () {
          elm.off('click', scope.triggerUploadDialog);
          /*Make sure to use selector to have correct reference because the blueimpfileuplaoder changes reference*/
          elm.find('input[type=file]').fileupload('destroy');
        });
      }
    };
  });<commit_msg>Catch exception when fileuplaoder has not been initialised yet<commit_after>angular.module('mwFileUpload')

  .directive('mwFileUploadButton', function ($q, $timeout, mwMimetype) {
    return {
      restrict: 'A',
      scope: {
        uploaderOptions: '=?',
        maxFileSizeByte: '=?',
        dropZoneElement: '=?',
        onBeforeUploadCallback: '=?',
        onProgressCallback: '=?',
        onSuccessCallback: '=?',
        onErrorCallback: '=?',
        onAbortCallback: '=?',
        abortFlag: '=?',
        accepts: '@?',
      },
      transclude: true,
      templateUrl: 'uikit/templates/mwFileUpload/mwFileUploadButton.html',
      link: function (scope, elm) {

        var hiddenfileEl = elm.find('input[type=file]'),
          userHasCanceled = false,
          uploadXhr;

        scope.mimeTypeGroup = mwMimetype.getMimeTypeGroup(scope.accepts);

        scope.file = null;

        if (!scope.mimeTypeGroup) {
          scope.inputValidator = '*/*';
        } else {
          scope.inputValidator = scope.accepts;
        }

        var error = function (xhr, type, result) {
          if (typeof scope.onErrorCallback === 'function') {
            $timeout(scope.onErrorCallback.bind(this, {type: type, xhr: xhr, result: result}));
          }
        };

        var getFileFromResponse = function (response) {
          if (response && response.results && _.isArray(response.results) && response.results.length > 0) {
            response = response.results[0];
          }
          return response;
        };

        var success = function (xhr, result) {
          if (typeof scope.onSuccessCallback === 'function') {
            $timeout(scope.onSuccessCallback.bind(this, {
              xhr: xhr,
              file: getFileFromResponse(result),
              response: result
            }));
          }
        };

        var abort = function () {
          if (typeof scope.onAbortCallback === 'function') {
            $timeout(scope.onAbortCallback.bind(this));
          }
        };

        var stateChange = function (data) {
          if (data && typeof scope.onProgressCallback === 'function') {
            var dataLoaded = data.loaded;
            var dataTotal = data.total;
            var progress = parseInt(dataLoaded / dataTotal * 100, 10);
            $timeout(scope.onProgressCallback.bind(this, {
                data: data,
                progress: progress,
                total: dataTotal,
                loaded: dataLoaded
              }
            ));
          }
        };

        var validateFileSize = function (files) {
          var isValid = true;
          if (scope.maxFileSizeByte) {
            // check each file if it is too large to upload.
            angular.forEach(files, function (file) {
              if (file.size > scope.maxFileSizeByte) {
                isValid = false;
              }
            });
          }
          return isValid;
        };

        scope.abort = function () {
          if (uploadXhr) {
            userHasCanceled = true;
            uploadXhr.abort();
          }
        };

        hiddenfileEl.fileupload({
          url: scope.url,
          dataType: 'json',
          formData: scope.formData,
          autoUpload: false
        });

        hiddenfileEl.bind('fileuploadadd', function (e, data) {
          if (!data || !angular.isArray(data.files) || data.files.length === 0) {
            return;
          }
          scope.file = data.files;
          userHasCanceled = false;

          if (typeof scope.onBeforeUploadCallback === 'function') {
            var result = scope.onBeforeUploadCallback(data.files);
            if (result === false) {
              error(this, 'CUSTOM_VALIDATION_FAILED', {
                files: data.files,
                response: null
              });
              scope.file = null;
              return;
            }
          }

          if (!validateFileSize(data.files)) {
            error(this, 'FILE_TOO_BIG', {
              files: data.files,
              response: null
            });
            scope.file = null;
            return;
          }

          uploadXhr = data.submit();
        });

        hiddenfileEl.bind('fileuploadstart', function () {
          scope.abortFlag = false;
        });

        hiddenfileEl.bind('fileuploadprogress', function (e, data) {
          stateChange(data);
        });

        hiddenfileEl.bind('fileuploaddone', function (e, data) {
          success(data, data.result);
        });

        hiddenfileEl.bind('fileuploadfail', function (e, data) {
          if (!userHasCanceled) {
            scope.uploadError = data.statusText;
            error(this, 'SERVER', {
              files: null,
              response: data.responseJSON
            });
          } else {
            abort();
          }
        });

        scope.triggerUploadDialog = function () {
          /*Unbind listener to prevent loop, prevent bubbling of event does not work */
          elm.off('click', scope.triggerUploadDialog);
          /*Make sure to use selector to have correct reference because the blueimpfileuplaoder changes reference*/
          elm.find('input[type=file]').click();
          elm.on('click', scope.triggerUploadDialog);
        };

        /*
          {
            url: ''
            formData: {}
          }
        */
        scope.$watch('uploaderOptions', function (val) {
          if (val) {
            hiddenfileEl.fileupload('option', val);
          }
        }, true);

        scope.$watch('abortFlag', function (abortFlag) {
          if (abortFlag) {
            scope.abort();
          }
        });

        scope.$watch('dropZoneElement', function (val) {
          if (val) {
            hiddenfileEl.fileupload('option', {
              dropZone: val
            });
          }
        });

        elm.on('click', scope.triggerUploadDialog);

        scope.$on('$destroy', function () {
          elm.off('click', scope.triggerUploadDialog);

          /*
           * Make sure to use selector to have correct reference because the blueimpfileuplaoder changes reference
           * Catch exception that fileuplaoder was bot initiliased yet and therefor can not be destroyed
           */
          try {
            elm.find('input[type=file]').fileupload('destroy');
          } catch (e) {

          }
        });
      }
    };
  });<|endoftext|>


<commit_before>import { Object3D } from 'three';
import { parseVector3, parseEuler, parseQuaternion } from '../parsers';
import {
  vector3,
  euler,
  quaternion,
  boolean,
  string,
} from '../validators';

/**
 * This is the base mixin component for most object components in VueGL,
 * corresponding [THREE.Object3D](https://threejs.org/docs/index.html#api/core/Object3D).
 * Object3d components inside a object3d component are added
 * as children via THREE.Object3D.prototype.add() method.
 *
 * VglObject3d components inside default slots are added as children.
 */

export default {
  props: {
    /** The object's local position as a 3D vector. */
    position: vector3,
    /** The object's local rotation as a euler angle. */
    rotation: euler,
    /**
     * The object's local rotation as a quaternion (specified in x, y, z, w order).
     * Do not use in conjunction with the rotation prop, since they both control the same property
     * of the underlying THREE.Object3D object.
     */
    rotationQuaternion: quaternion,
    /** The object's local scale as a 3D vector. */
    scale: vector3,
    /** Whether the object gets rendered into shadow map. */
    castShadow: boolean,
    /** Whether the material receives shadows. */
    receiveShadow: boolean,
    /** Optional name of the object. */
    name: string,
    /** Whether the object is visible. */
    visible: {
      type: boolean,
      default: true,
    },
  },
  computed: {
    inst: () => new Object3D(),
  },
  inject: {
    vglObject3d: { default: {} },
    vglNamespace: 'vglNamespace',
  },
  provide() {
    const vm = this;
    return { vglObject3d: { get inst() { return vm.inst; } } };
  },
  created() { this.vglNamespace.update(); },
  beforeUpdate() { this.vglNamespace.update(); },
  beforeDestroy() {
    const { vglNamespace, inst, name } = this;
    if (inst.parent) inst.parent.remove(inst);
    if (vglNamespace.object3ds[name] === inst) delete vglNamespace.object3ds[name];
    vglNamespace.update();
  },
  watch: {
    inst: {
      handler(inst, oldInst) {
        if (oldInst && oldInst.parent) oldInst.parent.remove(oldInst);
        if (this.vglObject3d.inst) this.vglObject3d.inst.add(inst);
        if (this.position) inst.position.copy(parseVector3(this.position));
        if (this.rotation) inst.rotation.copy(parseEuler(this.rotation));
        if (this.rotationQuaternion) inst.quaternion.copy(parseQuaternion(this.rotationQuaternion));
        if (this.scale) inst.scale.copy(parseVector3(this.scale));
        Object.assign(inst, {
          castShadow: this.castShadow,
          receiveShadow: this.receiveShadow,
          visible: this.visible,
        });
        if (this.name !== undefined) {
          // eslint-disable-next-line no-param-reassign
          inst.name = this.name;
          this.vglNamespace.object3ds[this.name] = inst;
        }
      },
      immediate: true,
    },
    'vglObject3d.inst': function parentInst(inst) { inst.add(this.inst); },
    position(position) { this.inst.position.copy(parseVector3(position)); },
    rotation(rotation) { this.inst.rotation.copy(parseEuler(rotation)); },
    rotationQuaternion(rotationQuaternion) {
      this.inst.quaternion.copy(parseQuaternion(rotationQuaternion));
    },
    scale(scale) { this.inst.scale.copy(parseVector3(scale)); },
    castShadow(castShadow) { this.inst.castShadow = castShadow; },
    receiveShadow(receiveShadow) { this.inst.receiveShadow = receiveShadow; },
    name(name, oldName) {
      const { vglNamespace: { object3ds }, inst } = this;
      if (object3ds[oldName] === inst) delete object3ds[oldName];
      this.inst.name = name;
      object3ds[name] = inst;
    },
    visible(visible) { this.inst.visible = visible; },
  },
  render(h) { return this.$slots.default ? h('div', this.$slots.default) : undefined; },
};
<commit_msg>Revert "Revert "add reactivity on object3ds (namespace)""<commit_after>import { Object3D } from 'three';
import { parseVector3, parseEuler, parseQuaternion } from '../parsers';
import {
  vector3,
  euler,
  quaternion,
  boolean,
  string,
} from '../validators';

/**
 * This is the base mixin component for most object components in VueGL,
 * corresponding [THREE.Object3D](https://threejs.org/docs/index.html#api/core/Object3D).
 * Object3d components inside a object3d component are added
 * as children via THREE.Object3D.prototype.add() method.
 *
 * VglObject3d components inside default slots are added as children.
 */

export default {
  props: {
    /** The object's local position as a 3D vector. */
    position: vector3,
    /** The object's local rotation as a euler angle. */
    rotation: euler,
    /**
     * The object's local rotation as a quaternion (specified in x, y, z, w order).
     * Do not use in conjunction with the rotation prop, since they both control the same property
     * of the underlying THREE.Object3D object.
     */
    rotationQuaternion: quaternion,
    /** The object's local scale as a 3D vector. */
    scale: vector3,
    /** Whether the object gets rendered into shadow map. */
    castShadow: boolean,
    /** Whether the material receives shadows. */
    receiveShadow: boolean,
    /** Optional name of the object. */
    name: string,
    /** Whether the object is visible. */
    visible: {
      type: boolean,
      default: true,
    },
  },
  computed: {
    inst: () => new Object3D(),
  },
  inject: {
    vglObject3d: { default: {} },
    vglNamespace: 'vglNamespace',
  },
  provide() {
    const vm = this;
    return { vglObject3d: { get inst() { return vm.inst; } } };
  },
  created() { this.vglNamespace.update(); },
  beforeUpdate() { this.vglNamespace.update(); },
  beforeDestroy() {
    const { vglNamespace, inst, name } = this;
    if (inst.parent) inst.parent.remove(inst);
    if (vglNamespace.object3ds[name] === inst) this.$delete(vglNamespace.object3ds, name);
    vglNamespace.update();
  },
  watch: {
    inst: {
      handler(inst, oldInst) {
        if (oldInst && oldInst.parent) oldInst.parent.remove(oldInst);
        if (this.vglObject3d.inst) this.vglObject3d.inst.add(inst);
        if (this.position) inst.position.copy(parseVector3(this.position));
        if (this.rotation) inst.rotation.copy(parseEuler(this.rotation));
        if (this.rotationQuaternion) inst.quaternion.copy(parseQuaternion(this.rotationQuaternion));
        if (this.scale) inst.scale.copy(parseVector3(this.scale));
        Object.assign(inst, {
          castShadow: this.castShadow,
          receiveShadow: this.receiveShadow,
          visible: this.visible,
        });
        if (this.name !== undefined) {
          // eslint-disable-next-line no-param-reassign
          inst.name = this.name;
          this.$set(this.vglNamespace.object3ds, this.name, inst);
        }
      },
      immediate: true,
    },
    'vglObject3d.inst': function parentInst(inst) { inst.add(this.inst); },
    position(position) { this.inst.position.copy(parseVector3(position)); },
    rotation(rotation) { this.inst.rotation.copy(parseEuler(rotation)); },
    rotationQuaternion(rotationQuaternion) {
      this.inst.quaternion.copy(parseQuaternion(rotationQuaternion));
    },
    scale(scale) { this.inst.scale.copy(parseVector3(scale)); },
    castShadow(castShadow) { this.inst.castShadow = castShadow; },
    receiveShadow(receiveShadow) { this.inst.receiveShadow = receiveShadow; },
    name(name, oldName) {
      const { vglNamespace: { object3ds }, inst } = this;
      if (object3ds[oldName] === inst) this.$delete(object3ds, oldName);
      this.inst.name = name;
      this.$set(object3ds, name, inst);
    },
    visible(visible) { this.inst.visible = visible; },
  },
  render(h) { return this.$slots.default ? h('div', this.$slots.default) : undefined; },
};
<|endoftext|>


<commit_before>var taToken;

function createLink(url){
  let link = document.createElement("a");
  link.id = "workspaceRedirect";
  link.rel= "noopener noreferrer";
  link.target= "_blank";
  link.href = url;
  link.style = "text-decoration: none;";
  link.innerText = "Go to Workspace";

  return link;
}

function notifyStudent(studentEmail){
  var params = window.location.search + "&studentEmail=" + studentEmail + "&taToken=" + taToken;
  const request = new Request("/notify-student" + params, {method: "POST"});

  fetch(request);
}

function endHelp(studentEmail){
  var params = window.location.search + "&studentEmail=" + studentEmail + "&taToken=" + taToken;
  const request = new Request("/end-help" + params, {method: "POST"});

  fetch(request).then(() => {
    document.getElementById('beingHelped').innerText = "";
  });
}

function createListElement(studentEmail) {
  let notifyElem = document.createElement("div");
  notifyElem.className = "student-container";

  let student = document.createElement('p');
  student.innerText = studentEmail;
  student.className = "student-info";

  let btn = document.createElement("input");
  btn.value = "notify student you're ready to help";
  btn.type = "button";
  btn.id = studentEmail;
  btn.className = "notify-button";
  btn.onclick = function(){notifyStudent(this.id);};

  notifyElem.appendChild(student);
  notifyElem.appendChild(btn);

  return notifyElem;
}

function createHelpedElem(studentEmail, url){
  let studentElem = document.createElement("div");
  studentElem.className = "help-container";

  let student = document.createElement('p');
  student.innerText = "You are helping " + studentEmail;
  student.className = "help-info";

  let btn = document.createElement("input");
  btn.value = "end interaction";
  btn.type = "button";
  btn.id = studentEmail;
  btn.className = "end-button";
  btn.onclick = function(){endHelp(this.id);};

  studentElem.appendChild(student);
  studentElem.appendChild(btn);
  studentElem.appendChild(createLink(url));

  return studentElem;
}

function getQueue() {
  var params = window.location.search;
  const request = new Request("/get-queue" + params + "&idToken=" + taToken, {method: "GET"});

  fetch(request).then(response => response.json()).then((queue) => {
    const queueListElement = document.getElementById('queue');
    queueListElement.innerText = "";
    queue.queue.forEach((studentEmail) => {
      queueListElement.appendChild(createListElement(studentEmail));
    });

    const beinghelpedElem = document.getElementById('beingHelped');

    if (queue.helping) {
      beinghelpedElem.innerHTML = "";
      document.getElementById('beingHelped').appendChild(createHelpedElem(queue.helping.email, queue.helping.workspace));
    } else {
      beinghelpedElem.innerHTML = "";
    }
  });
}

var repeat = setInterval(getQueue, 1000);
function setToken(token){
  taToken = token;
  getQueue();
}

function getToken() {
  var user = firebase.auth().currentUser;
  firebase.auth().onAuthStateChanged(function(user) {
    if (user) {
      console.log("User is signed in");
      user.getIdToken().then((token) => setToken(token));
    } else {
      console.log("User is not logged in");
      window.location.href = "/"; // Redirect to home page if not logged in
    }
  });
}

function onload() {
  getToken();
  document.getElementById("dashboard-link").href = `/dashboard.html${window.location.search}`;
}<commit_msg>Hide all notify-student buttons if ta is helping somebody.<commit_after>var taToken;

function createLink(url){
  let link = document.createElement("a");
  link.id = "workspaceRedirect";
  link.rel= "noopener noreferrer";
  link.target= "_blank";
  link.href = url;
  link.style = "text-decoration: none;";
  link.innerText = "Go to Workspace";

  return link;
}

function notifyStudent(studentEmail){
  var params = window.location.search + "&studentEmail=" + studentEmail + "&taToken=" + taToken;
  const request = new Request("/notify-student" + params, {method: "POST"});

  fetch(request);
}

function endHelp(studentEmail){
  var params = window.location.search + "&studentEmail=" + studentEmail + "&taToken=" + taToken;
  const request = new Request("/end-help" + params, {method: "POST"});

  fetch(request).then(() => {
    document.getElementById('beingHelped').innerText = "";
  });
}

function createListElement(studentEmail) {
  let notifyElem = document.createElement("div");
  notifyElem.className = "student-container";

  let student = document.createElement('p');
  student.innerText = studentEmail;
  student.className = "student-info";

  let btn = document.createElement("input");
  btn.value = "notify student you're ready to help";
  btn.type = "button";
  btn.id = studentEmail;
  btn.className = "notify-button";
  btn.onclick = function(){notifyStudent(this.id);};

  notifyElem.appendChild(student);
  notifyElem.appendChild(btn);

  return notifyElem;
}

function createHelpedElem(studentEmail, url){
  let studentElem = document.createElement("div");
  studentElem.className = "help-container";

  let student = document.createElement('p');
  student.innerText = "You are helping " + studentEmail;
  student.className = "help-info";

  let btn = document.createElement("input");
  btn.value = "end interaction";
  btn.type = "button";
  btn.id = studentEmail;
  btn.className = "end-button";
  btn.onclick = function(){endHelp(this.id);};

  studentElem.appendChild(student);
  studentElem.appendChild(btn);
  studentElem.appendChild(createLink(url));

  return studentElem;
}

function getQueue() {
  var params = window.location.search;
  const request = new Request("/get-queue" + params + "&idToken=" + taToken, {method: "GET"});

  fetch(request).then(response => response.json()).then((queue) => {
    const queueListElement = document.getElementById('queue');
    queueListElement.innerText = "";
    queue.queue.forEach((studentEmail) => {
      queueListElement.appendChild(createListElement(studentEmail));
    });

    const beinghelpedElem = document.getElementById('beingHelped');

    if (queue.helping) {
      queueListElement.querySelectorAll(".notify-button").forEach((ele) => ele.classList.add("hidden"));
      beinghelpedElem.innerHTML = "";
      document.getElementById('beingHelped').appendChild(createHelpedElem(queue.helping.email, queue.helping.workspace));
    } else {
      beinghelpedElem.innerHTML = "";
    }
  });
}

var repeat = setInterval(getQueue, 1000);
function setToken(token){
  taToken = token;
  getQueue();
}

function getToken() {
  var user = firebase.auth().currentUser;
  firebase.auth().onAuthStateChanged(function(user) {
    if (user) {
      console.log("User is signed in");
      user.getIdToken().then((token) => setToken(token));
    } else {
      console.log("User is not logged in");
      window.location.href = "/"; // Redirect to home page if not logged in
    }
  });
}

function onload() {
  getToken();
  document.getElementById("dashboard-link").href = `/dashboard.html${window.location.search}`;
}<|endoftext|>