<commit_before>/**
 * XBlockContainerPage is used to display Studio's container page for an xblock which has children.
 * This page allows the user to understand and manipulate the xblock and its children.
 */
define(['jquery', 'underscore', 'backbone', 'gettext', 'js/views/pages/base_page',
    'common/js/components/utils/view_utils', 'js/views/container', 'js/views/xblock',
    'js/views/components/add_xblock', 'js/views/modals/edit_xblock', 'js/views/modals/move_xblock_modal',
    'js/models/xblock_info', 'js/views/xblock_string_field_editor', 'js/views/xblock_access_editor',
    'js/views/pages/container_subviews', 'js/views/unit_outline', 'js/views/utils/xblock_utils'],
    function($, _, Backbone, gettext, BasePage, ViewUtils, ContainerView, XBlockView, AddXBlockComponent,
          EditXBlockModal, MoveXBlockModal, XBlockInfo, XBlockStringFieldEditor, XBlockAccessEditor,
          ContainerSubviews, UnitOutlineView, XBlockUtils) {
        'use strict';
        var XBlockContainerPage = BasePage.extend({
            // takes XBlockInfo as a model

            events: {
                'click .edit-button': 'editXBlock',
                'click .access-button': 'editVisibilitySettings',
                'click .duplicate-button': 'duplicateXBlock',
                'click .move-button': 'showMoveXBlockModal',
                'click .delete-button': 'deleteXBlock',
                'click .new-component-button': 'scrollToNewComponentButtons'
            },

            options: {
                collapsedClass: 'is-collapsed',
                canEdit: true // If not specified, assume user has permission to make changes
            },

            view: 'container_preview',


            defaultViewClass: ContainerView,

            // Overridable by subclasses-- determines whether the XBlock component
            // addition menu is added on initialization. You may set this to false
            // if your subclass handles it.
            components_on_init: true,

            initialize: function(options) {
                BasePage.prototype.initialize.call(this, options);
                this.viewClass = options.viewClass || this.defaultViewClass;
                this.isLibraryPage = (this.model.attributes.category === 'library');
                this.nameEditor = new XBlockStringFieldEditor({
                    el: this.$('.wrapper-xblock-field'),
                    model: this.model
                });
                this.nameEditor.render();
                if (!this.isLibraryPage) {
                    this.accessEditor = new XBlockAccessEditor({
                        el: this.$('.wrapper-xblock-field')
                    });
                    this.accessEditor.render();
                }
                if (this.options.action === 'new') {
                    this.nameEditor.$('.xblock-field-value-edit').click();
                }
                this.xblockView = this.getXBlockView();
                this.messageView = new ContainerSubviews.MessageView({
                    el: this.$('.container-message'),
                    model: this.model
                });
                this.messageView.render();
                // Display access message on units and split test components
                if (!this.isLibraryPage) {
                    this.containerAccessView = new ContainerSubviews.ContainerAccess({
                        el: this.$('.container-access'),
                        model: this.model
                    });
                    this.containerAccessView.render();

                    this.xblockPublisher = new ContainerSubviews.Publisher({
                        el: this.$('#publish-unit'),
                        model: this.model,
                        // When "Discard Changes" is clicked, the whole page must be re-rendered.
                        renderPage: this.render
                    });
                    this.xblockPublisher.render();

                    this.publishHistory = new ContainerSubviews.PublishHistory({
                        el: this.$('#publish-history'),
                        model: this.model
                    });
                    this.publishHistory.render();

                    this.viewLiveActions = new ContainerSubviews.ViewLiveButtonController({
                        el: this.$('.nav-actions'),
                        model: this.model
                    });
                    this.viewLiveActions.render();

                    this.unitOutlineView = new UnitOutlineView({
                        el: this.$('.wrapper-unit-overview'),
                        model: this.model
                    });
                    this.unitOutlineView.render();
                }

                this.listenTo(Backbone, 'move:onXBlockMoved', this.onXBlockMoved);
            },

            getViewParameters: function() {
                return {
                    el: this.$('.wrapper-xblock'),
                    model: this.model,
                    view: this.view
                };
            },

            getXBlockView: function() {
                return new this.viewClass(this.getViewParameters());
            },

            render: function(options) {
                var self = this,
                    xblockView = this.xblockView,
                    loadingElement = this.$('.ui-loading'),
                    unitLocationTree = this.$('.unit-location'),
                    hiddenCss = 'is-hidden';

                loadingElement.removeClass(hiddenCss);

                // Hide both blocks until we know which one to show
                xblockView.$el.addClass(hiddenCss);

                // Render the xblock
                xblockView.render({
                    done: function() {
                        // Show the xblock and hide the loading indicator
                        xblockView.$el.removeClass(hiddenCss);
                        loadingElement.addClass(hiddenCss);

                        // Notify the runtime that the page has been successfully shown
                        xblockView.notifyRuntime('page-shown', self);

                        if (self.components_on_init) {
                            // Render the add buttons. Paged containers should do this on their own.
                            self.renderAddXBlockComponents();
                        }

                        // Refresh the views now that the xblock is visible
                        self.onXBlockRefresh(xblockView);
                        unitLocationTree.removeClass(hiddenCss);

                        // Re-enable Backbone events for any updated DOM elements
                        self.delegateEvents();
                    },
                    block_added: options && options.block_added
                });
            },

            findXBlockElement: function(target) {
                return $(target).closest('.studio-xblock-wrapper');
            },

            getURLRoot: function() {
                return this.xblockView.model.urlRoot;
            },

            onXBlockRefresh: function(xblockView, block_added, is_duplicate) {
                this.xblockView.refresh(xblockView, block_added, is_duplicate);
                // Update publish and last modified information from the server.
                this.model.fetch();
            },

            renderAddXBlockComponents: function() {
                var self = this;
                if (self.options.canEdit) {
                    this.$('.add-xblock-component').each(function(index, element) {
                        var component = new AddXBlockComponent({
                            el: element,
                            createComponent: _.bind(self.createComponent, self),
                            collection: self.options.templates
                        });
                        component.render();
                    });
                } else {
                    this.$('.add-xblock-component').remove();
                }
            },

            editXBlock: function(event, options) {
                var xblockElement = this.findXBlockElement(event.target),
                    self = this,
                    modal = new EditXBlockModal(options);
                event.preventDefault();

                  // check if we want to launch with the new editors (behind waffle flag)
                var useNewTextEditor = this.$('.edit-button').attr("use-new-editor-text"),
                    useNewVideoEditor = this.$('.edit-button').attr("use-new-editor-video"),
                    useNewProblemEditor = this.$('.edit-button').attr("use-new-editor-problem"),
                    blockType = xblockElement.find('.xblock').attr("data-block-type");
                if( (useNewTextEditor === "True" && blockType === "html") ||
                    (useNewVideoEditor === "True" && blockType === "video") ||
                    (useNewProblemEditor === "True" && blockType === "problem")
                ) {
                    var destinationUrl = this.$('.edit-button').attr("authoring_MFE_base_url") + '/' + blockType + '/' + this.$('.studio-xblock-wrapper').attr("data-locator");
                    window.location.replace(destinationUrl);
                    return;
                }
                modal.edit(xblockElement, this.model, {
                    readOnlyView: !this.options.canEdit,
                    refresh: function() {
                        self.refreshXBlock(xblockElement, false);
                    }
                });
            },

            editVisibilitySettings: function(event) {
                this.editXBlock(event, {
                    view: 'visibility_view',<commit_msg>feat: encode uri on new editors (#29825)<commit_after>/**
 * XBlockContainerPage is used to display Studio's container page for an xblock which has children.
 * This page allows the user to understand and manipulate the xblock and its children.
 */
define(['jquery', 'underscore', 'backbone', 'gettext', 'js/views/pages/base_page',
    'common/js/components/utils/view_utils', 'js/views/container', 'js/views/xblock',
    'js/views/components/add_xblock', 'js/views/modals/edit_xblock', 'js/views/modals/move_xblock_modal',
    'js/models/xblock_info', 'js/views/xblock_string_field_editor', 'js/views/xblock_access_editor',
    'js/views/pages/container_subviews', 'js/views/unit_outline', 'js/views/utils/xblock_utils'],
    function($, _, Backbone, gettext, BasePage, ViewUtils, ContainerView, XBlockView, AddXBlockComponent,
          EditXBlockModal, MoveXBlockModal, XBlockInfo, XBlockStringFieldEditor, XBlockAccessEditor,
          ContainerSubviews, UnitOutlineView, XBlockUtils) {
        'use strict';
        var XBlockContainerPage = BasePage.extend({
            // takes XBlockInfo as a model

            events: {
                'click .edit-button': 'editXBlock',
                'click .access-button': 'editVisibilitySettings',
                'click .duplicate-button': 'duplicateXBlock',
                'click .move-button': 'showMoveXBlockModal',
                'click .delete-button': 'deleteXBlock',
                'click .new-component-button': 'scrollToNewComponentButtons'
            },

            options: {
                collapsedClass: 'is-collapsed',
                canEdit: true // If not specified, assume user has permission to make changes
            },

            view: 'container_preview',


            defaultViewClass: ContainerView,

            // Overridable by subclasses-- determines whether the XBlock component
            // addition menu is added on initialization. You may set this to false
            // if your subclass handles it.
            components_on_init: true,

            initialize: function(options) {
                BasePage.prototype.initialize.call(this, options);
                this.viewClass = options.viewClass || this.defaultViewClass;
                this.isLibraryPage = (this.model.attributes.category === 'library');
                this.nameEditor = new XBlockStringFieldEditor({
                    el: this.$('.wrapper-xblock-field'),
                    model: this.model
                });
                this.nameEditor.render();
                if (!this.isLibraryPage) {
                    this.accessEditor = new XBlockAccessEditor({
                        el: this.$('.wrapper-xblock-field')
                    });
                    this.accessEditor.render();
                }
                if (this.options.action === 'new') {
                    this.nameEditor.$('.xblock-field-value-edit').click();
                }
                this.xblockView = this.getXBlockView();
                this.messageView = new ContainerSubviews.MessageView({
                    el: this.$('.container-message'),
                    model: this.model
                });
                this.messageView.render();
                // Display access message on units and split test components
                if (!this.isLibraryPage) {
                    this.containerAccessView = new ContainerSubviews.ContainerAccess({
                        el: this.$('.container-access'),
                        model: this.model
                    });
                    this.containerAccessView.render();

                    this.xblockPublisher = new ContainerSubviews.Publisher({
                        el: this.$('#publish-unit'),
                        model: this.model,
                        // When "Discard Changes" is clicked, the whole page must be re-rendered.
                        renderPage: this.render
                    });
                    this.xblockPublisher.render();

                    this.publishHistory = new ContainerSubviews.PublishHistory({
                        el: this.$('#publish-history'),
                        model: this.model
                    });
                    this.publishHistory.render();

                    this.viewLiveActions = new ContainerSubviews.ViewLiveButtonController({
                        el: this.$('.nav-actions'),
                        model: this.model
                    });
                    this.viewLiveActions.render();

                    this.unitOutlineView = new UnitOutlineView({
                        el: this.$('.wrapper-unit-overview'),
                        model: this.model
                    });
                    this.unitOutlineView.render();
                }

                this.listenTo(Backbone, 'move:onXBlockMoved', this.onXBlockMoved);
            },

            getViewParameters: function() {
                return {
                    el: this.$('.wrapper-xblock'),
                    model: this.model,
                    view: this.view
                };
            },

            getXBlockView: function() {
                return new this.viewClass(this.getViewParameters());
            },

            render: function(options) {
                var self = this,
                    xblockView = this.xblockView,
                    loadingElement = this.$('.ui-loading'),
                    unitLocationTree = this.$('.unit-location'),
                    hiddenCss = 'is-hidden';

                loadingElement.removeClass(hiddenCss);

                // Hide both blocks until we know which one to show
                xblockView.$el.addClass(hiddenCss);

                // Render the xblock
                xblockView.render({
                    done: function() {
                        // Show the xblock and hide the loading indicator
                        xblockView.$el.removeClass(hiddenCss);
                        loadingElement.addClass(hiddenCss);

                        // Notify the runtime that the page has been successfully shown
                        xblockView.notifyRuntime('page-shown', self);

                        if (self.components_on_init) {
                            // Render the add buttons. Paged containers should do this on their own.
                            self.renderAddXBlockComponents();
                        }

                        // Refresh the views now that the xblock is visible
                        self.onXBlockRefresh(xblockView);
                        unitLocationTree.removeClass(hiddenCss);

                        // Re-enable Backbone events for any updated DOM elements
                        self.delegateEvents();
                    },
                    block_added: options && options.block_added
                });
            },

            findXBlockElement: function(target) {
                return $(target).closest('.studio-xblock-wrapper');
            },

            getURLRoot: function() {
                return this.xblockView.model.urlRoot;
            },

            onXBlockRefresh: function(xblockView, block_added, is_duplicate) {
                this.xblockView.refresh(xblockView, block_added, is_duplicate);
                // Update publish and last modified information from the server.
                this.model.fetch();
            },

            renderAddXBlockComponents: function() {
                var self = this;
                if (self.options.canEdit) {
                    this.$('.add-xblock-component').each(function(index, element) {
                        var component = new AddXBlockComponent({
                            el: element,
                            createComponent: _.bind(self.createComponent, self),
                            collection: self.options.templates
                        });
                        component.render();
                    });
                } else {
                    this.$('.add-xblock-component').remove();
                }
            },

            editXBlock: function(event, options) {
                var xblockElement = this.findXBlockElement(event.target),
                    self = this,
                    modal = new EditXBlockModal(options);
                event.preventDefault();

                  // check if we want to launch with the new editors (behind waffle flag)
                var useNewTextEditor = this.$('.edit-button').attr("use-new-editor-text"),
                    useNewVideoEditor = this.$('.edit-button').attr("use-new-editor-video"),
                    useNewProblemEditor = this.$('.edit-button').attr("use-new-editor-problem"),
                    blockType = xblockElement.find('.xblock').attr("data-block-type");
                if( (useNewTextEditor === "True" && blockType === "html") ||
                    (useNewVideoEditor === "True" && blockType === "video") ||
                    (useNewProblemEditor === "True" && blockType === "problem")
                ) {
                    var destinationUrl = this.$('.edit-button').attr("authoring_MFE_base_url") + '/' + blockType + '/' + encodeURI(xblockElement.find('.xblock').attr("data-usage-id"));
                    window.location.href = destinationUrl;
                    return;
                }
                modal.edit(xblockElement, this.model, {
                    readOnlyView: !this.options.canEdit,
                    refresh: function() {
                        self.refreshXBlock(xblockElement, false);
                    }
                });
            },

            editVisibilitySettings: function(event) {
                this.editXBlock(event, {
                    view: 'visibility_view',
{'fraction_non_alphanumeric': 0.10401272577996716, 'fraction_numerical': 0.000256568144499179, 'mean_word_length': 1.4060493827160494, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2218131', 'n_tokens_mistral': 4704, 'n_tokens_neox': 4347, 'n_words': 934}