<commit_before>var Promise = require('bluebird');
var async = require('asyncawait/async');
var await = require('asyncawait/await');

var _db = null;

function programInitIsThere()
{
	// console.log("programInitIsThere");
	return new Promise(function(success, failure)
	{
		_db.collection("programinit")
		.find({initialized: true})
		.toArray()
		.then(function(result)
		{
			if(result.length > 0)
			{
				// console.log("found an init document");
				success(true);
			}
			else
			{
				// console.log("no init document exists");
				success(false);
			}
		})
		.catch(function(err)
		{
			failure(err);
		});
	});
}

function insertInitialization()
{
	console.log("insertInitialization");
	return new Promise(function(success, failure)
	{
		return _db.collection("programinit")
		.insert({initialized: true})
		.then(function(result)
		{
			if(result.result.ok === 1)
			{
				console.log("inserted init document");
				// success(true);
				return insertDefaultSchedules();
			}
			else
			{
				// console.log("failed to insert init document");
				failure(new Error("Result was not ok: " + result.result));
			}
		})
		.then(function(result)
		{
			if(result === true)
			{
				success(true);
			}
			else
			{
				success(false);
			}
		});
	})
	.catch(function(error)
	{
		failure(error);
	});
}

function deleteEverything()
{
	// console.log("deleteEverything");
	return new Promise(function(success, failure)
	{
		return _db.collection("programinit")
		.remove({})
		.then(function(result)
		{
			if(result.result.ok === 1)
			{
				console.log("removeing all in schedule...");
				return _db.collection('schedule')
				.remove({});
			}
			else
			{
				failure("Result1 was not ok: " + result.result);
			}
		})
		.then(function(result)
		{
			console.log("removed all schedules, result:", result.result.ok);
			success(true);
			return;

			if(result.result.ok === 1)
			{
				success(true);
			}
			else
			{
				failure("Result2 was no ok: " + result.result);
			}
		})
		.catch(function(err)
		{
			failure(err);
		});
	});
}

function initialize()
{
	console.log("initialize");
	return new Promise(function(success, failure)
	{
		return programInitIsThere()
		.then(function(isThere)
		{
			console.log("isThere:", isThere);
			if(isThere === true)
			{
				success(true);
			}
			else
			{
				return insertInitialization();
			}
		})
		.then(function(injected)
		{
			if(injected === true)
			{
				success(true);
			}
			else
			{
				success(false);
			}
		});
	})
	.catch(function(error)
	{
		reject(error);
	});
}

var insertDefaultSchedules = async (function()
{
	console.log("insertDefaultSchedules");
	var level1schedule = require('./workouts/fixtures/level1schedule');
	var level2schedule = require('./workouts/fixtures/level2schedule');
	var level3schedule = require('./workouts/fixtures/level3schedule');

	var result = await(_db.collection("schedule").insertMany([level1schedule, level2schedule, level3schedule]));
	if(result.result.ok === 1)
	{
		return true;
	}
	else
	{
		return new Error("Result was not ok: " + result.result);
	}
});

var startingStrengthBootstrap = {
	initialize: initialize,
	deleteEverything: deleteEverything,
	get db()
	{
		return _db;
	},

	set db(newDB)
	{
		_db = newDB;
	},
};

module.exports = startingStrengthBootstrap;<commit_msg>much better<commit_after>var Promise = require('bluebird');
var async = require('asyncawait/async');
var await = require('asyncawait/await');

var _db = null;

var programInitIsThere = async (function()
{
	// console.log("programInitIsThere");
	var result = await (_db.collection("programinit")
	.find({initialized: true})
	.toArray());

	if(result.length > 0)
	{
		// console.log("found an init document");
		return true;
	}
	else
	{
		// console.log("no init document exists");
		return false;
	}
});

var insertInitialization = async (function()
{
	console.log("insertInitialization");
	var result = await (_db.collection("programinit")
	.insert({initialized: true}));
	if(result.result.ok === 1)
	{
		console.log("inserted init document");
		var defaultResult = await (insertDefaultSchedules());
		if(defaultResult === true)
		{
			return true;
		}
		else
		{
			return new Error("Insert of default schedules result was not ok: " + result.result);
		}
	}
	else
	{
		// console.log("failed to insert init document");
		return new Error("Result was not ok: " + result.result);
	}
});

var deleteEverything = async (function()
{
	// console.log("deleteEverything");
	var result = await (_db.collection("programinit")
	.remove({}));

	if(result.result.ok === 1)
	{
		console.log("removeing all in schedule...");
		var deleteScheduleResult = await (_db.collection('schedule')
		.remove({}));
		if(result.result.ok === 1)
		{
			return true;
		}
		else
		{
			return new Error("Result2 was no ok: " + result.result);
		}
	}
	else
	{
		return new Error("Result1 was not ok: " + result.result);
	}
});

