<commit_before>// @flow
import template from './templates/textAreaEditor.hbs';
import BaseEditorView from './base/BaseEditorView';
import { keyCode, helpers } from 'utils';
import { autosize } from 'lib';
import formRepository from '../formRepository';

const changeMode = {
    blur: 'blur',
    keydown: 'keydown'
};

const size = {
    auto: 'auto',
    fixed: 'fixed'
};

const defaultOptions = () => ({
    changeMode: changeMode.blur,
    size: size.auto,
    maxLength: null,
    height: null,
    minHeight: 1,
    maxHeight: null,
    showTitle: true
});

/**
 * @name TextAreaEditorView
 * @memberof module:core.form.editors
 * @class Multiline text editor. Supported data type: String.
 * @extends module:core.form.editors.base.BaseEditorView
 * @param {Object} options Options object. All the properties of {@link module:core.form.editors.base.BaseEditorView BaseEditorView} class are also supported.
 * @param {Number|null} [options.maxLength=null] The maximum number of characters. Not limited if null.
 * @param {String} [options.changeMode='blur'] Determines the moment the editor's value is updated:

 *
'keydown' - on key press.

 *
'blur' - on focus out.

 * @param {String} [options.size='auto'] Determines the strategy to compute the editor's height:

 *
'auto' - determined by the content (withing the range [minHeight, maxHeight]).

 *
'fixed' - fixed, determined by height option.

 * @param {String} [options.emptyPlaceholder='Field is empty'] Empty text placeholder.
 * @param {String} [options.readonlyPlaceholder='Field is readonly'] Текст placeholder, отображаемый
 * в случае если эдитор имеет флаг readonly.
 * @param {Number} [options.height=null] The height of the editor (in rows) when its size is fixed.
 * @param {Number} [options.minHeight=2] The minimum height of the editor (in rows).
 * @param {Number} [options.maxHeight=30] The maximum height of the editor (in rows).
 * @param {Boolean} {options.showTitle=true} Whether to show title attribute.
 * */
