<commit_before>var path = require('path')
  , vows = require('vows')
  , assert = require('assert')
  , fs = require('fs')
  , client = require('http').createClient(3333, 'localhost')

require.paths.unshift(path.join(path.dirname(__filename), '..'))

// local requires
var sleight = require('lib/sleight')
  , testServer = require('spec/fixtures/server')
  , public = path.join(path.dirname(__filename), 'fixtures', 'static')
  , publicIndex = fs.readFileSync(path.join(public, 'index.html')).toString('utf8')

// starting a test "remote" server
testServer(4444)

sleight.run({
	  public: public
	, port: 3333
	, target: {
		domain: 'localhost'
	  , port: 4444
	}
});

// wrapper to make a simple request
function get(path) {
	return function () {
		var testReq = client.request('GET', path, { host: 'localhost' })
		  , callback = this.callback
		testReq.end()

		testReq.on('response', function (response) {
			response.data = [];
			response.on('data', function (chunk) {
				response.data.push(chunk);
			})
			response.on('end', function () {
				callback(null, response)
			})
		})
	}
}

vows.describe('Sleight').addBatch({
	'get static file': {
		topic: get('/index.html')
		, 'is an ok response': function (response) {
			assert.equal (200, response.statusCode)
		}
		, 'is the correct file': function (response) {
			assert.equal (publicIndex, response.data)
		}
	}
	, 'get remote file': {
		topic: get('/hello')
		, 'is an ok response': function (response) {
			assert.equal (200, response.statusCode)
		}
		, 'is the correct file': function (response) {
			assert.equal ('Hello World!', response.data)
		}
	}
	, '404 transferred': {
		topic: get('/error')
		, 'is a 404 response': function (response) {
			assert.equal (404, response.statusCode)
		}
	}
}).export(module)
<commit_msg>changing param name to avoid ambiguity<commit_after>var path = require('path')
  , vows = require('vows')
  , assert = require('assert')
  , fs = require('fs')
  , client = require('http').createClient(3333, 'localhost')

require.paths.unshift(path.join(path.dirname(__filename), '..'))

// local requires
var sleight = require('lib/sleight')
  , testServer = require('spec/fixtures/server')
  , public = path.join(path.dirname(__filename), 'fixtures', 'static')
  , publicIndex = fs.readFileSync(path.join(public, 'index.html')).toString('utf8')

// starting a test "remote" server
testServer(4444)

sleight.run({
	  public: public
	, port: 3333
	, target: {
		domain: 'localhost'
	  , port: 4444
	}
});

// wrapper to make a simple request
function get(url) {
	return function () {
		var testReq = client.request('GET', url, { host: 'localhost' })
		  , callback = this.callback
		testReq.end()

		testReq.on('response', function (response) {
			response.data = [];
			response.on('data', function (chunk) {
				response.data.push(chunk);
			})
			response.on('end', function () {
				callback(null, response)
			})
		})
	}
}

vows.describe('Sleight').addBatch({
	'get static file': {
		topic: get('/index.html')
		, 'is an ok response': function (response) {
			assert.equal (200, response.statusCode)
		}
		, 'is the correct file': function (response) {
			assert.equal (publicIndex, response.data)
		}
	}
	, 'get remote file': {
		topic: get('/hello')
		, 'is an ok response': function (response) {
			assert.equal (200, response.statusCode)
		}
		, 'is the correct file': function (response) {
			assert.equal ('Hello World!', response.data)
		}
	}
	, '404 transferred': {
		topic: get('/error')
		, 'is a 404 response': function (response) {
			assert.equal (404, response.statusCode)
		}
	}
}).export(module)
<|endoftext|>


<commit_before>/**
 * 需要外部传入的app, 则`module.exports`为function
 */
define(function (require, exports, module) {
    'use strict';

    module.exports = function(app){
    //Step6: use `app.register` to register controller/service/directive/filter
    app.register.controller('mainCtrl', ['$scope', '$routeParams', '$location', '$http',
        function($scope, $routeParams, $location, $http) {
            $scope.main = {};
            $scope.main.inited = true;

            $scope.$watch("session.user", function() {
                if (!$scope.session.user) {
                    return;
                }
                var user = $scope.session.user;
                if (user.hasWexClasses()) { // 管理员/老师身份
                    var wexClass = user.wexClasses[0]
                    $scope.main.noticeUrl = '#/class/' + wexClass.id + '/notice';

                    $scope.main.messageUrl = '#/class/' + wexClass.id + '/message';
                    $scope.main.messageLabel = '班级留言';

                    $scope.main.myPhotoUrl = '#/school/' + user.schoolId + '/teacher/' + user.id + '/photo';

                    $scope.main.leaveUrl = '#/class/' + wexClass.id + '/leave';
                    $scope.main.leaveLabel = '请假考勤';

                    $scope.main.studentUrl = '#/class/' + wexClass.id + '/path';
                    $scope.main.studentLabel = '学生资料';

                    $scope.main.pathUrl = '#/class/' + wexClass.id + '/path';
                } else if (user.hasStudents()) { // 家长身份
                    var student = $scope.session.user.students[0];
                    $scope.main.noticeUrl = '#/class/' + student.classId + '/notice';

                    $scope.main.messageUrl = '#/student/' + student.id + '/message';
                    $scope.main.messageLabel = '我的留言';

                    $scope.main.myPhotoUrl = '#/school/' + user.schoolId + '/parent/' + user.id + '/photo';

                    $scope.main.leaveUrl = '#/student/' + student.id + '/leave';
                    $scope.main.leaveLabel = '我的请假';

                    $scope.main.studentUrl = '#/class/' + student.classId + '/student/' + student.id;
                    $scope.main.studentLabel = '家庭资料';

                    $scope.main.pathUrl = '#/class/' + student.classId + '/student/' + student.id + '/path';
                } else {
                    alert("当前用户数据异常，无法初始化导航页面。");
                    $scope.main.inited = false;
                }
            });
        }]
    );
    }
});<commit_msg>fix error<commit_after>/**
 * 需要外部传入的app, 则`module.exports`为function
 */
define(function (require, exports, module) {
    'use strict';

    module.exports = function(app){
    //Step6: use `app.register` to register controller/service/directive/filter
    app.register.controller('mainCtrl', ['$scope', '$routeParams', '$location', '$http',
        function($scope, $routeParams, $location, $http) {
            $scope.main = {};
            $scope.main.inited = true;

            $scope.$watch("session.user", function() {
                if (!$scope.session.user) {
                    return;
                }
                var user = $scope.session.user;
                if (user.hasWexClasses()) { // 管理员/老师身份
                    var wexClass = user.wexClasses[0]
                    $scope.main.noticeUrl = '#/class/' + wexClass.id + '/notice';

                    $scope.main.messageUrl = '#/class/' + wexClass.id + '/message';
                    $scope.main.messageLabel = '班级留言';

                    $scope.main.myPhotoUrl = '#/school/' + user.schoolId + '/teacher/' + user.id + '/photo';

                    $scope.main.leaveUrl = '#/class/' + wexClass.id + '/leave';
                    $scope.main.leaveLabel = '请假考勤';

                    $scope.main.studentUrl = '#/class/' + wexClass.id + '/student';
                    $scope.main.studentLabel = '学生资料';

                    $scope.main.pathUrl = '#/class/' + wexClass.id + '/path';
                } else if (user.hasStudents()) { // 家长身份
                    var student = $scope.session.user.students[0];
                    $scope.main.noticeUrl = '#/class/' + student.classId + '/notice';

                    $scope.main.messageUrl = '#/student/' + student.id + '/message';
                    $scope.main.messageLabel = '我的留言';

                    $scope.main.myPhotoUrl = '#/school/' + user.schoolId + '/parent/' + user.id + '/photo';

                    $scope.main.leaveUrl = '#/student/' + student.id + '/leave';
                    $scope.main.leaveLabel = '我的请假';

                    $scope.main.studentUrl = '#/class/' + student.classId + '/student/' + student.id;
                    $scope.main.studentLabel = '家庭资料';

                    $scope.main.pathUrl = '#/class/' + student.classId + '/student/' + student.id + '/path';
                } else {
                    alert("当前用户数据异常，无法初始化导航页面。");
                    $scope.main.inited = false;
                }
            });
        }]
    );
    }
});<|endoftext|>


<commit_before>import _ from 'underscore';