var initialize = async (function()
{
	console.log("initialize");
	var isThere = await (programInitIsThere());
	if(isThere === true)
	{
		return true;
	}
	else
	{
		var injected = await (insertInitialization());
		if(injected === true)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
});

var insertDefaultSchedules = async (function()
{
	console.log("insertDefaultSchedules");
	var level1schedule = require('./workouts/fixtures/level1schedule');
	var level2schedule = require('./workouts/fixtures/level2schedule');
	var level3schedule = require('./workouts/fixtures/level3schedule');

	var result = await(_db.collection("schedule").insertMany([level1schedule, level2schedule, level3schedule]));
	if(result.result.ok === 1)
	{
		return true;
	}
	else
	{
		return new Error("Result was not ok: " + result.result);
	}
});

var startingStrengthBootstrap = {
	initialize: initialize,
	deleteEverything: deleteEverything,
	get db()
	{
		return _db;
	},

	set db(newDB)
	{
		_db = newDB;
	},
};

module.exports = startingStrengthBootstrap;<|endoftext|>


<commit_before>"use strict";

const { AsyncEventEmitter } = require("emitter");
const { ServiceMgr } = require("service");
const rp = require("request-promise");
const JenkinsEventEmitter = require("./jenkins_event_emitter");
const Job = require("../../types/job");

/*
To get started with Jenkins integration:
1. Create a new functional user, make sure they have authority to start jobs
2. Make sure the Notification plugin is installed
    https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin
3. Edit the jobs you wish to run via jenkins to send notifications
   You will need to fill in the url and port to the jenkins backend you create

Creating a new Jenkins backend:

Example configuration:
    host -> "http://myjenkins.mycompany.com"

    The above will ...
*/

// Translation table Jenkins job codes => Codefarm job codes
const RESULTCODES = {
    "SUCCESS": "success",
    "FAILURE": "fail",
    "ABORTED": "aborted",
    "BUILDING": "ongoing"
};

class JenkinsBackend extends AsyncEventEmitter {
    constructor(id, backend) {
        super();
        this.id = id;
        this.backend = backend;
        this.crumb = false;
        this.crumbRequestField = false;
        this.locks = {};
        this.jenkinsEmitter = new JenkinsEventEmitter(
            ServiceMgr.instance.log.bind(ServiceMgr.instance)
        );
    }

    async start() {
        ServiceMgr.instance.log("verbose", `Retrieving crumb for ${this.backend.authUser} on ${this.backend.hostUrl}`);
        const url = `${this.backend.hostUrl}/crumbIssuer/api/json`;

        try {
            const response = await this._sendRequest(url, "GET", null, false);
            // TODO: What if crumb expires?
            this.crumb = response.crumb;
            this.crumbRequestField = response.crumbRequestField;
            ServiceMgr.instance.log("verbose", "Crumb retrieved");
        } catch (err) {
            ServiceMgr.instance.log("error", `Failed to retrieve crumb: ${err}`);
        }

        // Start event monitoring towards jenkins and towards console text events
        try {
            const result = await this._startMonitorEventStream();
            ServiceMgr.instance.log("verbose", result);
            this.addListener("consoleText", this._onJobConsoleText.bind(this));
        } catch (err) {
            ServiceMgr.instance.log("error", `Failed to setup Jenkins notification server: ${err}`);
        }
    }

    _createRequest(uri, method = "POST", body = null) {
        const auth = Buffer.from(`${this.backend.authUser}:${this.backend.authToken}`).toString("base64");
        const headers = {
            "User-Agent": "Code Farm",
            "Authorization": `Basic ${auth}`
        };

        // Use crumb if available (retrieved on start)
        if (this.crumb) {
            headers[this.crumbRequestField] = this.crumb;
        }

        const options = {
            method,
            uri,
            headers,
            body,
            json: true // Automatically stringifies the body to JSON
        };

        return options;
    }

    async _sendRequest(uri, method = "POST", body = null, fullResponse = true) {
        const options = this._createRequest(uri, method, body);
        options.resolveWithFullResponse = fullResponse;

        return rp(options);
    }

    // Get the console text log for a building job as a stream
    async getConsoleText(queuenr, jobUrl, offset) {
        const url = `${jobUrl}logText/progressiveText?start=${offset}`;
        const response = await this._sendRequest(url, "GET");
        this.emit("consoleText", { queuenr, jobUrl, offset, response });
    }

    // Start/Queue job
    async startJob(job) {
        const jenkinsJobName = job.script;
        // TODO: Send parameters in form
        const url = `${this.backend.hostUrl}/job/${jenkinsJobName}/build`;
        const response = await this._sendRequest(url);
        // Parse response to get queuenr from header
        const parts = response.headers.location.split("/");

        return parts[parts.length - 2];
    }

    async stopJob(url) {
        const stopUrl = `${url}stop`;

        return await this._sendRequest(stopUrl, "POST", null, false);
    }

    async dequeueJob(queuenr) {
        const dequeueUrl = `${this.backend.hostUrl}/queue/cancelItem?id=${queuenr}`

        return await this._sendRequest(dequeueUrl, "POST", null, false)
    }

    async verifySlaveJob(slave) {
        return new Job({
            name: `Verify_slave_${slave._id}`,
            // All slaves have their ID as a tag... This will match a specific slave
            criteria: `${slave._id}`,
            requeueOnFailure: false,
            script: "testJob",
            baseline: false
        });
    }

    async getJobStatus(url) {
        const jsonUrl = `${url}api/json`;
        const response = await this._sendRequest(jsonUrl, "GET", null, false);
        if (response.building) {
            return RESULTCODES.BUILDING;
        }

        return RESULTCODES[response.result];
    }

    _createEvent(event) {
        const obj = {
            jenkinsname: event.name,
            jenkinsurl: `${this.backend.hostUrl}/${event.build.url}`,
            queuenr: event.build.queue_id.toString(),
            status: event.build.status ? event.build.status.toLowerCase() : "unknown"
        };

        ServiceMgr.instance.log("debug", JSON.stringify(obj, null, 2));

        return obj;
    }

    async _onJobStarted(event) {
        ServiceMgr.instance.log("verbose", "job_started event received");
        ServiceMgr.instance.log("debug", JSON.stringify(event, null, 2));
        const outevent = this._createEvent(event);
        await this.emit("job_started", outevent);

        // Start polling console text, this will emit consoleText event
        this.getConsoleText(outevent.queuenr, outevent.jenkinsurl, 0);
    }

    async _onJobCompleted(event) {
        ServiceMgr.instance.log("verbose", "job_completed event received");
        ServiceMgr.instance.log("debug", JSON.stringify(event, null, 2));
        await this.emit("job_completed", this._createEvent(event));
    }

    async _onJobFinalized(event) {
        ServiceMgr.instance.log("verbose", "job_finalized event received");
        ServiceMgr.instance.log("debug", JSON.stringify(event, null, 2));
        await this.emit("job_finalized", this._createEvent(event));
    }

    async _onJobConsoleText(event) {
        ServiceMgr.instance.log("verbose", "console text event received");
        ServiceMgr.instance.log("debug", JSON.stringify(event, null, 2));

        await this.emit("job_consoletext", event);

        // If more data indicated: poll after interval
        if (event.response.headers["x-more-data"]) {
            const offset = parseInt(event.response.headers["x-text-size"], 10);
            setTimeout(() => {
                ServiceMgr.instance.log("debug", `Polling jenkins console (interval: ${this.backend.pollDelay})`);
                this.getConsoleText(event.queuenr, event.jobUrl, offset);
            }, this.backend.pollDelay);
        }
    }

    async _startMonitorEventStream() {
        this.jenkinsEmitter.addListener("job_started", this._onJobStarted.bind(this));
        this.jenkinsEmitter.addListener("job_completed", this._onJobCompleted.bind(this));

        return await this.jenkinsEmitter.start(this.backend.port);
    }

    get backendType() {
        return this.backend.backendType;
    }

    get jenkinsUrl() {
        return this.backend.hostUrl;
    }

    async dispose() {
        this.removeAllListeners();
        this.jenkinsEmitter.removeAllListeners();
        await this.jenkinsEmitter.dispose();
    }
}

module.exports = JenkinsBackend;
<commit_msg>Exec: Changed name of jenkins slave test job<commit_after>"use strict";

const { AsyncEventEmitter } = require("emitter");
const { ServiceMgr } = require("service");
const rp = require("request-promise");
const JenkinsEventEmitter = require("./jenkins_event_emitter");
const Job = require("../../types/job");

/*
To get started with Jenkins integration:
1. Create a new functional user, make sure they have authority to start jobs
2. Make sure the Notification plugin is installed
    https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin
3. Edit the jobs you wish to run via jenkins to send notifications
   You will need to fill in the url and port to the jenkins backend you create

Creating a new Jenkins backend:

Example configuration:
    host -> "http://myjenkins.mycompany.com"

    The above will ...
*/
const BACKEND_SLAVE_TEST_JOB = "codefarm_slave_test";

// Translation table Jenkins job codes => Codefarm job codes
const RESULTCODES = {
    "SUCCESS": "success",
    "FAILURE": "fail",
    "ABORTED": "aborted",
    "BUILDING": "ongoing"
};

class JenkinsBackend extends AsyncEventEmitter {
    constructor(id, backend) {
        super();
        this.id = id;
        this.backend = backend;
        this.crumb = false;
        this.crumbRequestField = false;
        this.locks = {};
        this.jenkinsEmitter = new JenkinsEventEmitter(
            ServiceMgr.instance.log.bind(ServiceMgr.instance)
        );
    }

    async start() {
        ServiceMgr.instance.log("verbose", `Retrieving crumb for ${this.backend.authUser} on ${this.backend.hostUrl}`);
        const url = `${this.backend.hostUrl}/crumbIssuer/api/json`;

        try {
            const response = await this._sendRequest(url, "GET", null, false);
            // TODO: What if crumb expires?
            this.crumb = response.crumb;
            this.crumbRequestField = response.crumbRequestField;
            ServiceMgr.instance.log("verbose", "Crumb retrieved");
        } catch (err) {
            ServiceMgr.instance.log("error", `Failed to retrieve crumb: ${err}`);
        }

        // Start event monitoring towards jenkins and towards console text events
        try {
            const result = await this._startMonitorEventStream();
            ServiceMgr.instance.log("verbose", result);
            this.addListener("consoleText", this._onJobConsoleText.bind(this));
        } catch (err) {
            ServiceMgr.instance.log("error", `Failed to setup Jenkins notification server: ${err}`);
        }
    }

    _createRequest(uri, method = "POST", body = null) {
        const auth = Buffer.from(`${this.backend.authUser}:${this.backend.authToken}`).toString("base64");
        const headers = {
            "User-Agent": "Code Farm",
            "Authorization": `Basic ${auth}`
        };

        // Use crumb if available (retrieved on start)
        if (this.crumb) {
            headers[this.crumbRequestField] = this.crumb;
        }

        const options = {
            method,
            uri,
            headers,
            body,
            json: true // Automatically stringifies the body to JSON
        };

        return options;
    }

    async _sendRequest(uri, method = "POST", body = null, fullResponse = true) {
        const options = this._createRequest(uri, method, body);
        options.resolveWithFullResponse = fullResponse;

        return rp(options);
    }

    // Get the console text log for a building job as a stream
    async getConsoleText(queuenr, jobUrl, offset) {
        const url = `${jobUrl}logText/progressiveText?start=${offset}`;
        const response = await this._sendRequest(url, "GET");
        this.emit("consoleText", { queuenr, jobUrl, offset, response });
    }

    // Start/Queue job
    async startJob(job) {
        const jenkinsJobName = job.script;
        // TODO: Send parameters in form
        const url = `${this.backend.hostUrl}/job/${jenkinsJobName}/build`;
        const response = await this._sendRequest(url);
        // Parse response to get queuenr from header
        const parts = response.headers.location.split("/");

        return parts[parts.length - 2];
    }

    async stopJob(url) {
        const stopUrl = `${url}stop`;

        return await this._sendRequest(stopUrl, "POST", null, false);
    }

    async dequeueJob(queuenr) {
        const dequeueUrl = `${this.backend.hostUrl}/queue/cancelItem?id=${queuenr}`

        return await this._sendRequest(dequeueUrl, "POST", null, false)
    }

    async verifySlaveJob(slave) {
        return new Job({
            name: `Verify_slave_${slave._id}`,
            // All slaves have their ID as a tag... This will match a specific slave
            criteria: `${slave._id}`,
            requeueOnFailure: false,
            script: BACKEND_SLAVE_TEST_JOB,
            baseline: false
        });
    }

    async getJobStatus(url) {
        const jsonUrl = `${url}api/json`;
        const response = await this._sendRequest(jsonUrl, "GET", null, false);
        if (response.building) {
            return RESULTCODES.BUILDING;
        }

        return RESULTCODES[response.result];
    }

    _createEvent(event) {
        const obj = {
            jenkinsname: event.name,
            jenkinsurl: `${this.backend.hostUrl}/${event.build.url}`,
            queuenr: event.build.queue_id.toString(),
            status: event.build.status ? event.build.status.toLowerCase() : "unknown"
        };

        ServiceMgr.instance.log("debug", JSON.stringify(obj, null, 2));

        return obj;
    }

    async _onJobStarted(event) {
        ServiceMgr.instance.log("verbose", "job_started event received");
        ServiceMgr.instance.log("debug", JSON.stringify(event, null, 2));
        const outevent = this._createEvent(event);
        await this.emit("job_started", outevent);

        // Start polling console text, this will emit consoleText event
        this.getConsoleText(outevent.queuenr, outevent.jenkinsurl, 0);
    }

    async _onJobCompleted(event) {
        ServiceMgr.instance.log("verbose", "job_completed event received");
        ServiceMgr.instance.log("debug", JSON.stringify(event, null, 2));
        await this.emit("job_completed", this._createEvent(event));
    }

    async _onJobFinalized(event) {
        ServiceMgr.instance.log("verbose", "job_finalized event received");
        ServiceMgr.instance.log("debug", JSON.stringify(event, null, 2));
        await this.emit("job_finalized", this._createEvent(event));
    }

    async _onJobConsoleText(event) {
        ServiceMgr.instance.log("verbose", "console text event received");
        ServiceMgr.instance.log("debug", JSON.stringify(event, null, 2));

        await this.emit("job_consoletext", event);

        // If more data indicated: poll after interval
        if (event.response.headers["x-more-data"]) {
            const offset = parseInt(event.response.headers["x-text-size"], 10);
            setTimeout(() => {
                ServiceMgr.instance.log("debug", `Polling jenkins console (interval: ${this.backend.pollDelay})`);
                this.getConsoleText(event.queuenr, event.jobUrl, offset);
            }, this.backend.pollDelay);
        }
    }

    async _startMonitorEventStream() {
        this.jenkinsEmitter.addListener("job_started", this._onJobStarted.bind(this));
        this.jenkinsEmitter.addListener("job_completed", this._onJobCompleted.bind(this));

        return await this.jenkinsEmitter.start(this.backend.port);
    }

    get backendType() {
        return this.backend.backendType;
    }

    get jenkinsUrl() {
        return this.backend.hostUrl;
    }

    async dispose() {
        this.removeAllListeners();
        this.jenkinsEmitter.removeAllListeners();
        await this.jenkinsEmitter.dispose();
    }
}

module.exports = JenkinsBackend;
<|endoftext|>


<commit_before>(function() {
    var Ext = window.Ext4 || window.Ext;

    Ext.define('Rally.apps.customlist.CustomListApp', {
        extend: 'Rally.app.GridBoardApp',
        requires: [
            'Deft.Promise',
            'Rally.apps.customlist.Settings',
            'Rally.data.ModelTypes',
            'Rally.data.util.Sorter',
            'Rally.data.wsapi.Filter'
        ],

        disallowedAddNewTypes: ['user', 'userprofile', 'useriterationcapacity', 'testcaseresult', 'task', 'scmrepository', 'project', 'changeset', 'change', 'builddefinition', 'build'],
        orderedAllowedPageSizes: [10, 25, 50, 100, 200],
        statePrefix: 'customlist',

        initComponent: function () {
            this.defaultSettings = {
                query: this.appContainer.query,
                order: this.appContainer.order,
                type: this.appContainer.url,
                columnNames: (this.appContainer.fetch || '').split(',')
            };
            this.callParent(arguments);
        },

        getSettingsFields: function() {
            return Rally.apps.customlist.Settings.getFields(this.getContext());
        },

        loadModelNames: function () {
            this.modelNames = _.compact([this.getSetting('type')]);
            this._setColumnNames(this.getSetting('columnNames'));
            return Deft.Promise.when(this.modelNames);
        },

        loadGridBoard: function () {
            if (_.isEmpty(this.modelNames)) {
                Ext.defer(function () {
                    this.owner.showSettings();
                    this.publishComponentReady();
                }, 1, this);
            } else {
                this.enableAddNew = this._shouldEnableAddNew();
                this.callParent(arguments);
            }
        },

        getGridConfig: function () {
            return _.merge(this.callParent(arguments), {
                listeners: {
                    beforestaterestore: this._onBeforeGridStateRestore,
                    beforestatesave: this._onBeforeGridStateSave,
                    scope: this
                },
                pagingToolbarCfg: {
                    pageSizes: this.orderedAllowedPageSizes
                }
            });
        },

        getFilterControlConfig: function () {
            return _.merge(this.callParent(arguments), {
                listeners: {
                    beforestaterestore: {
                        fn: this._onBeforeFilterButtonStateRestore,
                        scope: this
                    }
                }
            });
        },

        getGridStoreConfig: function () {
            var sorters = this._getValidSorters(Rally.data.util.Sorter.sorters(this.getSetting('order')));

            if (_.isEmpty(sorters)) {
                var rankField = this.getContext().getWorkspace().WorkspaceConfiguration.DragDropRankingEnabled ? 'DragAndDropRank' : 'Rank';
                var defaultSort = Rally.data.ModelTypes.areArtifacts(this.modelNames) ? rankField : Rally.data.util.Sorter.getDefaultSort(this.modelNames[0]);

                sorters = Rally.data.util.Sorter.sorters(defaultSort);
            }

            return {
                pageSize: this.appContainer.pagesize ? _.find(this.orderedAllowedPageSizes, function(pageSize, index, array){
                    return pageSize >= parseInt(this.appContainer.pagesize, 10) || index === array.length - 1;
                }, this) : 10,
                sorters: sorters
            };
        },

        getAddNewConfig: function () {
            return _.merge(this.callParent(arguments), {
                minWidth: 700,
                openEditorAfterAddFailure: false
            });
        },

        getFieldPickerConfig: function () {
            return _.merge(this.callParent(arguments), {
                buttonConfig: {
                    disabled: !this._userHasPermissionsToEditPanelSettings()
                }
            });
        },

        getPermanentFilters: function () {
            var projectFilter = this.getSetting('type').toLowerCase() === 'milestone' ? [
                Rally.data.wsapi.Filter.or([
                    { property: 'Projects', operator: 'contains', value: this.getContext().getProjectRef() },
                    { property: 'TargetProject', operator: '=', value: null }
                ])
            ] : null;

            var query = this.getSetting('query');
            var timeboxScopeFilter = this._getTimeboxScopeFilter().concat(query ? [ Rally.data.wsapi.Filter.fromQueryString(query) ] : []);
            return projectFilter ? projectFilter.concat(timeboxScopeFilter) : timeboxScopeFilter;
        },

        onTimeboxScopeChange: function() {
            this.callParent(arguments);
            this.loadGridBoard();
        },

        _getTimeboxScopeFilter: function () {
            var timeboxScope = this.getContext().getTimeboxScope();
            var hasTimeboxField = timeboxScope && _.any(this.models, function (model) {
                return model.hasField(Ext.String.capitalize(timeboxScope.getType()));
            });
            return hasTimeboxField ? [ timeboxScope.getQueryFilter() ] : [];
        },

        _shouldEnableAddNew: function() {
            return !_.contains(this.disallowedAddNewTypes, this.getSetting('type').toLowerCase());
        },

        _setColumnNames: function (columnNames) {
            columnNames = _.isString(columnNames) ? columnNames.split(',') : columnNames;

            // Note: When enableHierarchy is true (artifacts only for now), the FormattedID column is always added
            // If we include FormattedID in columns names, we get 2 ID columns, which is poopy.
            // This problem should be fixed for reals in the SDK somewhere eventually.
            if (Rally.data.ModelTypes.areArtifacts(this.modelNames)) {
                columnNames = _.reject(columnNames, function (columnName) {
                    return _.isString(columnName) && columnName.toLowerCase() === 'formattedid';
                });
            }

            this.columnNames = _.compact(columnNames);
        },

        _onBeforeFilterButtonStateRestore:  function (filterButton, state) {
            if (state && state.filters && state.filters.length) {
                var stateFilters = _.map(state.filters, function (filterStr) {
                    return Rally.data.wsapi.Filter.fromQueryString(filterStr);
                });
                var validFilters = Rally.util.Filter.removeNonapplicableTypeSpecificFilters(stateFilters, this.models);
                state.filters = _.invoke(validFilters, 'toString');
            }
        },

        _onBeforeGridStateRestore: function (grid, state) {
            if (!state) {
                return;
            }

            if (state.columns) {
                var appScopedColumnNames = this.getColumnCfgs();
                var userScopedColumnNames = this._getColumnNamesFromState(state);

                if(_.difference(appScopedColumnNames, userScopedColumnNames).length > 0) {
                    state.columns = appScopedColumnNames;
                } else {
                    state.columns = _.filter(state.columns, function (column) {
                        return _.contains(appScopedColumnNames, _.isObject(column) ? column.dataIndex : column);
                    });
                }
            }

            if (state.sorters) {
                state.sorters = this._getValidSorters(state.sorters);
                if (_.isEmpty(state.sorters)) {
                    delete state.sorters;
                }
            }
        },

        _onBeforeGridStateSave: function (grid, state) {
            var newColumnNames = this._getColumnNamesFromState(state);

            if (!_.isEmpty(newColumnNames)) {
                this._setColumnNames(newColumnNames);

                if (this._userHasPermissionsToEditPanelSettings()) {
                    this.updateSettingsValues({
                        settings: {
                            columnNames: newColumnNames.join(',')
                        }
                    });
                }
            }
        },

        _getValidSorters: function (sorters) {
            return _.filter(sorters, function (sorter) {
                return _.any(this.models, function (model) {
                    var field = model.getField(sorter.property);
                    return field && field.sortable;
                });
            }, this);
        },

        _userHasPermissionsToEditPanelSettings: function () {
            return this.owner.dashboard.arePanelSettingsEditable;
        },

        _getColumnNamesFromState: function (state) {
            return _(state && state.columns).map(function (newColumn) {
                return _.isObject(newColumn) ? newColumn.dataIndex : newColumn;
            }).compact().value();
        }
    });
})();
<commit_msg>S63406: Ensure inline editing works with non-artifact types<commit_after>(function() {
    var Ext = window.Ext4 || window.Ext;

    Ext.define('Rally.apps.customlist.CustomListApp', {
        extend: 'Rally.app.GridBoardApp',
        requires: [
            'Deft.Promise',
            'Rally.apps.customlist.Settings',
            'Rally.data.ModelTypes',
            'Rally.data.util.Sorter',
            'Rally.data.wsapi.Filter'
        ],

        disallowedAddNewTypes: ['user', 'userprofile', 'useriterationcapacity', 'testcaseresult', 'task', 'scmrepository', 'project', 'changeset', 'change', 'builddefinition', 'build', 'program'],
        orderedAllowedPageSizes: [10, 25, 50, 100, 200],
        readOnlyGridTypes: ['build', 'change', 'changeset'],
        statePrefix: 'customlist',

        initComponent: function () {
            this.defaultSettings = {
                query: this.appContainer.query,
                order: this.appContainer.order,
                type: this.appContainer.url,
                columnNames: (this.appContainer.fetch || '').split(',')
            };
            this.callParent(arguments);
        },

        getSettingsFields: function() {
            return Rally.apps.customlist.Settings.getFields(this.getContext());
        },

        loadModelNames: function () {
            this.modelNames = _.compact([this.getSetting('type')]);
            this._setColumnNames(this.getSetting('columnNames'));
            return Deft.Promise.when(this.modelNames);
        },

        loadGridBoard: function () {
            if (_.isEmpty(this.modelNames)) {
                Ext.defer(function () {
                    this.owner.showSettings();
                    this.publishComponentReady();
                }, 1, this);
            } else {
                this.enableAddNew = this._shouldEnableAddNew();
                this.callParent(arguments);
            }
        },

        getGridConfig: function () {
            return _.merge(this.callParent(arguments), {
                enableEditing: !_.contains(this.readOnlyGridTypes, this.getSetting('type').toLowerCase()),
                listeners: {
                    beforestaterestore: this._onBeforeGridStateRestore,
                    beforestatesave: this._onBeforeGridStateSave,
                    scope: this
                },
                pagingToolbarCfg: {
                    pageSizes: this.orderedAllowedPageSizes
                }
            });
        },

        getFilterControlConfig: function () {
            return _.merge(this.callParent(arguments), {
                listeners: {
                    beforestaterestore: {
                        fn: this._onBeforeFilterButtonStateRestore,
                        scope: this
                    }
                }
            });
        },

        getGridStoreConfig: function () {
            var sorters = this._getValidSorters(Rally.data.util.Sorter.sorters(this.getSetting('order')));

            if (_.isEmpty(sorters)) {
                var rankField = this.getContext().getWorkspace().WorkspaceConfiguration.DragDropRankingEnabled ? 'DragAndDropRank' : 'Rank';
                var defaultSort = Rally.data.ModelTypes.areArtifacts(this.modelNames) ? rankField : Rally.data.util.Sorter.getDefaultSort(this.modelNames[0]);

                sorters = Rally.data.util.Sorter.sorters(defaultSort);
            }

            return {
                pageSize: this.appContainer.pagesize ? _.find(this.orderedAllowedPageSizes, function(pageSize, index, array){
                    return pageSize >= parseInt(this.appContainer.pagesize, 10) || index === array.length - 1;
                }, this) : 10,
                sorters: sorters
            };
        },

        getAddNewConfig: function () {
            return _.merge(this.callParent(arguments), {
                minWidth: 700,
                openEditorAfterAddFailure: false
            });
        },

        getFieldPickerConfig: function () {
            return _.merge(this.callParent(arguments), {
                buttonConfig: {
                    disabled: !this._userHasPermissionsToEditPanelSettings()
                }
            });
        },

        getPermanentFilters: function () {
            var projectFilter = this.getSetting('type').toLowerCase() === 'milestone' ? [
                Rally.data.wsapi.Filter.or([
                    { property: 'Projects', operator: 'contains', value: this.getContext().getProjectRef() },
                    { property: 'TargetProject', operator: '=', value: null }
                ])
            ] : null;

            var query = this.getSetting('query');
            var timeboxScopeFilter = this._getTimeboxScopeFilter().concat(query ? [ Rally.data.wsapi.Filter.fromQueryString(query) ] : []);
            return projectFilter ? projectFilter.concat(timeboxScopeFilter) : timeboxScopeFilter;
        },

        onTimeboxScopeChange: function() {
            this.callParent(arguments);
            this.loadGridBoard();
        },

        _getTimeboxScopeFilter: function () {
            var timeboxScope = this.getContext().getTimeboxScope();
            var hasTimeboxField = timeboxScope && _.any(this.models, function (model) {
                return model.hasField(Ext.String.capitalize(timeboxScope.getType()));
            });
            return hasTimeboxField ? [ timeboxScope.getQueryFilter() ] : [];
        },

        _shouldEnableAddNew: function() {
            return !_.contains(this.disallowedAddNewTypes, this.getSetting('type').toLowerCase());
        },

        _setColumnNames: function (columnNames) {
            columnNames = _.isString(columnNames) ? columnNames.split(',') : columnNames;

            // Note: When enableHierarchy is true (artifacts only for now), the FormattedID column is always added
            // If we include FormattedID in columns names, we get 2 ID columns, which is poopy.
            // This problem should be fixed for reals in the SDK somewhere eventually.
            if (Rally.data.ModelTypes.areArtifacts(this.modelNames)) {
                columnNames = _.reject(columnNames, function (columnName) {
                    return _.isString(columnName) && columnName.toLowerCase() === 'formattedid';
                });
            }

            this.columnNames = _.compact(columnNames);
        },

        _onBeforeFilterButtonStateRestore:  function (filterButton, state) {
            if (state && state.filters && state.filters.length) {
                var stateFilters = _.map(state.filters, function (filterStr) {
                    return Rally.data.wsapi.Filter.fromQueryString(filterStr);
                });
                var validFilters = Rally.util.Filter.removeNonapplicableTypeSpecificFilters(stateFilters, this.models);
                state.filters = _.invoke(validFilters, 'toString');
            }
        },

        _onBeforeGridStateRestore: function (grid, state) {
            if (!state) {
                return;
            }

            if (state.columns) {
                var appScopedColumnNames = this.getColumnCfgs();
                var userScopedColumnNames = this._getColumnNamesFromState(state);

                if(_.difference(appScopedColumnNames, userScopedColumnNames).length > 0) {
                    state.columns = appScopedColumnNames;
                } else {
                    state.columns = _.filter(state.columns, function (column) {
                        return _.contains(appScopedColumnNames, _.isObject(column) ? column.dataIndex : column);
                    });
                }
            }

            if (state.sorters) {
                state.sorters = this._getValidSorters(state.sorters);
                if (_.isEmpty(state.sorters)) {
                    delete state.sorters;
                }
            }
        },

        _onBeforeGridStateSave: function (grid, state) {
            var newColumnNames = this._getColumnNamesFromState(state);

            if (!_.isEmpty(newColumnNames)) {
                this._setColumnNames(newColumnNames);

                if (this._userHasPermissionsToEditPanelSettings()) {
                    this.updateSettingsValues({
                        settings: {
                            columnNames: newColumnNames.join(',')
                        }
                    });
                }
            }
        },

        _getValidSorters: function (sorters) {
            return _.filter(sorters, function (sorter) {
                return _.any(this.models, function (model) {
                    var field = model.getField(sorter.property);
                    return field && field.sortable;
                });
            }, this);
        },

        _userHasPermissionsToEditPanelSettings: function () {
            return this.owner.dashboard.arePanelSettingsEditable;
        },

        _getColumnNamesFromState: function (state) {
            return _(state && state.columns).map(function (newColumn) {
                return _.isObject(newColumn) ? newColumn.dataIndex : newColumn;
            }).compact().value();
        }
    });
})();
<|endoftext|>


<commit_before>'use strict';

var _get = require('babel-runtime/helpers/get')['default'];

var _inherits = require('babel-runtime/helpers/inherits')['default'];

var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default'];

var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];