export default formRepository.editors.TextArea = BaseEditorView.extend({
    initialize(options) {
        this.__applyOptions(options, defaultOptions);
    },

    focusElement: '.js-input',

    className: 'editor editor_textarea',

    ui: {
        input: '.js-input'
    },

    events: {
        change: '__change',
        'input @ui.input': '__input',
        'keyup @ui.input': '__keyup'
    },

    template: Handlebars.compile(template),

    templateContext() {
        return this.options;
    },

    onRender() {
        const value = this.getValue() || '';
        this.ui.input.val(value);
        if (this.options.showTitle) {
            this.$editorEl.prop('title', value);
        }
        switch (this.options.size) {
            case size.auto:
                this.ui.input.attr('rows', this.options.minHeight);
                break;
            case size.fixed:
                this.ui.input.attr('rows', this.options.height);
                break;
            default:
                helpers.throwArgumentError('Invalid `size parameter`.');
        }
    },

    onAttach() {
        if (this.options.size === size.auto) {
            if (this.options.maxHeight) {
                const maxHeight = parseInt(this.ui.input.css('line-height'), 10) * this.options.maxHeight;
                this.ui.input.css('maxHeight', maxHeight);
            }
            autosize(this.ui.input);
        }
    },

    __value(value, updateUi, triggerChange) {
        if (this.value === value) {
            return;
        }
        this.value = value;

        if (triggerChange) {
            this.__triggerChange();
        }

        if (!this.isRendered()) {
            return;
        }

        if (this.options.showTitle) {
            this.$editorEl.prop('title', value);
        }
        if (updateUi) {
            this.ui.input.val(value);
        }
    },

    /**
     * Метод позволяет установить позицию курсора.
     * @param {Number} position Новая позиция курсора.
     * */
    setCaretPos(position) {
        this.ui.input.selectionStart = position;
        this.ui.input.selectionEnd = position;
    },

    setValue(value) {
        this.__value(value, true, false);
    },

    __change() {
        this.__triggerInput();
        this.__value(this.ui.input.val(), false, true);
    },

    __input() {
        this.__triggerInput();
        if (this.options.changeMode === changeMode.keydown) {
            this.__value(this.ui.input.val(), false, true);
        }
    },

    __keyup(e) {
        if (e.ctrlKey) {
            return;
        }
        if ([keyCode.LEFT, keyCode.RIGHT, keyCode.HOME, keyCode.END].indexOf(e.keyCode) === -1) {
            return;
        }

        const caret = {
            start: this.ui.input[0].selectionStart,
            end: this.ui.input[0].selectionEnd
        };

        if (this.oldCaret && this.oldCaret.start === caret.start && this.oldCaret.end === caret.end) {
            return;
        }

        this.oldCaret = caret;
        const text = this.ui.input.val();
        this.trigger('caretChange', text, caret);
    },

    onKeyup() {
        //for not to call the "change"
    },

    __triggerInput() {
        const text = this.ui.input.val();
        if (this.oldText === text) {
            return;
        }

        this.oldText = text;

        const caret = {
            start: this.ui.input[0].selectionStart,
            end: this.ui.input[0].selectionEnd
        };

        this.trigger('input', text, {
            start: caret.start,
            end: caret.end
        });
    },

    /**
     * Focuses the editor's input and selects all the text in it.
     * */
    select() {
        this.ui.input.select();
    }
});
<commit_msg> [#607865] Fix scroll on global configuration textarea<commit_after>// @flow
import template from './templates/textAreaEditor.hbs';
import BaseEditorView from './base/BaseEditorView';
import { keyCode, helpers } from 'utils';
import { autosize } from 'lib';
import formRepository from '../formRepository';

const changeMode = {
    blur: 'blur',
    keydown: 'keydown'
};

const size = {
    auto: 'auto',
    fixed: 'fixed'
};

const defaultOptions = () => ({
    changeMode: changeMode.blur,
    size: size.auto,
    maxLength: null,
    height: null,
    minHeight: 1,
    maxHeight: null,
    showTitle: true
});

/**
 * @name TextAreaEditorView
 * @memberof module:core.form.editors
 * @class Multiline text editor. Supported data type: String.
 * @extends module:core.form.editors.base.BaseEditorView
 * @param {Object} options Options object. All the properties of {@link module:core.form.editors.base.BaseEditorView BaseEditorView} class are also supported.
 * @param {Number|null} [options.maxLength=null] The maximum number of characters. Not limited if null.
 * @param {String} [options.changeMode='blur'] Determines the moment the editor's value is updated:

 *
'keydown' - on key press.

 *
'blur' - on focus out.

 * @param {String} [options.size='auto'] Determines the strategy to compute the editor's height:

 *
'auto' - determined by the content (withing the range [minHeight, maxHeight]).

 *
'fixed' - fixed, determined by height option.

 * @param {String} [options.emptyPlaceholder='Field is empty'] Empty text placeholder.
 * @param {String} [options.readonlyPlaceholder='Field is readonly'] Текст placeholder, отображаемый
 * в случае если эдитор имеет флаг readonly.
 * @param {Number} [options.height=null] The height of the editor (in rows) when its size is fixed.
 * @param {Number} [options.minHeight=2] The minimum height of the editor (in rows).
 * @param {Number} [options.maxHeight=30] The maximum height of the editor (in rows).
 * @param {Boolean} {options.showTitle=true} Whether to show title attribute.
 * */
export default formRepository.editors.TextArea = BaseEditorView.extend({
    initialize(options) {
        this.__applyOptions(options, defaultOptions);
    },

    focusElement: '.js-input',

    className: 'editor editor_textarea',

    ui: {
        input: '.js-input'
    },

    events: {
        change: '__change',
        'input @ui.input': '__input',
        'keyup @ui.input': '__keyup'
    },

    template: Handlebars.compile(template),

    templateContext() {
        return this.options;
    },

    onRender() {
        const value = this.getValue() || '';
        this.ui.input.val(value);
        if (this.options.showTitle) {
            this.$editorEl.prop('title', value);
        }
        switch (this.options.size) {
            case size.auto:
                this.ui.input.attr('rows', this.options.minHeight);
                break;
            case size.fixed:
                this.ui.input.attr('rows', this.options.height);
                break;
            default:
                helpers.throwArgumentError('Invalid `size parameter`.');
        }
    },

    onAttach() {
        if (this.options.size === size.auto) {
            if (this.options.maxHeight) {
                const maxHeight = parseInt(this.ui.input.css('line-height'), 10) * this.options.maxHeight;
                this.ui.input.css('maxHeight', maxHeight);
            }
            if (this.ui.input[0].scrollHeight > 0) {
                autosize(this.ui.input);
            }
        }
    },

    __value(value, updateUi, triggerChange) {
        if (this.value === value) {
            return;
        }
        this.value = value;

        if (triggerChange) {
            this.__triggerChange();
        }

        if (!this.isRendered()) {
            return;
        }

        if (this.options.showTitle) {
            this.$editorEl.prop('title', value);
        }
        if (updateUi) {
            this.ui.input.val(value);
            autosize(this.ui.input);
        }
    },

    /**
     * Метод позволяет установить позицию курсора.
     * @param {Number} position Новая позиция курсора.
     * */
    setCaretPos(position) {
        this.ui.input.selectionStart = position;
        this.ui.input.selectionEnd = position;
    },

    setValue(value) {
        this.__value(value, true, false);
    },

    __change() {
        this.__triggerInput();
        this.__value(this.ui.input.val(), false, true);
    },

    __input() {
        this.__triggerInput();
        if (this.options.changeMode === changeMode.keydown) {
            this.__value(this.ui.input.val(), false, true);
        }
    },

    __keyup(e) {
        if (e.ctrlKey) {
            return;
        }
        if ([keyCode.LEFT, keyCode.RIGHT, keyCode.HOME, keyCode.END].indexOf(e.keyCode) === -1) {
            return;
        }

        const caret = {
            start: this.ui.input[0].selectionStart,
            end: this.ui.input[0].selectionEnd
        };

        if (this.oldCaret && this.oldCaret.start === caret.start && this.oldCaret.end === caret.end) {
            return;
        }

        this.oldCaret = caret;
        const text = this.ui.input.val();
        this.trigger('caretChange', text, caret);
    },

    onKeyup() {
        //for not to call the "change"
    },

    __triggerInput() {
        const text = this.ui.input.val();
        if (this.oldText === text) {
            return;
        }

        this.oldText = text;

        const caret = {
            start: this.ui.input[0].selectionStart,
            end: this.ui.input[0].selectionEnd
        };

        this.trigger('input', text, {
            start: caret.start,
            end: caret.end
        });
    },

    /**
     * Focuses the editor's input and selects all the text in it.
     * */
    select() {
        this.ui.input.select();
    }
});
<|endoftext|>


<commit_before>/**
 * @license Copyright (c) CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.html or http://ckeditor.com/license
 */

(function() {
    if (!supportsLocalStorage()) {
        CKEDITOR.plugins.add("autosave", {}); //register a dummy plugin to pass CKEditor plugin initialization process
        return;
    }

    CKEDITOR.plugins.add("autosave", {
        lang: 'ca,de,en,es,jp,pl,pt-br,sv,zh,zh-cn', // %REMOVE_LINE_CORE%
        version: 0.10,
        init: function(editor) {
            CKEDITOR.document.appendStyleSheet(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'css/autosave.min.css'));

            if (typeof (jQuery) === 'undefined') {
                CKEDITOR.scriptLoader.load('//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js', function() {
                    jQuery.noConflict();

                    loadPlugin(editor);
                });

            } else {
                CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
                    loadPlugin(editor);
                });
            }
        }
    });

    function loadPlugin(editorInstance) {
        var autoSaveKey = editorInstance.config.autosave_SaveKey != null ? editorInstance.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editorInstance.id;
        var notOlderThan = editorInstance.config.autosave_NotOlderThan != null ? editorInstance.config.autosave_NotOlderThan : 1440;
        var saveOnDestroy = editorInstance.config.autosave_saveOnDestroy != null ? editorInstance.config.autosave_saveOnDestroy : false;
        var saveDetectionSelectors =
            editorInstance.config.autosave_saveDetectionSelectors != null ? editorInstance.config.autosave_saveDetectionSelectors : "a[href^='javascript:__doPostBack'][id*='Save'],a[id*='Cancel']";

        CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
            GenerateAutoSaveDialog(editorInstance, autoSaveKey);

            CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThan);
        });

        jQuery(saveDetectionSelectors).click(function() {
            RemoveStorage(autoSaveKey);
        });

        editorInstance.on('change', startTimer);

        editorInstance.on('destroy', function() {
            if (saveOnDestroy) {
                SaveData(autoSaveKey, editorInstance);
            }
        });

        editorInstance.on('uiSpace', function(event) {
            if (event.data.space == 'bottom') {
                event.data.html += '

'
                    + event.editor.lang.autosave.autoSaveMessage
                    + '

';
            }
        }, editorInstance, null, 100);
    }

    function autoSaveMessageId(editorInstance) {
        return 'cke_autoSaveMessage_' + editorInstance.name;
    }

    var timeOutId = 0,
        savingActive = false;

    var startTimer = function(event) {
        if (timeOutId) {
            clearTimeout(timeOutId);
        }
        var delay = CKEDITOR.config.autosave_delay != null ? CKEDITOR.config.autosave_delay : 10;
        timeOutId = setTimeout(onTimer, delay * 1000, event);
    };
    var onTimer = function(event) {
        if (savingActive) {
            startTimer(event);
        } else if (event.editor.checkDirty() || event.editor.plugins.bbcode) {
            savingActive = true;
            var editor = event.editor,
                autoSaveKey = editor.config.autosave_SaveKey != null ? editor.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editorInstance.id;

            SaveData(autoSaveKey, editor);

            savingActive = false;
        }
    };

    // localStorage detection
    function supportsLocalStorage() {
        if (typeof (Storage) === 'undefined') {
            return false;
        }

        try {
            localStorage.getItem("___test_key");
            return true;
        } catch (e) {
            return false;
        }
    }

    function GenerateAutoSaveDialog(editorInstance, autoSaveKey) {
        CKEDITOR.dialog.add('autosaveDialog', function() {
            return {
                title: editorInstance.lang.autosave.title,
                minHeight: 155,
                height: 300,
                width: 750,
                onShow: function() {
                    RenderDiff(this, editorInstance, autoSaveKey);
                },
                onOk: function() {
                    var jsonSavedContent = LoadData(autoSaveKey);

                    editorInstance.setData(jsonSavedContent.data);

                    RemoveStorage(autoSaveKey);
                },
                onCancel: function() {
                    RemoveStorage(autoSaveKey);
                },
                contents: [
                    {
                        label: '',
                        id: 'general',
                        elements: [
                            {
                                type: 'radio',
                                id: 'diffType',
                                label: editorInstance.lang.autosave.diffType,
                                items: [[editorInstance.lang.autosave.sideBySide, 'sideBySide'], [editorInstance.lang.autosave.inline, 'inline']],
                                'default': 'sideBySide',
                                onClick: function() {
                                    RenderDiff(this._.dialog, editorInstance, autoSaveKey);
                                }
                            }, {
                                type: 'html',
                                id: 'diffContent',
                                html: ''
                            }
                        ]
                    }
                ],
                buttons: [
                    {
                        id: 'ok',
                        type: 'button',
                        label: editorInstance.lang.autosave.ok,
                        'class': 'cke_dialog_ui_button_ok cke_dialog_autosave_ok',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('ok', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    },
                    {
                        id: 'cancel',
                        type: 'button',
                        label: editorInstance.lang.autosave.no,
                        'class': 'cke_dialog_ui_button_cancel',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('cancel', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    }
                ]
            };
        });
    }

    function CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThan) {
        // Checks If there is data available and load it
        if (localStorage.getItem(autoSaveKey)) {
            var jsonSavedContent = LoadData(autoSaveKey);

            var autoSavedContent = jsonSavedContent.data;
            var autoSavedContentDate = jsonSavedContent.saveTime;

            var editorLoadedContent = editorInstance.getData();

            // check if the loaded editor content is the same as the autosaved content
            if (editorLoadedContent == autoSavedContent) {
                localStorage.removeItem(autoSaveKey);
                return;
            }

            // Ignore if autosaved content is older then x minutes
            if (moment(new Date()).diff(autoSavedContentDate, 'minutes') > notOlderThan) {
                RemoveStorage(autoSaveKey);

                return;
            }

            var confirmMessage = editorInstance.lang.autosave.loadSavedContent.replace("{0}", moment(autoSavedContentDate).lang(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat));
            if (confirm(confirmMessage)) {
                // Open DIFF Dialog
                editorInstance.openDialog('autosaveDialog');
            } else {
                RemoveStorage(autoSaveKey);
            }
        }
    }

    function LoadData(autoSaveKey) {
        var compressedJSON = LZString.decompressFromUTF16(localStorage.getItem(autoSaveKey));
        return JSON.parse(compressedJSON);
    }

    function SaveData(autoSaveKey, editorInstance) {
        var compressedJSON = LZString.compressToUTF16(JSON.stringify({ data: editorInstance.getData(), saveTime: new Date() }));
        localStorage.setItem(autoSaveKey, compressedJSON);

        var autoSaveMessage = document.getElementById(autoSaveMessageId(editorInstance));

        if (autoSaveMessage) {
            autoSaveMessage.className = "show";

            setTimeout(function() {
                autoSaveMessage.className = "hidden";
            }, 2000);
        }
    }

    function RemoveStorage(autoSaveKey) {
        if (timeOutId) {
            clearTimeout(timeOutId);
        }

        localStorage.removeItem(autoSaveKey);
    }

    function RenderDiff(dialog, editorInstance, autoSaveKey) {
        var jsonSavedContent = LoadData(autoSaveKey);

        var base = difflib.stringAsLines(editorInstance.getData());
        var newtxt = difflib.stringAsLines(jsonSavedContent.data);
        var sm = new difflib.SequenceMatcher(base, newtxt);
        var opcodes = sm.get_opcodes();

        dialog.getContentElement('general', 'diffContent').getElement().setHtml('
' + diffview.buildView({
            baseTextLines: base,
            newTextLines: newtxt,
            opcodes: opcodes,
            baseTextName: editorInstance.lang.autosave.loadedContent,
            newTextName: editorInstance.lang.autosave.autoSavedContent + (moment(jsonSavedContent.saveTime).lang(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat)) + '\'',
            contextSize: 3,
            viewType: dialog.getContentElement('general', 'diffType').getValue() == "inline" ? 1 : 0
        }).outerHTML + '
');
    }
})();
<commit_msg>wrong name<commit_after>/**
 * @license Copyright (c) CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.html or http://ckeditor.com/license
 */