import eventStream from 'girder/utilities/EventStream';
import { getCurrentUser } from 'girder/auth';
import Panel from 'girder_plugins/slicer_cli_web/views/Panel';
import AnnotationModel from 'girder_plugins/large_image/models/AnnotationModel';

import events from '../events';
import showSaveAnnotationDialog from '../dialogs/saveAnnotation';

import annotationSelectorWidget from '../templates/panels/annotationSelector.pug';
import '../stylesheets/panels/annotationSelector.styl';

/**
 * Create a panel controlling the visibility of annotations
 * on the image view.
 */
var AnnotationSelector = Panel.extend({
    events: _.extend(Panel.prototype.events, {
        'click .h-annotation-name': 'editAnnotation',
        'click .h-toggle-annotation': 'toggleAnnotation',
        'click .h-delete-annotation': 'deleteAnnotation',
        'click .h-create-annotation': 'createAnnotation',
        'click .h-edit-annotation-metadata': 'editAnnotationMetadata',
        'change #h-toggle-labels': 'toggleLabels'
    }),

    /**
     * Create the panel.
     *
     * @param {object} settings
     * @param {AnnotationCollection} settings.collection
     *     The collection representing the annotations attached
     *     to the current image.
     */
    initialize(settings) {
        this.listenTo(this.collection, 'all', this.render);
        this.listenTo(eventStream, 'g:event.job_status', _.debounce(this._onJobUpdate, 500));
        this.listenTo(eventStream, 'g:eventStream.start', this._refreshAnnotations);
        this.listenTo(this.collection, 'change:annotation', this._saveAnnotation);
    },

    render() {
        this.$('[data-toggle="tooltip"]').tooltip('destroy');
        if (!this.viewer) {
            this.$el.empty();
            return;
        }
        this.$el.html(annotationSelectorWidget({
            annotations: this.collection.sortBy('created'),
            id: 'annotation-panel-container',
            title: 'Annotations',
            activeAnnotation: this._activeAnnotation ? this._activeAnnotation.id : '',
            showLabels: this._showLabels,
            user: getCurrentUser() || {},
            writeAccess: this._writeAccess
        }));
        this.$('.s-panel-content').collapse({toggle: false});
        this.$('[data-toggle="tooltip"]').tooltip({container: 'body'});
        return this;
    },

    /**
     * Set the ItemModel associated with the annotation collection.
     * As a side effect, this resets the AnnotationCollection and
     * fetches annotations from the server associated with the
     * item.
     *
     * @param {ItemModel} item
     */
    setItem(item) {
        if (this._parentId === item.id) {
            return;
        }

        this.parentItem = item;
        this._parentId = item.id;

        if (!this._parentId) {
            this.collection.reset();
            this.render();
            return;
        }
        this.collection.offset = 0;
        this.collection.reset();
        this.collection.fetch({itemId: this._parentId});

        return this;
    },

    /**
     * Set the image "viewer" instance.  This should be a subclass
     * of `large_image/imageViewerWidget` that is capable of rendering
     * annotations.
     */
    setViewer(viewer) {
        this.viewer = viewer;
        return this;
    },

    /**
     * Toggle the renderering of a specific annotation.  Sets the
     * `displayed` attribute of the `AnnotationModel`.
     */
    toggleAnnotation(evt) {
        var id = $(evt.currentTarget).parents('.h-annotation').data('id');
        var model = this.collection.get(id);
        model.set('displayed', !model.get('displayed'));
    },

    /**
     * Delete an annotation from the server.
     */
    deleteAnnotation(evt) {
        const id = $(evt.currentTarget).parents('.h-annotation').data('id');
        const model = this.collection.get(id);

        if (model) {
            const name = (model.get('annotation') || {}).name || 'unnamed annotation';
            events.trigger('h:confirmDialog', {
                title: 'Warning',
                message: `Are you sure you want to delete ${name}?`,
                submitButton: 'Delete',
                onSubmit: () => {
                    this.trigger('h:deleteAnnotation', model);
                    model.unset('displayed');
                    this.collection.remove(model);
                    model.destroy();
                }
            });
        }
    },

    editAnnotationMetadata(evt) {
        const id = $(evt.currentTarget).parents('.h-annotation').data('id');
        const model = this.collection.get(id);
        this.listenToOnce(
            showSaveAnnotationDialog(model, {title: 'Edit annotation'}),
            'g:submit',
            () => model.save()
        );
    },

    _onJobUpdate(evt) {
        if (this.parentItem && evt.data.status > 2) {
            this._refreshAnnotations();
        }
    },

    _refreshAnnotations() {
        if (!this.parentItem) {
            return;
        }
        var models = this.collection.indexBy(_.property('id'));
        this.collection.offset = 0;
        this.collection.fetch({itemId: this.parentItem.id}).then(() => {
            // don't add the active annotation to the list
            var activeAnnotation = this._getActiveAnnotation ? this._getActiveAnnotation() : null;
            if (activeAnnotation) {
                this.collection.remove(activeAnnotation, {silent: true});
            }
            this.collection.each((model) => {
                if (!_.has(models, model.id)) {
                    model.set('displayed', true);
                } else {
                    model.set('displayed', models[model.id].get('displayed'));
                }
            });
            this.render();
            return null;
        });
    },

    toggleLabels(evt) {
        this._showLabels = !this._showLabels;
        this.trigger('h:toggleLabels', {
            show: this._showLabels
        });
    },

    editAnnotation(evt) {
        var id = $(evt.currentTarget).parents('.h-annotation').data('id');
        var model = this.collection.get(id);
        if (!this._writeAccess(model)) {
            events.trigger('g:alert', {
                text: 'You do not have write access to this annotation.',
                type: 'warning',
                timeout: 2500,
                icon: 'info'
            });
            return;
        }
        model.fetch().done(() => {
            model.set('displayed', true);

            // TODO: expose this information publicly
            if (model._pageElements) {
                events.trigger('g:alert', {
                    text: 'This annotation has too many elements to be edited.',
                    type: 'warning',
                    timeout: 5000,
                    icon: 'info'
                });
            } else {
                this.trigger('h:editAnnotation', model);
                this._activeAnnotation = model;
            }
        });
    },

    createAnnotation(evt) {
        var model = new AnnotationModel({
            itemId: this.parentItem.id,
            annotation: {}
        });
        this.listenToOnce(
            showSaveAnnotationDialog(model, {title: 'Create annotation'}),
            'g:submit',
            () => {
                model.save().done(() => {
                    model.set('displayed', true);
                    this.collection.add(model);
                    this.trigger('h:editAnnotation', model);
                    this._activeAnnotation = model;
                });
            }
        );
    },

    _saveAnnotation(annotation) {
        if (!this._saving && annotation === this._activeAnnotation) {
            this._saving = true;
            annotation.save().always(() => {
                this._saving = false;
            });
        }
    },

    _writeAccess(annotation) {
        const user = getCurrentUser();
        if (!user || !annotation) {
            return false;
        }
        const admin = user.get && user.get('admin');
        const creator = user.id === annotation.get('creatorId');
        return admin || creator;
    }
});

export default AnnotationSelector;
<commit_msg>Fix race condition when rapidly changing active annotations<commit_after>import _ from 'underscore';

import eventStream from 'girder/utilities/EventStream';
import { getCurrentUser } from 'girder/auth';
import Panel from 'girder_plugins/slicer_cli_web/views/Panel';
import AnnotationModel from 'girder_plugins/large_image/models/AnnotationModel';

import events from '../events';
import showSaveAnnotationDialog from '../dialogs/saveAnnotation';

import annotationSelectorWidget from '../templates/panels/annotationSelector.pug';
import '../stylesheets/panels/annotationSelector.styl';

/**
 * Create a panel controlling the visibility of annotations
 * on the image view.
 */