Object.defineProperty(exports, '__esModule', {
  value: true
});

var _util = require('util');

var _util2 = _interopRequireDefault(_util);

var _uuidV4 = require('uuid-v4');

var _uuidV42 = _interopRequireDefault(_uuidV4);

var _middlewareCsError = require('../../middleware/csError');

var _middlewareCsError2 = _interopRequireDefault(_middlewareCsError);

var _getProperties2 = require('./getProperties');

var _getProperties3 = _interopRequireDefault(_getProperties2);

var _branchNameParse = require('./branchNameParse');

var _branchNameParse2 = _interopRequireDefault(_branchNameParse);

//TODO: do we want this kind of library to know about status codes?

var DeveoCommitMalformedError = (function (_CSError) {
  _inherits(DeveoCommitMalformedError, _CSError);

  function DeveoCommitMalformedError(error, pushEvent) {
    _classCallCheck(this, DeveoCommitMalformedError);

    _get(Object.getPrototypeOf(DeveoCommitMalformedError.prototype), 'constructor', this).call(this, ['There was an unexpected error when processing your Deveo push event.']);
    this.originalError = error;
    this.pushEvent = pushEvent;
  }

  return DeveoCommitMalformedError;
})(_middlewareCsError2['default']);

var deveoTranslator = {
  family: 'Deveo',
  translatePush: function translatePush(pushEvent, instanceId, digestId, inboxId) {
    try {
      var _ret = (function () {
        var branch = (0, _branchNameParse2['default'])(pushEvent.ref);
        var repository = {
          id: pushEvent.repository.uuid,
          name: pushEvent.project.name + '/' + pushEvent.repository.name
        };

        return {
          v: pushEvent.commits.map(function (aCommit) {
            var commit = {
              sha: aCommit.id,
              commit: {
                author: pushEvent.pusher.display_name,
                committer: {
                  name: aCommit.author.name,
                  email: aCommit.author.email,
                  date: aCommit.timestamp
                },
                message: aCommit.message
              },
              html_url: aCommit.url,
              repository: repository,
              branch: branch,
              originalMessage: aCommit
            };
            return {
              eventId: (0, _uuidV42['default'])(),
              eventType: 'DeveoCommitReceived',
              data: commit,
              metadata: {
                instanceId: instanceId,
                digestId: digestId,
                inboxId: inboxId
              }
            };
          })
        };
      })();

      if (typeof _ret === 'object') return _ret.v;
    } catch (ex) {
      var otherEx = new DeveoCommitMalformedError(ex, pushEvent);
      //console.log(otherEx, otherEx.originalError.stack);
      throw otherEx;
    }
  },
  canTranslate: function canTranslate(request) {
    var headers = request.headers;
    return headers.hasOwnProperty('x-deveo-event') && headers['x-deveo-event'] === 'push';
  },
  getProperties: function getProperties(event) {
    return (0, _getProperties3['default'])(event, '/commit', 'tree');
  }
};