(function() {
    if (!supportsLocalStorage()) {
        CKEDITOR.plugins.add("autosave", {}); //register a dummy plugin to pass CKEditor plugin initialization process
        return;
    }

    CKEDITOR.plugins.add("autosave", {
        lang: 'ca,de,en,es,jp,pl,pt-br,sv,zh,zh-cn', // %REMOVE_LINE_CORE%
        version: 0.10,
        init: function(editor) {
            CKEDITOR.document.appendStyleSheet(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'css/autosave.min.css'));

            if (typeof (jQuery) === 'undefined') {
                CKEDITOR.scriptLoader.load('//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js', function() {
                    jQuery.noConflict();

                    loadPlugin(editor);
                });

            } else {
                CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
                    loadPlugin(editor);
                });
            }
        }
    });

    function loadPlugin(editorInstance) {
        var autoSaveKey = editorInstance.config.autosave_SaveKey != null ? editorInstance.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editorInstance.id;
        var notOlderThan = editorInstance.config.autosave_NotOlderThan != null ? editorInstance.config.autosave_NotOlderThan : 1440;
        var saveOnDestroy = editorInstance.config.autosave_saveOnDestroy != null ? editorInstance.config.autosave_saveOnDestroy : false;
        var saveDetectionSelectors =
            editorInstance.config.autosave_saveDetectionSelectors != null ? editorInstance.config.autosave_saveDetectionSelectors : "a[href^='javascript:__doPostBack'][id*='Save'],a[id*='Cancel']";

        CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
            GenerateAutoSaveDialog(editorInstance, autoSaveKey);

            CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThan);
        });

        jQuery(saveDetectionSelectors).click(function() {
            RemoveStorage(autoSaveKey);
        });

        editorInstance.on('change', startTimer);

        editorInstance.on('destroy', function() {
            if (saveOnDestroy) {
                SaveData(autoSaveKey, editorInstance);
            }
        });

        editorInstance.on('uiSpace', function(event) {
            if (event.data.space == 'bottom') {
                event.data.html += '

'
                    + event.editor.lang.autosave.autoSaveMessage
                    + '

';
            }
        }, editorInstance, null, 100);
    }

    function autoSaveMessageId(editorInstance) {
        return 'cke_autoSaveMessage_' + editorInstance.name;
    }

    var timeOutId = 0,
        savingActive = false;

    var startTimer = function(event) {
        if (timeOutId) {
            clearTimeout(timeOutId);
        }
        var delay = CKEDITOR.config.autosave_delay != null ? CKEDITOR.config.autosave_delay : 10;
        timeOutId = setTimeout(onTimer, delay * 1000, event);
    };
    var onTimer = function(event) {
        if (savingActive) {
            startTimer(event);
        } else if (event.editor.checkDirty() || event.editor.plugins.bbcode) {
            savingActive = true;
            var editor = event.editor,
                autoSaveKey = editor.config.autosave_SaveKey != null ? editor.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editor.id;

            SaveData(autoSaveKey, editor);

            savingActive = false;
        }
    };

    // localStorage detection
    function supportsLocalStorage() {
        if (typeof (Storage) === 'undefined') {
            return false;
        }

        try {
            localStorage.getItem("___test_key");
            return true;
        } catch (e) {
            return false;
        }
    }

    function GenerateAutoSaveDialog(editorInstance, autoSaveKey) {
        CKEDITOR.dialog.add('autosaveDialog', function() {
            return {
                title: editorInstance.lang.autosave.title,
                minHeight: 155,
                height: 300,
                width: 750,
                onShow: function() {
                    RenderDiff(this, editorInstance, autoSaveKey);
                },
                onOk: function() {
                    var jsonSavedContent = LoadData(autoSaveKey);

                    editorInstance.setData(jsonSavedContent.data);

                    RemoveStorage(autoSaveKey);
                },
                onCancel: function() {
                    RemoveStorage(autoSaveKey);
                },
                contents: [
                    {
                        label: '',
                        id: 'general',
                        elements: [
                            {
                                type: 'radio',
                                id: 'diffType',
                                label: editorInstance.lang.autosave.diffType,
                                items: [[editorInstance.lang.autosave.sideBySide, 'sideBySide'], [editorInstance.lang.autosave.inline, 'inline']],
                                'default': 'sideBySide',
                                onClick: function() {
                                    RenderDiff(this._.dialog, editorInstance, autoSaveKey);
                                }
                            }, {
                                type: 'html',
                                id: 'diffContent',
                                html: ''
                            }
                        ]
                    }
                ],
                buttons: [
                    {
                        id: 'ok',
                        type: 'button',
                        label: editorInstance.lang.autosave.ok,
                        'class': 'cke_dialog_ui_button_ok cke_dialog_autosave_ok',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('ok', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    },
                    {
                        id: 'cancel',
                        type: 'button',
                        label: editorInstance.lang.autosave.no,
                        'class': 'cke_dialog_ui_button_cancel',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('cancel', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    }
                ]
            };
        });
    }

    function CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThan) {
        // Checks If there is data available and load it
        if (localStorage.getItem(autoSaveKey)) {
            var jsonSavedContent = LoadData(autoSaveKey);

            var autoSavedContent = jsonSavedContent.data;
            var autoSavedContentDate = jsonSavedContent.saveTime;

            var editorLoadedContent = editorInstance.getData();

            // check if the loaded editor content is the same as the autosaved content
            if (editorLoadedContent == autoSavedContent) {
                localStorage.removeItem(autoSaveKey);
                return;
            }

            // Ignore if autosaved content is older then x minutes
            if (moment(new Date()).diff(autoSavedContentDate, 'minutes') > notOlderThan) {
                RemoveStorage(autoSaveKey);

                return;
            }

            var confirmMessage = editorInstance.lang.autosave.loadSavedContent.replace("{0}", moment(autoSavedContentDate).lang(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat));
            if (confirm(confirmMessage)) {
                // Open DIFF Dialog
                editorInstance.openDialog('autosaveDialog');
            } else {
                RemoveStorage(autoSaveKey);
            }
        }
    }

    function LoadData(autoSaveKey) {
        var compressedJSON = LZString.decompressFromUTF16(localStorage.getItem(autoSaveKey));
        return JSON.parse(compressedJSON);
    }

    function SaveData(autoSaveKey, editorInstance) {
        var compressedJSON = LZString.compressToUTF16(JSON.stringify({ data: editorInstance.getData(), saveTime: new Date() }));
        localStorage.setItem(autoSaveKey, compressedJSON);

        var autoSaveMessage = document.getElementById(autoSaveMessageId(editorInstance));

        if (autoSaveMessage) {
            autoSaveMessage.className = "show";

            setTimeout(function() {
                autoSaveMessage.className = "hidden";
            }, 2000);
        }
    }

    function RemoveStorage(autoSaveKey) {
        if (timeOutId) {
            clearTimeout(timeOutId);
        }

        localStorage.removeItem(autoSaveKey);
    }

    function RenderDiff(dialog, editorInstance, autoSaveKey) {
        var jsonSavedContent = LoadData(autoSaveKey);

        var base = difflib.stringAsLines(editorInstance.getData());
        var newtxt = difflib.stringAsLines(jsonSavedContent.data);
        var sm = new difflib.SequenceMatcher(base, newtxt);
        var opcodes = sm.get_opcodes();

        dialog.getContentElement('general', 'diffContent').getElement().setHtml('
' + diffview.buildView({
            baseTextLines: base,
            newTextLines: newtxt,
            opcodes: opcodes,
            baseTextName: editorInstance.lang.autosave.loadedContent,
            newTextName: editorInstance.lang.autosave.autoSavedContent + (moment(jsonSavedContent.saveTime).lang(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat)) + '\'',
            contextSize: 3,
            viewType: dialog.getContentElement('general', 'diffType').getValue() == "inline" ? 1 : 0
        }).outerHTML + '
');
    }
})();
<|endoftext|>


<commit_before>/*
Copyright 2016 First People's Cultural Council

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { Component, PropTypes } from 'react'
import selectn from 'selectn'
import NavigationHelpers from 'common/NavigationHelpers'
import IntlService from 'views/services/intl'

const intl = IntlService.instance

/**
 * Data List View
 * NOTE: The `class` that `extends` `DataListView` must define `fetchData`, `_fetchListViewData` functions
 * TODO: Convert to composition vs. inheritance https://facebook.github.io/react/docs/composition-vs-inheritance.html
 */
export default class DataListView extends Component {
  constructor(props, context) {
    super(props, context)

    if (typeof this.fetchData === 'undefined') {
      // eslint-disable-next-line
      console.warn("The `class` that `extends` `DataListView` must define a `fetchData` function")
    }

    if (typeof this._fetchListViewData === 'undefined') {
      // eslint-disable-next-line
      console.warn("The `class` that `extends` `DataListView` must define a `_fetchListViewData` function")
    }
  }

  static defaultProps = {}
  static propTypes = {
    controlViaURL: PropTypes.any, // TODO: set appropriate propType
    routeParams: PropTypes.any, // TODO: set appropriate propType
    DEFAULT_PAGE: PropTypes.any, // TODO: set appropriate propType
    DEFAULT_PAGE_SIZE: PropTypes.any, // TODO: set appropriate propType
    DEFAULT_SORT_TYPE: PropTypes.any, // TODO: set appropriate propType
    DEFAULT_SORT_COL: PropTypes.any, // TODO: set appropriate propType
    windowPath: PropTypes.any, // TODO: set appropriate propType
    filter: PropTypes.any, // TODO: set appropriate propType
    pushWindowPath: PropTypes.any, // TODO: set appropriate propType
    splitWindowPath: PropTypes.any, // TODO: set appropriate propType
    onPaginationReset: PropTypes.any, // TODO: set appropriate propType
    DISABLED_SORT_COLS: PropTypes.any, // TODO: set appropriate propType
    onPagePropertiesChange: PropTypes.any, // TODO: set appropriate propType
  }