var AnnotationSelector = Panel.extend({
    events: _.extend(Panel.prototype.events, {
        'click .h-annotation-name': 'editAnnotation',
        'click .h-toggle-annotation': 'toggleAnnotation',
        'click .h-delete-annotation': 'deleteAnnotation',
        'click .h-create-annotation': 'createAnnotation',
        'click .h-edit-annotation-metadata': 'editAnnotationMetadata',
        'change #h-toggle-labels': 'toggleLabels'
    }),

    /**
     * Create the panel.
     *
     * @param {object} settings
     * @param {AnnotationCollection} settings.collection
     *     The collection representing the annotations attached
     *     to the current image.
     */
    initialize(settings) {
        this.listenTo(this.collection, 'all', this.render);
        this.listenTo(eventStream, 'g:event.job_status', _.debounce(this._onJobUpdate, 500));
        this.listenTo(eventStream, 'g:eventStream.start', this._refreshAnnotations);
        this.listenTo(this.collection, 'change:annotation', this._saveAnnotation);
    },

    render() {
        this.$('[data-toggle="tooltip"]').tooltip('destroy');
        if (!this.viewer) {
            this.$el.empty();
            return;
        }
        this.$el.html(annotationSelectorWidget({
            annotations: this.collection.sortBy('created'),
            id: 'annotation-panel-container',
            title: 'Annotations',
            activeAnnotation: this._activeAnnotation ? this._activeAnnotation.id : '',
            showLabels: this._showLabels,
            user: getCurrentUser() || {},
            writeAccess: this._writeAccess
        }));
        this.$('.s-panel-content').collapse({toggle: false});
        this.$('[data-toggle="tooltip"]').tooltip({container: 'body'});
        return this;
    },

    /**
     * Set the ItemModel associated with the annotation collection.
     * As a side effect, this resets the AnnotationCollection and
     * fetches annotations from the server associated with the
     * item.
     *
     * @param {ItemModel} item
     */
    setItem(item) {
        if (this._parentId === item.id) {
            return;
        }

        this.parentItem = item;
        this._parentId = item.id;

        if (!this._parentId) {
            this.collection.reset();
            this.render();
            return;
        }
        this.collection.offset = 0;
        this.collection.reset();
        this.collection.fetch({itemId: this._parentId});

        return this;
    },

    /**
     * Set the image "viewer" instance.  This should be a subclass
     * of `large_image/imageViewerWidget` that is capable of rendering
     * annotations.
     */
    setViewer(viewer) {
        this.viewer = viewer;
        return this;
    },

    /**
     * Toggle the renderering of a specific annotation.  Sets the
     * `displayed` attribute of the `AnnotationModel`.
     */
    toggleAnnotation(evt) {
        var id = $(evt.currentTarget).parents('.h-annotation').data('id');
        var model = this.collection.get(id);
        model.set('displayed', !model.get('displayed'));
    },

    /**
     * Delete an annotation from the server.
     */
    deleteAnnotation(evt) {
        const id = $(evt.currentTarget).parents('.h-annotation').data('id');
        const model = this.collection.get(id);

        if (model) {
            const name = (model.get('annotation') || {}).name || 'unnamed annotation';
            events.trigger('h:confirmDialog', {
                title: 'Warning',
                message: `Are you sure you want to delete ${name}?`,
                submitButton: 'Delete',
                onSubmit: () => {
                    this.trigger('h:deleteAnnotation', model);
                    model.unset('displayed');
                    this.collection.remove(model);
                    model.destroy();
                }
            });
        }
    },

    editAnnotationMetadata(evt) {
        const id = $(evt.currentTarget).parents('.h-annotation').data('id');
        const model = this.collection.get(id);
        this.listenToOnce(
            showSaveAnnotationDialog(model, {title: 'Edit annotation'}),
            'g:submit',
            () => model.save()
        );
    },

    _onJobUpdate(evt) {
        if (this.parentItem && evt.data.status > 2) {
            this._refreshAnnotations();
        }
    },

    _refreshAnnotations() {
        if (!this.parentItem) {
            return;
        }
        var models = this.collection.indexBy(_.property('id'));
        this.collection.offset = 0;
        this.collection.fetch({itemId: this.parentItem.id}).then(() => {
            // don't add the active annotation to the list
            var activeAnnotation = this._getActiveAnnotation ? this._getActiveAnnotation() : null;
            if (activeAnnotation) {
                this.collection.remove(activeAnnotation, {silent: true});
            }
            this.collection.each((model) => {
                if (!_.has(models, model.id)) {
                    model.set('displayed', true);
                } else {
                    model.set('displayed', models[model.id].get('displayed'));
                }
            });
            this.render();
            return null;
        });
    },

    toggleLabels(evt) {
        this._showLabels = !this._showLabels;
        this.trigger('h:toggleLabels', {
            show: this._showLabels
        });
    },

    editAnnotation(evt) {
        var id = $(evt.currentTarget).parents('.h-annotation').data('id');
        var model = this.collection.get(id);
        if (!this._writeAccess(model)) {
            events.trigger('g:alert', {
                text: 'You do not have write access to this annotation.',
                type: 'warning',
                timeout: 2500,
                icon: 'info'
            });
            return;
        }
        this._activeAnnotation = model;
        model.fetch().done(() => {
            if (this._activeAnnotation && this._activeAnnotation.id !== model.id) {
                return;
            }
            model.set('displayed', true);

            // TODO: expose this information publicly
            if (model._pageElements) {
                events.trigger('g:alert', {
                    text: 'This annotation has too many elements to be edited.',
                    type: 'warning',
                    timeout: 5000,
                    icon: 'info'
                });
            } else {
                this.trigger('h:editAnnotation', model);
            }
        });
    },

    createAnnotation(evt) {
        var model = new AnnotationModel({
            itemId: this.parentItem.id,
            annotation: {}
        });
        this.listenToOnce(
            showSaveAnnotationDialog(model, {title: 'Create annotation'}),
            'g:submit',
            () => {
                model.save().done(() => {
                    model.set('displayed', true);
                    this.collection.add(model);
                    this.trigger('h:editAnnotation', model);
                    this._activeAnnotation = model;
                });
            }
        );
    },

    _saveAnnotation(annotation) {
        if (!this._saving && annotation === this._activeAnnotation) {
            this._saving = true;
            annotation.save().always(() => {
                this._saving = false;
            });
        }
    },

    _writeAccess(annotation) {
        const user = getCurrentUser();
        if (!user || !annotation) {
            return false;
        }
        const admin = user.get && user.get('admin');
        const creator = user.id === annotation.get('creatorId');
        return admin || creator;
    }
});

export default AnnotationSelector;
<|endoftext|>


<commit_before>import _ from 'underscore';

import eventStream from 'girder/utilities/EventStream';
import { getCurrentUser } from 'girder/auth';
import Panel from 'girder_plugins/slicer_cli_web/views/Panel';
import AnnotationModel from 'girder_plugins/large_image/models/AnnotationModel';

import events from '../events';
import showSaveAnnotationDialog from '../dialogs/saveAnnotation';

import annotationSelectorWidget from '../templates/panels/annotationSelector.pug';
import '../stylesheets/panels/annotationSelector.styl';

// Too many elements in the draw panel will crash the browser,
// so we only allow editing of annnotations with less than this
// many elements.
const MAX_ELEMENTS_LIST_LENGTH = 5000;

/**
 * Create a panel controlling the visibility of annotations
 * on the image view.
 */