exports['default'] = deveoTranslator;
module.exports = exports['default'];
<commit_msg>Use commit author instead of push event author.<commit_after>'use strict';

var _get = require('babel-runtime/helpers/get')['default'];

var _inherits = require('babel-runtime/helpers/inherits')['default'];

var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default'];

var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];

Object.defineProperty(exports, '__esModule', {
  value: true
});

var _util = require('util');

var _util2 = _interopRequireDefault(_util);

var _uuidV4 = require('uuid-v4');

var _uuidV42 = _interopRequireDefault(_uuidV4);

var _middlewareCsError = require('../../middleware/csError');

var _middlewareCsError2 = _interopRequireDefault(_middlewareCsError);

var _getProperties2 = require('./getProperties');

var _getProperties3 = _interopRequireDefault(_getProperties2);

var _branchNameParse = require('./branchNameParse');

var _branchNameParse2 = _interopRequireDefault(_branchNameParse);

//TODO: do we want this kind of library to know about status codes?

var DeveoCommitMalformedError = (function (_CSError) {
  _inherits(DeveoCommitMalformedError, _CSError);

  function DeveoCommitMalformedError(error, pushEvent) {
    _classCallCheck(this, DeveoCommitMalformedError);

    _get(Object.getPrototypeOf(DeveoCommitMalformedError.prototype), 'constructor', this).call(this, ['There was an unexpected error when processing your Deveo push event.']);
    this.originalError = error;
    this.pushEvent = pushEvent;
  }

  return DeveoCommitMalformedError;
})(_middlewareCsError2['default']);