  // NOTE: The `class` that `extends` `DataListView` must define a `fetchData` function
  fetchData() {
    // eslint-disable-next-line
    console.warn("The `class` that `extends` `DataListView` must define a `fetchData` function")
  }

  // NOTE: The `class` that `extends` `DataListView` must define a `_fetchListViewData` function
  _fetchListViewData() {
    // eslint-disable-next-line
    console.warn("The `class` that `extends` `DataListView` must define a `_fetchListViewData` function")
  }

  // Fetch data on initial render
  componentDidMount() {
    this._resetColumns(this.props)
    this.fetchData(this.props)
  }

  // Refetch data on URL change
  // TODO: At minimum, migrate to `getDerivedStateFromProps()` or https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
  componentWillReceiveProps(nextProps) {
    if (nextProps.controlViaURL) {
      if (
        nextProps.routeParams.page !== this.props.routeParams.page ||
        nextProps.routeParams.pageSize !== this.props.routeParams.pageSize
      ) {
        this._fetchListViewData(
          nextProps,
          nextProps.DEFAULT_PAGE,
          nextProps.DEFAULT_PAGE_SIZE,
          nextProps.DEFAULT_SORT_TYPE,
          nextProps.DEFAULT_SORT_COL
        )
        this._resetPagination(nextProps)
      }
    } else {
      if (nextProps.windowPath !== this.props.windowPath) {
        this.fetchData(nextProps)
      }
    }

    if (nextProps.routeParams.area !== this.props.routeParams.area) {
      this._resetColumns(nextProps)
      this._resetPagination(nextProps)
    }

    if (
      this.props.filter.has('currentAppliedFilter') &&
      !this.props.filter.get('currentAppliedFilter').equals(nextProps.filter.get('currentAppliedFilter'))
    ) {
      this._fetchListViewData(
        nextProps,
        nextProps.DEFAULT_PAGE,
        nextProps.DEFAULT_PAGE_SIZE,
        nextProps.DEFAULT_SORT_TYPE,
        nextProps.DEFAULT_SORT_COL
      )
    }
  }

  _onNavigateRequest(path) {
    this.props.pushWindowPath(this.props.windowPath.replace('sections', 'Workspaces') + '/' + path)
  }

  _handleRefetch(dataGridProps, page, pageSize) {
    this.setState({
      pageInfo: {
        page: page,
        pageSize: pageSize,
      },
    })

    let sortInfo = null
    let currentSortCols = null

    if (this.state.hasOwnProperty('sortInfo') && this.state.sortInfo.hasOwnProperty('currentSortType')) {
      sortInfo = this.state.sortInfo.currentSortType
      currentSortCols = this.state.sortInfo.currentSortCols
    }

    if (!this.props.controlViaURL) {
      this._fetchListViewData(this.props, page, pageSize, sortInfo, currentSortCols)
    } else {
      const _urlPage = selectn('page', this.props.routeParams)
      const _urlPageSize = selectn('pageSize', this.props.routeParams)
      const urlPage = _urlPage !== undefined ? parseInt(_urlPage, 10) : _urlPage
      const urlPageSize = _urlPageSize !== undefined ? parseInt(_urlPageSize, 10) : _urlPageSize
      // If page and pageSize exist, and are different, replace them; otherwise - add them
      if (urlPage && urlPageSize) {
        if (urlPage !== page || urlPageSize !== pageSize) {
          NavigationHelpers.navigateForwardReplaceMultiple(
            this.props.splitWindowPath,
            [pageSize, page],
            this.props.pushWindowPath
          )
        }
      } else {
        NavigationHelpers.navigateForward(
          this.props.splitWindowPath,
          [pageSize, page],
          this.props.pushWindowPath
        )
      }

      // If pageSize has changed, reset page
      if (urlPageSize && pageSize !== urlPageSize && this.props.onPaginationReset) {
        this.props.onPaginationReset(pageSize)
      }
    }
  }

  _handleSortChange(sortInfo) {
    let colRequestSkipped = false
    let sortCol = []
    let sortType = []

    sortInfo.map((sortColumn, i) => {
      const name = selectn('[' + i + '].name', sortInfo)

      if (this.props.DISABLED_SORT_COLS.indexOf(name) === -1) {
        const definedCol = this.state.columns.find((item) => item.name === name)

        sortCol.push(selectn('sortName', definedCol) ? selectn('sortName', definedCol) : name)
        sortType.push(selectn('[' + i + '].dir', sortInfo) === -1 ? 'desc' : 'asc')
      } else {
        if (i === sortInfo.length - 1) colRequestSkipped = true
      }
    })

    if (sortCol.length === 0) {
      sortCol = [this.props.DEFAULT_SORT_COL]
      sortType = [this.props.DEFAULT_SORT_TYPE]
    }

    const joinedSortType = sortType.join()
    const joinedSortCols = sortCol.join()

    // Skip updating if last sort addition is disabled
    if (colRequestSkipped) return

    this._fetchListViewData(
      this.props,
      this.props.DEFAULT_PAGE,
      this.props.DEFAULT_PAGE_SIZE,
      joinedSortType,
      joinedSortCols
    )

    const newSortInfo = {
      uiSortOrder: sortInfo,
      currentSortCols: joinedSortCols,
      currentSortType: joinedSortType,
    }

    // Update page properties to use when navigating away
    this.props.onPagePropertiesChange({ sortInfo: newSortInfo })

    this.setState({
      sortInfo: newSortInfo,
    })
  }

  _handleColumnOrderChange(index, dropIndex) {
    const col = this.state.columns[index]
    this.state.columns.splice(index, 1)
    this.state.columns.splice(dropIndex, 0, col)
    this.setState({})
  }

  _resetColumns(props) {
    if (this.state.fixedCols || this.state.hideStateColumn) {
      return
    }

    // Toggle 'state' column for section/workspaces view
    if (this.state.hasOwnProperty('columns')) {
      if (props.routeParams.area === 'sections') {
        const stateCol = this.state.columns.findIndex((item) => item.name === 'state')

        this.state.columns.splice(stateCol, 1)
      } else {
        this.state.columns.push({ name: 'state', title: intl.trans('state', 'State', 'first') })
      }
    }
  }

  _resetPagination(props) {
    this.setState({
      pageInfo: {
        page: props.DEFAULT_PAGE,
        pageSize: props.DEFAULT_PAGE_SIZE,
      },
    })
  }
}
<commit_msg>DataListView: prettier change<commit_after>/*
Copyright 2016 First People's Cultural Council

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { Component, PropTypes } from 'react'
import selectn from 'selectn'
import NavigationHelpers from 'common/NavigationHelpers'
import IntlService from 'views/services/intl'

const intl = IntlService.instance

/**
 * Data List View
 * NOTE: The `class` that `extends` `DataListView` must define `fetchData`, `_fetchListViewData` functions
 * TODO: Convert to composition vs. inheritance https://facebook.github.io/react/docs/composition-vs-inheritance.html
 */
export default class DataListView extends Component {
  constructor(props, context) {
    super(props, context)

    if (typeof this.fetchData === 'undefined') {
      // eslint-disable-next-line
      console.warn("The `class` that `extends` `DataListView` must define a `fetchData` function")
    }

    if (typeof this._fetchListViewData === 'undefined') {
      // eslint-disable-next-line
      console.warn("The `class` that `extends` `DataListView` must define a `_fetchListViewData` function")
    }
  }

  static defaultProps = {}
  static propTypes = {
    controlViaURL: PropTypes.any, // TODO: set appropriate propType
    routeParams: PropTypes.any, // TODO: set appropriate propType
    DEFAULT_PAGE: PropTypes.any, // TODO: set appropriate propType
    DEFAULT_PAGE_SIZE: PropTypes.any, // TODO: set appropriate propType
    DEFAULT_SORT_TYPE: PropTypes.any, // TODO: set appropriate propType
    DEFAULT_SORT_COL: PropTypes.any, // TODO: set appropriate propType
    windowPath: PropTypes.any, // TODO: set appropriate propType
    filter: PropTypes.any, // TODO: set appropriate propType
    pushWindowPath: PropTypes.any, // TODO: set appropriate propType
    splitWindowPath: PropTypes.any, // TODO: set appropriate propType
    onPaginationReset: PropTypes.any, // TODO: set appropriate propType
    DISABLED_SORT_COLS: PropTypes.any, // TODO: set appropriate propType
    onPagePropertiesChange: PropTypes.any, // TODO: set appropriate propType
  }

  // NOTE: The `class` that `extends` `DataListView` must define a `fetchData` function
  fetchData() {
    // eslint-disable-next-line
    console.warn("The `class` that `extends` `DataListView` must define a `fetchData` function")
  }

  // NOTE: The `class` that `extends` `DataListView` must define a `_fetchListViewData` function
  _fetchListViewData() {
    // eslint-disable-next-line
    console.warn("The `class` that `extends` `DataListView` must define a `_fetchListViewData` function")
  }

  // Fetch data on initial render
  componentDidMount() {
    this._resetColumns(this.props)
    this.fetchData(this.props)
  }