var AnnotationSelector = Panel.extend({
    events: _.extend(Panel.prototype.events, {
        'click .h-annotation-name': 'editAnnotation',
        'click .h-toggle-annotation': 'toggleAnnotation',
        'click .h-delete-annotation': 'deleteAnnotation',
        'click .h-create-annotation': 'createAnnotation',
        'click .h-edit-annotation-metadata': 'editAnnotationMetadata',
        'click .h-show-all-annotations': 'showAllAnnotations',
        'click .h-hide-all-annotations': 'hideAllAnnotations',
        'mouseenter .h-annotation': '_highlightAnnotation',
        'mouseleave .h-annotation': '_unhighlightAnnotation',
        'change #h-toggle-labels': 'toggleLabels'
    }),

    /**
     * Create the panel.
     *
     * @param {object} settings
     * @param {AnnotationCollection} settings.collection
     *     The collection representing the annotations attached
     *     to the current image.
     */
    initialize(settings) {
        this.listenTo(this.collection, 'sync remove update reset change:displayed change:loading', this.render);
        this.listenTo(this.collection, 'change:highlight', this._changeAnnotationHighlight);
        this.listenTo(eventStream, 'g:event.job_status', _.debounce(this._onJobUpdate, 500));
        this.listenTo(eventStream, 'g:eventStream.start', this._refreshAnnotations);
        this.listenTo(this.collection, 'change:annotation', this._saveAnnotation);
    },

    render() {
        this.$('[data-toggle="tooltip"]').tooltip('destroy');
        if (!this.viewer) {
            this.$el.empty();
            return;
        }
        this.$el.html(annotationSelectorWidget({
            annotations: this.collection.sortBy('created'),
            id: 'annotation-panel-container',
            title: 'Annotations',
            activeAnnotation: this._activeAnnotation ? this._activeAnnotation.id : '',
            showLabels: this._showLabels,
            user: getCurrentUser() || {},
            writeAccess: this._writeAccess
        }));
        this.$('.s-panel-content').collapse({toggle: false});
        this.$('[data-toggle="tooltip"]').tooltip({container: 'body'});
        return this;
    },

    /**
     * Set the ItemModel associated with the annotation collection.
     * As a side effect, this resets the AnnotationCollection and
     * fetches annotations from the server associated with the
     * item.
     *
     * @param {ItemModel} item
     */
    setItem(item) {
        if (this._parentId === item.id) {
            return;
        }

        this.parentItem = item;
        this._parentId = item.id;

        if (!this._parentId) {
            this.collection.reset();
            this.render();
            return;
        }
        this.collection.offset = 0;
        this.collection.reset();
        this.collection.fetch({itemId: this._parentId});

        return this;
    },

    /**
     * Set the image "viewer" instance.  This should be a subclass
     * of `large_image/imageViewerWidget` that is capable of rendering
     * annotations.
     */
    setViewer(viewer) {
        this.viewer = viewer;
        return this;
    },

    /**
     * Toggle the renderering of a specific annotation.  Sets the
     * `displayed` attribute of the `AnnotationModel`.
     */
    toggleAnnotation(evt) {
        var id = $(evt.currentTarget).parents('.h-annotation').data('id');
        var model = this.collection.get(id);
        model.set('displayed', !model.get('displayed'));
        if (model.get('displayed')) {
            model.set('highlight', true);
        } else {
            model.unset('highlight');
        }
    },

    /**
     * Delete an annotation from the server.
     */
    deleteAnnotation(evt) {
        const id = $(evt.currentTarget).parents('.h-annotation').data('id');
        const model = this.collection.get(id);

        if (model) {
            const name = (model.get('annotation') || {}).name || 'unnamed annotation';
            events.trigger('h:confirmDialog', {
                title: 'Warning',
                message: `Are you sure you want to delete ${name}?`,
                submitButton: 'Delete',
                onSubmit: () => {
                    this.trigger('h:deleteAnnotation', model);
                    model.unset('displayed');
                    model.unset('highlight');
                    this.collection.remove(model);
                    model.destroy();
                }
            });
        }
    },

    editAnnotationMetadata(evt) {
        const id = $(evt.currentTarget).parents('.h-annotation').data('id');
        const model = this.collection.get(id);
        this.listenToOnce(
            showSaveAnnotationDialog(model, {title: 'Edit annotation'}),
            'g:submit',
            () => model.save()
        );
    },

    _onJobUpdate(evt) {
        if (this.parentItem && evt.data.status > 2) {
            this._refreshAnnotations();
        }
    },

    _refreshAnnotations() {
        if (!this.parentItem || !this.parentItem.id) {
            return;
        }
        var models = this.collection.indexBy(_.property('id'));
        this.collection.offset = 0;
        this.collection.fetch({itemId: this.parentItem.id}).then(() => {
            this.collection.each((model) => {
                if (!_.has(models, model.id)) {
                    model.set('displayed', true);
                } else {
                    model.set('displayed', models[model.id].get('displayed'));
                }
            });
            this.render();
            return null;
        });
    },

    toggleLabels(evt) {
        this._showLabels = !this._showLabels;
        this.trigger('h:toggleLabels', {
            show: this._showLabels
        });
    },

    editAnnotation(evt) {
        var id = $(evt.currentTarget).parents('.h-annotation').data('id');
        var model = this.collection.get(id);

        // deselect the annotation if it is already selected
        if (this._activeAnnotation && model && this._activeAnnotation.id === model.id) {
            this._activeAnnotation = null;
            this.trigger('h:editAnnotation', null);
            this.render();
            return;
        }

        if (!this._writeAccess(model)) {
            events.trigger('g:alert', {
                text: 'You do not have write access to this annotation.',
                type: 'warning',
                timeout: 2500,
                icon: 'info'
            });
            return;
        }
        this._activeAnnotation = model;
        model.set('loading', true);
        model.fetch().done(() => {
            const numElements = ((model.get('annotation') || {}).elements || []).length;
            if (this._activeAnnotation && this._activeAnnotation.id !== model.id) {
                return;
            }
            model.set('displayed', true);

            if (numElements > MAX_ELEMENTS_LIST_LENGTH) {
                events.trigger('g:alert', {
                    text: 'This annotation has too many elements to be edited.',
                    type: 'warning',
                    timeout: 5000,
                    icon: 'info'
                });
                this._activeAnnotation = null;
                this.trigger('h:editAnnotation', null);
            } else {
                this.trigger('h:editAnnotation', model);
            }
        }).always(() => {
            model.unset('loading');
        });
    },

    createAnnotation(evt) {
        var model = new AnnotationModel({
            itemId: this.parentItem.id,
            annotation: {}
        });
        this.listenToOnce(
            showSaveAnnotationDialog(model, {title: 'Create annotation'}),
            'g:submit',
            () => {
                model.save().done(() => {
                    model.set('displayed', true);
                    this.collection.add(model);
                    this.trigger('h:editAnnotation', model);
                    this._activeAnnotation = model;
                });
            }
        );
    },

    _saveAnnotation(annotation) {
        if (!this._saving && annotation === this._activeAnnotation) {
            this._saving = true;
            annotation.save().always(() => {
                this._saving = false;
            });
        }
    },

    _writeAccess(annotation) {
        const user = getCurrentUser();
        if (!user || !annotation) {
            return false;
        }
        const admin = user.get && user.get('admin');
        const creator = user.id === annotation.get('creatorId');
        return admin || creator;
    },

    showAllAnnotations() {
        this.collection.each((model) => {
            model.set('displayed', true);
        });
    },

    hideAllAnnotations() {
        this.collection.each((model) => {
            model.set('displayed', false);
        });
    },

    _highlightAnnotation(evt) {
        const id = $(evt.currentTarget).data('id');
        const model = this.collection.get(id);
        if (model.get('displayed')) {
            this.parentView.trigger('h:highlightAnnotation', id);
        }
    },

    _unhighlightAnnotation() {
        this.parentView.trigger('h:highlightAnnotation');
    },

    _changeAnnotationHighlight(model) {
        this.$(`.h-annotation[data-id="${model.id}"]`).toggleClass('h-highlight-annotation', model.get('highlighted'));
    }
});

export default AnnotationSelector;
<commit_msg>Don't highlight annotation when toggling it on<commit_after>import _ from 'underscore';

import eventStream from 'girder/utilities/EventStream';
import { getCurrentUser } from 'girder/auth';
import Panel from 'girder_plugins/slicer_cli_web/views/Panel';
import AnnotationModel from 'girder_plugins/large_image/models/AnnotationModel';

import events from '../events';
import showSaveAnnotationDialog from '../dialogs/saveAnnotation';

import annotationSelectorWidget from '../templates/panels/annotationSelector.pug';
import '../stylesheets/panels/annotationSelector.styl';

// Too many elements in the draw panel will crash the browser,
// so we only allow editing of annnotations with less than this
// many elements.
const MAX_ELEMENTS_LIST_LENGTH = 5000;

/**
 * Create a panel controlling the visibility of annotations
 * on the image view.
 */