var deveoTranslator = {
  family: 'Deveo',
  translatePush: function translatePush(pushEvent, instanceId, digestId, inboxId) {
    try {
      var _ret = (function () {
        var branch = (0, _branchNameParse2['default'])(pushEvent.ref);
        var repository = {
          id: pushEvent.repository.uuid,
          name: pushEvent.project.name + '/' + pushEvent.repository.name
        };

        return {
          v: pushEvent.commits.map(function (aCommit) {
            var commit = {
              sha: aCommit.id,
              commit: {
                author: aCommit.author.name,
                committer: {
                  name: aCommit.author.name,
                  email: aCommit.author.email,
                  date: aCommit.timestamp
                },
                message: aCommit.message
              },
              html_url: aCommit.url,
              repository: repository,
              branch: branch,
              originalMessage: aCommit
            };
            return {
              eventId: (0, _uuidV42['default'])(),
              eventType: 'DeveoCommitReceived',
              data: commit,
              metadata: {
                instanceId: instanceId,
                digestId: digestId,
                inboxId: inboxId
              }
            };
          })
        };
      })();

      if (typeof _ret === 'object') return _ret.v;
    } catch (ex) {
      var otherEx = new DeveoCommitMalformedError(ex, pushEvent);
      //console.log(otherEx, otherEx.originalError.stack);
      throw otherEx;
    }
  },
  canTranslate: function canTranslate(request) {
    var headers = request.headers;
    return headers.hasOwnProperty('x-deveo-event') && headers['x-deveo-event'] === 'push';
  },
  getProperties: function getProperties(event) {
    return (0, _getProperties3['default'])(event, '/commit', 'tree');
  }
};