  // Refetch data on URL change
  // TODO: At minimum, migrate to `getDerivedStateFromProps()` or https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
  componentWillReceiveProps(nextProps) {
    if (nextProps.controlViaURL) {
      if (
        nextProps.routeParams.page !== this.props.routeParams.page ||
        nextProps.routeParams.pageSize !== this.props.routeParams.pageSize
      ) {
        this._fetchListViewData(
          nextProps,
          nextProps.DEFAULT_PAGE,
          nextProps.DEFAULT_PAGE_SIZE,
          nextProps.DEFAULT_SORT_TYPE,
          nextProps.DEFAULT_SORT_COL
        )
        this._resetPagination(nextProps)
      }
    } else {
      if (nextProps.windowPath !== this.props.windowPath) {
        this.fetchData(nextProps)
      }
    }

    if (nextProps.routeParams.area !== this.props.routeParams.area) {
      this._resetColumns(nextProps)
      this._resetPagination(nextProps)
    }

    if (
      this.props.filter.has('currentAppliedFilter') &&
      !this.props.filter.get('currentAppliedFilter').equals(nextProps.filter.get('currentAppliedFilter'))
    ) {
      this._fetchListViewData(
        nextProps,
        nextProps.DEFAULT_PAGE,
        nextProps.DEFAULT_PAGE_SIZE,
        nextProps.DEFAULT_SORT_TYPE,
        nextProps.DEFAULT_SORT_COL
      )
    }
  }

  _onNavigateRequest(path) {
    this.props.pushWindowPath(this.props.windowPath.replace('sections', 'Workspaces') + '/' + path)
  }

  _handleRefetch(dataGridProps, page, pageSize) {
    this.setState({
      pageInfo: {
        page: page,
        pageSize: pageSize,
      },
    })

    let sortInfo = null
    let currentSortCols = null

    if (this.state.hasOwnProperty('sortInfo') && this.state.sortInfo.hasOwnProperty('currentSortType')) {
      sortInfo = this.state.sortInfo.currentSortType
      currentSortCols = this.state.sortInfo.currentSortCols
    }

    if (!this.props.controlViaURL) {
      this._fetchListViewData(this.props, page, pageSize, sortInfo, currentSortCols)
    } else {
      const _urlPage = selectn('page', this.props.routeParams)
      const _urlPageSize = selectn('pageSize', this.props.routeParams)
      const urlPage = _urlPage !== undefined ? parseInt(_urlPage, 10) : _urlPage
      const urlPageSize = _urlPageSize !== undefined ? parseInt(_urlPageSize, 10) : _urlPageSize
      // If page and pageSize exist, and are different, replace them; otherwise - add them
      if (urlPage && urlPageSize) {
        if (urlPage !== page || urlPageSize !== pageSize) {
          NavigationHelpers.navigateForwardReplaceMultiple(
            this.props.splitWindowPath,
            [pageSize, page],
            this.props.pushWindowPath
          )
        }
      } else {
        NavigationHelpers.navigateForward(this.props.splitWindowPath, [pageSize, page], this.props.pushWindowPath)
      }

      // If pageSize has changed, reset page
      if (urlPageSize && pageSize !== urlPageSize && this.props.onPaginationReset) {
        this.props.onPaginationReset(pageSize)
      }
    }
  }

  _handleSortChange(sortInfo) {
    let colRequestSkipped = false
    let sortCol = []
    let sortType = []

    sortInfo.map((sortColumn, i) => {
      const name = selectn('[' + i + '].name', sortInfo)

      if (this.props.DISABLED_SORT_COLS.indexOf(name) === -1) {
        const definedCol = this.state.columns.find((item) => item.name === name)

        sortCol.push(selectn('sortName', definedCol) ? selectn('sortName', definedCol) : name)
        sortType.push(selectn('[' + i + '].dir', sortInfo) === -1 ? 'desc' : 'asc')
      } else {
        if (i === sortInfo.length - 1) colRequestSkipped = true
      }
    })

    if (sortCol.length === 0) {
      sortCol = [this.props.DEFAULT_SORT_COL]
      sortType = [this.props.DEFAULT_SORT_TYPE]
    }

    const joinedSortType = sortType.join()
    const joinedSortCols = sortCol.join()

    // Skip updating if last sort addition is disabled
    if (colRequestSkipped) return

    this._fetchListViewData(
      this.props,
      this.props.DEFAULT_PAGE,
      this.props.DEFAULT_PAGE_SIZE,
      joinedSortType,
      joinedSortCols
    )

    const newSortInfo = {
      uiSortOrder: sortInfo,
      currentSortCols: joinedSortCols,
      currentSortType: joinedSortType,
    }

    // Update page properties to use when navigating away
    this.props.onPagePropertiesChange({ sortInfo: newSortInfo })

    this.setState({
      sortInfo: newSortInfo,
    })
  }

  _handleColumnOrderChange(index, dropIndex) {
    const col = this.state.columns[index]
    this.state.columns.splice(index, 1)
    this.state.columns.splice(dropIndex, 0, col)
    this.setState({})
  }

  _resetColumns(props) {
    if (this.state.fixedCols || this.state.hideStateColumn) {
      return
    }

    // Toggle 'state' column for section/workspaces view
    if (this.state.hasOwnProperty('columns')) {
      if (props.routeParams.area === 'sections') {
        const stateCol = this.state.columns.findIndex((item) => item.name === 'state')

        this.state.columns.splice(stateCol, 1)
      } else {
        this.state.columns.push({ name: 'state', title: intl.trans('state', 'State', 'first') })
      }
    }
  }

  _resetPagination(props) {
    this.setState({
      pageInfo: {
        page: props.DEFAULT_PAGE,
        pageSize: props.DEFAULT_PAGE_SIZE,
      },
    })
  }
}
<|endoftext|>


<commit_before>var _ = require('underscore'),
    Backbone = require('backbone'),
    ControlBones;

ControlBones = function(options) {
   var self = this;

   // Copy all options to object
   _.each(options, function(value, key) {
      self[key] = value;
   });
};

ControlBones.prototype = {
   classes: ''
};

/**
 * This is called to render the view using
 * the latest data from the model.
 */
ControlBones.prototype.render = function() {
   // noop
};

   /**
    * @return Backbone.Model
    */
ControlBones.prototype._createSummaryModel = function() {
      return new Backbone.Model({
         'header': this.title,
         'classes': this.classes
      });
   };

// Benefit from Backbone.Events
_.extend(ControlBones.prototype, Backbone.Events);

ControlBones.extend = function(prototypeAdditions) {
   var parent = this,
       child;

   child = function(){
      return parent.apply(this, arguments);
   };

   _.extend(child, parent);
   _.extend(child.prototype, parent.prototype);

   if (prototypeAdditions) {
      _.extend(child.prototype, prototypeAdditions);
   }

   return child;
};

module.exports = ControlBones;
<commit_msg>Remove custom extend to use the one from Backbone<commit_after>var _ = require('underscore'),
    Backbone = require('backbone'),
    ControlBones;

ControlBones = function(options) {
   var self = this;

   // Copy all options to object
   _.each(options, function(value, key) {
      self[key] = value;
   });
};

ControlBones.prototype = {
   classes: ''
};

/**
 * This is called to render the view using
 * the latest data from the model.
 */
ControlBones.prototype.render = function() {
   // noop
};

   /**
    * @return Backbone.Model
    */
ControlBones.prototype._createSummaryModel = function() {
      return new Backbone.Model({
         'header': this.title,
         'classes': this.classes
      });
   };

// Benefit from Backbone.Events
_.extend(ControlBones.prototype, Backbone.Events);

// Snag the extend function from Backbone.Model
ControlBones.extend = Backbone.Model.extend;

module.exports = ControlBones;
<|endoftext|>


<commit_before>// Copyright 2013 Joyent, Inc.  All rights reserved.

var test = require('tap').test;
var libuuid = require('libuuid');
function uuid() {
    return (libuuid.create());
}
var util = require('util');
var common = require('./common');

///--- Globals

var client, server, THE_PACKAGE;

// May or not be created by previous test run or whatever else:
var sdc_512_ownership = {
    name: 'sdc_512_ownership',
    version: '1.0.0',
    max_physical_memory: 512,
    quota: 10240,
    max_swap: 1024,
    cpu_cap: 150,
    max_lwps: 1000,
    zfs_io_priority: 10,
    'default': false,
    vcpus: 1,
    urn: 'sdc:' + uuid() + ':sdc_512_ownership:1.0.0',
    active: true,
    owner_uuid: uuid()
};

var sdc_128_ok = {
    name: 'sdc_128_ok',
    version: '1.0.0',
    max_physical_memory: 128,
    quota: 10240,
    max_swap: 512,
    cpu_cap: 150,
    max_lwps: 1000,
    zfs_io_priority: 10,
    'default': false,
    vcpus: 1,
    urn: 'sdc:' + uuid() + ':sdc_128_ok:1.0.0',
    active: true,
    owner_uuid: uuid()
};

var sdc_512_ownership_entry, sdc_128_ok_entry;

// Add custom packages, given "sdc_" default ones will be owner by admin user.
function add128Ok(t, cb) {
    return client.pkg.get(sdc_128_ok.urn, function (err, pkg) {
        if (err) {
            if (err.restCode === 'ResourceNotFound') {
                return client.pkg.add(sdc_128_ok, function (err2, pkg2) {
                    t.ifError(err2, 'Error creating package');
                    t.ok(pkg2, 'Package created OK');
                    sdc_128_ok_entry = pkg2;
                    return cb();
                });
            } else {
                t.ifError(err, 'Error fetching package');
                return cb();
            }
        } else {
            sdc_128_ok_entry = pkg;
            return cb();
        }
    });
}