var AnnotationSelector = Panel.extend({
    events: _.extend(Panel.prototype.events, {
        'click .h-annotation-name': 'editAnnotation',
        'click .h-toggle-annotation': 'toggleAnnotation',
        'click .h-delete-annotation': 'deleteAnnotation',
        'click .h-create-annotation': 'createAnnotation',
        'click .h-edit-annotation-metadata': 'editAnnotationMetadata',
        'click .h-show-all-annotations': 'showAllAnnotations',
        'click .h-hide-all-annotations': 'hideAllAnnotations',
        'mouseenter .h-annotation': '_highlightAnnotation',
        'mouseleave .h-annotation': '_unhighlightAnnotation',
        'change #h-toggle-labels': 'toggleLabels'
    }),

    /**
     * Create the panel.
     *
     * @param {object} settings
     * @param {AnnotationCollection} settings.collection
     *     The collection representing the annotations attached
     *     to the current image.
     */
    initialize(settings) {
        this.listenTo(this.collection, 'sync remove update reset change:displayed change:loading', this.render);
        this.listenTo(this.collection, 'change:highlight', this._changeAnnotationHighlight);
        this.listenTo(eventStream, 'g:event.job_status', _.debounce(this._onJobUpdate, 500));
        this.listenTo(eventStream, 'g:eventStream.start', this._refreshAnnotations);
        this.listenTo(this.collection, 'change:annotation', this._saveAnnotation);
    },

    render() {
        this.$('[data-toggle="tooltip"]').tooltip('destroy');
        if (!this.viewer) {
            this.$el.empty();
            return;
        }
        this.$el.html(annotationSelectorWidget({
            annotations: this.collection.sortBy('created'),
            id: 'annotation-panel-container',
            title: 'Annotations',
            activeAnnotation: this._activeAnnotation ? this._activeAnnotation.id : '',
            showLabels: this._showLabels,
            user: getCurrentUser() || {},
            writeAccess: this._writeAccess
        }));
        this.$('.s-panel-content').collapse({toggle: false});
        this.$('[data-toggle="tooltip"]').tooltip({container: 'body'});
        return this;
    },

    /**
     * Set the ItemModel associated with the annotation collection.
     * As a side effect, this resets the AnnotationCollection and
     * fetches annotations from the server associated with the
     * item.
     *
     * @param {ItemModel} item
     */
    setItem(item) {
        if (this._parentId === item.id) {
            return;
        }

        this.parentItem = item;
        this._parentId = item.id;

        if (!this._parentId) {
            this.collection.reset();
            this.render();
            return;
        }
        this.collection.offset = 0;
        this.collection.reset();
        this.collection.fetch({itemId: this._parentId});

        return this;
    },

    /**
     * Set the image "viewer" instance.  This should be a subclass
     * of `large_image/imageViewerWidget` that is capable of rendering
     * annotations.
     */
    setViewer(viewer) {
        this.viewer = viewer;
        return this;
    },

    /**
     * Toggle the renderering of a specific annotation.  Sets the
     * `displayed` attribute of the `AnnotationModel`.
     */
    toggleAnnotation(evt) {
        var id = $(evt.currentTarget).parents('.h-annotation').data('id');
        var model = this.collection.get(id);
        model.set('displayed', !model.get('displayed'));
        if (!model.get('displayed')) {
            model.unset('highlight');
        }
    },

    /**
     * Delete an annotation from the server.
     */
    deleteAnnotation(evt) {
        const id = $(evt.currentTarget).parents('.h-annotation').data('id');
        const model = this.collection.get(id);

        if (model) {
            const name = (model.get('annotation') || {}).name || 'unnamed annotation';
            events.trigger('h:confirmDialog', {
                title: 'Warning',
                message: `Are you sure you want to delete ${name}?`,
                submitButton: 'Delete',
                onSubmit: () => {
                    this.trigger('h:deleteAnnotation', model);
                    model.unset('displayed');
                    model.unset('highlight');
                    this.collection.remove(model);
                    model.destroy();
                }
            });
        }
    },

    editAnnotationMetadata(evt) {
        const id = $(evt.currentTarget).parents('.h-annotation').data('id');
        const model = this.collection.get(id);
        this.listenToOnce(
            showSaveAnnotationDialog(model, {title: 'Edit annotation'}),
            'g:submit',
            () => model.save()
        );
    },

    _onJobUpdate(evt) {
        if (this.parentItem && evt.data.status > 2) {
            this._refreshAnnotations();
        }
    },

    _refreshAnnotations() {
        if (!this.parentItem || !this.parentItem.id) {
            return;
        }
        var models = this.collection.indexBy(_.property('id'));
        this.collection.offset = 0;
        this.collection.fetch({itemId: this.parentItem.id}).then(() => {
            this.collection.each((model) => {
                if (!_.has(models, model.id)) {
                    model.set('displayed', true);
                } else {
                    model.set('displayed', models[model.id].get('displayed'));
                }
            });
            this.render();
            return null;
        });
    },

    toggleLabels(evt) {
        this._showLabels = !this._showLabels;
        this.trigger('h:toggleLabels', {
            show: this._showLabels
        });
    },

    editAnnotation(evt) {
        var id = $(evt.currentTarget).parents('.h-annotation').data('id');
        var model = this.collection.get(id);

        // deselect the annotation if it is already selected
        if (this._activeAnnotation && model && this._activeAnnotation.id === model.id) {
            this._activeAnnotation = null;
            this.trigger('h:editAnnotation', null);
            this.render();
            return;
        }

        if (!this._writeAccess(model)) {
            events.trigger('g:alert', {
                text: 'You do not have write access to this annotation.',
                type: 'warning',
                timeout: 2500,
                icon: 'info'
            });
            return;
        }
        this._activeAnnotation = model;
        model.set('loading', true);
        model.fetch().done(() => {
            const numElements = ((model.get('annotation') || {}).elements || []).length;
            if (this._activeAnnotation && this._activeAnnotation.id !== model.id) {
                return;
            }
            model.set('displayed', true);

            if (numElements > MAX_ELEMENTS_LIST_LENGTH) {
                events.trigger('g:alert', {
                    text: 'This annotation has too many elements to be edited.',
                    type: 'warning',
                    timeout: 5000,
                    icon: 'info'
                });
                this._activeAnnotation = null;
                this.trigger('h:editAnnotation', null);
            } else {
                this.trigger('h:editAnnotation', model);
            }
        }).always(() => {
            model.unset('loading');
        });
    },

    createAnnotation(evt) {
        var model = new AnnotationModel({
            itemId: this.parentItem.id,
            annotation: {}
        });
        this.listenToOnce(
            showSaveAnnotationDialog(model, {title: 'Create annotation'}),
            'g:submit',
            () => {
                model.save().done(() => {
                    model.set('displayed', true);
                    this.collection.add(model);
                    this.trigger('h:editAnnotation', model);
                    this._activeAnnotation = model;
                });
            }
        );
    },

    _saveAnnotation(annotation) {
        if (!this._saving && annotation === this._activeAnnotation) {
            this._saving = true;
            annotation.save().always(() => {
                this._saving = false;
            });
        }
    },

    _writeAccess(annotation) {
        const user = getCurrentUser();
        if (!user || !annotation) {
            return false;
        }
        const admin = user.get && user.get('admin');
        const creator = user.id === annotation.get('creatorId');
        return admin || creator;
    },

    showAllAnnotations() {
        this.collection.each((model) => {
            model.set('displayed', true);
        });
    },

    hideAllAnnotations() {
        this.collection.each((model) => {
            model.set('displayed', false);
        });
    },

    _highlightAnnotation(evt) {
        const id = $(evt.currentTarget).data('id');
        const model = this.collection.get(id);
        if (model.get('displayed')) {
            this.parentView.trigger('h:highlightAnnotation', id);
        }
    },

    _unhighlightAnnotation() {
        this.parentView.trigger('h:highlightAnnotation');
    },

    _changeAnnotationHighlight(model) {
        this.$(`.h-annotation[data-id="${model.id}"]`).toggleClass('h-highlight-annotation', model.get('highlighted'));
    }
});

export default AnnotationSelector;
<|endoftext|>


<commit_before>/*jslint browser:true*/
/*global window*/
/**
 * This file contains javascript functions for buttons, etc on the map page
 * Created on 11/30/16.
 */

/**
 * Function to change page based on left or right arrow button click from the simulation menu
 * NOTE: all_sim_with_model_list is ORDERED from most recent to least recent. Thus, the most recent
 * simulation will have index 0 and the oldest simulation will have index length-1.
 *
 * @param all_sim_with_model_list: List of all simulations that have the chosen model
 * @param current_sim_index: Index of the currently selected simulation
 * @param prev_or_next: Indicator whether the left (previous, or 0) button was clicked or the
 *        right (next, or 1) button was clicked
 */
function prevNextSimBtnClick(all_sim_with_model_list, current_sim_index, prev_or_next) {
    "use strict";
    var segments = window.location.pathname.toString().split("/");
    // the previous button was clicked, want to go back in time
    if (prev_or_next === 0) {
        // if the current simulation index is not the oldest in the list, increase index
        if (current_sim_index !== (all_sim_with_model_list.length - 1)) {
            segments[segments.length - 2] = all_sim_with_model_list[current_sim_index + 1].id;
        } else {
            window.alert("You are looking at the oldest simulation");
        }
    } else if (prev_or_next === 1) {  // next button was clicked, want to go forward in time
        // if the current simulation index is not the most recent in the list, decrease index
        if (current_sim_index !== 0) {
            segments[segments.length - 2] = all_sim_with_model_list[current_sim_index - 1].id;
        } else {
            window.alert("You are looking at the most recent simulation");
        }
    } else {
        window.alert("Error changing simulations. Please try again.");
    }
    window.location = segments.join("/");
}