exports['default'] = deveoTranslator;
module.exports = exports['default'];
<|endoftext|>


<commit_before>import React from 'react';
import VideoPlayer from 'react-video-js-player';
import '../../styles/css/player.css';

const VideoMediaCard = props => (

    <VideoPlayer
      controls
      src={props.videoPath}
      poster={props.posterPath}
      width="auto"
      height="420"
      className="video-media-player"
    />

);

export default VideoMediaCard;
<commit_msg>Ticket #6839 - fix videojs error<commit_after>import React from 'react';
import VideoPlayer from 'react-video-js-player';
import '../../styles/css/player.css';

const VideoMediaCard = props => (

    <VideoPlayer
      controls
      src={props.videoPath}
      poster={props.posterPath}
      height="420"
      className="video-media-player"
    />

);

export default VideoMediaCard;
<|endoftext|>


<commit_before>import { createSelector } from 'reselect';
import { SiteConf, getDate } from 'base';

export const postsState = state => state.Blog.posts;
export const paginationState = state => state.Blog.pagination;

export const postsSelector = createSelector(
  postsState,
  posts => (
    posts.map(post => {
      let opening;
      if (!post.get('rendered')) {
        const reg = new RegExp(`^(.+?)${ SiteConf.postOpeningSplitChar }`);
        const result = reg.exec(post.get('html'));
        opening = result[1] ? result[1] : post.get('title');
      }
      return post
        .set('html', '')
        .set('rendered', true)
        .set('opening', opening)
        .set('updated_at', getDate(post.get('updated_at')));
    })
  ));<commit_msg>Fix blog selector<commit_after>import { createSelector } from 'reselect';
import { SiteConf, getDate } from 'base';

export const postsState = state => state.Blog.posts;
export const paginationState = state => state.Blog.pagination;

export const postsSelector = createSelector(
  postsState,
  posts => (
    posts.map(post => {
      let opening;
      if (!post.get('rendered')) {
        const reg = new RegExp(`^(.+?)${ SiteConf.postOpeningSplitChar }`);
        const result = reg.exec(post.get('html'));
        opening = result ? result[1] : post.get('title');
      }
      return post
        .set('html', '')
        .set('rendered', true)
        .set('opening', opening)
        .set('updated_at', getDate(post.get('updated_at')));
    })
  ));<|endoftext|>


<commit_before>import { FontAwesomeIcon } from 'substance'
import ModelComponent from '../shared/ModelComponent'
import FormRowComponent from './FormRowComponent'

const REQUIRED_PROPERTIES = {
  'book': {
    'authors': true,
    'title': true
  },
  'chapter': {
    'title': true,
    'containerTitle': true,
    'authors': true,
  },
  'data-publication': {
    'title': true,
    'containerTitle': true,
    'authors': true,
  },
  'magazine-article': {
    'title': true,
    'containerTitle': true,
    'authors': true,
  },
  'newspaper-article': {
    'title': true,
    'containerTitle': true,
    'authors': true,
  },
  '_patent': {
    'title': true,
    'containerTitle': true,
    'inventors': true,
  },
  'journal-article': {
    'title': true,
    'containerTitle': true,
    'authors': true,
  },
  'conference-paper': {
    'title': true,
    'authors': true
  },
  'report': {
    'title': true,
    'authors': true
  },
  'software': {
    'title': true,
    'authors': true
  },
  'thesis': {
    'title': true,
    'authors': true,
    'year': true
  },
  'webpage': {
    'title': true,
    'authors': true,
    'containerTitle': true
  },
  'person': {
    'surname': true,
    'givenNames': true
  },
  'ref-contrib': {
    'name': true,
    'givenNames': true
  },
  'group': {
    'name': true
  },
  'organisation': {
    'name': true
  },
  'award': {
    'institution': true
  },
  'keyword': {
    'name': true
  },
  'subject': {
    'name': true
  },
  'article-record': {
  }
}

export default class EntityEditor extends ModelComponent {
  constructor (...args) {
    super(...args)

    this.handleActions({
      'set-value': this._setValue
    })
  }

  render ($$) {
    const fullMode = this.state.fullMode
    const model = this.props.model
    const api = this.context.api
    // FIXME: compute derived properties when props change, i.e. initially and on willReceiveProps()
    const el = $$('div').addClass('sc-entity-editor').append(
      $$('div').addClass('se-header').html(
        this.context.api.renderEntity(model)
      )
    )

    const propertyStates = this._computePropertyStates()
    const hasWarnings = propertyStates.some(prop => prop.warnings.length > 0)
    const hasHiddenProps = propertyStates.some(prop => prop.hidden)

    const el = $$('div').addClass('sc-entity-editor')
      .addClass(`sm-${model.type}`)
      .append(
        $$('div').addClass('se-entity-header').html(
          api.renderEntity(model)
        )
      )

    if (hasWarnings) el.addClass('sm-warning')

    // [{
    //   property: NodeProperty
    //   warnings: [{message: 'property is required'}],
    //   hidden: false
    // }]
    propertyStates.forEach(propertyState => {
      const property = propertyState.property
      if (propertyState.hidden && !fullMode) return
      const warnings = propertyState.warnings.map(w => w.message)

      const PropertyEditorClass = this._getPropertyEditorClass(property)
      if (PropertyEditorClass) {
        el.append(
          $$(FormRowComponent, {
            label: this.getLabel(property.name),
            warnings: warnings
          }).append(
            $$(PropertyEditorClass, {
              model,
              property,
              warning: warnings.length > 0
            }).ref(property.name)
          )
        )
      }
    })

    const controlEl = $$('div').addClass('se-control')
      .on('click', this._toggleMode)

    if (hasHiddenProps) {
      if (!fullMode) {
        controlEl.append(
          $$(FontAwesomeIcon, { icon: 'fa-chevron-down' }).addClass('se-icon'),
          this.getLabel('show-more-fields')
        )
      } else {
        controlEl.append(
          $$(FontAwesomeIcon, { icon: 'fa-chevron-up' }).addClass('se-icon'),
          this.getLabel('show-less-fields')
        )
      }
    }

    el.append(
      $$('div').addClass('se-footer').append(
        controlEl,
        $$('button').addClass('se-remove-item').append(
          $$(FontAwesomeIcon, { icon: 'fa-trash' }).addClass('se-icon'),
          'Remove'
        ).on('click', this._removeEntity)
      )
    )

    return el
  }

  /*
    Return complete form data
  */
  getData() {
    let result = {}
    let schema = this._getNodeSchema()
    for (let property of schema) {
      const name = property.name
      let input = this.refs[name]
      if (input) {
        result[name] = input.getValue()
      }
    }
    return result
  }

  /*
    Toogle form, by default we are showing only filled and required filds
  */
  _toggleMode() {
    const fullMode = this.state.fullMode
    this.extendState({fullMode: !fullMode})
  }

  /*
    [
      {
        property: NodeProperty
        warnings: [{message: 'property is required'}],
        hidden: false
      }
    ]
  */
  _computePropertyStates() {
    let model = this.props.model
    let schema = model.getSchema()
    let result = []

    for (let property of schema) {
      if (property.name === 'id') continue
      let empty = this._isPropertyEmpty(property)
      let warnings = this._getWarnings(property, empty)
      let hidden = empty && warnings.length === 0

      result.push({
        property,
        warnings,
        hidden
      })
    }
    return result
  }

  _isPropertyEmpty(property) {
    let model = this.props.model
    return model._node[property.name] ? String(model._node[property.name]).length === 0 : true
  }

  _getWarnings(property, empty) {
    let model = this.props.model

    let isRequired = REQUIRED_PROPERTIES[model.type][property.name]
    if (isRequired && empty) {
      return [{ message: `${property.name} is required` }]
    } else {
      return []
    }
  }