function add512Ownership(t, owner_uuid, cb) {
    sdc_512_ownership.owner_uuid = [sdc_512_ownership.owner_uuid,
        client.account.uuid];
    return client.pkg.get(sdc_512_ownership.urn, function (err4, pkg) {
        if (err4) {
            if (err4.restCode === 'ResourceNotFound') {
                return client.pkg.add(sdc_512_ownership,
                    function (err5, pkg2) {
                    t.ifError(err5, 'Error creating package');
                    t.ok(pkg2, 'Package created OK');
                    sdc_512_ownership_entry = pkg2;
                    return cb();
                });
            } else {
                t.ifError(err4, 'Error fetching package');
                return cb();
            }
        } else {
            sdc_512_ownership_entry = pkg;
            return cb();
        }
    });
}

///--- Helpers

function checkPackage_6_5(t, pkg) {
    t.ok(pkg, 'Package OK');
    t.ok(pkg.name, 'Package name');
    t.notOk(pkg.id, 'Package id not OK');
    t.ok(pkg.memory, 'Package memory');
    t.ok(pkg.disk, 'Package Disk');
    t.ok(!isNaN(pkg.vcpus), 'Package VCPUs OK');
    t.notOk(pkg.version, 'Package version not OK');
    t.ok(pkg.swap, 'Package swap');
    t.ok(pkg['default'] !== undefined, 'Package default');
}

function checkPackage_7(t, pkg) {
    t.ok(pkg, 'Package OK');
    t.ok(pkg.name, 'Package name');
    t.ok(pkg.id, 'Package id OK');
    t.ok(pkg.memory, 'Package memory');
    t.ok(pkg.disk, 'Package Disk');
    t.ok(!isNaN(pkg.vcpus), 'Package VCPUs OK');
    t.ok(pkg.version, 'Package version OK');
    t.ok(pkg.swap, 'Package swap');
    t.ok(pkg['default'] !== undefined, 'Package default');
}

///--- Tests

test('setup', function (t) {
    common.setup(function (err, _client, _server) {
        t.ifError(err);
        t.ok(_client);
        client = _client;
        if (!process.env.SDC_SETUP_TESTS) {
            t.ok(_server);
        }
        server = _server;
        add128Ok(t, function () {
            add512Ownership(t, client.account.uuid, function () {
                t.end();
            });
        });

    });
});