// function prevNextDateBtnClick(new_date) {
//     "use strict";
//     // If we already have a date, we want to replace that date with the previous date in the list
//     if (window.location.pathname.match("(/(1|2)[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])/$)")){
//         var basePath = window.location.pathname.toString();
//         var segments = basePath.split("/");
//         segments[segments.length - 2] = "" + new_date;
//         var newUrl = segments.join("/");
//         window.location = newUrl;
//     }
//     // else {
//     //     window.location = prev + '/';
//     // }
// }

<commit_msg>retain municipality code on button click<commit_after>/*jslint browser:true*/
/*global window*/
/**
 * This file contains javascript functions for buttons, etc on the map page
 * Created on 11/30/16.
 */

/**
 * Function to change page based on left or right arrow button click from the simulation menu
 * NOTE: all_sim_with_model_list is ORDERED from most recent to least recent. Thus, the most recent
 * simulation will have index 0 and the oldest simulation will have index length-1.
 *
 * @param all_sim_with_model_list: List of all simulations that have the chosen model
 * @param current_sim_index: Index of the currently selected simulation
 * @param prev_or_next: Indicator whether the left (previous, or 0) button was clicked or the
 *        right (next, or 1) button was clicked
 */
function prevNextSimBtnClick(all_sim_with_model_list, current_sim_index, prev_or_next) {
    "use strict";
    var segments = window.location.pathname.toString().split("/");
    // We only want to change the simulation id when the button is clicked.
    // if there are 6 segments, then no municipality code is included. If there are 7 segments
    // then the municipality code is in the url.
    var replace_index = null;
    if (segments.length === 6) {
        replace_index = segments.length - 2;
    } else if (segments.length === 7) {
        replace_index = segments.length - 3;
    }
    // the previous button was clicked, want to go back in time
    if (prev_or_next === 0) {
        // if the current simulation index is not the oldest in the list, increase index
        if (current_sim_index !== (all_sim_with_model_list.length - 1)) {
            segments[replace_index] = all_sim_with_model_list[current_sim_index + 1].id;
        } else {
            window.alert("You are looking at the oldest simulation");
        }
    } else if (prev_or_next === 1) {  // next button was clicked, want to go forward in time
        // if the current simulation index is not the most recent in the list, decrease index
        if (current_sim_index !== 0) {
            segments[replace_index] = all_sim_with_model_list[current_sim_index - 1].id;
        } else {
            window.alert("You are looking at the most recent simulation");
        }
    } else {
        window.alert("Error changing simulations. Please try again.");
    }
    window.location = segments.join("/");
}

// function prevNextDateBtnClick(new_date) {
//     "use strict";
//     // If we already have a date, we want to replace that date with the previous date in the list
//     if (window.location.pathname.match("(/(1|2)[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])/$)")){
//         var basePath = window.location.pathname.toString();
//         var segments = basePath.split("/");
//         segments[segments.length - 2] = "" + new_date;
//         var newUrl = segments.join("/");
//         window.location = newUrl;
//     }
//     // else {
//     //     window.location = prev + '/';
//     // }
// }

<|endoftext|>


<commit_before>import React from 'react';
import cx from 'classnames';
import { VelocityComponent, VelocityTransitionGroup } from 'velocity-react';

const STATIC_SITE_SVG = (
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 26 26">
    <path d="M 25.15625 0.1875 C 23.885328 0.2454375 20.96425 0.5555 18.0625 2 C 16.8205 2.62 15.58275 3.4505 14.46875 4.5625 C 12.648519 6.3827313 10.066928 9.4736107 7.90625 12.125 L 3.6875 12.0625 C 3.5455 12.0325 3.36325 12.0865 3.28125 12.1875 L 0.90625 15.21875 C 0.82525 15.31675 0.88925 15.43775 1.03125 15.46875 L 4.65625 16.25 C 4.651574 16.342561 4.691676 16.488906 4.78125 16.75 L 4.09375 18.25 C 4.09375 18.25 3.80625 18.74475 5.53125 20.46875 C 7.25525 22.19275 7.75 21.90625 7.75 21.90625 L 9.28125 21.21875 C 9.5673018 21.312365 9.7068625 21.321578 9.78125 21.3125 L 10.5625 25 C 10.5895 25.141 10.7145 25.207 10.8125 25.125 L 13.84375 22.75 C 13.94475 22.67 13.99975 22.48575 13.96875 22.34375 L 13.90625 18.03125 C 16.571535 15.855539 19.672077 13.296113 21.4375 11.53125 C 22.5455 10.42125 23.38 9.1815 24 7.9375 C 25.919 4.0755 25.8125 0.1875 25.8125 0.1875 C 25.8125 0.1875 25.579891 0.1681875 25.15625 0.1875 z M 18 5.9375 C 19.131 5.9375 20.0625 6.869 20.0625 8 C 20.0625 9.131 19.131 10.0625 18 10.0625 C 16.869 10.0625 15.9375 9.131 15.9375 8 C 15.9375 6.869 16.869 5.9375 18 5.9375 z M 2.84375 18.8125 C 2.60375 19.0145 2.357 19.2055 2.125 19.4375 C -0.204 21.7675 0.125 25.875 0.125 25.875 C 0.125 25.875 4.2335 26.205 6.5625 23.875 C 6.7935 23.644 6.9865 23.39525 7.1875 23.15625 C 7.0475 23.08225 6.89075 22.989 6.71875 22.875 C 4.75875 24.378 1.84375 24.15625 1.84375 24.15625 C 1.84375 24.15625 1.622 21.23925 3.125 19.28125 C 3.01 19.10825 2.91775 18.9535 2.84375 18.8125 z"></path>
  </svg>
);

class StaticSiteGenerator extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  render() {
    const props = this.props;
    const state = this.state;

    let description;

    switch (props.staticSiteGenerator) {
      case 'jekyll':
        description = (

            Jekyll — Simple, blog-aware, static site generator. The engine behind GitHub Pages.

        );
        break;
      case 'middleman':
        description = (

            Middleman — A static site generator using all the shortcuts and tools in modern web development.

        );
        break;
      default:
        description =

;
    }

    let note;

    if (props.staticSiteGenerator) {
      note = (

          Note:
          Requires Ruby 2.0.0 or higher.

      );
    } else {
      note =

;
    }

    const validationError = props.staticSiteGeneratorValidationError ? (

 {props.staticSiteGeneratorValidationError}

    ) : null;

    if (props.staticSiteGeneratorValidationError) {
      if (props.disableAutoScroll) {
        $(this.refs.staticSiteGenerator).velocity('scroll', { duration: 0 });
      } else {
        $(this.refs.staticSiteGenerator).velocity('scroll');
      }
    }

    return (

{STATIC_SITE_SVG}{props.staticSiteGenerator || 'Static Site Generator'}

          {description}

              <input type="radio" id="jekyllRadio" name="staticSiteGeneratorRadios" value="jekyll" onChange={props.handleChange} checked={props.staticSiteGenerator === 'jekyll'}/>
              Jekyll

              <input type="radio" id="middlemanRadio" name="staticSiteGeneratorRadios" value="middleman" onChange={props.handleChange} checked={props.staticSiteGenerator === 'middleman'}/>
              Middleman

          {note}
          {validationError}

    );
  }
}

export default StaticSiteGenerator;
<commit_msg>Theme attribution for jekyll<commit_after>import React from 'react';
import cx from 'classnames';