  _getPropertyEditorClass(property) {
    let propertyEditors = this.context.configurator.getPropertyEditors()
    let Editor = propertyEditors.find(Editor => {
      return Editor.matches(property)
    })
    return Editor
  }

  _setValue(propName, value) {
    const model = this.props.model
    model.setValue(propName, value)
  }

  _removeEntity() {
    const model = this.props.model
    this.send('remove-item', model)
  }
}
<commit_msg>Fix rebase conflicts.<commit_after>import { FontAwesomeIcon } from 'substance'
import ModelComponent from '../shared/ModelComponent'
import FormRowComponent from './FormRowComponent'

const REQUIRED_PROPERTIES = {
  'book': {
    'authors': true,
    'title': true
  },
  'chapter': {
    'title': true,
    'containerTitle': true,
    'authors': true,
  },
  'data-publication': {
    'title': true,
    'containerTitle': true,
    'authors': true,
  },
  'magazine-article': {
    'title': true,
    'containerTitle': true,
    'authors': true,
  },
  'newspaper-article': {
    'title': true,
    'containerTitle': true,
    'authors': true,
  },
  '_patent': {
    'title': true,
    'containerTitle': true,
    'inventors': true,
  },
  'journal-article': {
    'title': true,
    'containerTitle': true,
    'authors': true,
  },
  'conference-paper': {
    'title': true,
    'authors': true
  },
  'report': {
    'title': true,
    'authors': true
  },
  'software': {
    'title': true,
    'authors': true
  },
  'thesis': {
    'title': true,
    'authors': true,
    'year': true
  },
  'webpage': {
    'title': true,
    'authors': true,
    'containerTitle': true
  },
  'person': {
    'surname': true,
    'givenNames': true
  },
  'ref-contrib': {
    'name': true,
    'givenNames': true
  },
  'group': {
    'name': true
  },
  'organisation': {
    'name': true
  },
  'award': {
    'institution': true
  },
  'keyword': {
    'name': true
  },
  'subject': {
    'name': true
  },
  'article-record': {
  }
}

export default class EntityEditor extends ModelComponent {
  constructor (...args) {
    super(...args)

    this.handleActions({
      'set-value': this._setValue
    })
  }

  render ($$) {
    const fullMode = this.state.fullMode
    const model = this.props.model
    const api = this.context.api
    // FIXME: compute derived properties when props change, i.e. initially and on willReceiveProps()
    const propertyStates = this._computePropertyStates()
    const hasWarnings = propertyStates.some(prop => prop.warnings.length > 0)
    const hasHiddenProps = propertyStates.some(prop => prop.hidden)

    const el = $$('div').addClass('sc-entity-editor')
      .addClass(`sm-${model.type}`)
      .append(
        $$('div').addClass('se-header').html(
          api.renderEntity(model)
        )
      )

    if (hasWarnings) el.addClass('sm-warning')

    // [{
    //   property: NodeProperty
    //   warnings: [{message: 'property is required'}],
    //   hidden: false
    // }]
    propertyStates.forEach(propertyState => {
      const property = propertyState.property
      if (propertyState.hidden && !fullMode) return
      const warnings = propertyState.warnings.map(w => w.message)

      const PropertyEditorClass = this._getPropertyEditorClass(property)
      if (PropertyEditorClass) {
        el.append(
          $$(FormRowComponent, {
            label: this.getLabel(property.name),
            warnings: warnings
          }).append(
            $$(PropertyEditorClass, {
              model,
              property,
              warning: warnings.length > 0
            }).ref(property.name)
          )
        )
      }
    })

    const controlEl = $$('div').addClass('se-control')
      .on('click', this._toggleMode)

    if (hasHiddenProps) {
      if (!fullMode) {
        controlEl.append(
          $$(FontAwesomeIcon, { icon: 'fa-chevron-down' }).addClass('se-icon'),
          this.getLabel('show-more-fields')
        )
      } else {
        controlEl.append(
          $$(FontAwesomeIcon, { icon: 'fa-chevron-up' }).addClass('se-icon'),
          this.getLabel('show-less-fields')
        )
      }
    }

    el.append(
      $$('div').addClass('se-footer').append(
        controlEl,
        $$('button').addClass('se-remove-item').append(
          $$(FontAwesomeIcon, { icon: 'fa-trash' }).addClass('se-icon'),
          'Remove'
        ).on('click', this._removeEntity)
      )
    )

    return el
  }

  /*
    Return complete form data
  */
  getData() {
    let result = {}
    let schema = this._getNodeSchema()
    for (let property of schema) {
      const name = property.name
      let input = this.refs[name]
      if (input) {
        result[name] = input.getValue()
      }
    }
    return result
  }

  /*
    Toogle form, by default we are showing only filled and required filds
  */
  _toggleMode() {
    const fullMode = this.state.fullMode
    this.extendState({fullMode: !fullMode})
  }

  /*
    [
      {
        property: NodeProperty
        warnings: [{message: 'property is required'}],
        hidden: false
      }
    ]
  */
  _computePropertyStates() {
    let model = this.props.model
    let schema = model.getSchema()
    let result = []

    for (let property of schema) {
      if (property.name === 'id') continue
      let empty = this._isPropertyEmpty(property)
      let warnings = this._getWarnings(property, empty)
      let hidden = empty && warnings.length === 0

      result.push({
        property,
        warnings,
        hidden
      })
    }
    return result
  }

  _isPropertyEmpty(property) {
    let model = this.props.model
    return model._node[property.name] ? String(model._node[property.name]).length === 0 : true
  }

  _getWarnings(property, empty) {
    let model = this.props.model

    let isRequired = REQUIRED_PROPERTIES[model.type][property.name]
    if (isRequired && empty) {
      return [{ message: `${property.name} is required` }]
    } else {
      return []
    }
  }

  _getPropertyEditorClass(property) {
    let propertyEditors = this.context.configurator.getPropertyEditors()
    let Editor = propertyEditors.find(Editor => {
      return Editor.matches(property)
    })
    return Editor
  }

  _setValue(propName, value) {
    const model = this.props.model
    model.setValue(propName, value)
  }

  _removeEntity() {
    const model = this.props.model
    this.send('remove-item', model)
  }
}
<|endoftext|>


<commit_before>// DataTable component is beta, over-writing buggy logic on it before they get fixed on YUI

var CHILD_NODES = 'childNodes',
	COLUMNSET = 'columnset',
	DATA = 'data',
	HEADERS = 'headers',
	ID = 'id',

	_HASH = '#',
	_SPACE = ' ';

A.DataTable.Base = A.Base.create('datatable', A.DataTable.Base, [], {
	initializer: function() {
		var instance = this;

		instance.after('render', instance._afterRender);
		instance.after('recordsetChange', instance._afterRecordsetChangeExt);
	},

	getCellNode: function(record, column) {
		var row = A.one(_HASH+record.get(ID));

		return row.get(CHILD_NODES).item(column.keyIndex);
	},

	getColumnByCell: function(cell) {
		var instance = this;
		var dataHeaderId = cell.getAttribute(HEADERS).split(_SPACE).pop() || cell.get(ID);

		return instance.get(COLUMNSET).getColumn(dataHeaderId);
	},

	getColNode: function(cell) {
		var instance = this;
		var index = instance.get(COLUMNSET).getColumnIndex(instance.getColumnByCell(cell));

		return instance._colgroupNode.get(CHILD_NODES).item(index);
	},

	_afterRender: function() {
		var instance = this;

		instance._bindPluginsEvents();
		instance._fixPluginsUI();
	},

	_afterRecordsetChangeExt: function(event) {
		var instance = this;

		instance._fixPluginsUI();
	},

	_bindPluginsEvents: function() {
		var instance = this;
		var sort = instance.sort;

		if (sort) {
			sort.after('lastSortedByChange', A.bind(instance._fixPluginsUI, instance));
		}
	},

	_fixPluginsUI: function() {
		var instance = this;
		var sort = instance.sort;
		var scroll = instance.scroll;

		if (sort && scroll) {
			scroll.syncUI();
		}
	}
}, {});

A.Columnset = A.Base.create('columnset', A.Columnset, [], {
	getColumn: function(i) {
		return this.idHash[i];
	},

	getColumnIndex: function(column) {
		return column.keyIndex;
	},

	_setDefinitions: function(val) {
		return val;
	}
}, {});