test('ListPackages OK (6.5)', function (t) {
    client.get({
        path: '/my/packages',
        headers: {
            'accept-version': '~6.5'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        t.ok(body);
        t.ok(Array.isArray(body));
        t.ok(body.length);
        body.forEach(function (p) {
            checkPackage_6_5(t, p);
        });
        t.end();
    });
});

test('GetPackage OK (6.5)', function (t) {
    client.get({
        path: '/my/packages/sdc_128_ok',
        headers: {
            'accept-version': '~6.5'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.ok(body);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        checkPackage_6_5(t, body);
        t.end();
    });
});

test('ListPackages OK (7.0)', function (t) {
    client.get({
        path: '/my/packages',
        headers: {
            'accept-version': '~7.0'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        t.ok(body);
        t.ok(Array.isArray(body));
        t.ok(body.length);
        body.forEach(function (p) {
            checkPackage_7(t, p);
        });
        t.end();
    });
});

test('search packages (7.0)', function (t) {
    client.get({
        path: '/my/packages?memory=128',
        headers: {
            'accept-version': '~7.0'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        t.ok(body);
        t.ok(Array.isArray(body));
        t.ok(body.length);
        body.forEach(function (p) {
            checkPackage_7(t, p);
            t.equal(128, p.memory);
        });
        t.end();
    });
});

test('GetPackage by name OK (7.0)', function (t) {
    client.get({
        path: '/my/packages/sdc_128_ok',
        headers: {
            'accept-version': '~7.0'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.ok(body);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        checkPackage_7(t, body);
        THE_PACKAGE = body;
        t.end();
    });
});

test('GetPackage by id OK (7.0)', function (t) {
    client.get({
        path: '/my/packages/' + THE_PACKAGE.id,
        headers: {
            'accept-version': '~7.0'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.ok(body);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        checkPackage_7(t, body);
        t.end();
    });
});

test('GetPackage 404', function (t) {
    client.get('/my/packages/' + uuid(), function (err) {
        t.ok(err);
        t.equal(err.statusCode, 404);
        t.equal(err.restCode, 'ResourceNotFound');
        t.ok(err.message);
        t.end();
    });
});

test('teardown', function (t) {
    client.teardown(function (err) {
        t.ifError(err, 'client teardown error');
        if (!process.env.SDC_SETUP_TESTS) {
            Object.keys(server._clients).forEach(function (c) {
                if (typeof (server._clients[c].client) !== 'undefined' &&
                    typeof (server._clients[c].client.close) ===
                        'function') {
                    server._clients[c].client.close();
                    }
            });
            server._clients.ufds.client.removeAllListeners('close');
            server.close(function () {
                t.end();
            });
        } else {
            t.end();
        }
    });
});
<commit_msg>PUBAPI-784: Package tests have been broken for a while w/o noticing it?<commit_after>// Copyright 2013 Joyent, Inc.  All rights reserved.

var test = require('tap').test;
var libuuid = require('libuuid');
function uuid() {
    return (libuuid.create());
}
var util = require('util');
var common = require('./common');

///--- Globals

var client, server, THE_PACKAGE;

// May or not be created by previous test run or whatever else:
var sdc_512_ownership = {
    name: 'sdc_512_ownership',
    version: '1.0.0',
    max_physical_memory: 512,
    quota: 10240,
    max_swap: 1024,
    cpu_cap: 150,
    max_lwps: 1000,
    zfs_io_priority: 10,
    'default': false,
    vcpus: 1,
    urn: 'sdc:' + uuid() + ':sdc_512_ownership:1.0.0',
    active: true,
    owner_uuid: uuid()
};

var sdc_128_ok = {
    name: 'sdc_128_ok',
    version: '1.0.0',
    max_physical_memory: 128,
    quota: 10240,
    max_swap: 512,
    cpu_cap: 150,
    max_lwps: 1000,
    zfs_io_priority: 10,
    'default': false,
    vcpus: 1,
    urn: 'sdc:' + uuid() + ':sdc_128_ok:1.0.0',
    active: true,
    owner_uuid: uuid()
};

var sdc_512_ownership_entry, sdc_128_ok_entry;

// Add custom packages, given "sdc_" default ones will be owner by admin user.
function add128Ok(t, cb) {
    return client.pkg.get(sdc_128_ok.urn, function (err, pkg) {
        if (err) {
            if (err.restCode === 'ResourceNotFound') {
                return client.pkg.add(sdc_128_ok, function (err2, pkg2) {
                    t.ifError(err2, 'Error creating package');
                    t.ok(pkg2, 'Package created OK');
                    sdc_128_ok_entry = pkg2;
                    return cb();
                });
            } else {
                t.ifError(err, 'Error fetching package');
                return cb();
            }
        } else {
            sdc_128_ok_entry = pkg;
            return cb();
        }
    });
}

function add512Ownership(t, owner_uuid, cb) {
    sdc_512_ownership.owner_uuid = [sdc_512_ownership.owner_uuid,
        client.account.uuid];
    return client.pkg.get(sdc_512_ownership.urn, function (err4, pkg) {
        if (err4) {
            if (err4.restCode === 'ResourceNotFound') {
                return client.pkg.add(sdc_512_ownership,
                    function (err5, pkg2) {
                    t.ifError(err5, 'Error creating package');
                    t.ok(pkg2, 'Package created OK');
                    sdc_512_ownership_entry = pkg2;
                    return cb();
                });
            } else {
                t.ifError(err4, 'Error fetching package');
                return cb();
            }
        } else {
            sdc_512_ownership_entry = pkg;
            return cb();
        }
    });
}

///--- Helpers

function checkPackage_6_5(t, pkg) {
    t.ok(pkg, 'Package OK');
    t.ok(pkg.name, 'Package name');
    t.notOk(pkg.id, 'Package id not OK');
    t.ok(pkg.memory, 'Package memory');
    t.ok(pkg.disk, 'Package Disk');
    t.ok(!isNaN(pkg.vcpus), 'Package VCPUs OK');
    t.notOk(pkg.version, 'Package version not OK');
    t.ok(pkg.swap, 'Package swap');
    t.ok(pkg['default'] !== undefined, 'Package default');
}

function checkPackage_7(t, pkg) {
    t.ok(pkg, 'Package OK');
    t.ok(pkg.name, 'Package name');
    t.ok(pkg.id, 'Package id OK');
    t.ok(pkg.memory, 'Package memory');
    t.ok(pkg.disk, 'Package Disk');
    t.ok(!isNaN(pkg.vcpus), 'Package VCPUs OK');
    t.ok(pkg.version, 'Package version OK');
    t.ok(pkg.swap, 'Package swap');
    t.ok(pkg['default'] !== undefined, 'Package default');
}

///--- Tests

test('setup', function (t) {
    common.setup(function (err, _client, _server) {
        t.ifError(err);
        t.ok(_client);
        client = _client;
        if (!process.env.SDC_SETUP_TESTS) {
            t.ok(_server);
        }
        server = _server;
        add128Ok(t, function () {
            add512Ownership(t, client.account.uuid, function () {
                t.end();
            });
        });

    });
});

test('ListPackages OK (6.5)', function (t) {
    client.get({
        path: '/my/packages',
        headers: {
            'accept-version': '~6.5'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        t.ok(body);
        t.ok(Array.isArray(body));
        t.ok(body.length);
        body.forEach(function (p) {
            checkPackage_6_5(t, p);
        });
        t.end();
    });
});

test('GetPackage OK (6.5)', function (t) {
    client.get({
        path: '/my/packages/sdc_512_ownership',
        headers: {
            'accept-version': '~6.5'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.ok(body);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        checkPackage_6_5(t, body);
        t.end();
    });
});

test('ListPackages OK (7.0)', function (t) {
    client.get({
        path: '/my/packages',
        headers: {
            'accept-version': '~7.0'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        t.ok(body);
        t.ok(Array.isArray(body));
        t.ok(body.length);
        body.forEach(function (p) {
            checkPackage_7(t, p);
        });
        t.end();
    });
});

test('search packages (7.0)', function (t) {
    client.get({
        path: '/my/packages?memory=128',
        headers: {
            'accept-version': '~7.0'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        t.ok(body);
        t.ok(Array.isArray(body));
        t.ok(body.length);
        body.forEach(function (p) {
            checkPackage_7(t, p);
            t.equal(128, p.memory);
        });
        t.end();
    });
});

test('GetPackage by name OK (7.0)', function (t) {
    client.get({
        path: '/my/packages/sdc_512_ownership',
        headers: {
            'accept-version': '~7.0'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.ok(body);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        checkPackage_7(t, body);
        THE_PACKAGE = body;
        t.end();
    });
});

test('GetPackage by id OK (7.0)', function (t) {
    client.get({
        path: '/my/packages/' + THE_PACKAGE.id,
        headers: {
            'accept-version': '~7.0'
        }
    }, function (err, req, res, body) {
        t.ifError(err);
        t.ok(body);
        t.equal(res.statusCode, 200);
        common.checkHeaders(t, res.headers);
        checkPackage_7(t, body);
        t.end();
    });
});

test('GetPackage 404', function (t) {
    client.get('/my/packages/' + uuid(), function (err) {
        t.ok(err);
        t.equal(err.statusCode, 404);
        t.equal(err.restCode, 'ResourceNotFound');
        t.ok(err.message);
        t.end();
    });
});

test('teardown', function (t) {
    client.teardown(function (err) {
        t.ifError(err, 'client teardown error');
        if (!process.env.SDC_SETUP_TESTS) {
            Object.keys(server._clients).forEach(function (c) {
                if (typeof (server._clients[c].client) !== 'undefined' &&
                    typeof (server._clients[c].client.close) ===
                        'function') {
                    server._clients[c].client.close();
                    }
            });
            server._clients.ufds.client.removeAllListeners('close');
            server.close(function () {
                t.end();
            });
        } else {
            t.end();
        }
    });
});
<|endoftext|>


<commit_before>var libxml = require('../index');

if (!global.gc) {
    throw new Error('must run with --expose_gc for ref integrity tests');
}

module.exports.gc = function(assert) {
    var doc = libxml.Document();
    doc.node('root').node('child').node('grandchild').parent().node('child2');
    gc();
    assert.ok(doc, "doc");
    gc();
    assert.ok(doc.root(), "root");
    gc();
    assert.equal("child", doc.root().childNodes()[0].name(), "child name");
    assert.done();
};

module.exports.references = function(assert) {
    var nodes = libxml.parseXml('<root> <child> <grandchildren/> </child> <child2/></root>').childNodes();

    gc();

    assert.ok(nodes[0].doc());
    assert.equal("child", nodes[1].name());
    assert.done();
};
<commit_msg>add a test for double free detection<commit_after>var libxml = require('../index');

if (!global.gc) {
    throw new Error('must run with --expose_gc for ref integrity tests');
}

module.exports.gc = function(assert) {
    var doc = libxml.Document();
    doc.node('root').node('child').node('grandchild').parent().node('child2');
    gc();
    assert.ok(doc, "doc");
    gc();
    assert.ok(doc.root(), "root");
    gc();
    assert.equal("child", doc.root().childNodes()[0].name(), "child name");
    assert.done();
};

module.exports.references = function(assert) {
    var nodes = libxml.parseXml('<root> <child> <grandchildren/> </child> <child2/></root>').childNodes();

    gc();

    assert.ok(nodes[0].doc());
    assert.equal("child", nodes[1].name());
    assert.done();
};

// test that double-freeing XmlNode's doesn't cause a segfault
module.exports.double_free = function(assert) {
    var children = null;

    // stick this portion of code into a self-executing function so
    // its internal variables can be garbage collected
    (function(){
        var html = '

';
        var doc = libxml.parseHtml(html);

        doc.find('//div').forEach(function(tag){
            // provide a reference to childNodes so they are exposed as XmlNodes
            // and therefore subject to V8's garbage collection
            children = tag.childNodes();
            tag.remove();
        });
    })();

    global.gc();
    assert.ok(children[0].attrs());
    assert.done();
};
<|endoftext|>


<commit_before>'use strict';

var supertest = require('supertest-as-promised'),
  path = require('path');

var app = require('../../server'),
  config = app.config,
  models = app.models,
  s3 = app.helpers.s3;

exports.expect = global.expect = require('chai').expect;
exports.request = supertest(app.init());
exports.fixtures = path.resolve(__dirname, './fixtures');
exports.app = app;
exports.config = config;
exports.models = models;
exports.s3 = s3;
<commit_msg>use callback instead of doing init<commit_after>'use strict';

var supertest = require('supertest-as-promised'),
  path = require('path');

var app = require('../../server'),
  config = app.config,
  models = app.models,
  s3 = app.helpers.s3;

exports.expect = global.expect = require('chai').expect;
exports.request = supertest(app.callback());
exports.fixtures = path.resolve(__dirname, './fixtures');
exports.app = app;
exports.config = config;
exports.models = models;
exports.s3 = s3;
<|endoftext|>


<commit_before>/*global describe, beforeEach, it*/
'use strict';

var path    = require('path');
var helpers = require('yeoman-generator').test;

describe('backbone-module generator', function () {
  beforeEach(function (done) {
    helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
      if (err) {
        return done(err);
      }

      this.app = helpers.createGenerator('backbone-module:app', [
        '../../app'
      ]);
      done();
    }.bind(this));
  });

  it('creates expected files', function (done) {
    var expected = [
      // add files you expect to exist here.
      '.jshintrc',
      '.editorconfig'
    ];

    helpers.mockPrompt(this.app, {
      'someOption': 'Y'
    });
    this.app.options['skip-install'] = true;
    this.app.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });
});
<commit_msg>Wrote basic file creation and template tests.<commit_after>/*global describe, beforeEach, it*/
'use strict';

var path    = require('path');
var helpers = require('yeoman-generator').test;

describe('backbone-module generator', function () {
  beforeEach(function (done) {
    helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
      if (err) {
        return done(err);
      }

      this.app = helpers.createGenerator('backbone-module:app', [
        '../../app'
      ]);
      done();
    }.bind(this));
  });

  it('creates expected files', function (done) {
    var expected = [
      // add files you expect to exist here.
      ['lib/fried-chicken.js', /root.friedChicken/],
      'test/test.config.js',
      'test/test.fried-chicken.js',
      'example/example.html',
      'util/web-server.js',
      ['bower.json', /"name": "fried-chicken"/],
      ['package.json', /"author": "Leroy Jenkins"/],
      'testrunner.html',
      'Gruntfile.js',
      'README.md',
      'LICENSE.md',
      '.bowerrc',
      '.gitignore',
      '.jshintrc',
      '.editorconfig'
    ];

    helpers.mockPrompt(this.app, {
      'moduleName': 'fried-chicken',
      'authorName': 'Leroy Jenkins'
    });
    this.app.options['skip-install'] = true;
    this.app.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });
});
<|endoftext|>


<commit_before>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2015 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

const InspectorChangeVersion = React.createClass({

  propTypes: {
    acl: React.PropTypes.object.isRequired,
    addCharm: React.PropTypes.func.isRequired,
    addNotification: React.PropTypes.func.isRequired,
    changeState: React.PropTypes.func.isRequired,
    charmId: React.PropTypes.string.isRequired,
    getAvailableVersions: React.PropTypes.func.isRequired,
    getCharm: React.PropTypes.func.isRequired,
    service: React.PropTypes.object.isRequired,
    setCharm: React.PropTypes.func.isRequired
  },

  versionsXhr: null,

  /**
    Get the current state.

    @method getInitialState
    @returns {String} The current state.
  */
  getInitialState: function() {
    return {
      loading: false,
      versionsList: null
    };
  },

  componentDidMount: function() {
    this._getVersions(this.props.charmId);
  },

  componentWillReceiveProps: function(nextProps) {
    this._getVersions(nextProps.charmId);
  },

  componentWillUnmount: function() {
    this.versionsXhr.abort();
  },

  /**
    The callable to be passed to the version item to view the charm details.

    @method _viewCharmDetails
    @param {Object} url The charm url as a window.jujulib.URL instance.
    @param {Object} evt The click event.
  */
  _viewCharmDetails: function(url, evt) {
    this.props.changeState({store: url.path()});
  },

  /**
    The callable to be passed to the version item to change versions.

      @method _versionButtonAction
      @param {String} charmId The charm id.
      @param {Object} e The click event.
  */
  _versionButtonAction: function(charmId, e) {
    const callback = this._addCharmCallback.bind(this, charmId);
    // XXX hatch: the ecs doesn't yet support addCharm so we are going to
    // send the command to juju immediately.
    this.props.addCharm(charmId, callback, {immediate: true});
  },

  /**
    Callback for handling the results of addCharm.

    @method _addCharmCallback
    @param {String} charmId The charm id.
    @param {Object} data The response object from the addCharm call in the
      format {err, url}.
  */
  _addCharmCallback: function(charmId, data) {
    var error = data.err;
    if (error) {
      this._addFailureNotification(charmId, error);
      return;
    }
    this.props.setCharm(this.props.service.get('id'), charmId, false, false,
      this._setCharmCallback.bind(this, charmId));
  },

  /**
    Callback for handling the results of setCharm.

    @method _setCharmCallback
  */
  _setCharmCallback: function(charmId, data) {
    if (data.err) {
      this._addFailureNotification(charmId, data.err);
      return;
    }
    this.props.getCharm(charmId, this._getCharmCallback.bind(this, charmId));
  },

  /**
    Callback for handling the results of getCharm.

    @method _getCharmCallback
  */
  _getCharmCallback: function(charmId, data) {
    if (data.err) {
      this._addFailureNotification(charmId, data.err);
      return;
    }
    this.props.service.set('charm', charmId);
  },

  /**
    Add a notification for an upgrade failure.

    @method _addFailureNotification
    @param {String} charmId The charm id.
    @param {Object} error The upgrade error.
  */
  _addFailureNotification: function(charmId, error) {
    this.props.addNotification({
      title: 'Charm upgrade failed',
      message: 'The charm ' + charmId + ' failed to upgrade:' + error,
      level: 'error'
    });
  },

  /**
    Get a list of versions for the charm.

    @method _getVersions
    @param {String} charmId The charm id.
  */
  _getVersions: function(charmId) {
    this.setState({loading: true});
    this.versionsXhr = this.props.getAvailableVersions(
      charmId, this._getVersionsCallback);
  },

  /**
    Update the state with the returned versions.

    @method _getVersionsSuccess
    @param {String} error The error message, if any. Null if no error.
    @param {Array} versions The available versions.
  */
  _getVersionsCallback: function(error, versions) {
    if (error) {
      console.error(error);
      versions = null;
    }
    let components = [];
    if (!versions || versions.length === 1) {
      components =

            No other versions found.

;
    } else {
      const url = window.jujulib.URL.fromLegacyString(this.props.charmId);
      versions.forEach(function(version) {
        const versionURL = window.jujulib.URL.fromLegacyString(version);
        let downgrade = false;
        if (versionURL.revision === url.revision) {
          return true;
        } else if (versionURL.revision < url.revision) {
          downgrade = true;
        }
        components.push(
          <juju.components.InspectorChangeVersionItem
            acl={this.props.acl}
            key={version}
            downgrade={downgrade}
            itemAction={this._viewCharmDetails.bind(this, versionURL)}
            buttonAction={this._versionButtonAction.bind(this, version)}
            url={versionURL}
          />);
      }, this);
    }
    this.setState({loading: false});
    this.setState({versionsList: components});
  },

  /**
    Display the versions list or a spinner if it is loading.

    @method _displayVersionsList
  */
  _displayVersionsList: function(loading, versionsList) {
    if (loading) {
      return(

          <juju.components.Spinner />

      );
    } else {
      return (

          {versionsList}

      );
    }
  },

  render: function() {
    const url = window.jujulib.URL.fromLegacyString(this.props.charmId);
    return (

          Current version:

            {url.path()}

        {this._displayVersionsList(this.state.loading,
          this.state.versionsList)}

    );
  }

});

YUI.add('inspector-change-version', function() {
  juju.components.InspectorChangeVersion = InspectorChangeVersion;
}, '0.1.0', { requires: [
  'inspector-change-version-item',
  'loading-spinner'
]});
<commit_msg>Update InspectorChangeVersion to use es6 class.<commit_after>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2015 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

class InspectorChangeVersion extends React.Component {
  constructor() {
    super();
    this.versionsXhr = null;
    this.state = {
      loading: false,
      versionsList: null
    };
  }

  componentDidMount() {
    this._getVersions(this.props.charmId);
  }

  componentWillReceiveProps(nextProps) {
    this._getVersions(nextProps.charmId);
  }

  componentWillUnmount() {
    this.versionsXhr.abort();
  }

  /**
    The callable to be passed to the version item to view the charm details.

    @method _viewCharmDetails
    @param {Object} url The charm url as a window.jujulib.URL instance.
    @param {Object} evt The click event.
  */
  _viewCharmDetails(url, evt) {
    this.props.changeState({store: url.path()});
  }

  /**
    The callable to be passed to the version item to change versions.

      @method _versionButtonAction
      @param {String} charmId The charm id.
      @param {Object} e The click event.
  */
  _versionButtonAction(charmId, e) {
    const callback = this._addCharmCallback.bind(this, charmId);
    // XXX hatch: the ecs doesn't yet support addCharm so we are going to
    // send the command to juju immediately.
    this.props.addCharm(charmId, callback, {immediate: true});
  }

  /**
    Callback for handling the results of addCharm.

    @method _addCharmCallback
    @param {String} charmId The charm id.
    @param {Object} data The response object from the addCharm call in the
      format {err, url}.
  */
  _addCharmCallback(charmId, data) {
    var error = data.err;
    if (error) {
      this._addFailureNotification(charmId, error);
      return;
    }
    this.props.setCharm(this.props.service.get('id'), charmId, false, false,
      this._setCharmCallback.bind(this, charmId));
  }

  /**
    Callback for handling the results of setCharm.

    @method _setCharmCallback
  */
  _setCharmCallback(charmId, data) {
    if (data.err) {
      this._addFailureNotification(charmId, data.err);
      return;
    }
    this.props.getCharm(charmId, this._getCharmCallback.bind(this, charmId));
  }

  /**
    Callback for handling the results of getCharm.

    @method _getCharmCallback
  */
  _getCharmCallback(charmId, data) {
    if (data.err) {
      this._addFailureNotification(charmId, data.err);
      return;
    }
    this.props.service.set('charm', charmId);
  }

  /**
    Add a notification for an upgrade failure.

    @method _addFailureNotification
    @param {String} charmId The charm id.
    @param {Object} error The upgrade error.
  */
  _addFailureNotification(charmId, error) {
    this.props.addNotification({
      title: 'Charm upgrade failed',
      message: 'The charm ' + charmId + ' failed to upgrade:' + error,
      level: 'error'
    });
  }

  /**
    Get a list of versions for the charm.

    @method _getVersions
    @param {String} charmId The charm id.
  */
  _getVersions(charmId) {
    this.setState({loading: true});
    this.versionsXhr = this.props.getAvailableVersions(
      charmId, this._getVersionsCallback.bind(this));
  }

  /**
    Update the state with the returned versions.

    @method _getVersionsSuccess
    @param {String} error The error message, if any. Null if no error.
    @param {Array} versions The available versions.
  */
  _getVersionsCallback(error, versions) {
    if (error) {
      console.error(error);
      versions = null;
    }
    let components = [];
    if (!versions || versions.length === 1) {
      components =

            No other versions found.

;
    } else {
      const url = window.jujulib.URL.fromLegacyString(this.props.charmId);
      versions.forEach(function(version) {
        const versionURL = window.jujulib.URL.fromLegacyString(version);
        let downgrade = false;
        if (versionURL.revision === url.revision) {
          return true;
        } else if (versionURL.revision < url.revision) {
          downgrade = true;
        }
        components.push(
          <juju.components.InspectorChangeVersionItem
            acl={this.props.acl}
            key={version}
            downgrade={downgrade}
            itemAction={this._viewCharmDetails.bind(this, versionURL)}
            buttonAction={this._versionButtonAction.bind(this, version)}
            url={versionURL}
          />);
      }, this);
    }
    this.setState({loading: false});
    this.setState({versionsList: components});
  }

  /**
    Display the versions list or a spinner if it is loading.

    @method _displayVersionsList
  */
  _displayVersionsList(loading, versionsList) {
    if (loading) {
      return(

          <juju.components.Spinner />

      );
    } else {
      return (

          {versionsList}

      );
    }
  }

  render() {
    const url = window.jujulib.URL.fromLegacyString(this.props.charmId);
    return (

          Current version:

            {url.path()}

        {this._displayVersionsList(this.state.loading,
          this.state.versionsList)}

    );
  }
};

InspectorChangeVersion.propTypes = {
  acl: React.PropTypes.object.isRequired,
  addCharm: React.PropTypes.func.isRequired,
  addNotification: React.PropTypes.func.isRequired,
  changeState: React.PropTypes.func.isRequired,
  charmId: React.PropTypes.string.isRequired,
  getAvailableVersions: React.PropTypes.func.isRequired,
  getCharm: React.PropTypes.func.isRequired,
  service: React.PropTypes.object.isRequired,
  setCharm: React.PropTypes.func.isRequired
};

YUI.add('inspector-change-version', function() {
  juju.components.InspectorChangeVersion = InspectorChangeVersion;
}, '0.1.0', { requires: [
  'inspector-change-version-item',
  'loading-spinner'
]});
<|endoftext|>