const STATIC_SITE_SVG = (
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 26 26">
    <path d="M 25.15625 0.1875 C 23.885328 0.2454375 20.96425 0.5555 18.0625 2 C 16.8205 2.62 15.58275 3.4505 14.46875 4.5625 C 12.648519 6.3827313 10.066928 9.4736107 7.90625 12.125 L 3.6875 12.0625 C 3.5455 12.0325 3.36325 12.0865 3.28125 12.1875 L 0.90625 15.21875 C 0.82525 15.31675 0.88925 15.43775 1.03125 15.46875 L 4.65625 16.25 C 4.651574 16.342561 4.691676 16.488906 4.78125 16.75 L 4.09375 18.25 C 4.09375 18.25 3.80625 18.74475 5.53125 20.46875 C 7.25525 22.19275 7.75 21.90625 7.75 21.90625 L 9.28125 21.21875 C 9.5673018 21.312365 9.7068625 21.321578 9.78125 21.3125 L 10.5625 25 C 10.5895 25.141 10.7145 25.207 10.8125 25.125 L 13.84375 22.75 C 13.94475 22.67 13.99975 22.48575 13.96875 22.34375 L 13.90625 18.03125 C 16.571535 15.855539 19.672077 13.296113 21.4375 11.53125 C 22.5455 10.42125 23.38 9.1815 24 7.9375 C 25.919 4.0755 25.8125 0.1875 25.8125 0.1875 C 25.8125 0.1875 25.579891 0.1681875 25.15625 0.1875 z M 18 5.9375 C 19.131 5.9375 20.0625 6.869 20.0625 8 C 20.0625 9.131 19.131 10.0625 18 10.0625 C 16.869 10.0625 15.9375 9.131 15.9375 8 C 15.9375 6.869 16.869 5.9375 18 5.9375 z M 2.84375 18.8125 C 2.60375 19.0145 2.357 19.2055 2.125 19.4375 C -0.204 21.7675 0.125 25.875 0.125 25.875 C 0.125 25.875 4.2335 26.205 6.5625 23.875 C 6.7935 23.644 6.9865 23.39525 7.1875 23.15625 C 7.0475 23.08225 6.89075 22.989 6.71875 22.875 C 4.75875 24.378 1.84375 24.15625 1.84375 24.15625 C 1.84375 24.15625 1.622 21.23925 3.125 19.28125 C 3.01 19.10825 2.91775 18.9535 2.84375 18.8125 z"></path>
  </svg>
);

class StaticSiteGenerator extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  render() {
    const props = this.props;

    let description;

    switch (props.staticSiteGenerator) {
      case 'jekyll':
        description = (

            Jekyll — Simple, blog-aware, static site generator. The engine behind GitHub Pages. (Theme by @vormwald)

        );
        break;
      case 'middleman':
        description = (

            Middleman — A static site generator using all the shortcuts and tools in modern web development.

        );
        break;
      default:
        description =

;
    }

    let note;

    if (props.staticSiteGenerator) {
      note = (

          Note:
          Requires Ruby 2.0.0 or higher.

      );
    } else {
      note =

;
    }

    const validationError = props.staticSiteGeneratorValidationError ? (

 {props.staticSiteGeneratorValidationError}

    ) : null;

    if (props.staticSiteGeneratorValidationError) {
      if (props.disableAutoScroll) {
        $(this.refs.staticSiteGenerator).velocity('scroll', { duration: 0 });
      } else {
        $(this.refs.staticSiteGenerator).velocity('scroll');
      }
    }

    return (

{STATIC_SITE_SVG}{props.staticSiteGenerator || 'Static Site Generator'}

          {description}

              <input type="radio" id="jekyllRadio" name="staticSiteGeneratorRadios" value="jekyll" onChange={props.handleChange} checked={props.staticSiteGenerator === 'jekyll'}/>
              Jekyll

              <input type="radio" id="middlemanRadio" name="staticSiteGeneratorRadios" value="middleman" onChange={props.handleChange} checked={props.staticSiteGenerator === 'middleman'}/>
              Middleman

          {note}
          {validationError}

    );
  }
}

export default StaticSiteGenerator;
<|endoftext|>


<commit_before>var m = require('mithril');
var $ = require('jquery');
var $osf = require('js/osfHelpers');
var waterbutler = require('js/waterbutler');

var util = require('./util.js');

// Helper for filtering
function TRUTHY(item) {
    return !!item; //Force cast to a bool
}

var model = {
    revisions: [],
    loaded: m.prop(false),
    errorMessage: undefined,
    hasUser: false,
    hasDate: false,
    selectedRevision: 0
};

var FileRevisionsTable = {
    controller: function(file, node, enableEditing, canEdit) {
        var self = {};
        self.node = node;
        self.file = file;
        self.canEdit = canEdit;
        self.enableEditing = enableEditing;
        self.baseUrl = (window.location.href).split('?')[0];

        model.hasDate = self.file.provider !== 'dataverse';

        self.reload = function() {
            model.loaded(false);
            m.redraw();
            $.ajax({
                dataType: 'json',
                async: true,
                url: self.file.urls.revisions,
                beforeSend: $osf.setXHRAuthorization
            }).done(function(response) {
                m.startComputation();
                var urlParmas = $osf.urlParams();
                model.revisions = response.data.map(function(rev, index) {
                    rev = FileRevisionsTable.postProcessRevision(self.file, self.node, rev, index);
                    if (urlParmas[rev.versionIdentifier] === rev.version) {
                        model.selectedRevision = index;
                    }
                    return rev;
                });
                model.loaded(true);
                // Can only edit the latest version of a file
                if (model.selectedRevision === 0) {
                    self.enableEditing();
                }
                model.hasUser = model.revisions[0] && model.revisions[0].extra && model.revisions[0].extra.user;
                m.endComputation();
            }).fail(function(response) {
                m.startComputation();
                model.loaded(true);
                model.errorMessage = response.responseJSON ?
                    response.responseJSON.message || 'Unable to fetch versions' :
                    'Unable to fetch versions';
                m.endComputation();

                // model.errorMessage(err);

                if (self.file.provider === 'figshare') {
                    // Hack for Figshare
                    // only figshare will error on a revisions request
                    // so dont allow downloads and set a fake current version
                    $.ajax({
                        method: 'GET',
                        url: self.file.urls.metadata,
                        beforeSend: $osf.setXHRAuthorization
                    }).done(function(resp) {
                        self.canEdit(self.canEdit() && resp.data.extra.canDelete);
                        m.redraw();
                    }).fail(function(xhr) {
                        self.canEdit(false);
                        m.redraw();
                    });
                }
            });
        };

        self.getTableHead = function() {
            return m('thead', [
                m('tr', [
                    m('th', 'Version ID'),
                    model.hasDate ? m('th', 'Date') : false,
                    model.hasUser ? m('th', 'User') : false,
                    m('th[colspan=2]', 'Download'),
                ].filter(TRUTHY))
            ]);
        };

        self.makeTableRow = function(revision, index) {
            var isSelected = index === model.selectedRevision;

            return m('tr' + (isSelected ? '.active' : ''), [
                m('td',  isSelected ? revision.displayVersion :
                  m('a', {href: parseInt(revision.displayVersion) === model.revisions.length ? self.baseUrl : revision.osfViewUrl}, revision.displayVersion)
                ),
                model.hasDate ? m('td', revision.displayDate) : false,
                model.hasUser ?
                    m('td', revision.extra.user.url ?
                            m('a', {href: revision.extra.user.url}, revision.extra.user.name) :
                            revision.extra.user.name
                    ) : false,
                m('td', revision.extra.downloads > -1 ? m('.badge', revision.extra.downloads) : ''),
                m('td',
                    m('a.btn.btn-primary.btn-sm.file-download', {
                        href: revision.osfDownloadUrl,
                        onclick: function() {
                            window.location = revision.waterbutlerDownloadUrl;
                            return false;
                        }
                    }, m('i.fa.fa-download'))
                ),
            ].filter(TRUTHY));
        };

        if (!model.loaded()) {
            self.reload();
        }
        $(document).on('fileviewpage:reload', self.reload);
        return self;
    },
    view: function(ctrl) {
        return m('#revisionsPanel.panel.panel-default', [
                m('.panel-heading.clearfix', m('h3.panel-title', 'Revisions')),
                m('.panel-body', {style:{'padding-right': '0px','padding-left':'0px'}}, (function() {
                    if (!model.loaded()) {
                        return util.Spinner;
                    }
                    if (model.errorMessage) {
                        return m('.alert.alert-warning', {style:{margin: '10px'}}, model.errorMessage);
                    }

                    return m('table.table', [
                        ctrl.getTableHead(),
                        m('tbody', model.revisions.map(ctrl.makeTableRow))
                    ]);
                })())
            ]);
    },
    postProcessRevision: function(file, node, revision, index) {
        var options = {};
        var urlParams = $osf.urlParams();

        if (urlParams.branch !== undefined) {
            options.branch = urlParams.branch;
        }
        options[revision.versionIdentifier] = revision.version;

        revision.date = new $osf.FormattableDate(revision.modified);
        revision.displayDate = revision.date.local !== 'Invalid date' ?
            revision.date.local :
            revision.date;

        switch (file.provider) {
            // Note: Google Drive version identifiers often begin with the same sequence
            case 'googledrive':
                revision.displayVersion = revision.version.substring(revision.version.length - 8);
                break;
            // Note: Dataverse internal version names are ugly; Substitute our own
            case 'dataverse':
                var displayMap = {
                    'latest': 'Draft',
                    'latest-published': 'Published'
                };

                revision.displayVersion = revision.version in displayMap ?
                    displayMap[revision.version] : revision.version.substring(0, 8);
                break;
            default:
                revision.displayVersion = revision.version.substring(0, 8);
        }

        if (file.provider === 'osfstorage' && file.name && index !== 0) {
            var parts = file.name.split('.');
            if (parts.length === 1) {
                options.displayName = parts[0] + '-' + revision.modified;
            } else {
                options.displayName = parts.slice(0, parts.length - 1).join('') + '-' + revision.modified + '.' + parts[parts.length - 1];
            }
        }

        revision.osfViewUrl = '?' + $.param(options);
        revision.osfDownloadUrl = '?' + $.param($.extend({action: 'download'}, options));
        revision.waterbutlerDownloadUrl = waterbutler.buildDownloadUrl(file.path, file.provider, node.id, options);

        return revision;
    }
};