A.Recordset = A.Base.create('recordset', A.Recordset, [], {
	getRecordByRow: function(row) {
		var instance = this;

		return instance.getRecord(row.get(ID));
	},

	getRecordIndex: function(record) {
		var instance = this;

		return instance._items.indexOf(record);
	},

	updateRecordDataByKey: function(record, key, value) {
		var instance = this;
		var data = record.get(DATA);

		if (data) {
			data[key] = value;
			record.set(DATA, data);
		}

		instance.update(record, instance.getRecordIndex(record));
	}
}, {});<commit_msg>AUI-413 Source formatting<commit_after>// DataTable component is beta, over-writing buggy logic on it before they get fixed on YUI

var CHILD_NODES = 'childNodes',
	COLUMNSET = 'columnset',
	DATA = 'data',
	HEADERS = 'headers',
	ID = 'id',

	_HASH = '#',
	_SPACE = ' ';

A.DataTable.Base = A.Base.create('datatable', A.DataTable.Base, [], {
	initializer: function() {
		var instance = this;

		instance.after('render', instance._afterRender);
		instance.after('recordsetChange', instance._afterRecordsetChangeExt);
	},

	getCellNode: function(record, column) {
		var row = A.one(_HASH+record.get(ID));

		return row.get(CHILD_NODES).item(column.keyIndex);
	},

	getColumnByCell: function(cell) {
		var instance = this;
		var dataHeaderId = cell.getAttribute(HEADERS).split(_SPACE).pop() || cell.get(ID);

		return instance.get(COLUMNSET).getColumn(dataHeaderId);
	},

	getColNode: function(cell) {
		var instance = this;
		var index = instance.get(COLUMNSET).getColumnIndex(instance.getColumnByCell(cell));

		return instance._colgroupNode.get(CHILD_NODES).item(index);
	},

	_afterRender: function() {
		var instance = this;

		instance._bindPluginsEvents();
		instance._fixPluginsUI();
	},

	_afterRecordsetChangeExt: function(event) {
		var instance = this;

		instance._fixPluginsUI();
	},

	_bindPluginsEvents: function() {
		var instance = this;
		var sort = instance.sort;

		if (sort) {
			sort.after('lastSortedByChange', A.bind(instance._fixPluginsUI, instance));
		}
	},

	_fixPluginsUI: function() {
		var instance = this;
		var sort = instance.sort;
		var scroll = instance.scroll;

		if (sort && scroll) {
			scroll.syncUI();
		}
	}
}, {});

A.Columnset = A.Base.create('columnset', A.Columnset, [], {
	getColumn: function(i) {
		return this.idHash[i];
	},

	getColumnIndex: function(column) {
		return column.keyIndex;
	},

	_setDefinitions: function(val) {
		return val;
	}
}, {});

A.Recordset = A.Base.create('recordset', A.Recordset, [], {
	getRecordByRow: function(row) {
		var instance = this;

		return instance.getRecord(row.get(ID));
	},

	getRecordIndex: function(record) {
		var instance = this;

		return A.Array.indexOf(instance._items, record);
	},

	updateRecordDataByKey: function(record, key, value) {
		var instance = this;
		var data = record.get(DATA);

		if (data) {
			data[key] = value;
			record.set(DATA, data);
		}

		instance.update(record, instance.getRecordIndex(record));
	}
}, {});<|endoftext|>


<commit_before>(function() {
    'use strict';

    angular
        .module('app.layout.topnav')
        .factory('menuhelper', menuhelper);

    /* @ngInject */
    function menuhelper() {

        var allMenus = [];

        var service = {
            configureMenus: configureMenus,
            getAllMenus: getAllMenus,
            setClickHandler: setClickHandler,
            resetClickHandler: resetClickHandler
        };

        return service;
        ///////////////

        /**
         * configure Menus for a workbench component
         * @param  {String} component component which menu is being configured
         *                            (should be the same as title of the title element set in config.route.js
         * @param  {Array} menus      menu description
         */
        function configureMenus(component, menus) {
            allMenus.push({'component':component, 'menus': menus});
        }

        /**
         * get menus for all components
         * @return {Array} array of menus by component
         */
        function getAllMenus() {
            return allMenus;
        }

        /**
         * define click handler for a component menu
         * @param {String} menupath     menu item path,
         *                              in the form (ex: /componentid/menuid/menuitemid)
         * @param {Function} handler    function that will be called whe user click
         *                              on corresponding menu item
         */
        function setClickHandler(menupath, handler) {
            var menuitem = getMenuItem(menupath);
            if (menuitem) {
                if (menuitem.handler) {
                    throw { message: 'click handler already exists for menu item ' + menupath};
                } else {
                  // set handler
                  menuitem.handler = handler;
                }
            } else {
                throw { message: 'couldn\'t find menu item ' + menupath};
            }
        }

        /**
         * reset a click handler
         * @param {String} menupath     menu item path,
         */
        function resetClickHandler(menupath) {
            var menuitem = getMenuItem(menupath);
            if (menuitem && menuitem.handler) {
                delete menuitem.handler;
            } else {
                throw { message: 'couldn\'t find menu item ' + menupath};
            }
        }

        ///////////////
        // private

        /**
         * retrieve a menu item (or null from its menupath)
         * @param  {String} menupath menu item path,
         *                           in the form (ex: /componentid/menuid/menuitemid)
         * @return {Object}          menu item
         */
        function getMenuItem(menupath) {
            var menuitem = null;
            var path = menupath.split('/');
            path.shift();

            // find menu item
            try {
                var component = _.find(allMenus, function(m) { return m.component === path[0]; });
                var menu = _.find(component.menus, function(menu) { return menu.id === path[1]; });
                menuitem = _.find(menu.items, function(item) { return item.id === path[2]; });
            }
            catch(e) {}
            return menuitem;
        }
    }
})();
<commit_msg>jshint jscs<commit_after>(function() {
    'use strict';

    angular
        .module('app.layout.topnav')
        .factory('menuhelper', menuhelper);

    /* @ngInject */
    function menuhelper(_) {

        var allMenus = [];

        var service = {
            configureMenus: configureMenus,
            getAllMenus: getAllMenus,
            setClickHandler: setClickHandler,
            resetClickHandler: resetClickHandler
        };

        return service;
        ///////////////

        /**
         * configure Menus for a workbench component
         * @param  {String} component component which menu is being configured
         *                            (should be the same as title of the title element set in config.route.js
         * @param  {Array} menus      menu description
         */
        function configureMenus(component, menus) {
            allMenus.push({'component':component, 'menus': menus});
        }

        /**
         * get menus for all components
         * @return {Array} array of menus by component
         */
        function getAllMenus() {
            return allMenus;
        }

        /**
         * define click handler for a component menu
         * @param {String} menupath     menu item path,
         *                              in the form (ex: /componentid/menuid/menuitemid)
         * @param {Function} handler    function that will be called whe user click
         *                              on corresponding menu item
         */
        function setClickHandler(menupath, handler) {
            var menuitem = getMenuItem(menupath);
            if (menuitem) {
                if (menuitem.handler) {
                    throw {message: 'click handler already exists for menu item ' + menupath};
                } else {
                    // set handler
                    menuitem.handler = handler;
                }
            } else {
                throw {message: 'couldn\'t find menu item ' + menupath};
            }
        }

        /**
         * reset a click handler
         * @param {String} menupath     menu item path,
         */
        function resetClickHandler(menupath) {
            var menuitem = getMenuItem(menupath);
            if (menuitem && menuitem.handler) {
                delete menuitem.handler;
            } else {
                throw {message: 'couldn\'t find menu item ' + menupath};
            }
        }

        ///////////////
        // private

        /**
         * retrieve a menu item (or null from its menupath)
         * @param  {String} menupath menu item path,
         *                           in the form (ex: /componentid/menuid/menuitemid)
         * @return {Object}          menu item
         */
        function getMenuItem(menupath) {
            var menuitem = null;
            var path = menupath.split('/');
            path.shift();

            // find menu item
            try {
                var component = _.find(allMenus, function(m) { return m.component === path[0]; });
                var menu = _.find(component.menus, function(menu) { return menu.id === path[1]; });
                menuitem = _.find(menu.items, function(item) { return item.id === path[2]; });
            }
            catch (e) {}
            return menuitem;
        }
    }
})();
<|endoftext|>