module.exports = FileRevisionsTable;
<commit_msg>Remove spacing at the bottom of the revisions table<commit_after>var m = require('mithril');
var $ = require('jquery');
var $osf = require('js/osfHelpers');
var waterbutler = require('js/waterbutler');

var util = require('./util.js');

// Helper for filtering
function TRUTHY(item) {
    return !!item; //Force cast to a bool
}

var model = {
    revisions: [],
    loaded: m.prop(false),
    errorMessage: undefined,
    hasUser: false,
    hasDate: false,
    selectedRevision: 0
};

var FileRevisionsTable = {
    controller: function(file, node, enableEditing, canEdit) {
        var self = {};
        self.node = node;
        self.file = file;
        self.canEdit = canEdit;
        self.enableEditing = enableEditing;
        self.baseUrl = (window.location.href).split('?')[0];

        model.hasDate = self.file.provider !== 'dataverse';

        self.reload = function() {
            model.loaded(false);
            m.redraw();
            $.ajax({
                dataType: 'json',
                async: true,
                url: self.file.urls.revisions,
                beforeSend: $osf.setXHRAuthorization
            }).done(function(response) {
                m.startComputation();
                var urlParmas = $osf.urlParams();
                model.revisions = response.data.map(function(rev, index) {
                    rev = FileRevisionsTable.postProcessRevision(self.file, self.node, rev, index);
                    if (urlParmas[rev.versionIdentifier] === rev.version) {
                        model.selectedRevision = index;
                    }
                    return rev;
                });
                model.loaded(true);
                // Can only edit the latest version of a file
                if (model.selectedRevision === 0) {
                    self.enableEditing();
                }
                model.hasUser = model.revisions[0] && model.revisions[0].extra && model.revisions[0].extra.user;
                m.endComputation();
            }).fail(function(response) {
                m.startComputation();
                model.loaded(true);
                model.errorMessage = response.responseJSON ?
                    response.responseJSON.message || 'Unable to fetch versions' :
                    'Unable to fetch versions';
                m.endComputation();

                // model.errorMessage(err);

                if (self.file.provider === 'figshare') {
                    // Hack for Figshare
                    // only figshare will error on a revisions request
                    // so dont allow downloads and set a fake current version
                    $.ajax({
                        method: 'GET',
                        url: self.file.urls.metadata,
                        beforeSend: $osf.setXHRAuthorization
                    }).done(function(resp) {
                        self.canEdit(self.canEdit() && resp.data.extra.canDelete);
                        m.redraw();
                    }).fail(function(xhr) {
                        self.canEdit(false);
                        m.redraw();
                    });
                }
            });
        };

        self.getTableHead = function() {
            return m('thead', [
                m('tr', [
                    m('th', 'Version ID'),
                    model.hasDate ? m('th', 'Date') : false,
                    model.hasUser ? m('th', 'User') : false,
                    m('th[colspan=2]', 'Download'),
                ].filter(TRUTHY))
            ]);
        };

        self.makeTableRow = function(revision, index) {
            var isSelected = index === model.selectedRevision;

            return m('tr' + (isSelected ? '.active' : ''), [
                m('td',  isSelected ? revision.displayVersion :
                  m('a', {href: parseInt(revision.displayVersion) === model.revisions.length ? self.baseUrl : revision.osfViewUrl}, revision.displayVersion)
                ),
                model.hasDate ? m('td', revision.displayDate) : false,
                model.hasUser ?
                    m('td', revision.extra.user.url ?
                            m('a', {href: revision.extra.user.url}, revision.extra.user.name) :
                            revision.extra.user.name
                    ) : false,
                m('td', revision.extra.downloads > -1 ? m('.badge', revision.extra.downloads) : ''),
                m('td',
                    m('a.btn.btn-primary.btn-sm.file-download', {
                        href: revision.osfDownloadUrl,
                        onclick: function() {
                            window.location = revision.waterbutlerDownloadUrl;
                            return false;
                        }
                    }, m('i.fa.fa-download'))
                ),
            ].filter(TRUTHY));
        };

        if (!model.loaded()) {
            self.reload();
        }
        $(document).on('fileviewpage:reload', self.reload);
        return self;
    },
    view: function(ctrl) {
        return m('#revisionsPanel.panel.panel-default', [
                m('.panel-heading.clearfix', m('h3.panel-title', 'Revisions')),
                m('.panel-body', {style:{'padding-right': '0','padding-left':'0', 'padding-bottom' : '0'}}, (function() {
                    if (!model.loaded()) {
                        return util.Spinner;
                    }
                    if (model.errorMessage) {
                        return m('.alert.alert-warning', {style:{margin: '10px'}}, model.errorMessage);
                    }

                    return m('table.table',{style:{'margin-bottom': '0'}}, [
                        ctrl.getTableHead(),
                        m('tbody', model.revisions.map(ctrl.makeTableRow))
                    ]);
                })())
            ]);
    },
    postProcessRevision: function(file, node, revision, index) {
        var options = {};
        var urlParams = $osf.urlParams();

        if (urlParams.branch !== undefined) {
            options.branch = urlParams.branch;
        }
        options[revision.versionIdentifier] = revision.version;

        revision.date = new $osf.FormattableDate(revision.modified);
        revision.displayDate = revision.date.local !== 'Invalid date' ?
            revision.date.local :
            revision.date;

        switch (file.provider) {
            // Note: Google Drive version identifiers often begin with the same sequence
            case 'googledrive':
                revision.displayVersion = revision.version.substring(revision.version.length - 8);
                break;
            // Note: Dataverse internal version names are ugly; Substitute our own
            case 'dataverse':
                var displayMap = {
                    'latest': 'Draft',
                    'latest-published': 'Published'
                };

                revision.displayVersion = revision.version in displayMap ?
                    displayMap[revision.version] : revision.version.substring(0, 8);
                break;
            default:
                revision.displayVersion = revision.version.substring(0, 8);
        }

        if (file.provider === 'osfstorage' && file.name && index !== 0) {
            var parts = file.name.split('.');
            if (parts.length === 1) {
                options.displayName = parts[0] + '-' + revision.modified;
            } else {
                options.displayName = parts.slice(0, parts.length - 1).join('') + '-' + revision.modified + '.' + parts[parts.length - 1];
            }
        }

        revision.osfViewUrl = '?' + $.param(options);
        revision.osfDownloadUrl = '?' + $.param($.extend({action: 'download'}, options));
        revision.waterbutlerDownloadUrl = waterbutler.buildDownloadUrl(file.path, file.provider, node.id, options);

        return revision;
    }
};

module.exports = FileRevisionsTable;
<|endoftext|>


<commit_before>describe("Augment", function () {
	var extend,
		_augment;

	beforeEach(function () {
		extend = ArtisanStack.augment.extend;
		_augment = ArtisanStack.augment;
	});

	it("should correctly create class", function () {
		var extend = augment.extend;
	});

	it("should correctly extend class", function () {

	});
});

<commit_msg>fixed typo<commit_after>describe("Augment", function () {
	var extend,
		_augment;

	beforeEach(function () {
		extend = ArtisanStack.augment.extend;
		_augment = ArtisanStack.augment;
	});

	it("should correctly create class", function () {
		var extend = _augment.extend;
	});

	it("should correctly extend class", function () {

	});
});

<|endoftext|>